Merge "Correct annotation of ActivityOptions.SourceInfo.SourceType"
diff --git a/Android.bp b/Android.bp
index b1eb4a5..598f4fc 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1335,8 +1335,6 @@
sdk_version: "module_current",
min_sdk_version: "30",
srcs: [
- "core/java/android/content/pm/BaseParceledListSlice.java",
- "core/java/android/content/pm/ParceledListSlice.java",
"core/java/android/os/HandlerExecutor.java",
"core/java/com/android/internal/util/AsyncChannel.java",
"core/java/com/android/internal/util/AsyncService.java",
@@ -1355,12 +1353,6 @@
],
}
-filegroup {
- name: "framework-wifi-util-lib-aidls",
- srcs: ["core/java/android/content/pm/ParceledListSlice.aidl"],
- path: "core/java",
-}
-
// utility classes statically linked into wifi-service
filegroup {
name: "framework-wifi-service-shared-srcs",
diff --git a/apct-tests/perftests/packagemanager/Android.bp b/apct-tests/perftests/packagemanager/Android.bp
index 17033e0..c15b641 100644
--- a/apct-tests/perftests/packagemanager/Android.bp
+++ b/apct-tests/perftests/packagemanager/Android.bp
@@ -10,6 +10,7 @@
"androidx.test.ext.junit",
"androidx.annotation_annotation",
"apct-perftests-utils",
+ "collector-device-lib-platform",
],
libs: ["android.test.base"],
@@ -18,4 +19,8 @@
test_suites: ["device-tests"],
+ data: [":perfetto_artifacts"],
+
+ certificate: "platform",
+
}
diff --git a/apct-tests/perftests/packagemanager/AndroidTest.xml b/apct-tests/perftests/packagemanager/AndroidTest.xml
index c112d87..4903510 100644
--- a/apct-tests/perftests/packagemanager/AndroidTest.xml
+++ b/apct-tests/perftests/packagemanager/AndroidTest.xml
@@ -15,74 +15,122 @@
~ limitations under the License.
-->
<configuration description="Runs PackageManagerPerfTests metric instrumentation.">
- <option name="test-suite-tag" value="apct" />
- <option name="test-suite-tag" value="apct-metric-instrumentation" />
+ <option name="test-suite-tag" value="apct"/>
+ <option name="test-suite-tag" value="apct-metric-instrumentation"/>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
- <option name="cleanup-apks" value="true" />
- <option name="test-file-name" value="PackageManagerPerfTests.apk" />
+ <option name="cleanup-apks" value="true"/>
+ <option name="test-file-name" value="PackageManagerPerfTests.apk"/>
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
- <option name="cleanup-apks" value="true" />
- <option name="force-queryable" value="false" />
- <option name="test-file-name" value="QueriesAll0.apk" />
- <option name="test-file-name" value="QueriesAll1.apk" />
- <option name="test-file-name" value="QueriesAll2.apk" />
- <option name="test-file-name" value="QueriesAll3.apk" />
- <option name="test-file-name" value="QueriesAll4.apk" />
- <option name="test-file-name" value="QueriesAll5.apk" />
- <option name="test-file-name" value="QueriesAll6.apk" />
- <option name="test-file-name" value="QueriesAll7.apk" />
- <option name="test-file-name" value="QueriesAll8.apk" />
- <option name="test-file-name" value="QueriesAll9.apk" />
- <option name="test-file-name" value="QueriesAll10.apk" />
- <option name="test-file-name" value="QueriesAll11.apk" />
- <option name="test-file-name" value="QueriesAll12.apk" />
- <option name="test-file-name" value="QueriesAll13.apk" />
- <option name="test-file-name" value="QueriesAll14.apk" />
- <option name="test-file-name" value="QueriesAll15.apk" />
- <option name="test-file-name" value="QueriesAll16.apk" />
- <option name="test-file-name" value="QueriesAll17.apk" />
- <option name="test-file-name" value="QueriesAll18.apk" />
- <option name="test-file-name" value="QueriesAll19.apk" />
- <option name="test-file-name" value="QueriesAll20.apk" />
- <option name="test-file-name" value="QueriesAll21.apk" />
- <option name="test-file-name" value="QueriesAll22.apk" />
- <option name="test-file-name" value="QueriesAll23.apk" />
- <option name="test-file-name" value="QueriesAll24.apk" />
- <option name="test-file-name" value="QueriesAll25.apk" />
- <option name="test-file-name" value="QueriesAll26.apk" />
- <option name="test-file-name" value="QueriesAll27.apk" />
- <option name="test-file-name" value="QueriesAll28.apk" />
- <option name="test-file-name" value="QueriesAll29.apk" />
- <option name="test-file-name" value="QueriesAll30.apk" />
- <option name="test-file-name" value="QueriesAll31.apk" />
- <option name="test-file-name" value="QueriesAll32.apk" />
- <option name="test-file-name" value="QueriesAll33.apk" />
- <option name="test-file-name" value="QueriesAll34.apk" />
- <option name="test-file-name" value="QueriesAll35.apk" />
- <option name="test-file-name" value="QueriesAll36.apk" />
- <option name="test-file-name" value="QueriesAll37.apk" />
- <option name="test-file-name" value="QueriesAll38.apk" />
- <option name="test-file-name" value="QueriesAll39.apk" />
- <option name="test-file-name" value="QueriesAll40.apk" />
- <option name="test-file-name" value="QueriesAll41.apk" />
- <option name="test-file-name" value="QueriesAll42.apk" />
- <option name="test-file-name" value="QueriesAll43.apk" />
- <option name="test-file-name" value="QueriesAll44.apk" />
- <option name="test-file-name" value="QueriesAll45.apk" />
- <option name="test-file-name" value="QueriesAll46.apk" />
- <option name="test-file-name" value="QueriesAll47.apk" />
- <option name="test-file-name" value="QueriesAll48.apk" />
- <option name="test-file-name" value="QueriesAll49.apk" />
+ <option name="cleanup-apks" value="true"/>
+ <option name="force-queryable" value="false"/>
+ <option name="test-file-name" value="QueriesAll0.apk"/>
+ <option name="test-file-name" value="QueriesAll1.apk"/>
+ <option name="test-file-name" value="QueriesAll2.apk"/>
+ <option name="test-file-name" value="QueriesAll3.apk"/>
+ <option name="test-file-name" value="QueriesAll4.apk"/>
+ <option name="test-file-name" value="QueriesAll5.apk"/>
+ <option name="test-file-name" value="QueriesAll6.apk"/>
+ <option name="test-file-name" value="QueriesAll7.apk"/>
+ <option name="test-file-name" value="QueriesAll8.apk"/>
+ <option name="test-file-name" value="QueriesAll9.apk"/>
+ <option name="test-file-name" value="QueriesAll10.apk"/>
+ <option name="test-file-name" value="QueriesAll11.apk"/>
+ <option name="test-file-name" value="QueriesAll12.apk"/>
+ <option name="test-file-name" value="QueriesAll13.apk"/>
+ <option name="test-file-name" value="QueriesAll14.apk"/>
+ <option name="test-file-name" value="QueriesAll15.apk"/>
+ <option name="test-file-name" value="QueriesAll16.apk"/>
+ <option name="test-file-name" value="QueriesAll17.apk"/>
+ <option name="test-file-name" value="QueriesAll18.apk"/>
+ <option name="test-file-name" value="QueriesAll19.apk"/>
+ <option name="test-file-name" value="QueriesAll20.apk"/>
+ <option name="test-file-name" value="QueriesAll21.apk"/>
+ <option name="test-file-name" value="QueriesAll22.apk"/>
+ <option name="test-file-name" value="QueriesAll23.apk"/>
+ <option name="test-file-name" value="QueriesAll24.apk"/>
+ <option name="test-file-name" value="QueriesAll25.apk"/>
+ <option name="test-file-name" value="QueriesAll26.apk"/>
+ <option name="test-file-name" value="QueriesAll27.apk"/>
+ <option name="test-file-name" value="QueriesAll28.apk"/>
+ <option name="test-file-name" value="QueriesAll29.apk"/>
+ <option name="test-file-name" value="QueriesAll30.apk"/>
+ <option name="test-file-name" value="QueriesAll31.apk"/>
+ <option name="test-file-name" value="QueriesAll32.apk"/>
+ <option name="test-file-name" value="QueriesAll33.apk"/>
+ <option name="test-file-name" value="QueriesAll34.apk"/>
+ <option name="test-file-name" value="QueriesAll35.apk"/>
+ <option name="test-file-name" value="QueriesAll36.apk"/>
+ <option name="test-file-name" value="QueriesAll37.apk"/>
+ <option name="test-file-name" value="QueriesAll38.apk"/>
+ <option name="test-file-name" value="QueriesAll39.apk"/>
+ <option name="test-file-name" value="QueriesAll40.apk"/>
+ <option name="test-file-name" value="QueriesAll41.apk"/>
+ <option name="test-file-name" value="QueriesAll42.apk"/>
+ <option name="test-file-name" value="QueriesAll43.apk"/>
+ <option name="test-file-name" value="QueriesAll44.apk"/>
+ <option name="test-file-name" value="QueriesAll45.apk"/>
+ <option name="test-file-name" value="QueriesAll46.apk"/>
+ <option name="test-file-name" value="QueriesAll47.apk"/>
+ <option name="test-file-name" value="QueriesAll48.apk"/>
+ <option name="test-file-name" value="QueriesAll49.apk"/>
</target_preparer>
- <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
- <option name="package" value="com.android.perftests.packagemanager" />
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="com.android.perftests.packagemanager"/>
<option name="hidden-api-checks" value="false"/>
</test>
<metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
- <option name="directory-keys" value="/data/local/PackageManagerPerfTests" />
- <option name="collect-on-run-ended-only" value="true" />
+ <option name="directory-keys" value="/data/local/PackageManagerPerfTests"/>
+ <option name="collect-on-run-ended-only" value="true"/>
</metrics_collector>
+
+ <!-- Needed for pushing the trace config file -->
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="push-file" key="trace_config_detailed.textproto"
+ value="/data/misc/perfetto-traces/trace_config.textproto"/>
+ <!--Install the content provider automatically when we push some file in sdcard folder.-->
+ <!--Needed to avoid the installation during the test suite.-->
+ <option name="push-file" key="trace_config_detailed.textproto"
+ value="/sdcard/sample.textproto"/>
+ </target_preparer>
+
+ <!-- Needed for pulling the collected trace config on to the host -->
+ <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+ <option name="pull-pattern-keys" value="perfetto_file_path"/>
+ </metrics_collector>
+
+ <!-- Needed for storing the perfetto trace files in the sdcard/test_results -->
+ <option name="isolated-storage" value="false"/>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="com.android.perftests.packagemanager"/>
+ <option name="hidden-api-checks" value="false"/>
+
+ <!-- Listener related args for collecting the traces and waiting for the device to
+ stabilize. -->
+ <option name="device-listeners"
+ value="android.device.collectors.ProcLoadListener,android.device.collectors.PerfettoListener"/>
+ <!-- Guarantee that user defined RunListeners will be running before any of the default
+ listeners defined in this runner. -->
+ <option name="instrumentation-arg" key="newRunListenerMode" value="true"/>
+
+ <!-- ProcLoadListener related arguments -->
+ <!-- Wait for device last minute threshold to reach 3 with 2 minute timeout before starting
+ the test run -->
+ <option name="instrumentation-arg" key="procload-collector:per_run" value="true"/>
+ <option name="instrumentation-arg" key="proc-loadavg-threshold" value="3"/>
+ <option name="instrumentation-arg" key="proc-loadavg-timeout" value="120000"/>
+ <option name="instrumentation-arg" key="proc-loadavg-interval" value="10000"/>
+
+ <!-- PerfettoListener related arguments -->
+ <option name="instrumentation-arg" key="perfetto_config_text_proto" value="true"/>
+ <option name="instrumentation-arg" key="perfetto_config_file"
+ value="trace_config.textproto"/>
+
+ </test>
+
+
</configuration>
diff --git a/apex/appsearch/OWNERS b/apex/appsearch/OWNERS
index ce0c212..1703369 100644
--- a/apex/appsearch/OWNERS
+++ b/apex/appsearch/OWNERS
@@ -1 +1,3 @@
+adorokhine@google.com
sudheersai@google.com
+yamasani@google.com
diff --git a/apex/appsearch/framework/api/current.txt b/apex/appsearch/framework/api/current.txt
index 380c646..8713499 100644
--- a/apex/appsearch/framework/api/current.txt
+++ b/apex/appsearch/framework/api/current.txt
@@ -66,6 +66,21 @@
method @NonNull public android.app.appsearch.AppSearchSchema.PropertyConfig.Builder setTokenizerType(int);
}
+ public final class AppSearchSession {
+ method public void getByUri(@NonNull android.app.appsearch.GetByUriRequest, @NonNull java.util.concurrent.Executor, @NonNull android.app.appsearch.BatchResultCallback<java.lang.String,android.app.appsearch.GenericDocument>);
+ method public void getSchema(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.appsearch.AppSearchResult<java.util.Set<android.app.appsearch.AppSearchSchema>>>);
+ method public void putDocuments(@NonNull android.app.appsearch.PutDocumentsRequest, @NonNull java.util.concurrent.Executor, @NonNull android.app.appsearch.BatchResultCallback<java.lang.String,java.lang.Void>);
+ method @NonNull public android.app.appsearch.SearchResults query(@NonNull String, @NonNull android.app.appsearch.SearchSpec, @NonNull java.util.concurrent.Executor);
+ method public void removeByQuery(@NonNull String, @NonNull android.app.appsearch.SearchSpec, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.appsearch.AppSearchResult<java.lang.Void>>);
+ method public void removeByUri(@NonNull android.app.appsearch.RemoveByUriRequest, @NonNull java.util.concurrent.Executor, @NonNull android.app.appsearch.BatchResultCallback<java.lang.String,java.lang.Void>);
+ method public void setSchema(@NonNull android.app.appsearch.SetSchemaRequest, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.app.appsearch.AppSearchResult<java.lang.Void>>);
+ }
+
+ public interface BatchResultCallback<KeyType, ValueType> {
+ method public void onResult(@NonNull android.app.appsearch.AppSearchBatchResult<KeyType,ValueType>);
+ method public default void onSystemError(@Nullable Throwable);
+ }
+
public class GenericDocument {
ctor protected GenericDocument(@NonNull android.app.appsearch.GenericDocument);
method public long getCreationTimestampMillis();
@@ -162,6 +177,11 @@
method public int getStart();
}
+ public class SearchResults implements java.io.Closeable {
+ method public void close();
+ method public void getNextPage(@NonNull java.util.function.Consumer<android.app.appsearch.AppSearchResult<java.util.List<android.app.appsearch.SearchResult>>>);
+ }
+
public final class SearchSpec {
method public int getMaxSnippetSize();
method @NonNull public java.util.List<java.lang.String> getNamespaces();
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
index b7cd4f5..3e813ea 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java
@@ -18,10 +18,10 @@
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 android.util.ArraySet;
import java.util.ArrayList;
import java.util.List;
@@ -34,7 +34,8 @@
/**
* Represents a connection to an AppSearch storage system where {@link GenericDocument}s can be
* placed and queried.
- * @hide
+ *
+ * This class is thread safe.
*/
public final class AppSearchSession {
private final String mDatabaseName;
@@ -79,7 +80,7 @@
}
/**
- * Sets the schema will be used by documents provided to the {@link #putDocuments} method.
+ * Sets the schema that 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
@@ -123,11 +124,19 @@
* <p>It is a no-op to set the same schema as has been previously set; this is handled
* efficiently.
*
+ * <p>By default, documents are visible on platform surfaces. To opt out, call {@code
+ * SetSchemaRequest.Builder#setPlatformSurfaceable} with {@code surfaceable} as false. Any
+ * visibility settings apply only to the schemas that are included in the {@code request}.
+ * Visibility settings for a schema type do not apply or persist across
+ * {@link SetSchemaRequest}s.
+ *
* @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}.
*/
+ // TODO(b/169883602): Change @code references to @link when setPlatformSurfaceable APIs are
+ // exposed.
public void setSchema(
@NonNull SetSchemaRequest request,
@NonNull @CallbackExecutor Executor executor,
@@ -156,6 +165,43 @@
}
/**
+ * Retrieves the schema most recently successfully provided to {@link #setSchema}.
+ *
+ * @param executor Executor on which to invoke the callback.
+ * @param callback Callback to receive the pending results of schema.
+ */
+ public void getSchema(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull Consumer<AppSearchResult<Set<AppSearchSchema>>> callback) {
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(callback);
+ try {
+ mService.getSchema(
+ mDatabaseName,
+ new IAppSearchResultCallback.Stub() {
+ public void onResult(AppSearchResult result) {
+ executor.execute(() -> {
+ if (result.isSuccess()) {
+ List<Bundle> schemaBundles =
+ (List<Bundle>) result.getResultValue();
+ Set<AppSearchSchema> schemas = new ArraySet<>(
+ schemaBundles.size());
+ for (int i = 0; i < schemaBundles.size(); i++) {
+ schemas.add(new AppSearchSchema(schemaBundles.get(i)));
+ }
+ callback.accept(AppSearchResult.newSuccessfulResult(schemas));
+ } else {
+ 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
@@ -167,9 +213,9 @@
* 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.
+ * Or {@link BatchResultCallback#onSystemError} will be invoked with a
+ * {@link Throwable} if an unexpected internal error occurred in AppSearch
+ * service.
*/
public void putDocuments(
@NonNull PutDocumentsRequest request,
@@ -210,9 +256,9 @@
* {@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.
+ * Or {@link BatchResultCallback#onSystemError} will be invoked with a
+ * {@link Throwable} if an unexpected internal error occurred in AppSearch
+ * service.
*/
public void getByUri(
@NonNull GetByUriRequest request,
@@ -338,9 +384,9 @@
* 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.
+ * Or {@link BatchResultCallback#onSystemError} will be invoked with a
+ * {@link Throwable} if an unexpected internal error occurred in AppSearch
+ * service.
*/
public void removeByUri(
@NonNull RemoveByUriRequest request,
@@ -369,7 +415,7 @@
/**
* Removes {@link GenericDocument}s from the index by Query. Documents will be removed if they
* match the {@code queryExpression} in given namespaces and schemaTypes which is set via
- * {@link SearchSpec.Builder#addNamespace} and {@link SearchSpec.Builder#addSchema}.
+ * {@link SearchSpec.Builder#addNamespace} and {@link SearchSpec.Builder#addSchemaType}.
*
* <p> An empty {@code queryExpression} matches all documents.
*
@@ -377,10 +423,13 @@
* the current database.
*
* @param queryExpression Query String to search.
- * @param searchSpec Defines what and how to remove
- * @param executor Executor on which to invoke the callback.
- * @param callback Callback to receive errors resulting from removing the documents. If the
- * operation succeeds, the callback will be invoked with {@code null}.
+ * @param searchSpec Spec containing schemaTypes, namespaces and query expression indicates
+ * how document will be removed. All specific about how to scoring,
+ * ordering, snippeting and resulting will be ignored.
+ * @param executor Executor on which to invoke the callback.
+ * @param callback Callback to receive errors resulting from removing the documents. If
+ * the operation succeeds, the callback will be invoked with
+ * {@code null}.
*/
public void removeByQuery(@NonNull String queryExpression,
@NonNull SearchSpec searchSpec,
diff --git a/apex/appsearch/framework/java/android/app/appsearch/BatchResultCallback.java b/apex/appsearch/framework/java/android/app/appsearch/BatchResultCallback.java
index 1689e02..49049b6 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/BatchResultCallback.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/BatchResultCallback.java
@@ -16,13 +16,15 @@
package android.app.appsearch;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
/**
* 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> {
@@ -31,15 +33,14 @@
*
* @param result The result of the executed request.
*/
- void onResult(AppSearchBatchResult<KeyType, ValueType> result);
-
+ void onResult(@NonNull AppSearchBatchResult<KeyType, ValueType> result);
/**
* Called when a system error occurred.
*
* @param throwable The cause throwable.
*/
- default void onSystemError(Throwable throwable) {
+ default void onSystemError(@Nullable Throwable throwable) {
if (throwable != null) {
throw new RuntimeException(throwable);
}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java b/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java
index d2aa8ea..07938b7 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java
@@ -115,7 +115,7 @@
* @return The search result of performing this operation.
*/
@NonNull
- public SearchResults globalQuery(
+ public SearchResults query(
@NonNull String queryExpression,
@NonNull SearchSpec searchSpec,
@NonNull @CallbackExecutor Executor executor) {
diff --git a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
index 1d7cb87..7883046 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
+++ b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl
@@ -28,10 +28,10 @@
/** {@hide} */
interface IAppSearchManager {
/**
- * Sets the schema.
+ * Updates the AppSearch schema for this database.
*
- * @param databaseName The databaseName this document resides in.
- * @param schemaBundles List of AppSearchSchema bundles.
+ * @param databaseName The name of the database where this schema lives.
+ * @param schemaBundles List of {@link AppSearchSchema} bundles.
* @param schemasNotPlatformSurfaceable Schema types that should not be surfaced on platform
* surfaces.
* @param forceOverride Whether to apply the new schema even if it is incompatible. All
@@ -46,6 +46,17 @@
boolean forceOverride,
in IAppSearchResultCallback callback);
+
+ /**
+ * Retrieves the AppSearch schema for this database.
+ *
+ * @param databaseName The name of the database to retrieve.
+ * @param callback {@link IAppSearchResultCallback#onResult} will be called with an
+ * {@link AppSearchResult}<{@link List}<{@link Bundle}>>, where the value are
+ * AppSearchSchema bundle.
+ */
+ void getSchema(in String databaseName, in IAppSearchResultCallback callback);
+
/**
* Inserts documents into the index.
*
diff --git a/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java b/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java
index 8548d20..7dc13b4 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java
@@ -39,7 +39,6 @@
* <p>Should close this object after finish fetching results.
*
* <p>This class is not thread safe.
- * @hide
*/
public class SearchResults implements Closeable {
private static final String TAG = "SearchResults";
@@ -77,7 +76,7 @@
* <p>Re-call this method to get next page of {@link SearchResult}, until it returns an
* empty list.
*
- * <p>The page size is set by {@link SearchSpec.Builder#setNumPerPage}.
+ * <p>The page size is set by {@link SearchSpec.Builder#setResultCountPerPage}.
*
* @param callback Callback to receive the pending result of performing this operation.
*/
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/PackageIdentifier.java b/apex/appsearch/framework/java/external/android/app/appsearch/PackageIdentifier.java
new file mode 100644
index 0000000..b567dee
--- /dev/null
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/PackageIdentifier.java
@@ -0,0 +1,61 @@
+/*
+ * 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.NonNull;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * This class represents a uniquely identifiable package.
+ *
+ * @hide
+ */
+public class PackageIdentifier {
+ public final String packageName;
+ public final byte[] certificate;
+
+ /**
+ * Creates a unique identifier for a package.
+ *
+ * @param packageName Name of the package.
+ * @param certificate SHA256 certificate digest of the package.
+ */
+ public PackageIdentifier(@NonNull String packageName, @NonNull byte[] certificate) {
+ this.packageName = packageName;
+ this.certificate = certificate;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || !(obj instanceof PackageIdentifier)) {
+ return false;
+ }
+ final PackageIdentifier other = (PackageIdentifier) obj;
+ return this.packageName.equals(other.packageName)
+ && Arrays.equals(this.certificate, other.certificate);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(packageName, Arrays.hashCode(certificate));
+ }
+}
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/RemoveByUriRequest.java b/apex/appsearch/framework/java/external/android/app/appsearch/RemoveByUriRequest.java
index be6d157..a04da34 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/RemoveByUriRequest.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/RemoveByUriRequest.java
@@ -46,7 +46,7 @@
return mNamespace;
}
- /** Returns the URIs to remove from the namespace. */
+ /** Returns the URIs of documents to remove from the namespace. */
@NonNull
public Set<String> getUris() {
return Collections.unmodifiableSet(mUris);
diff --git a/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaRequest.java b/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaRequest.java
index 0e03131..4ef30c3 100644
--- a/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaRequest.java
+++ b/apex/appsearch/framework/java/external/android/app/appsearch/SetSchemaRequest.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.SuppressLint;
import android.app.appsearch.exceptions.AppSearchException;
+import android.util.ArrayMap;
import android.util.ArraySet;
import com.android.internal.util.Preconditions;
@@ -28,6 +29,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
import java.util.Set;
/**
@@ -38,14 +40,17 @@
public final class SetSchemaRequest {
private final Set<AppSearchSchema> mSchemas;
private final Set<String> mSchemasNotPlatformSurfaceable;
+ private final Map<String, Set<PackageIdentifier>> mSchemasPackageAccessible;
private final boolean mForceOverride;
SetSchemaRequest(
@NonNull Set<AppSearchSchema> schemas,
@NonNull Set<String> schemasNotPlatformSurfaceable,
+ @NonNull Map<String, Set<PackageIdentifier>> schemasPackageAccessible,
boolean forceOverride) {
mSchemas = Preconditions.checkNotNull(schemas);
mSchemasNotPlatformSurfaceable = Preconditions.checkNotNull(schemasNotPlatformSurfaceable);
+ mSchemasPackageAccessible = Preconditions.checkNotNull(schemasPackageAccessible);
mForceOverride = forceOverride;
}
@@ -65,6 +70,39 @@
return Collections.unmodifiableSet(mSchemasNotPlatformSurfaceable);
}
+ /**
+ * Returns a mapping of schema types to the set of packages that have access to that schema
+ * type. Each package is represented by a {@link PackageIdentifier}. name and byte[]
+ * certificate.
+ *
+ * <p>This method is inefficient to call repeatedly.
+ *
+ * @hide
+ */
+ @NonNull
+ public Map<String, Set<PackageIdentifier>> getSchemasPackageAccessible() {
+ Map<String, Set<PackageIdentifier>> copy = new ArrayMap<>();
+ for (String key : mSchemasPackageAccessible.keySet()) {
+ copy.put(key, new ArraySet<>(mSchemasPackageAccessible.get(key)));
+ }
+ return copy;
+ }
+
+ /**
+ * Returns a mapping of schema types to the set of packages that have access to that schema
+ * type. Each package is represented by a {@link PackageIdentifier}. name and byte[]
+ * certificate.
+ *
+ * <p>A more efficient version of {@code #getSchemasPackageAccessible}, but it returns a
+ * modifiable map. This is not meant to be unhidden and should only be used by internal classes.
+ *
+ * @hide
+ */
+ @NonNull
+ public Map<String, Set<PackageIdentifier>> getSchemasPackageAccessibleInternal() {
+ return mSchemasPackageAccessible;
+ }
+
/** Returns whether this request will force the schema to be overridden. */
public boolean isForceOverride() {
return mForceOverride;
@@ -74,6 +112,8 @@
public static final class Builder {
private final Set<AppSearchSchema> mSchemas = new ArraySet<>();
private final Set<String> mSchemasNotPlatformSurfaceable = new ArraySet<>();
+ private final Map<String, Set<PackageIdentifier>> mSchemasPackageAccessible =
+ new ArrayMap<>();
private boolean mForceOverride = false;
private boolean mBuilt = false;
@@ -102,32 +142,62 @@
}
/**
- * Sets visibility on system UI surfaces for schema types.
+ * Sets visibility on system UI surfaces for the given {@code schemaType}.
*
+ * @param schemaType The schema type to set visibility on.
+ * @param visible Whether the {@code schemaType} will be visible or not.
* @hide
*/
@NonNull
public Builder setSchemaTypeVisibilityForSystemUi(
- boolean visible, @NonNull String... schemaTypes) {
- Preconditions.checkNotNull(schemaTypes);
- return this.setSchemaTypeVisibilityForSystemUi(visible, Arrays.asList(schemaTypes));
+ @NonNull String schemaType, boolean visible) {
+ Preconditions.checkNotNull(schemaType);
+ Preconditions.checkState(!mBuilt, "Builder has already been used");
+
+ if (visible) {
+ mSchemasNotPlatformSurfaceable.remove(schemaType);
+ } else {
+ mSchemasNotPlatformSurfaceable.add(schemaType);
+ }
+ return this;
}
/**
- * Sets visibility on system UI surfaces for schema types.
+ * Sets visibility for a package for the given {@code schemaType}.
*
+ * @param schemaType The schema type to set visibility on.
+ * @param visible Whether the {@code schemaType} will be visible or not.
+ * @param packageIdentifier Represents the package that will be granted visibility.
* @hide
*/
@NonNull
- public Builder setSchemaTypeVisibilityForSystemUi(
- boolean visible, @NonNull Collection<String> schemaTypes) {
+ public Builder setSchemaTypeVisibilityForPackage(
+ @NonNull String schemaType,
+ boolean visible,
+ @NonNull PackageIdentifier packageIdentifier) {
+ Preconditions.checkNotNull(schemaType);
+ Preconditions.checkNotNull(packageIdentifier);
Preconditions.checkState(!mBuilt, "Builder has already been used");
- Preconditions.checkNotNull(schemaTypes);
+
+ Set<PackageIdentifier> packageIdentifiers = mSchemasPackageAccessible.get(schemaType);
if (visible) {
- mSchemasNotPlatformSurfaceable.removeAll(schemaTypes);
+ if (packageIdentifiers == null) {
+ packageIdentifiers = new ArraySet<>();
+ }
+ packageIdentifiers.add(packageIdentifier);
+ mSchemasPackageAccessible.put(schemaType, packageIdentifiers);
} else {
- mSchemasNotPlatformSurfaceable.addAll(schemaTypes);
+ if (packageIdentifiers == null) {
+ // Return early since there was nothing set to begin with.
+ return this;
+ }
+ packageIdentifiers.remove(packageIdentifier);
+ if (packageIdentifiers.isEmpty()) {
+ // Remove the entire key so that we don't have empty sets as values.
+ mSchemasPackageAccessible.remove(schemaType);
+ }
}
+
return this;
}
@@ -159,21 +229,24 @@
// Verify that any schema types with visibility settings refer to a real schema.
// Create a copy because we're going to remove from the set for verification purposes.
- Set<String> schemasNotPlatformSurfaceableCopy =
- new ArraySet<>(mSchemasNotPlatformSurfaceable);
+ Set<String> referencedSchemas = new ArraySet<>(mSchemasNotPlatformSurfaceable);
+ referencedSchemas.addAll(mSchemasPackageAccessible.keySet());
+
for (AppSearchSchema schema : mSchemas) {
- schemasNotPlatformSurfaceableCopy.remove(schema.getSchemaType());
+ referencedSchemas.remove(schema.getSchemaType());
}
- if (!schemasNotPlatformSurfaceableCopy.isEmpty()) {
+ if (!referencedSchemas.isEmpty()) {
// We still have schema types that weren't seen in our mSchemas set. This means
// there wasn't a corresponding AppSearchSchema.
throw new IllegalArgumentException(
- "Schema types "
- + schemasNotPlatformSurfaceableCopy
- + " referenced, but were not added.");
+ "Schema types " + referencedSchemas + " referenced, but were not added.");
}
- return new SetSchemaRequest(mSchemas, mSchemasNotPlatformSurfaceable, mForceOverride);
+ return new SetSchemaRequest(
+ mSchemas,
+ mSchemasNotPlatformSurfaceable,
+ mSchemasPackageAccessible,
+ mForceOverride);
}
}
}
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 551347c..d81b794 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
@@ -47,7 +47,6 @@
*/
public class AppSearchManagerService extends SystemService {
private static final String TAG = "AppSearchManagerService";
- private static final char CALLING_NAME_DATABASE_DELIMITER = '$';
public AppSearchManagerService(Context context) {
super(context);
@@ -78,8 +77,9 @@
schemas.add(new AppSearchSchema(schemaBundles.get(i)));
}
AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
- databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid);
- impl.setSchema(databaseName, schemas, schemasNotPlatformSurfaceable, forceOverride);
+ String packageName = convertUidToPackageName(callingUid);
+ impl.setSchema(packageName, databaseName, schemas, schemasNotPlatformSurfaceable,
+ forceOverride);
invokeCallbackOnResult(callback,
AppSearchResult.newSuccessfulResult(/*result=*/ null));
} catch (Throwable t) {
@@ -90,6 +90,32 @@
}
@Override
+ public void getSchema(
+ @NonNull String databaseName,
+ @NonNull IAppSearchResultCallback callback) {
+ Preconditions.checkNotNull(databaseName);
+ Preconditions.checkNotNull(callback);
+ int callingUid = Binder.getCallingUidOrThrow();
+ int callingUserId = UserHandle.getUserId(callingUid);
+ final long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
+ String packageName = convertUidToPackageName(callingUid);
+ List<AppSearchSchema> schemas = impl.getSchema(packageName, databaseName);
+ List<Bundle> schemaBundles = new ArrayList<>(schemas.size());
+ for (int i = 0; i < schemas.size(); i++) {
+ schemaBundles.add(schemas.get(i).getBundle());
+ }
+ invokeCallbackOnResult(callback,
+ AppSearchResult.newSuccessfulResult(schemaBundles));
+ } catch (Throwable t) {
+ invokeCallbackOnError(callback, t);
+ } finally {
+ Binder.restoreCallingIdentity(callingIdentity);
+ }
+ }
+
+ @Override
public void putDocuments(
@NonNull String databaseName,
@NonNull List<Bundle> documentBundles,
@@ -104,13 +130,13 @@
AppSearchBatchResult.Builder<String, Void> resultBuilder =
new AppSearchBatchResult.Builder<>();
AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
- databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid);
+ String packageName = convertUidToPackageName(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);
+ impl.putDocument(packageName, databaseName, document);
resultBuilder.setSuccess(document.getUri(), /*result=*/ null);
} catch (Throwable t) {
resultBuilder.setResult(document.getUri(), throwableToFailedResult(t));
@@ -139,11 +165,12 @@
AppSearchBatchResult.Builder<String, Bundle> resultBuilder =
new AppSearchBatchResult.Builder<>();
AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
- databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid);
+ String packageName = convertUidToPackageName(callingUid);
for (int i = 0; i < uris.size(); i++) {
String uri = uris.get(i);
try {
- GenericDocument document = impl.getDocument(databaseName, namespace, uri);
+ GenericDocument document = impl.getDocument(packageName, databaseName,
+ namespace, uri);
resultBuilder.setSuccess(uri, document.getBundle());
} catch (Throwable t) {
resultBuilder.setResult(uri, throwableToFailedResult(t));
@@ -173,8 +200,9 @@
final long callingIdentity = Binder.clearCallingIdentity();
try {
AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
- databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid);
+ String packageName = convertUidToPackageName(callingUid);
SearchResultPage searchResultPage = impl.query(
+ packageName,
databaseName,
queryExpression,
new SearchSpec(searchSpecBundle));
@@ -257,15 +285,15 @@
int callingUid = Binder.getCallingUidOrThrow();
int callingUserId = UserHandle.getUserId(callingUid);
final long callingIdentity = Binder.clearCallingIdentity();
- AppSearchBatchResult.Builder<String, Void> resultBuilder =
- new AppSearchBatchResult.Builder<>();
try {
+ AppSearchBatchResult.Builder<String, Void> resultBuilder =
+ new AppSearchBatchResult.Builder<>();
AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
- databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid);
+ String packageName = convertUidToPackageName(callingUid);
for (int i = 0; i < uris.size(); i++) {
String uri = uris.get(i);
try {
- impl.remove(databaseName, namespace, uri);
+ impl.remove(packageName, databaseName, namespace, uri);
resultBuilder.setSuccess(uri, /*result= */null);
} catch (Throwable t) {
resultBuilder.setResult(uri, throwableToFailedResult(t));
@@ -294,8 +322,8 @@
final long callingIdentity = Binder.clearCallingIdentity();
try {
AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId);
- databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid);
- impl.removeByQuery(databaseName, queryExpression,
+ String packageName = convertUidToPackageName(callingUid);
+ impl.removeByQuery(packageName, databaseName, queryExpression,
new SearchSpec(searchSpecBundle));
invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null));
} catch (Throwable t) {
@@ -322,13 +350,13 @@
}
/**
- * Rewrites the database name by adding a prefix of unique name for the given uid.
+ * Returns a package name for the given uid.
*
* <p>The current implementation returns the package name of the app with this uid in a
* format like {@code com.example.package} or {@code com.example.sharedname:5678}.
*/
@NonNull
- private String rewriteDatabaseNameWithUid(String databaseName, int callingUid) {
+ private String convertUidToPackageName(int callingUid) {
// For regular apps, this call will return the package name. If callingUid is an
// android:sharedUserId, this value may be another type of name and have a :uid suffix.
String callingUidName = getContext().getPackageManager().getNameForUid(callingUid);
@@ -337,12 +365,12 @@
throw new IllegalStateException(
"Failed to look up package name for uid " + callingUid);
}
- return callingUidName + CALLING_NAME_DATABASE_DELIMITER + databaseName;
+ return callingUidName;
}
- /** Invokes the {@link IAppSearchResultCallback} with the result. */
+ /** Invokes the {@link IAppSearchResultCallback} with the result. */
private void invokeCallbackOnResult(IAppSearchResultCallback callback,
- AppSearchResult result) {
+ AppSearchResult<?> result) {
try {
callback.onResult(result);
} catch (RemoteException e) {
@@ -350,9 +378,9 @@
}
}
- /** Invokes the {@link IAppSearchBatchResultCallback} with the result. */
+ /** Invokes the {@link IAppSearchBatchResultCallback} with the result. */
private void invokeCallbackOnResult(IAppSearchBatchResultCallback callback,
- AppSearchBatchResult result) {
+ AppSearchBatchResult<?, ?> result) {
try {
callback.onResult(result);
} catch (RemoteException e) {
@@ -361,9 +389,9 @@
}
/**
- * Invokes the {@link IAppSearchResultCallback} with an throwable.
+ * Invokes the {@link IAppSearchResultCallback} with an throwable.
*
- * <p>The throwable is convert to a {@link AppSearchResult};
+ * <p>The throwable is convert to a {@link AppSearchResult};
*/
private void invokeCallbackOnError(IAppSearchResultCallback callback, Throwable throwable) {
try {
@@ -374,7 +402,7 @@
}
/**
- * Invokes the {@link IAppSearchBatchResultCallback} with an throwable.
+ * Invokes the {@link IAppSearchBatchResultCallback} with an unexpected internal throwable.
*
* <p>The throwable is converted to {@link ParcelableException}.
*/
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
index 62b81d0..c806af5 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
@@ -75,15 +75,17 @@
*
* <p>Never create two instances using the same folder.
*
- * <p>A single instance of {@link AppSearchImpl} can support all databases. Schemas and documents
- * are physically saved together in {@link IcingSearchEngine}, but logically isolated:
+ * <p>A single instance of {@link AppSearchImpl} can support all packages and databases. This is
+ * done by combining the package and database name into a unique prefix and prefixing the schemas
+ * and documents stored under that owner. Schemas and documents are physically saved together in
+ * {@link IcingSearchEngine}, but logically isolated:
*
* <ul>
- * <li>Rewrite SchemaType in SchemaProto by adding database name prefix and save into SchemaTypes
- * set in {@link #setSchema}.
- * <li>Rewrite namespace and SchemaType in DocumentProto by adding database name prefix and save
- * to namespaces set in {@link #putDocument}.
- * <li>Remove database name prefix when retrieve documents in {@link #getDocument} and {@link
+ * <li>Rewrite SchemaType in SchemaProto by adding the package-database prefix and save into
+ * SchemaTypes set in {@link #setSchema}.
+ * <li>Rewrite namespace and SchemaType in DocumentProto by adding package-database prefix and
+ * save to namespaces set in {@link #putDocument}.
+ * <li>Remove package-database prefix when retrieving documents in {@link #getDocument} and {@link
* #query}.
* <li>Rewrite filters in {@link SearchSpecProto} to have all namespaces and schema types of the
* queried database when user using empty filters in {@link #query}.
@@ -108,6 +110,8 @@
@VisibleForTesting static final char DATABASE_DELIMITER = '/';
+ @VisibleForTesting static final char PACKAGE_DELIMITER = '$';
+
@VisibleForTesting static final int OPTIMIZE_THRESHOLD_DOC_COUNT = 1000;
@VisibleForTesting static final int OPTIMIZE_THRESHOLD_BYTES = 1_000_000; // 1MB
@VisibleForTesting static final int CHECK_OPTIMIZE_INTERVAL = 100;
@@ -120,12 +124,14 @@
@GuardedBy("mReadWriteLock")
private final VisibilityStore mVisibilityStoreLocked;
- // The map contains schemaTypes and namespaces for all database. All values in the map have
- // the database name prefix.
+ // This map contains schemaTypes for all package-database prefixes. All values in the map are
+ // prefixed with the package-database prefix.
// TODO(b/172360376): Check if this can be replaced with an ArrayMap
@GuardedBy("mReadWriteLock")
private final Map<String, Set<String>> mSchemaMapLocked = new HashMap<>();
+ // This map contains namespaces for all package-database prefixes. All values in the map are
+ // prefixed with the package-database prefix.
// TODO(b/172360376): Check if this can be replaced with an ArrayMap
@GuardedBy("mReadWriteLock")
private final Map<String, Set<String>> mNamespaceMapLocked = new HashMap<>();
@@ -179,19 +185,13 @@
// Populate schema map
for (SchemaTypeConfigProto schema : schemaProto.getTypesList()) {
- String qualifiedSchemaType = schema.getSchemaType();
- addToMap(
- mSchemaMapLocked,
- getDatabaseName(qualifiedSchemaType),
- qualifiedSchemaType);
+ String prefixedSchemaType = schema.getSchemaType();
+ addToMap(mSchemaMapLocked, getPrefix(prefixedSchemaType), prefixedSchemaType);
}
// Populate namespace map
- for (String qualifiedNamespace : getAllNamespacesResultProto.getNamespacesList()) {
- addToMap(
- mNamespaceMapLocked,
- getDatabaseName(qualifiedNamespace),
- qualifiedNamespace);
+ for (String prefixedNamespace : getAllNamespacesResultProto.getNamespacesList()) {
+ addToMap(mNamespaceMapLocked, getPrefix(prefixedNamespace), prefixedNamespace);
}
// TODO(b/155939114): It's possible to optimize after init, which would reduce the time
@@ -225,6 +225,7 @@
*
* <p>This method belongs to mutate group.
*
+ * @param packageName The package name that owns the schemas.
* @param databaseName The name of the database where this schema lives.
* @param schemas Schemas to set for this app.
* @param schemasNotPlatformSurfaceable Schema types that should not be surfaced on platform
@@ -234,6 +235,7 @@
* @throws AppSearchException on IcingSearchEngine error.
*/
public void setSchema(
+ @NonNull String packageName,
@NonNull String databaseName,
@NonNull List<AppSearchSchema> schemas,
@NonNull List<String> schemasNotPlatformSurfaceable,
@@ -250,10 +252,11 @@
newSchemaBuilder.addTypes(schemaTypeProto);
}
- // Combine the existing schema (which may have types from other databases) with this
- // database's new schema. Modifies the existingSchemaBuilder.
+ String prefix = createPrefix(packageName, databaseName);
+ // Combine the existing schema (which may have types from other prefixes) with this
+ // prefix's new schema. Modifies the existingSchemaBuilder.
RewrittenSchemaResults rewrittenSchemaResults =
- rewriteSchema(databaseName, existingSchemaBuilder, newSchemaBuilder.build());
+ rewriteSchema(prefix, existingSchemaBuilder, newSchemaBuilder.build());
// Apply schema
SetSchemaResultProto setSchemaResultProto =
@@ -280,17 +283,15 @@
}
// Update derived data structures.
- mSchemaMapLocked.put(databaseName, rewrittenSchemaResults.mRewrittenQualifiedTypes);
+ mSchemaMapLocked.put(prefix, rewrittenSchemaResults.mRewrittenPrefixedTypes);
- String databasePrefix = getDatabasePrefix(databaseName);
- Set<String> qualifiedSchemasNotPlatformSurfaceable =
+ Set<String> prefixedSchemasNotPlatformSurfaceable =
new ArraySet<>(schemasNotPlatformSurfaceable.size());
for (int i = 0; i < schemasNotPlatformSurfaceable.size(); i++) {
- qualifiedSchemasNotPlatformSurfaceable.add(
- databasePrefix + schemasNotPlatformSurfaceable.get(i));
+ prefixedSchemasNotPlatformSurfaceable.add(
+ prefix + schemasNotPlatformSurfaceable.get(i));
}
- mVisibilityStoreLocked.setVisibility(
- databaseName, qualifiedSchemasNotPlatformSurfaceable);
+ mVisibilityStoreLocked.setVisibility(prefix, prefixedSchemasNotPlatformSurfaceable);
// Determine whether to schedule an immediate optimize.
if (setSchemaResultProto.getDeletedSchemaTypesCount() > 0
@@ -307,15 +308,17 @@
}
/**
- * Retrieves the AppSearch schema for this database.
+ * Retrieves the AppSearch schema for this package name, database.
*
* <p>This method belongs to query group.
*
+ * @param packageName Package name that owns this schema
* @param databaseName The name of the database where this schema lives.
* @throws AppSearchException on IcingSearchEngine error.
*/
@NonNull
- public List<AppSearchSchema> getSchema(@NonNull String databaseName) throws AppSearchException {
+ public List<AppSearchSchema> getSchema(
+ @NonNull String packageName, @NonNull String databaseName) throws AppSearchException {
SchemaProto fullSchema;
mReadWriteLock.readLock().lock();
try {
@@ -324,16 +327,16 @@
mReadWriteLock.readLock().unlock();
}
+ String prefix = createPrefix(packageName, databaseName);
List<AppSearchSchema> result = new ArrayList<>();
for (int i = 0; i < fullSchema.getTypesCount(); i++) {
- String typeDatabase = getDatabaseName(fullSchema.getTypes(i).getSchemaType());
- if (!databaseName.equals(typeDatabase)) {
+ String typePrefix = getPrefix(fullSchema.getTypes(i).getSchemaType());
+ if (!prefix.equals(typePrefix)) {
continue;
}
// Rewrite SchemaProto.types.schema_type
SchemaTypeConfigProto.Builder typeConfigBuilder = fullSchema.getTypes(i).toBuilder();
- String newSchemaType =
- typeConfigBuilder.getSchemaType().substring(databaseName.length() + 1);
+ String newSchemaType = typeConfigBuilder.getSchemaType().substring(prefix.length());
typeConfigBuilder.setSchemaType(newSchemaType);
// Rewrite SchemaProto.types.properties.schema_type
@@ -344,9 +347,7 @@
typeConfigBuilder.getProperties(propertyIdx).toBuilder();
if (!propertyConfigBuilder.getSchemaType().isEmpty()) {
String newPropertySchemaType =
- propertyConfigBuilder
- .getSchemaType()
- .substring(databaseName.length() + 1);
+ propertyConfigBuilder.getSchemaType().substring(prefix.length());
propertyConfigBuilder.setSchemaType(newPropertySchemaType);
typeConfigBuilder.setProperties(propertyIdx, propertyConfigBuilder);
}
@@ -363,21 +364,26 @@
*
* <p>This method belongs to mutate group.
*
+ * @param packageName The package name that owns this document.
* @param databaseName The databaseName this document resides in.
* @param document The document to index.
* @throws AppSearchException on IcingSearchEngine error.
*/
- public void putDocument(@NonNull String databaseName, @NonNull GenericDocument document)
+ public void putDocument(
+ @NonNull String packageName,
+ @NonNull String databaseName,
+ @NonNull GenericDocument document)
throws AppSearchException {
DocumentProto.Builder documentBuilder =
GenericDocumentToProtoConverter.toDocumentProto(document).toBuilder();
- addPrefixToDocument(documentBuilder, getDatabasePrefix(databaseName));
+ String prefix = createPrefix(packageName, databaseName);
+ addPrefixToDocument(documentBuilder, prefix);
PutResultProto putResultProto;
mReadWriteLock.writeLock().lock();
try {
putResultProto = mIcingSearchEngineLocked.put(documentBuilder.build());
- addToMap(mNamespaceMapLocked, databaseName, documentBuilder.getNamespace());
+ addToMap(mNamespaceMapLocked, prefix, documentBuilder.getNamespace());
// The existing documents with same URI will be deleted, so there maybe some resources
// could be released after optimize().
checkForOptimizeLocked(/* force= */ false);
@@ -392,6 +398,7 @@
*
* <p>This method belongs to query group.
*
+ * @param packageName The package that owns this document.
* @param databaseName The databaseName this document resides in.
* @param namespace The namespace this document resides in.
* @param uri The URI of the document to get.
@@ -400,20 +407,24 @@
*/
@NonNull
public GenericDocument getDocument(
- @NonNull String databaseName, @NonNull String namespace, @NonNull String uri)
+ @NonNull String packageName,
+ @NonNull String databaseName,
+ @NonNull String namespace,
+ @NonNull String uri)
throws AppSearchException {
GetResultProto getResultProto;
mReadWriteLock.readLock().lock();
try {
getResultProto =
- mIcingSearchEngineLocked.get(getDatabasePrefix(databaseName) + namespace, uri);
+ mIcingSearchEngineLocked.get(
+ createPrefix(packageName, databaseName) + namespace, uri);
} finally {
mReadWriteLock.readLock().unlock();
}
checkSuccess(getResultProto.getStatus());
DocumentProto.Builder documentBuilder = getResultProto.getDocument().toBuilder();
- removeDatabasesFromDocument(documentBuilder);
+ removePrefixesFromDocument(documentBuilder);
return GenericDocumentToProtoConverter.toGenericDocument(documentBuilder.build());
}
@@ -422,6 +433,7 @@
*
* <p>This method belongs to query group.
*
+ * @param packageName The package name that is performing the query.
* @param databaseName The databaseName this query for.
* @param queryExpression Query String to search.
* @param searchSpec Spec for setting filters, raw query etc.
@@ -431,20 +443,24 @@
*/
@NonNull
public SearchResultPage query(
+ @NonNull String packageName,
@NonNull String databaseName,
@NonNull String queryExpression,
@NonNull SearchSpec searchSpec)
throws AppSearchException {
mReadWriteLock.readLock().lock();
try {
- return doQueryLocked(Collections.singleton(databaseName), queryExpression, searchSpec);
+ return doQueryLocked(
+ Collections.singleton(createPrefix(packageName, databaseName)),
+ queryExpression,
+ searchSpec);
} finally {
mReadWriteLock.readLock().unlock();
}
}
/**
- * Executes a global query, i.e. over all permitted databases, against the AppSearch index and
+ * Executes a global query, i.e. over all permitted prefixes, against the AppSearch index and
* returns results.
*
* <p>This method belongs to query group.
@@ -464,9 +480,15 @@
// verified.
mReadWriteLock.readLock().lock();
try {
- // We use the mNamespaceMap.keySet here because it's the smaller set of valid databases
+ // We use the mNamespaceMap.keySet here because it's the smaller set of valid prefixes
// that could exist.
- return doQueryLocked(mNamespaceMapLocked.keySet(), queryExpression, searchSpec);
+ Set<String> prefixes = mNamespaceMapLocked.keySet();
+
+ // Filter out any VisibilityStore documents which are AppSearch-internal only.
+ prefixes.remove(
+ createPrefix(VisibilityStore.PACKAGE_NAME, VisibilityStore.DATABASE_NAME));
+
+ return doQueryLocked(prefixes, queryExpression, searchSpec);
} finally {
mReadWriteLock.readLock().unlock();
}
@@ -474,7 +496,7 @@
@GuardedBy("mReadWriteLock")
private SearchResultPage doQueryLocked(
- @NonNull Set<String> databases,
+ @NonNull Set<String> prefixes,
@NonNull String queryExpression,
@NonNull SearchSpec searchSpec)
throws AppSearchException {
@@ -486,12 +508,10 @@
ScoringSpecProto scoringSpec = SearchSpecToProtoConverter.toScoringSpecProto(searchSpec);
SearchResultProto searchResultProto;
- // rewriteSearchSpecForDatabases will return false if none of the databases that the
+ // rewriteSearchSpecForPrefixesLocked will return false if none of the prefixes that the
// client is trying to search on exist, so we can return an empty SearchResult and skip
// sending request to Icing.
- // We use the mNamespaceMap.keySet here because it's the smaller set of valid databases
- // that could exist.
- if (!rewriteSearchSpecForDatabasesLocked(searchSpecBuilder, databases)) {
+ if (!rewriteSearchSpecForPrefixesLocked(searchSpecBuilder, prefixes)) {
return new SearchResultPage(Bundle.EMPTY);
}
searchResultProto =
@@ -546,18 +566,23 @@
*
* <p>This method belongs to mutate group.
*
+ * @param packageName The package name that owns the document.
* @param databaseName The databaseName the document is in.
* @param namespace Namespace of the document to remove.
* @param uri URI of the document to remove.
* @throws AppSearchException on IcingSearchEngine error.
*/
- public void remove(@NonNull String databaseName, @NonNull String namespace, @NonNull String uri)
+ public void remove(
+ @NonNull String packageName,
+ @NonNull String databaseName,
+ @NonNull String namespace,
+ @NonNull String uri)
throws AppSearchException {
- String qualifiedNamespace = getDatabasePrefix(databaseName) + namespace;
+ String prefixedNamespace = createPrefix(packageName, databaseName) + namespace;
DeleteResultProto deleteResultProto;
mReadWriteLock.writeLock().lock();
try {
- deleteResultProto = mIcingSearchEngineLocked.delete(qualifiedNamespace, uri);
+ deleteResultProto = mIcingSearchEngineLocked.delete(prefixedNamespace, uri);
checkForOptimizeLocked(/* force= */ false);
} finally {
mReadWriteLock.writeLock().unlock();
@@ -570,12 +595,14 @@
*
* <p>This method belongs to mutate group.
*
+ * @param packageName The package name that owns the documents.
* @param databaseName The databaseName the document is in.
* @param queryExpression Query String to search.
* @param searchSpec Defines what and how to remove
* @throws AppSearchException on IcingSearchEngine error.
*/
public void removeByQuery(
+ @NonNull String packageName,
@NonNull String databaseName,
@NonNull String queryExpression,
@NonNull SearchSpec searchSpec)
@@ -586,11 +613,12 @@
DeleteResultProto deleteResultProto;
mReadWriteLock.writeLock().lock();
try {
- // Only rewrite SearchSpec for non empty database.
- // rewriteSearchSpecForNonEmptyDatabase will return false for empty database, we
+ // Only rewrite SearchSpec for non empty prefixes.
+ // rewriteSearchSpecForPrefixesLocked will return false for empty prefixes, we
// should skip sending request to Icing and return in here.
- if (!rewriteSearchSpecForDatabasesLocked(
- searchSpecBuilder, Collections.singleton(databaseName))) {
+ if (!rewriteSearchSpecForPrefixesLocked(
+ searchSpecBuilder,
+ Collections.singleton(createPrefix(packageName, databaseName)))) {
return;
}
deleteResultProto = mIcingSearchEngineLocked.deleteByQuery(searchSpecBuilder.build());
@@ -605,7 +633,7 @@
}
/**
- * Clears documents and schema across all databaseNames.
+ * Clears documents and schema across all packages and databaseNames.
*
* <p>This method belongs to mutate group.
*
@@ -632,33 +660,30 @@
/** Wrapper around schema changes */
@VisibleForTesting
static class RewrittenSchemaResults {
- // Any database-qualified types that used to exist in the schema, but are deleted in the
- // new one.
- final Set<String> mDeletedQualifiedTypes = new ArraySet<>();
+ // Any prefixed types that used to exist in the schema, but are deleted in the new one.
+ final Set<String> mDeletedPrefixedTypes = new ArraySet<>();
- // Database-qualified types that were part of the new schema.
- final Set<String> mRewrittenQualifiedTypes = new ArraySet<>();
+ // Prefixed types that were part of the new schema.
+ final Set<String> mRewrittenPrefixedTypes = new ArraySet<>();
}
/**
* Rewrites all types mentioned in the given {@code newSchema} to prepend {@code prefix}.
* Rewritten types will be added to the {@code existingSchema}.
*
- * @param databaseName The name of the database where this schema lives.
- * @param existingSchema A schema that may contain existing types from across all database
- * instances. Will be mutated to contain the properly rewritten schema types from {@code
- * newSchema}.
+ * @param prefix The full prefix to prepend to the schema.
+ * @param existingSchema A schema that may contain existing types from across all prefixes. Will
+ * be mutated to contain the properly rewritten schema types from {@code newSchema}.
* @param newSchema Schema with types to add to the {@code existingSchema}.
- * @return a RewrittenSchemaResults contains all qualified schema type names in the given
- * database as well as a set of schema types that were deleted from the database.
+ * @return a RewrittenSchemaResults that contains all prefixed schema type names in the given
+ * prefix as well as a set of schema types that were deleted.
*/
@VisibleForTesting
static RewrittenSchemaResults rewriteSchema(
- @NonNull String databaseName,
+ @NonNull String prefix,
@NonNull SchemaProto.Builder existingSchema,
@NonNull SchemaProto newSchema)
throws AppSearchException {
- String prefix = getDatabasePrefix(databaseName);
HashMap<String, SchemaTypeConfigProto> newTypesToProto = new HashMap<>();
// Rewrite the schema type to include the typePrefix.
for (int typeIdx = 0; typeIdx < newSchema.getTypesCount(); typeIdx++) {
@@ -687,10 +712,10 @@
// newTypesToProto is modified below, so we need a copy first
RewrittenSchemaResults rewrittenSchemaResults = new RewrittenSchemaResults();
- rewrittenSchemaResults.mRewrittenQualifiedTypes.addAll(newTypesToProto.keySet());
+ rewrittenSchemaResults.mRewrittenPrefixedTypes.addAll(newTypesToProto.keySet());
- // Combine the existing schema (which may have types from other databases) with this
- // database's new schema. Modifies the existingSchemaBuilder.
+ // Combine the existing schema (which may have types from other prefixes) with this
+ // prefix's new schema. Modifies the existingSchemaBuilder.
// Check if we need to replace any old schema types with the new ones.
for (int i = 0; i < existingSchema.getTypesCount(); i++) {
String schemaType = existingSchema.getTypes(i).getSchemaType();
@@ -698,11 +723,11 @@
if (newProto != null) {
// Replacement
existingSchema.setTypes(i, newProto);
- } else if (databaseName.equals(getDatabaseName(schemaType))) {
+ } else if (prefix.equals(getPrefix(schemaType))) {
// All types existing before but not in newSchema should be removed.
existingSchema.removeTypes(i);
--i;
- rewrittenSchemaResults.mDeletedQualifiedTypes.add(schemaType);
+ rewrittenSchemaResults.mDeletedPrefixedTypes.add(schemaType);
}
}
// We've been removing existing types from newTypesToProto, so everything that remains is
@@ -749,17 +774,16 @@
}
/**
- * Removes any database names from types and namespaces mentioned anywhere in {@code
- * documentBuilder}.
+ * Removes any prefixes from types and namespaces mentioned anywhere in {@code documentBuilder}.
*
* @param documentBuilder The document to mutate
*/
@VisibleForTesting
- static void removeDatabasesFromDocument(@NonNull DocumentProto.Builder documentBuilder)
+ static void removePrefixesFromDocument(@NonNull DocumentProto.Builder documentBuilder)
throws AppSearchException {
// Rewrite the type name and namespace to remove the prefix.
- documentBuilder.setSchema(removeDatabasePrefix(documentBuilder.getSchema()));
- documentBuilder.setNamespace(removeDatabasePrefix(documentBuilder.getNamespace()));
+ documentBuilder.setSchema(removePrefix(documentBuilder.getSchema()));
+ documentBuilder.setNamespace(removePrefix(documentBuilder.getNamespace()));
// Recurse into derived documents
for (int propertyIdx = 0;
@@ -772,7 +796,7 @@
for (int documentIdx = 0; documentIdx < documentCount; documentIdx++) {
DocumentProto.Builder derivedDocumentBuilder =
propertyBuilder.getDocumentValues(documentIdx).toBuilder();
- removeDatabasesFromDocument(derivedDocumentBuilder);
+ removePrefixesFromDocument(derivedDocumentBuilder);
propertyBuilder.setDocumentValues(documentIdx, derivedDocumentBuilder);
}
documentBuilder.setProperties(propertyIdx, propertyBuilder);
@@ -781,27 +805,25 @@
}
/**
- * Rewrites the schemaTypeFilters and namespacesFilters that exist in {@code databaseNames}.
+ * Rewrites the schemaTypeFilters and namespacesFilters that exist with {@code prefixes}.
*
- * <p>If the searchSpec has empty filter lists, all existing databases from {@code
- * databaseNames} will be added.
+ * <p>If the searchSpec has empty filter lists, all prefixes filters will be added.
*
* <p>This method should be only called in query methods and get the READ lock to keep thread
* safety.
*
- * @return false if none of the requested databases exist.
+ * @return false if none of the requested prefixes exist.
*/
@VisibleForTesting
@GuardedBy("mReadWriteLock")
- boolean rewriteSearchSpecForDatabasesLocked(
- @NonNull SearchSpecProto.Builder searchSpecBuilder,
- @NonNull Set<String> databaseNames) {
+ boolean rewriteSearchSpecForPrefixesLocked(
+ @NonNull SearchSpecProto.Builder searchSpecBuilder, @NonNull Set<String> prefixes) {
// Create a copy since retainAll() modifies the original set.
- Set<String> existingDatabases = new ArraySet<>(mNamespaceMapLocked.keySet());
- existingDatabases.retainAll(databaseNames);
+ Set<String> existingPrefixes = new ArraySet<>(mNamespaceMapLocked.keySet());
+ existingPrefixes.retainAll(prefixes);
- if (existingDatabases.isEmpty()) {
- // None of the databases exist, empty query.
+ if (existingPrefixes.isEmpty()) {
+ // None of the prefixes exist, empty query.
return false;
}
@@ -812,33 +834,32 @@
List<String> namespaceFilters = searchSpecBuilder.getNamespaceFiltersList();
searchSpecBuilder.clearNamespaceFilters();
- // Rewrite filters to include a database prefix.
- for (String databaseName : existingDatabases) {
- Set<String> existingSchemaTypes = mSchemaMapLocked.get(databaseName);
- String databaseNamePrefix = getDatabasePrefix(databaseName);
+ // Rewrite filters to include a prefix.
+ for (String prefix : existingPrefixes) {
+ Set<String> existingSchemaTypes = mSchemaMapLocked.get(prefix);
if (schemaTypeFilters.isEmpty()) {
// Include all schema types
searchSpecBuilder.addAllSchemaTypeFilters(existingSchemaTypes);
} else {
- // Qualify the given schema types
+ // Add the prefix to the given schema types
for (int i = 0; i < schemaTypeFilters.size(); i++) {
- String qualifiedType = databaseNamePrefix + schemaTypeFilters.get(i);
- if (existingSchemaTypes.contains(qualifiedType)) {
- searchSpecBuilder.addSchemaTypeFilters(qualifiedType);
+ String prefixedType = prefix + schemaTypeFilters.get(i);
+ if (existingSchemaTypes.contains(prefixedType)) {
+ searchSpecBuilder.addSchemaTypeFilters(prefixedType);
}
}
}
- Set<String> existingNamespaces = mNamespaceMapLocked.get(databaseName);
+ Set<String> existingNamespaces = mNamespaceMapLocked.get(prefix);
if (namespaceFilters.isEmpty()) {
// Include all namespaces
searchSpecBuilder.addAllNamespaceFilters(existingNamespaces);
} else {
- // Qualify the given namespaces.
+ // Prefix the given namespaces.
for (int i = 0; i < namespaceFilters.size(); i++) {
- String qualifiedNamespace = databaseNamePrefix + namespaceFilters.get(i);
- if (existingNamespaces.contains(qualifiedNamespace)) {
- searchSpecBuilder.addNamespaceFilters(qualifiedNamespace);
+ String prefixedNamespace = prefix + namespaceFilters.get(i);
+ if (existingNamespaces.contains(prefixedNamespace)) {
+ searchSpecBuilder.addNamespaceFilters(prefixedNamespace);
}
}
}
@@ -857,36 +878,41 @@
return schemaProto.getSchema();
}
- /** Returns true if {@code databaseName} has a {@code schemaType} */
+ /**
+ * Returns true if the {@code packageName} and {@code databaseName} has the {@code schemaType}
+ */
@GuardedBy("mReadWriteLock")
- boolean hasSchemaTypeLocked(@NonNull String databaseName, @NonNull String schemaType) {
+ boolean hasSchemaTypeLocked(
+ @NonNull String packageName, @NonNull String databaseName, @NonNull String schemaType) {
+ Preconditions.checkNotNull(packageName);
Preconditions.checkNotNull(databaseName);
Preconditions.checkNotNull(schemaType);
- Set<String> schemaTypes = mSchemaMapLocked.get(databaseName);
+ String prefix = createPrefix(packageName, databaseName);
+ Set<String> schemaTypes = mSchemaMapLocked.get(prefix);
if (schemaTypes == null) {
return false;
}
- return schemaTypes.contains(getDatabasePrefix(databaseName) + schemaType);
+ return schemaTypes.contains(prefix + schemaType);
}
- /** Returns a set of all databases AppSearchImpl knows about. */
+ /** Returns a set of all prefixes AppSearchImpl knows about. */
@GuardedBy("mReadWriteLock")
@NonNull
- Set<String> getDatabasesLocked() {
+ Set<String> getPrefixesLocked() {
return mSchemaMapLocked.keySet();
}
@NonNull
- private static String getDatabasePrefix(@NonNull String databaseName) {
- // TODO(b/170370381): Reconsider the way we separate database names for security reasons.
- return databaseName + DATABASE_DELIMITER;
+ static String createPrefix(@NonNull String packageName, @NonNull String databaseName) {
+ return packageName + PACKAGE_DELIMITER + databaseName + DATABASE_DELIMITER;
}
@NonNull
- private static String removeDatabasePrefix(@NonNull String prefixedString)
- throws AppSearchException {
+ private static String removePrefix(@NonNull String prefixedString) throws AppSearchException {
+ // The prefix is made up of the package, then the database. So we only need to find the
+ // database cutoff.
int delimiterIndex;
if ((delimiterIndex = prefixedString.indexOf(DATABASE_DELIMITER)) != -1) {
// Add 1 to include the char size of the DATABASE_DELIMITER
@@ -898,22 +924,24 @@
}
@NonNull
- private static String getDatabaseName(@NonNull String prefixedValue) throws AppSearchException {
- int delimiterIndex = prefixedValue.indexOf(DATABASE_DELIMITER);
- if (delimiterIndex == -1) {
+ private static String getPrefix(@NonNull String prefixedString) throws AppSearchException {
+ int databaseDelimiterIndex = prefixedString.indexOf(DATABASE_DELIMITER);
+ if (databaseDelimiterIndex == -1) {
throw new AppSearchException(
AppSearchResult.RESULT_UNKNOWN_ERROR,
"The databaseName prefixed value doesn't contains a valid database name.");
}
- return prefixedValue.substring(0, delimiterIndex);
+
+ // Add 1 to include the char size of the DATABASE_DELIMITER
+ return prefixedString.substring(0, databaseDelimiterIndex + 1);
}
private static void addToMap(
- Map<String, Set<String>> map, String databaseName, String prefixedValue) {
- Set<String> values = map.get(databaseName);
+ Map<String, Set<String>> map, String prefix, String prefixedValue) {
+ Set<String> values = map.get(prefix);
if (values == null) {
values = new ArraySet<>();
- map.put(databaseName, values);
+ map.put(prefix, values);
}
values.add(prefixedValue);
}
@@ -994,7 +1022,7 @@
SearchResultProto.ResultProto.Builder resultBuilder =
searchResultProto.getResults(i).toBuilder();
DocumentProto.Builder documentBuilder = resultBuilder.getDocument().toBuilder();
- removeDatabasesFromDocument(documentBuilder);
+ removePrefixesFromDocument(documentBuilder);
resultBuilder.setDocument(documentBuilder);
resultsBuilder.setResults(i, resultBuilder);
}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/VisibilityStore.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/VisibilityStore.java
index 0b68ebc..411da2f 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/VisibilityStore.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/VisibilityStore.java
@@ -51,24 +51,58 @@
* this class. Take care to not cause any circular dependencies.
*/
class VisibilityStore {
- // Schema type for documents that hold AppSearch's metadata, e.g. visibility settings
+ /** Schema type for documents that hold AppSearch's metadata, e.g. visibility settings */
@VisibleForTesting static final String SCHEMA_TYPE = "Visibility";
- // Property that holds the list of platform-hidden schemas, as part of the visibility
- // settings.
+ /**
+ * Property that holds the list of platform-hidden schemas, as part of the visibility settings.
+ */
@VisibleForTesting
static final String NOT_PLATFORM_SURFACEABLE_PROPERTY = "notPlatformSurfaceable";
- // Database name to prefix all visibility schemas and documents with. Special-cased to
- // minimize the chance of collision with a client-supplied database.
- @VisibleForTesting static final String DATABASE_NAME = "$$__AppSearch__Database";
+ /** Schema for the VisibilityStore's docuemnts. */
+ @VisibleForTesting
+ static final AppSearchSchema SCHEMA =
+ new AppSearchSchema.Builder(SCHEMA_TYPE)
+ .addProperty(
+ new AppSearchSchema.PropertyConfig.Builder(
+ NOT_PLATFORM_SURFACEABLE_PROPERTY)
+ .setDataType(AppSearchSchema.PropertyConfig.DATA_TYPE_STRING)
+ .setCardinality(
+ AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED)
+ .build())
+ .build();
- // Namespace of documents that contain visibility settings
- private static final String NAMESPACE = "namespace";
+ /**
+ * These cannot have any of the special characters used by AppSearchImpl (e.g. {@link
+ * AppSearchImpl#PACKAGE_DELIMITER} or {@link AppSearchImpl#DATABASE_DELIMITER}.
+ */
+ static final String PACKAGE_NAME = "VS#Pkg";
+
+ static final String DATABASE_NAME = "VS#Db";
+
+ /**
+ * Prefix that AppSearchImpl creates for the VisibilityStore based on our package name and
+ * database name. Tracked here to tell when we're looking at our own prefix when looking through
+ * AppSearchImpl.
+ */
+ private static final String VISIBILITY_STORE_PREFIX =
+ AppSearchImpl.createPrefix(PACKAGE_NAME, DATABASE_NAME);
+
+ /** Namespace of documents that contain visibility settings */
+ private static final String NAMESPACE = GenericDocument.DEFAULT_NAMESPACE;
+
+ /**
+ * Prefix to add to all visibility document uri's. IcingSearchEngine doesn't allow empty uri's.
+ */
+ private static final String URI_PREFIX = "uri:";
+
private final AppSearchImpl mAppSearchImpl;
- // The map contains schemas that are platform-hidden for each database. All schemas in the map
- // have a database name prefix.
+ /**
+ * Maps prefixes to the set of schemas that are platform-hidden within that prefix. All schemas
+ * in the map are prefixed.
+ */
private final Map<String, Set<String>> mNotPlatformSurfaceableMap = new ArrayMap<>();
/**
@@ -92,42 +126,36 @@
* @throws AppSearchException AppSearchException on AppSearchImpl error.
*/
public void initialize() throws AppSearchException {
- if (!mAppSearchImpl.hasSchemaTypeLocked(DATABASE_NAME, SCHEMA_TYPE)) {
+ if (!mAppSearchImpl.hasSchemaTypeLocked(PACKAGE_NAME, DATABASE_NAME, SCHEMA_TYPE)) {
// Schema type doesn't exist yet. Add it.
mAppSearchImpl.setSchema(
+ PACKAGE_NAME,
DATABASE_NAME,
- Collections.singletonList(
- new AppSearchSchema.Builder(SCHEMA_TYPE)
- .addProperty(
- new AppSearchSchema.PropertyConfig.Builder(
- NOT_PLATFORM_SURFACEABLE_PROPERTY)
- .setDataType(
- AppSearchSchema.PropertyConfig
- .DATA_TYPE_STRING)
- .setCardinality(
- AppSearchSchema.PropertyConfig
- .CARDINALITY_REPEATED)
- .build())
- .build()),
+ Collections.singletonList(SCHEMA),
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*forceOverride=*/ false);
}
- // Populate visibility settings map
- for (String database : mAppSearchImpl.getDatabasesLocked()) {
- if (database.equals(DATABASE_NAME)) {
- // Our own database. Skip
+ // Populate visibility settings set
+ mNotPlatformSurfaceableMap.clear();
+ for (String prefix : mAppSearchImpl.getPrefixesLocked()) {
+ if (prefix.equals(VISIBILITY_STORE_PREFIX)) {
+ // Our own prefix. Skip
continue;
}
try {
- // Note: We use the other clients' database names as uris
+ // Note: We use the other clients' prefixed names as uris
GenericDocument document =
- mAppSearchImpl.getDocument(DATABASE_NAME, NAMESPACE, /*uri=*/ database);
+ mAppSearchImpl.getDocument(
+ PACKAGE_NAME,
+ DATABASE_NAME,
+ NAMESPACE,
+ /*uri=*/ addUriPrefix(prefix));
String[] schemas =
document.getPropertyStringArray(NOT_PLATFORM_SURFACEABLE_PROPERTY);
- mNotPlatformSurfaceableMap.put(database, new ArraySet<>(Arrays.asList(schemas)));
+ mNotPlatformSurfaceableMap.put(prefix, new ArraySet<>(Arrays.asList(schemas)));
} catch (AppSearchException e) {
if (e.getResultCode() == AppSearchResult.RESULT_NOT_FOUND) {
// TODO(b/172068212): This indicates some desync error. We were expecting a
@@ -142,51 +170,46 @@
}
/**
- * Sets visibility settings for {@code databaseName}. Any previous visibility settings will be
+ * Sets visibility settings for {@code prefix}. Any previous visibility settings will be
* overwritten.
*
- * @param databaseName Database name that owns the {@code schemasNotPlatformSurfaceable}.
- * @param schemasNotPlatformSurfaceable Set of database-qualified schemas that should be hidden
- * from the platform.
+ * @param prefix Prefix that identifies who owns the {@code schemasNotPlatformSurfaceable}.
+ * @param schemasNotPlatformSurfaceable Set of prefixed schemas that should be hidden from the
+ * platform.
* @throws AppSearchException on AppSearchImpl error.
*/
public void setVisibility(
- @NonNull String databaseName, @NonNull Set<String> schemasNotPlatformSurfaceable)
+ @NonNull String prefix, @NonNull Set<String> schemasNotPlatformSurfaceable)
throws AppSearchException {
- Preconditions.checkNotNull(databaseName);
+ Preconditions.checkNotNull(prefix);
Preconditions.checkNotNull(schemasNotPlatformSurfaceable);
// Persist the document
GenericDocument.Builder visibilityDocument =
- new GenericDocument.Builder(/*uri=*/ databaseName, SCHEMA_TYPE)
+ new GenericDocument.Builder(/*uri=*/ addUriPrefix(prefix), SCHEMA_TYPE)
.setNamespace(NAMESPACE);
if (!schemasNotPlatformSurfaceable.isEmpty()) {
visibilityDocument.setPropertyString(
NOT_PLATFORM_SURFACEABLE_PROPERTY,
schemasNotPlatformSurfaceable.toArray(new String[0]));
}
- mAppSearchImpl.putDocument(DATABASE_NAME, visibilityDocument.build());
+ mAppSearchImpl.putDocument(PACKAGE_NAME, DATABASE_NAME, visibilityDocument.build());
// Update derived data structures.
- mNotPlatformSurfaceableMap.put(databaseName, schemasNotPlatformSurfaceable);
+ mNotPlatformSurfaceableMap.put(prefix, schemasNotPlatformSurfaceable);
}
- /**
- * Returns the set of database-qualified schemas in {@code databaseName} that are hidden from
- * the platform.
- *
- * @param databaseName Database name to retrieve schemas for
- * @return Set of database-qualified schemas that are hidden from the platform. Empty set if
- * none exist.
- */
+ /** Returns if the schema is surfaceable by the platform. */
@NonNull
- public Set<String> getSchemasNotPlatformSurfaceable(@NonNull String databaseName) {
- Preconditions.checkNotNull(databaseName);
- Set<String> schemasNotPlatformSurfaceable = mNotPlatformSurfaceableMap.get(databaseName);
- if (schemasNotPlatformSurfaceable == null) {
- return Collections.emptySet();
+ public boolean isSchemaPlatformSurfaceable(
+ @NonNull String prefix, @NonNull String prefixedSchema) {
+ Preconditions.checkNotNull(prefix);
+ Preconditions.checkNotNull(prefixedSchema);
+ Set<String> notPlatformSurfaceableSchemas = mNotPlatformSurfaceableMap.get(prefix);
+ if (notPlatformSurfaceableSchemas == null) {
+ return true;
}
- return schemasNotPlatformSurfaceable;
+ return !notPlatformSurfaceableSchemas.contains(prefixedSchema);
}
/**
@@ -199,4 +222,14 @@
mNotPlatformSurfaceableMap.clear();
initialize();
}
+
+ /**
+ * Adds a uri prefix to create a visibility store document's uri.
+ *
+ * @param uri Non-prefixed uri
+ * @return Prefixed uri
+ */
+ private static String addUriPrefix(String uri) {
+ return URI_PREFIX + uri;
+ }
}
diff --git a/apex/appsearch/synced_jetpack_changeid.txt b/apex/appsearch/synced_jetpack_changeid.txt
index 57c48d8..5a7ab1d 100644
--- a/apex/appsearch/synced_jetpack_changeid.txt
+++ b/apex/appsearch/synced_jetpack_changeid.txt
@@ -1 +1 @@
-If5fd2bd705d5507d044706701a94b2e1496ef1df
+Ia04e81bb574831fa7e8a26c725e53133b39ee3ef
diff --git a/core/api/current.txt b/core/api/current.txt
index e888115..ab5b0e7 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -6023,7 +6023,7 @@
public class NotificationManager {
method public String addAutomaticZenRule(android.app.AutomaticZenRule);
- method public boolean areBubblesAllowed();
+ method @Deprecated public boolean areBubblesAllowed();
method public boolean areNotificationsEnabled();
method public boolean areNotificationsPaused();
method public boolean canNotifyAsPackage(@NonNull String);
@@ -6040,6 +6040,7 @@
method public android.service.notification.StatusBarNotification[] getActiveNotifications();
method public android.app.AutomaticZenRule getAutomaticZenRule(String);
method public java.util.Map<java.lang.String,android.app.AutomaticZenRule> getAutomaticZenRules();
+ method public int getBubblePreference();
method @NonNull public android.app.NotificationManager.Policy getConsolidatedNotificationPolicy();
method public final int getCurrentInterruptionFilter();
method public int getImportance();
@@ -6074,6 +6075,9 @@
field public static final int AUTOMATIC_RULE_STATUS_ENABLED = 1; // 0x1
field public static final int AUTOMATIC_RULE_STATUS_REMOVED = 3; // 0x3
field public static final int AUTOMATIC_RULE_STATUS_UNKNOWN = -1; // 0xffffffff
+ field public static final int BUBBLE_PREFERENCE_ALL = 1; // 0x1
+ field public static final int BUBBLE_PREFERENCE_NONE = 0; // 0x0
+ field public static final int BUBBLE_PREFERENCE_SELECTED = 2; // 0x2
field public static final String EXTRA_AUTOMATIC_RULE_ID = "android.app.extra.AUTOMATIC_RULE_ID";
field public static final String EXTRA_AUTOMATIC_ZEN_RULE_ID = "android.app.extra.AUTOMATIC_ZEN_RULE_ID";
field public static final String EXTRA_AUTOMATIC_ZEN_RULE_STATUS = "android.app.extra.AUTOMATIC_ZEN_RULE_STATUS";
@@ -12263,6 +12267,7 @@
field public static final String FEATURE_NFC_HOST_CARD_EMULATION_NFCF = "android.hardware.nfc.hcef";
field public static final String FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE = "android.hardware.nfc.ese";
field public static final String FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC = "android.hardware.nfc.uicc";
+ field public static final String FEATURE_OPENGLES_DEQP_LEVEL = "android.software.opengles.deqp.level";
field public static final String FEATURE_OPENGLES_EXTENSION_PACK = "android.hardware.opengles.aep";
field public static final String FEATURE_PC = "android.hardware.type.pc";
field public static final String FEATURE_PICTURE_IN_PICTURE = "android.software.picture_in_picture";
@@ -29926,6 +29931,7 @@
field public static final String ID;
field public static final String MANUFACTURER;
field public static final String MODEL;
+ field @NonNull public static final String ODM_SKU;
field public static final String PRODUCT;
field @Deprecated public static final String RADIO;
field @Deprecated public static final String SERIAL;
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 821d3f1..6085fac 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -1344,6 +1344,7 @@
public abstract class RoleControllerService extends android.app.Service {
ctor public RoleControllerService();
+ method @NonNull public android.app.role.RolePrivileges getRolePrivileges(@NonNull String);
method @WorkerThread public abstract boolean onAddRoleHolder(@NonNull String, @NonNull String, int);
method @Nullable public final android.os.IBinder onBind(@Nullable android.content.Intent);
method @WorkerThread public abstract boolean onClearRoleHolders(@NonNull String, int);
@@ -1370,6 +1371,18 @@
field public static final int MANAGE_HOLDERS_FLAG_DONT_KILL_APP = 1; // 0x1
}
+ public final class RolePrivileges implements android.os.Parcelable {
+ ctor public RolePrivileges(@NonNull java.util.List<java.lang.String>, @NonNull java.util.List<java.lang.String>, @NonNull java.util.List<java.lang.String>, @NonNull java.util.List<java.lang.String>);
+ method public int describeContents();
+ method @NonNull public java.util.List<java.lang.String> getAppOpPermissions();
+ method @NonNull public java.util.List<java.lang.String> getAppOps();
+ method @NonNull public java.util.List<java.lang.String> getCapabilities();
+ method @NonNull public java.util.List<java.lang.String> getPermissions();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final String CAPABILITY_NOTIFICATION_LISTENER = "android.app.role.capability.NOTIFICATION_LISTENER";
+ field @NonNull public static final android.os.Parcelable.Creator<android.app.role.RolePrivileges> CREATOR;
+ }
+
}
package android.app.time {
@@ -6955,6 +6968,19 @@
method @NonNull public android.net.StaticIpConfiguration.Builder setIpAddress(@Nullable android.net.LinkAddress);
}
+ public final class TcpKeepalivePacketData extends android.net.KeepalivePacketData implements android.os.Parcelable {
+ ctor public TcpKeepalivePacketData(@NonNull java.net.InetAddress, int, @NonNull java.net.InetAddress, int, @NonNull byte[], int, int, int, int, int, int) throws android.net.InvalidPacketException;
+ method public int describeContents();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.TcpKeepalivePacketData> CREATOR;
+ field public final int ipTos;
+ field public final int ipTtl;
+ field public final int tcpAck;
+ field public final int tcpSeq;
+ field public final int tcpWindow;
+ field public final int tcpWindowScale;
+ }
+
public class TrafficStats {
method public static void setThreadStatsTagApp();
method public static void setThreadStatsTagBackup();
@@ -8466,6 +8492,7 @@
field public static final String NAMESPACE_INTELLIGENCE_ATTENTION = "intelligence_attention";
field public static final String NAMESPACE_MEDIA_NATIVE = "media_native";
field public static final String NAMESPACE_NETD_NATIVE = "netd_native";
+ field public static final String NAMESPACE_OTA = "ota";
field public static final String NAMESPACE_PACKAGE_MANAGER_SERVICE = "package_manager_service";
field public static final String NAMESPACE_PERMISSIONS = "permissions";
field public static final String NAMESPACE_PRIVACY = "privacy";
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index ffe2736f..1998563 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -2440,7 +2440,6 @@
}
public class DisplayAreaOrganizer extends android.window.WindowOrganizer {
- ctor public DisplayAreaOrganizer();
method public void onDisplayAreaAppeared(@NonNull android.window.DisplayAreaInfo, @NonNull android.view.SurfaceControl);
method public void onDisplayAreaVanished(@NonNull android.window.DisplayAreaInfo);
method @CallSuper @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public java.util.List<android.window.DisplayAreaAppearedInfo> registerOrganizer(int);
diff --git a/core/java/android/accounts/ChooseAccountActivity.java b/core/java/android/accounts/ChooseAccountActivity.java
index b27d9cd..bc7f4d6 100644
--- a/core/java/android/accounts/ChooseAccountActivity.java
+++ b/core/java/android/accounts/ChooseAccountActivity.java
@@ -33,6 +33,7 @@
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
+
import com.android.internal.R;
import java.util.HashMap;
@@ -56,6 +57,9 @@
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ getWindow().addSystemFlags(
+ android.view.WindowManager.LayoutParams
+ .SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
mAccounts = getIntent().getParcelableArrayExtra(AccountManager.KEY_ACCOUNTS);
mAccountManagerResponse =
getIntent().getParcelableExtra(AccountManager.KEY_ACCOUNT_MANAGER_RESPONSE);
diff --git a/core/java/android/accounts/ChooseAccountTypeActivity.java b/core/java/android/accounts/ChooseAccountTypeActivity.java
index e3352bc..63e005f 100644
--- a/core/java/android/accounts/ChooseAccountTypeActivity.java
+++ b/core/java/android/accounts/ChooseAccountTypeActivity.java
@@ -31,6 +31,7 @@
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
+
import com.android.internal.R;
import java.util.ArrayList;
@@ -51,6 +52,9 @@
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ getWindow().addSystemFlags(
+ android.view.WindowManager.LayoutParams
+ .SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "ChooseAccountTypeActivity.onCreate(savedInstanceState="
diff --git a/core/java/android/accounts/ChooseTypeAndAccountActivity.java b/core/java/android/accounts/ChooseTypeAndAccountActivity.java
index a2464d5..2be88ab 100644
--- a/core/java/android/accounts/ChooseTypeAndAccountActivity.java
+++ b/core/java/android/accounts/ChooseTypeAndAccountActivity.java
@@ -15,8 +15,6 @@
*/
package android.accounts;
-import com.google.android.collect.Sets;
-
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
@@ -35,6 +33,8 @@
import com.android.internal.R;
+import com.google.android.collect.Sets;
+
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
@@ -139,6 +139,9 @@
Log.v(TAG, "ChooseTypeAndAccountActivity.onCreate(savedInstanceState="
+ savedInstanceState + ")");
}
+ getWindow().addSystemFlags(
+ android.view.WindowManager.LayoutParams
+ .SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
mCallingUid = getLaunchedFromUid();
mCallingPackage = getLaunchedFromPackage();
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index d8cb7a6..294a363 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -7098,7 +7098,7 @@
if (getWindow() != null &&
getWindow().peekDecorView() != null &&
getWindow().peekDecorView().getViewRootImpl() != null) {
- getWindow().peekDecorView().getViewRootImpl().dump(prefix, fd, writer, args);
+ getWindow().peekDecorView().getViewRootImpl().dump(prefix, writer);
}
mHandler.getLooper().dump(new PrintWriterPrinter(writer), prefix);
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 1009f66..20953c6 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1169,9 +1169,18 @@
public static final int OP_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER =
AppProtoEnums.APP_OP_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER;
+ /**
+ * App output audio is being recorded
+ *
+ * @hide
+ */
+ // TODO: Add as AppProtoEnums
+ public static final int OP_RECORD_AUDIO_OUTPUT = 106;
+
+
/** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public static final int _NUM_OP = 106;
+ public static final int _NUM_OP = 107;
/** Access to coarse location information. */
public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -1537,6 +1546,12 @@
@TestApi
public static final String OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER =
"android:use_icc_auth_with_device_identifier";
+ /**
+ * App output audio is being recorded
+ *
+ * @hide
+ */
+ public static final String OPSTR_RECORD_AUDIO_OUTPUT = "android:record_audio_output";
/** {@link #sAppOpsToNote} not initialized yet for this op */
private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0;
@@ -1735,6 +1750,7 @@
OP_MANAGE_ONGOING_CALLS, // MANAGE_ONGOING_CALLS
OP_MANAGE_CREDENTIALS, // MANAGE_CREDENTIALS
OP_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
+ OP_RECORD_AUDIO_OUTPUT, // RECORD_AUDIO_OUTPUT
};
/**
@@ -1847,6 +1863,7 @@
OPSTR_MANAGE_ONGOING_CALLS,
OPSTR_MANAGE_CREDENTIALS,
OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER,
+ OPSTR_RECORD_AUDIO_OUTPUT,
};
/**
@@ -1960,6 +1977,7 @@
"MANAGE_ONGOING_CALLS",
"MANAGE_CREDENTIALS",
"USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER",
+ "RECORD_AUDIO_OUTPUT",
};
/**
@@ -2074,6 +2092,7 @@
Manifest.permission.MANAGE_ONGOING_CALLS,
null, // no permission for OP_MANAGE_CREDENTIALS
Manifest.permission.USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER,
+ null, // no permission for OP_RECORD_AUDIO_OUTPUT
};
/**
@@ -2188,6 +2207,7 @@
null, // MANAGE_ONGOING_CALLS
null, // MANAGE_CREDENTIALS
null, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
+ null, // RECORD_AUDIO_OUTPUT
};
/**
@@ -2301,6 +2321,7 @@
null, // MANAGE_ONGOING_CALLS
null, // MANAGE_CREDENTIALS
null, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
+ null, // RECORD_AUDIO_OUTPUT
};
/**
@@ -2413,6 +2434,7 @@
AppOpsManager.MODE_DEFAULT, // MANAGE_ONGOING_CALLS
AppOpsManager.MODE_DEFAULT, // MANAGE_CREDENTIALS
AppOpsManager.MODE_DEFAULT, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
+ AppOpsManager.MODE_ALLOWED, // RECORD_AUDIO_OUTPUT
};
/**
@@ -2529,6 +2551,7 @@
true, // MANAGE_ONGOING_CALLS
false, // MANAGE_CREDENTIALS
true, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
+ false, // RECORD_AUDIO_OUTPUT
};
/**
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 82f61a4..c528588 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -5163,16 +5163,10 @@
bindHeaderChronometerAndTime(contentView, p, hasTextToLeft);
bindProfileBadge(contentView, p);
bindAlertedIcon(contentView, p);
- bindFeedbackIcon(contentView, p);
bindExpandButton(contentView, p);
mN.mUsesStandardHeader = true;
}
- private void bindFeedbackIcon(RemoteViews contentView, StandardTemplateParams p) {
- int color = getNeutralColor(p);
- contentView.setDrawableTint(R.id.feedback, false, color, PorterDuff.Mode.SRC_ATOP);
- }
-
private void bindExpandButton(RemoteViews contentView, StandardTemplateParams p) {
int color = isColorized(p) ? getPrimaryTextColor(p) : getSecondaryTextColor(p);
contentView.setDrawableTint(R.id.expand_button, false, color,
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index da7a29f..58f382d 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -34,6 +34,7 @@
import android.content.pm.ShortcutInfo;
import android.graphics.drawable.Icon;
import android.net.Uri;
+import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
@@ -532,15 +533,23 @@
public static final int IMPORTANCE_MAX = 5;
/**
- * @hide
+ * Indicates that the no bubbles are allowed from the app. If the app sends bubbles, only the
+ * notification will appear. The notification will have an affordance allowing the user to
+ * bubble it. If the user selects this affordance, that notification is approved to bubble
+ * and the apps' bubble preference will be upgraded to {@link #BUBBLE_PREFERENCE_SELECTED}.
*/
public static final int BUBBLE_PREFERENCE_NONE = 0;
+
/**
- * @hide
+ * Indicates that all bubbles are allowed from the app. If the app sends bubbles, the bubble
+ * will appear along with the notification.
*/
public static final int BUBBLE_PREFERENCE_ALL = 1;
+
/**
- * @hide
+ * Indicates that only notifications selected by the user will appear as bubbles. If
+ * the app sends bubbles that haven't been selected, only the notification appear. If the
+ * bubble has been approved by the user, it will appear along with the notification.
*/
public static final int BUBBLE_PREFERENCE_SELECTED = 2;
@@ -1323,10 +1332,12 @@
* notification shade, floating over other apps' content.
*
* <p>This value will be ignored for notifications that are posted to channels that do not
- * allow bubbles ({@link NotificationChannel#canBubble()}.
+ * allow bubbles ({@link NotificationChannel#canBubble()}).
*
* @see Notification#getBubbleMetadata()
+ * @deprecated use {@link #getBubblePreference()} instead.
*/
+ @Deprecated
public boolean areBubblesAllowed() {
INotificationManager service = getService();
try {
@@ -1337,6 +1348,34 @@
}
/**
+ * Gets the bubble preference for the app. This preference only applies to notifications that
+ * have been properly configured to bubble.
+ *
+ * <p>
+ * If {@link #BUBBLE_PREFERENCE_ALL}, then any bubble notification will appear as a bubble, as
+ * long as the user hasn't excluded it ({@link NotificationChannel#canBubble()}).
+ *
+ * <p>
+ * If {@link #BUBBLE_PREFERENCE_SELECTED}, then any bubble notification will appear as a bubble,
+ * as long as the user has selected it.
+ *
+ * <p>
+ * If {@link #BUBBLE_PREFERENCE_NONE}, then no notification may appear as a bubble from the app.
+ *
+ * @see Notification#getBubbleMetadata()
+ * @return the users' bubble preference for the app.
+ */
+ public int getBubblePreference() {
+ INotificationManager service = getService();
+ try {
+ return service.getBubblePreferenceForPackage(mContext.getPackageName(),
+ Binder.getCallingUid());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Silences the current notification sound, if ones currently playing.
* <p>
* It is intended to handle use-cases such as silencing a ringing call
diff --git a/core/java/android/app/OWNERS b/core/java/android/app/OWNERS
index abdd537..06ad9c9 100644
--- a/core/java/android/app/OWNERS
+++ b/core/java/android/app/OWNERS
@@ -15,22 +15,18 @@
# Notification
per-file *Notification* = file:/packages/SystemUI/OWNERS
-#Wallpaper
-per-file Wallpaper*.java = file:/core/java/android/service/wallpaper/OWNERS
-per-file IWallpaper*.aidl = file:/core/java/android/service/wallpaper/OWNERS
+# ResourcesManager
+per-file ResourcesManager = rtmitchell@google.com, toddke@google.com
+
+# Wallpaper
+per-file *Wallpaper* = file:/core/java/android/service/wallpaper/OWNERS
# WindowManager
-per-file Activity*.aidl = file:/services/core/java/com/android/server/wm/OWNERS
-per-file Activity*.java = file:/services/core/java/com/android/server/wm/OWNERS
+per-file *Activity* = file:/services/core/java/com/android/server/wm/OWNERS
per-file ClientTransactionHandler.java = file:/services/core/java/com/android/server/wm/OWNERS
per-file Fragment.java = file:/services/core/java/com/android/server/wm/OWNERS
-per-file IActivity*.aidl = file:/services/core/java/com/android/server/wm/OWNERS
-per-file IAppTask.aidl = file:/services/core/java/com/android/server/wm/OWNERS
-per-file ITaskStackListener.aidl = file:/services/core/java/com/android/server/wm/OWNERS
-per-file LocalActivityManager.java = file:/services/core/java/com/android/server/wm/OWNERS
-per-file Task*.java = file:/services/core/java/com/android/server/wm/OWNERS
-per-file Window*.aidl = file:/services/core/java/com/android/server/wm/OWNERS
-per-file Window*.java = file:/services/core/java/com/android/server/wm/OWNERS
+per-file *Task* = file:/services/core/java/com/android/server/wm/OWNERS
+per-file Window* = file:/services/core/java/com/android/server/wm/OWNERS
# TODO(b/174932174): determine the ownership of KeyguardManager.java
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index a6bf4ddd..5326bf3 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -117,7 +117,6 @@
import android.media.tv.tunerresourcemanager.TunerResourceManager;
import android.net.ConnectivityDiagnosticsManager;
import android.net.ConnectivityManager;
-import android.net.ConnectivityThread;
import android.net.EthernetManager;
import android.net.IConnectivityManager;
import android.net.IEthernetManager;
@@ -781,8 +780,7 @@
public LowpanManager createService(ContextImpl ctx) throws ServiceNotFoundException {
IBinder b = ServiceManager.getServiceOrThrow(Context.LOWPAN_SERVICE);
ILowpanManager service = ILowpanManager.Stub.asInterface(b);
- return new LowpanManager(ctx.getOuterContext(), service,
- ConnectivityThread.getInstanceLooper());
+ return new LowpanManager(ctx.getOuterContext(), service);
}});
registerService(Context.ETHERNET_SERVICE, EthernetManager.class,
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 94084b85..a1c644a 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -12675,4 +12675,21 @@
}
}
}
+
+ // TODO(b/175392542): remove if not needed by ManagedProvisioning app anymore
+ /**
+ * Used by ManagedProvisioning app to factory reset the device when DO cannto be provisioned.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.MASTER_CLEAR)
+ public void factoryReset(String reason) {
+ if (mService != null) {
+ try {
+ mService.factoryReset(reason);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+ }
}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index bcc90f7..a81b506 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -488,4 +488,6 @@
boolean canProfileOwnerResetPasswordWhenLocked(int userId);
void setNextOperationSafety(int operation, boolean safe);
+ // TODO(b/175392542): remove if not needed by ManagedProvisioning app anymore
+ void factoryReset(String reason);
}
diff --git a/core/java/android/app/admin/OWNERS b/core/java/android/app/admin/OWNERS
index 64a1d27..8462cbe 100644
--- a/core/java/android/app/admin/OWNERS
+++ b/core/java/android/app/admin/OWNERS
@@ -1,4 +1,11 @@
# Bug component: 142675
-yamasani@google.com
+# Android Enterprise team
rubinxu@google.com
+sandness@google.com
+eranm@google.com
+alexkershaw@google.com
+pgrafov@google.com
+
+# Emeritus
+yamasani@google.com
diff --git a/core/java/android/app/role/IRoleController.aidl b/core/java/android/app/role/IRoleController.aidl
index 8a43d7f..fbf79a4 100644
--- a/core/java/android/app/role/IRoleController.aidl
+++ b/core/java/android/app/role/IRoleController.aidl
@@ -16,7 +16,9 @@
package android.app.role;
+import android.app.role.RolePrivileges;
import android.os.RemoteCallback;
+import com.android.internal.infra.AndroidFuture;
/**
* @hide
@@ -40,4 +42,6 @@
in RemoteCallback callback);
void isRoleVisible(in String roleName, in RemoteCallback callback);
+
+ void getRolePrivileges(in String roleName, in AndroidFuture<RolePrivileges> callback);
}
diff --git a/core/java/android/app/role/RoleControllerService.java b/core/java/android/app/role/RoleControllerService.java
index d92c956..4c6aa8d 100644
--- a/core/java/android/app/role/RoleControllerService.java
+++ b/core/java/android/app/role/RoleControllerService.java
@@ -16,6 +16,8 @@
package android.app.role;
+import static java.util.Collections.emptyList;
+
import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -32,6 +34,7 @@
import android.os.RemoteCallback;
import android.os.UserHandle;
+import com.android.internal.infra.AndroidFuture;
import com.android.internal.util.Preconditions;
import com.android.internal.util.function.pooled.PooledLambda;
@@ -177,6 +180,20 @@
boolean visible = onIsRoleVisible(roleName);
callback.sendResult(visible ? Bundle.EMPTY : null);
}
+
+ @Override
+ public void getRolePrivileges(String roleName, AndroidFuture<RolePrivileges> callback) {
+ enforceCallingPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, null);
+
+ Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
+ Objects.requireNonNull(callback, "callback cannot be null");
+
+ try {
+ callback.complete(RoleControllerService.this.getRolePrivileges(roleName));
+ } catch (Throwable t) {
+ callback.completeExceptionally(t);
+ }
+ }
};
}
@@ -302,4 +319,14 @@
* @return whether the role should be visible to user
*/
public abstract boolean onIsRoleVisible(@NonNull String roleName);
+
+ /**
+ * Queries the {@link RolePrivileges privileges} that the given role grants.
+ *
+ * @param roleName name of the role to quey for
+ * @return the {@link RolePrivileges} for the role
+ */
+ public @NonNull RolePrivileges getRolePrivileges(@NonNull String roleName) {
+ return new RolePrivileges(emptyList(), emptyList(), emptyList(), emptyList());
+ }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerState.java b/core/java/android/app/role/RolePrivileges.aidl
similarity index 63%
copy from libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerState.java
copy to core/java/android/app/role/RolePrivileges.aidl
index 23d86a0..1561ad4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerState.java
+++ b/core/java/android/app/role/RolePrivileges.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 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,12 +14,7 @@
* limitations under the License.
*/
-package com.android.wm.shell.splitscreen;
-/**
- * Class to hold state of divider that needs to persist across configuration changes.
- */
-final class DividerState {
- public boolean animateAfterRecentsDrawn;
- public float mRatioPositionBeforeMinimized;
-}
+package android.app.role;
+
+parcelable RolePrivileges;
diff --git a/core/java/android/app/role/RolePrivileges.java b/core/java/android/app/role/RolePrivileges.java
new file mode 100644
index 0000000..5fc0b0a08
--- /dev/null
+++ b/core/java/android/app/role/RolePrivileges.java
@@ -0,0 +1,221 @@
+/*
+ * 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.role;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+import java.util.List;
+
+/**
+ * Describes a set of privileges granted by a {@link RoleManager role}
+ *
+ * @hide
+ */
+@SystemApi
+@DataClass
+public final class RolePrivileges implements Parcelable {
+
+ /**
+ * An identifier of a role holder app being granted the
+ * {@link android.service.notification.NotificationListenerService Notification Access}
+ * privilege.
+ */
+ public static final String CAPABILITY_NOTIFICATION_LISTENER =
+ "android.app.role.capability.NOTIFICATION_LISTENER";
+
+ /**
+ * Permissions granted to the role holder(s).
+ */
+ private @NonNull List<String> mPermissions;
+ /**
+ * Appop permissions granted to the role holder(s).
+ */
+ private @NonNull List<String> mAppOpPermissions;
+ /**
+ * Appops granted to the role holder(s).
+ */
+ private @NonNull List<String> mAppOps;
+ /**
+ * Special access granted to the role holder(s).
+ *
+ * @see #CAPABILITY_NOTIFICATION_LISTENER
+ */
+ private @NonNull List<String> mCapabilities;
+
+
+
+ // Code below generated by codegen v1.0.22.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/app/role/RolePrivileges.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ /**
+ * Creates a new RolePrivileges.
+ *
+ * @param permissions
+ * Permissions granted to the role holder(s).
+ * @param appOpPermissions
+ * Appop permissions granted to the role holder(s).
+ * @param appOps
+ * Appops granted to the role holder(s).
+ * @param capabilities
+ * Special access granted to the role holder(s).
+ */
+ @DataClass.Generated.Member
+ public RolePrivileges(
+ @NonNull List<String> permissions,
+ @NonNull List<String> appOpPermissions,
+ @NonNull List<String> appOps,
+ @NonNull List<String> capabilities) {
+ this.mPermissions = permissions;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mPermissions);
+ this.mAppOpPermissions = appOpPermissions;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mAppOpPermissions);
+ this.mAppOps = appOps;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mAppOps);
+ this.mCapabilities = capabilities;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mCapabilities);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ /**
+ * Permissions granted to the role holder(s).
+ */
+ @DataClass.Generated.Member
+ public @NonNull List<String> getPermissions() {
+ return mPermissions;
+ }
+
+ /**
+ * Appop permissions granted to the role holder(s).
+ */
+ @DataClass.Generated.Member
+ public @NonNull List<String> getAppOpPermissions() {
+ return mAppOpPermissions;
+ }
+
+ /**
+ * Appops granted to the role holder(s).
+ */
+ @DataClass.Generated.Member
+ public @NonNull List<String> getAppOps() {
+ return mAppOps;
+ }
+
+ /**
+ * Special access granted to the role holder(s).
+ *
+ * @see #CAPABILITY_NOTIFICATION_LISTENER
+ */
+ @DataClass.Generated.Member
+ public @NonNull List<String> getCapabilities() {
+ return mCapabilities;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ dest.writeStringList(mPermissions);
+ dest.writeStringList(mAppOpPermissions);
+ dest.writeStringList(mAppOps);
+ dest.writeStringList(mCapabilities);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ /* package-private */ RolePrivileges(@NonNull android.os.Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ List<String> permissions = new java.util.ArrayList<>();
+ in.readStringList(permissions);
+ List<String> appOpPermissions = new java.util.ArrayList<>();
+ in.readStringList(appOpPermissions);
+ List<String> appOps = new java.util.ArrayList<>();
+ in.readStringList(appOps);
+ List<String> capabilities = new java.util.ArrayList<>();
+ in.readStringList(capabilities);
+
+ this.mPermissions = permissions;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mPermissions);
+ this.mAppOpPermissions = appOpPermissions;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mAppOpPermissions);
+ this.mAppOps = appOps;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mAppOps);
+ this.mCapabilities = capabilities;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mCapabilities);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<RolePrivileges> CREATOR
+ = new Parcelable.Creator<RolePrivileges>() {
+ @Override
+ public RolePrivileges[] newArray(int size) {
+ return new RolePrivileges[size];
+ }
+
+ @Override
+ public RolePrivileges createFromParcel(@NonNull android.os.Parcel in) {
+ return new RolePrivileges(in);
+ }
+ };
+
+ @DataClass.Generated(
+ time = 1607546429137L,
+ codegenVersion = "1.0.22",
+ sourceFile = "frameworks/base/core/java/android/app/role/RolePrivileges.java",
+ inputSignatures = "public static final java.lang.String CAPABILITY_NOTIFICATION_LISTENER\nprivate @android.annotation.NonNull java.util.List<java.lang.String> mPermissions\nprivate @android.annotation.NonNull java.util.List<java.lang.String> mAppOpPermissions\nprivate @android.annotation.NonNull java.util.List<java.lang.String> mAppOps\nprivate @android.annotation.NonNull java.util.List<java.lang.String> mCapabilities\nclass RolePrivileges extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/core/java/android/app/time/OWNERS b/core/java/android/app/time/OWNERS
new file mode 100644
index 0000000..8f80897
--- /dev/null
+++ b/core/java/android/app/time/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 847766
+mingaleev@google.com
+include /core/java/android/app/timedetector/OWNERS
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerState.java b/core/java/android/app/timedetector/GnssTimeSuggestion.aidl
similarity index 63%
copy from libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerState.java
copy to core/java/android/app/timedetector/GnssTimeSuggestion.aidl
index 23d86a0..81475ec 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerState.java
+++ b/core/java/android/app/timedetector/GnssTimeSuggestion.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 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,12 +14,6 @@
* limitations under the License.
*/
-package com.android.wm.shell.splitscreen;
+package android.app.timedetector;
-/**
- * Class to hold state of divider that needs to persist across configuration changes.
- */
-final class DividerState {
- public boolean animateAfterRecentsDrawn;
- public float mRatioPositionBeforeMinimized;
-}
+parcelable GnssTimeSuggestion;
diff --git a/core/java/android/app/timedetector/GnssTimeSuggestion.java b/core/java/android/app/timedetector/GnssTimeSuggestion.java
new file mode 100644
index 0000000..6478a2d
--- /dev/null
+++ b/core/java/android/app/timedetector/GnssTimeSuggestion.java
@@ -0,0 +1,135 @@
+/*
+ * 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.timedetector;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.TimestampedValue;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A time signal from a GNSS source.
+ *
+ * <p>{@code utcTime} is the suggested time. The {@code utcTime.value} is the number of milliseconds
+ * elapsed since 1/1/1970 00:00:00 UTC. The {@code utcTime.referenceTimeMillis} is the value of the
+ * elapsed realtime clock when the {@code utcTime.value} was established.
+ * Note that the elapsed realtime clock is considered accurate but it is volatile, so time
+ * suggestions cannot be persisted across device resets.
+ *
+ * <p>{@code debugInfo} contains debugging metadata associated with the suggestion. This is used to
+ * record why the suggestion exists and how it was entered. This information exists only to aid in
+ * debugging and therefore is used by {@link #toString()}, but it is not for use in detection
+ * logic and is not considered in {@link #hashCode()} or {@link #equals(Object)}.
+ *
+ * @hide
+ */
+public final class GnssTimeSuggestion implements Parcelable {
+
+ public static final @NonNull Creator<GnssTimeSuggestion> CREATOR =
+ new Creator<GnssTimeSuggestion>() {
+ public GnssTimeSuggestion createFromParcel(Parcel in) {
+ return GnssTimeSuggestion.createFromParcel(in);
+ }
+
+ public GnssTimeSuggestion[] newArray(int size) {
+ return new GnssTimeSuggestion[size];
+ }
+ };
+
+ @NonNull private final TimestampedValue<Long> mUtcTime;
+ @Nullable private ArrayList<String> mDebugInfo;
+
+ public GnssTimeSuggestion(@NonNull TimestampedValue<Long> utcTime) {
+ mUtcTime = Objects.requireNonNull(utcTime);
+ Objects.requireNonNull(utcTime.getValue());
+ }
+
+ private static GnssTimeSuggestion createFromParcel(Parcel in) {
+ TimestampedValue<Long> utcTime = in.readParcelable(null /* classLoader */);
+ GnssTimeSuggestion suggestion = new GnssTimeSuggestion(utcTime);
+ @SuppressWarnings("unchecked")
+ ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */);
+ suggestion.mDebugInfo = debugInfo;
+ return suggestion;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeParcelable(mUtcTime, 0);
+ dest.writeList(mDebugInfo);
+ }
+
+ @NonNull
+ public TimestampedValue<Long> getUtcTime() {
+ return mUtcTime;
+ }
+
+ @NonNull
+ public List<String> getDebugInfo() {
+ return mDebugInfo == null
+ ? Collections.emptyList() : Collections.unmodifiableList(mDebugInfo);
+ }
+
+ /**
+ * Associates information with the instance that can be useful for debugging / logging. The
+ * information is present in {@link #toString()} but is not considered for
+ * {@link #equals(Object)} and {@link #hashCode()}.
+ */
+ public void addDebugInfo(String... debugInfos) {
+ if (mDebugInfo == null) {
+ mDebugInfo = new ArrayList<>();
+ }
+ mDebugInfo.addAll(Arrays.asList(debugInfos));
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ GnssTimeSuggestion that = (GnssTimeSuggestion) o;
+ return Objects.equals(mUtcTime, that.mUtcTime);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mUtcTime);
+ }
+
+ @Override
+ public String toString() {
+ return "GnssTimeSuggestion{"
+ + "mUtcTime=" + mUtcTime
+ + ", mDebugInfo=" + mDebugInfo
+ + '}';
+ }
+}
diff --git a/core/java/android/app/timedetector/ITimeDetectorService.aidl b/core/java/android/app/timedetector/ITimeDetectorService.aidl
index 7bea5d7..87e7233 100644
--- a/core/java/android/app/timedetector/ITimeDetectorService.aidl
+++ b/core/java/android/app/timedetector/ITimeDetectorService.aidl
@@ -16,6 +16,7 @@
package android.app.timedetector;
+import android.app.timedetector.GnssTimeSuggestion;
import android.app.timedetector.ManualTimeSuggestion;
import android.app.timedetector.NetworkTimeSuggestion;
import android.app.timedetector.TelephonyTimeSuggestion;
@@ -34,6 +35,7 @@
* {@hide}
*/
interface ITimeDetectorService {
+ void suggestGnssTime(in GnssTimeSuggestion timeSuggestion);
boolean suggestManualTime(in ManualTimeSuggestion timeSuggestion);
void suggestNetworkTime(in NetworkTimeSuggestion timeSuggestion);
void suggestTelephonyTime(in TelephonyTimeSuggestion timeSuggestion);
diff --git a/core/java/android/app/timedetector/OWNERS b/core/java/android/app/timedetector/OWNERS
index 8c11324..941eed8 100644
--- a/core/java/android/app/timedetector/OWNERS
+++ b/core/java/android/app/timedetector/OWNERS
@@ -1,4 +1,4 @@
# Bug component: 847766
-
+mingaleev@google.com
narayan@google.com
nfuller@google.com
diff --git a/core/java/android/app/timedetector/TimeDetector.java b/core/java/android/app/timedetector/TimeDetector.java
index 162e182..52016b6 100644
--- a/core/java/android/app/timedetector/TimeDetector.java
+++ b/core/java/android/app/timedetector/TimeDetector.java
@@ -71,4 +71,12 @@
*/
@RequiresPermission(android.Manifest.permission.SET_TIME)
void suggestNetworkTime(NetworkTimeSuggestion timeSuggestion);
+
+ /**
+ * Suggests the time according to a gnss time source.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.SET_TIME)
+ void suggestGnssTime(GnssTimeSuggestion timeSuggestion);
}
diff --git a/core/java/android/app/timedetector/TimeDetectorImpl.java b/core/java/android/app/timedetector/TimeDetectorImpl.java
index ac02c89..b0aa3c8 100644
--- a/core/java/android/app/timedetector/TimeDetectorImpl.java
+++ b/core/java/android/app/timedetector/TimeDetectorImpl.java
@@ -74,4 +74,16 @@
throw e.rethrowFromSystemServer();
}
}
+
+ @Override
+ public void suggestGnssTime(GnssTimeSuggestion timeSuggestion) {
+ if (DEBUG) {
+ Log.d(TAG, "suggestGnssTime called: " + timeSuggestion);
+ }
+ try {
+ mITimeDetectorService.suggestGnssTime(timeSuggestion);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/app/timezone/OWNERS b/core/java/android/app/timezone/OWNERS
index 8c11324..8f80897 100644
--- a/core/java/android/app/timezone/OWNERS
+++ b/core/java/android/app/timezone/OWNERS
@@ -1,4 +1,3 @@
# Bug component: 847766
-
-narayan@google.com
-nfuller@google.com
+mingaleev@google.com
+include /core/java/android/app/timedetector/OWNERS
diff --git a/core/java/android/app/timezonedetector/OWNERS b/core/java/android/app/timezonedetector/OWNERS
new file mode 100644
index 0000000..8f80897
--- /dev/null
+++ b/core/java/android/app/timezonedetector/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 847766
+mingaleev@google.com
+include /core/java/android/app/timedetector/OWNERS
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 67a1ad6..bd27099 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2682,6 +2682,23 @@
/**
* Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature(String, int)}: If this feature is supported, the feature version
+ * specifies a date such that the device is known to pass the OpenGLES dEQP test suite
+ * associated with that date. The date is encoded as follows:
+ * <ul>
+ * <li>Year in bits 31-16</li>
+ * <li>Month in bits 15-8</li>
+ * <li>Day in bits 7-0</li>
+ * </ul>
+ * <p>
+ * Example: 2021-03-01 is encoded as 0x07E50301, and would indicate that the device passes the
+ * OpenGL ES dEQP test suite version that was current on 2021-03-01.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_OPENGLES_DEQP_LEVEL = "android.software.opengles.deqp.level";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device includes broadcast radio tuner.
* @hide
*/
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index ae10f40..3a73de6 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -350,7 +350,7 @@
*
* @hide
*/
- public static final int HDMI_CEC_VERSION_1_4_b = 0x05;
+ public static final int HDMI_CEC_VERSION_1_4_B = 0x05;
/**
* Version constant for HDMI-CEC v2.0.
*
@@ -361,7 +361,7 @@
* @hide
*/
@IntDef({
- HDMI_CEC_VERSION_1_4_b,
+ HDMI_CEC_VERSION_1_4_B,
HDMI_CEC_VERSION_2_0
})
@Retention(RetentionPolicy.SOURCE)
diff --git a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java
index a8cafef..c0b177d 100644
--- a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java
+++ b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java
@@ -203,7 +203,7 @@
public HdmiDeviceInfo(int logicalAddress, int physicalAddress, int portId, int deviceType,
int vendorId, String displayName, int powerStatus) {
this(logicalAddress, physicalAddress, portId, deviceType,
- vendorId, displayName, powerStatus, HdmiControlManager.HDMI_CEC_VERSION_1_4_b);
+ vendorId, displayName, powerStatus, HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
}
/**
@@ -221,7 +221,7 @@
int vendorId, String displayName) {
this(logicalAddress, physicalAddress, portId, deviceType,
vendorId, displayName, HdmiControlManager.POWER_STATUS_UNKNOWN,
- HdmiControlManager.HDMI_CEC_VERSION_1_4_b);
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
}
/**
@@ -239,7 +239,7 @@
mId = idForHardware(portId);
mLogicalAddress = -1;
mDeviceType = DEVICE_RESERVED;
- mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_b;
+ mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_B;
mVendorId = 0;
mDevicePowerStatus = HdmiControlManager.POWER_STATUS_UNKNOWN;
mDisplayName = "HDMI" + portId;
@@ -265,7 +265,7 @@
mId = idForMhlDevice(portId);
mLogicalAddress = -1;
mDeviceType = DEVICE_RESERVED;
- mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_b;
+ mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_B;
mVendorId = 0;
mDevicePowerStatus = HdmiControlManager.POWER_STATUS_UNKNOWN;
mDisplayName = "Mobile";
@@ -287,7 +287,7 @@
mLogicalAddress = -1;
mDeviceType = DEVICE_INACTIVE;
- mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_b;
+ mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_B;
mPortId = PORT_INVALID;
mDevicePowerStatus = HdmiControlManager.POWER_STATUS_UNKNOWN;
mDisplayName = "Inactive";
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 3f2c966..09c3050 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -2108,17 +2108,6 @@
// ignored
}
- /** {@hide} */
- @Deprecated
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public NetworkQuotaInfo getActiveNetworkQuotaInfo() {
- try {
- return mService.getActiveNetworkQuotaInfo();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
/**
* @hide
* @deprecated Talk to TelephonyManager directly
@@ -3163,9 +3152,9 @@
}
/**
- * Set sign in error notification to visible or in visible
+ * Set sign in error notification to visible or invisible
*
- * {@hide}
+ * @hide
* @deprecated Doesn't properly deal with multiple connected networks of the same type.
*/
@Deprecated
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 4173200..fb01283 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -25,7 +25,6 @@
import android.net.NetworkAgentConfig;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
-import android.net.NetworkQuotaInfo;
import android.net.NetworkRequest;
import android.net.NetworkState;
import android.net.ISocketKeepaliveCallback;
@@ -76,7 +75,6 @@
@UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
NetworkState[] getAllNetworkState();
- NetworkQuotaInfo getActiveNetworkQuotaInfo();
boolean isActiveNetworkMetered();
boolean requestRouteToHostAddress(int networkType, in byte[] hostAddress,
diff --git a/core/java/android/net/TcpKeepalivePacketData.java b/core/java/android/net/TcpKeepalivePacketData.java
new file mode 100644
index 0000000..ddb3a6a7
--- /dev/null
+++ b/core/java/android/net/TcpKeepalivePacketData.java
@@ -0,0 +1,163 @@
+/*
+ * 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.net;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.net.InetAddress;
+import java.util.Objects;
+
+/**
+ * Represents the actual tcp keep alive packets which will be used for hardware offload.
+ * @hide
+ */
+@SystemApi
+public final class TcpKeepalivePacketData extends KeepalivePacketData implements Parcelable {
+ private static final String TAG = "TcpKeepalivePacketData";
+
+ /** TCP sequence number. */
+ public final int tcpSeq;
+
+ /** TCP ACK number. */
+ public final int tcpAck;
+
+ /** TCP RCV window. */
+ public final int tcpWindow;
+
+ /** TCP RCV window scale. */
+ public final int tcpWindowScale;
+
+ /** IP TOS. */
+ public final int ipTos;
+
+ /** IP TTL. */
+ public final int ipTtl;
+
+ public TcpKeepalivePacketData(@NonNull final InetAddress srcAddress, int srcPort,
+ @NonNull final InetAddress dstAddress, int dstPort, @NonNull final byte[] data,
+ int tcpSeq, int tcpAck, int tcpWindow, int tcpWindowScale, int ipTos, int ipTtl)
+ throws InvalidPacketException {
+ super(srcAddress, srcPort, dstAddress, dstPort, data);
+ this.tcpSeq = tcpSeq;
+ this.tcpAck = tcpAck;
+ this.tcpWindow = tcpWindow;
+ this.tcpWindowScale = tcpWindowScale;
+ this.ipTos = ipTos;
+ this.ipTtl = ipTtl;
+ }
+
+ @Override
+ public boolean equals(@Nullable final Object o) {
+ if (!(o instanceof TcpKeepalivePacketData)) return false;
+ final TcpKeepalivePacketData other = (TcpKeepalivePacketData) o;
+ final InetAddress srcAddress = getSrcAddress();
+ final InetAddress dstAddress = getDstAddress();
+ return srcAddress.equals(other.getSrcAddress())
+ && dstAddress.equals(other.getDstAddress())
+ && getSrcPort() == other.getSrcPort()
+ && getDstPort() == other.getDstPort()
+ && this.tcpAck == other.tcpAck
+ && this.tcpSeq == other.tcpSeq
+ && this.tcpWindow == other.tcpWindow
+ && this.tcpWindowScale == other.tcpWindowScale
+ && this.ipTos == other.ipTos
+ && this.ipTtl == other.ipTtl;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(getSrcAddress(), getDstAddress(), getSrcPort(), getDstPort(),
+ tcpAck, tcpSeq, tcpWindow, tcpWindowScale, ipTos, ipTtl);
+ }
+
+ /**
+ * Parcelable Implementation.
+ * Note that this object implements parcelable (and needs to keep doing this as it inherits
+ * from a class that does), but should usually be parceled as a stable parcelable using
+ * the toStableParcelable() and fromStableParcelable() methods.
+ */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Write to parcel. */
+ @Override
+ public void writeToParcel(@NonNull Parcel out, int flags) {
+ out.writeString(getSrcAddress().getHostAddress());
+ out.writeString(getDstAddress().getHostAddress());
+ out.writeInt(getSrcPort());
+ out.writeInt(getDstPort());
+ out.writeByteArray(getPacket());
+ out.writeInt(tcpSeq);
+ out.writeInt(tcpAck);
+ out.writeInt(tcpWindow);
+ out.writeInt(tcpWindowScale);
+ out.writeInt(ipTos);
+ out.writeInt(ipTtl);
+ }
+
+ private static TcpKeepalivePacketData readFromParcel(Parcel in) throws InvalidPacketException {
+ InetAddress srcAddress = InetAddresses.parseNumericAddress(in.readString());
+ InetAddress dstAddress = InetAddresses.parseNumericAddress(in.readString());
+ int srcPort = in.readInt();
+ int dstPort = in.readInt();
+ byte[] packet = in.createByteArray();
+ int tcpSeq = in.readInt();
+ int tcpAck = in.readInt();
+ int tcpWnd = in.readInt();
+ int tcpWndScale = in.readInt();
+ int ipTos = in.readInt();
+ int ipTtl = in.readInt();
+ return new TcpKeepalivePacketData(srcAddress, srcPort, dstAddress, dstPort, packet, tcpSeq,
+ tcpAck, tcpWnd, tcpWndScale, ipTos, ipTtl);
+ }
+
+ /** Parcelable Creator. */
+ public static final @NonNull Parcelable.Creator<TcpKeepalivePacketData> CREATOR =
+ new Parcelable.Creator<TcpKeepalivePacketData>() {
+ public TcpKeepalivePacketData createFromParcel(Parcel in) {
+ try {
+ return readFromParcel(in);
+ } catch (InvalidPacketException e) {
+ throw new IllegalArgumentException(
+ "Invalid TCP keepalive data: " + e.getError());
+ }
+ }
+
+ public TcpKeepalivePacketData[] newArray(int size) {
+ return new TcpKeepalivePacketData[size];
+ }
+ };
+
+ @Override
+ public String toString() {
+ return "saddr: " + getSrcAddress()
+ + " daddr: " + getDstAddress()
+ + " sport: " + getSrcPort()
+ + " dport: " + getDstPort()
+ + " seq: " + tcpSeq
+ + " ack: " + tcpAck
+ + " window: " + tcpWindow
+ + " windowScale: " + tcpWindowScale
+ + " tos: " + ipTos
+ + " ttl: " + ipTtl;
+ }
+}
diff --git a/core/java/android/os/BatteryConsumer.java b/core/java/android/os/BatteryConsumer.java
index 74880b2..3956ef9 100644
--- a/core/java/android/os/BatteryConsumer.java
+++ b/core/java/android/os/BatteryConsumer.java
@@ -42,9 +42,10 @@
public static @interface PowerComponent {
}
- public static final int POWER_COMPONENT_CPU = 0;
+ public static final int POWER_COMPONENT_USAGE = 0;
+ public static final int POWER_COMPONENT_CPU = 1;
- public static final int POWER_COMPONENT_COUNT = 1;
+ public static final int POWER_COMPONENT_COUNT = 2;
public static final int FIRST_CUSTOM_POWER_COMPONENT_ID = 1000;
public static final int LAST_CUSTOM_POWER_COMPONENT_ID = 9999;
@@ -63,10 +64,11 @@
public static @interface TimeComponent {
}
- public static final int TIME_COMPONENT_CPU = 0;
- public static final int TIME_COMPONENT_CPU_FOREGROUND = 1;
+ public static final int TIME_COMPONENT_USAGE = 0;
+ public static final int TIME_COMPONENT_CPU = 1;
+ public static final int TIME_COMPONENT_CPU_FOREGROUND = 2;
- public static final int TIME_COMPONENT_COUNT = 2;
+ public static final int TIME_COMPONENT_COUNT = 3;
public static final int FIRST_CUSTOM_TIME_COMPONENT_ID = 1000;
public static final int LAST_CUSTOM_TIME_COMPONENT_ID = 9999;
@@ -131,4 +133,80 @@
protected void writeToParcel(Parcel dest, int flags) {
mPowerComponents.writeToParcel(dest, flags);
}
+
+ protected abstract static class BaseBuilder<T extends BaseBuilder<?>> {
+ final PowerComponents.Builder mPowerComponentsBuilder;
+
+ public BaseBuilder(int customPowerComponentCount, int customTimeComponentCount) {
+ mPowerComponentsBuilder = new PowerComponents.Builder(customPowerComponentCount,
+ customTimeComponentCount);
+ }
+
+ /**
+ * Sets the amount of drain attributed to the specified drain type, e.g. CPU, WiFi etc.
+ *
+ * @param componentId The ID of the power component, e.g.
+ * {@link BatteryConsumer#POWER_COMPONENT_CPU}.
+ * @param componentPower Amount of consumed power in mAh.
+ */
+ @SuppressWarnings("unchecked")
+ @NonNull
+ public T setConsumedPower(@PowerComponent int componentId, double componentPower) {
+ mPowerComponentsBuilder.setConsumedPower(componentId, componentPower);
+ return (T) this;
+ }
+
+ /**
+ * Sets the amount of drain attributed to the specified custom drain type.
+ *
+ * @param componentId The ID of the custom power component.
+ * @param componentPower Amount of consumed power in mAh.
+ */
+ @SuppressWarnings("unchecked")
+ @NonNull
+ public T setConsumedPowerForCustomComponent(int componentId, double componentPower) {
+ mPowerComponentsBuilder.setConsumedPowerForCustomComponent(componentId, componentPower);
+ return (T) this;
+ }
+
+ /**
+ * Sets the total amount of power consumed since BatteryStats reset, mAh.
+ */
+ @SuppressWarnings("unchecked")
+ @NonNull
+ public T setConsumedPower(double consumedPower) {
+ mPowerComponentsBuilder.setTotalPowerConsumed(consumedPower);
+ return (T) this;
+ }
+
+ /**
+ * Sets the amount of time used by the specified component, e.g. CPU, WiFi etc.
+ *
+ * @param componentId The ID of the time component, e.g.
+ * {@link UidBatteryConsumer#TIME_COMPONENT_CPU}.
+ * @param componentUsageTimeMillis Amount of time in microseconds.
+ */
+ @SuppressWarnings("unchecked")
+ @NonNull
+ public T setUsageDurationMillis(@UidBatteryConsumer.TimeComponent int componentId,
+ long componentUsageTimeMillis) {
+ mPowerComponentsBuilder.setUsageDurationMillis(componentId, componentUsageTimeMillis);
+ return (T) this;
+ }
+
+ /**
+ * Sets the amount of time used by the specified custom component.
+ *
+ * @param componentId The ID of the custom power component.
+ * @param componentUsageTimeMillis Amount of time in microseconds.
+ */
+ @SuppressWarnings("unchecked")
+ @NonNull
+ public T setUsageDurationForCustomComponentMillis(int componentId,
+ long componentUsageTimeMillis) {
+ mPowerComponentsBuilder.setUsageDurationForCustomComponentMillis(componentId,
+ componentUsageTimeMillis);
+ return (T) this;
+ }
+ }
}
diff --git a/core/java/android/os/BatteryUsageStats.java b/core/java/android/os/BatteryUsageStats.java
index 79f58f6..af8e8de 100644
--- a/core/java/android/os/BatteryUsageStats.java
+++ b/core/java/android/os/BatteryUsageStats.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.SuppressLint;
+import android.util.SparseArray;
import java.util.ArrayList;
import java.util.List;
@@ -31,14 +32,20 @@
private final double mConsumedPower;
private final int mDischargePercentage;
private final ArrayList<UidBatteryConsumer> mUidBatteryConsumers;
+ private final ArrayList<SystemBatteryConsumer> mSystemBatteryConsumers;
private BatteryUsageStats(@NonNull Builder builder) {
mConsumedPower = builder.mConsumedPower;
mDischargePercentage = builder.mDischargePercentage;
- final int uidBatteryConsumerCount = builder.mUidBatteryConsumerBuilders.size();
+ int uidBatteryConsumerCount = builder.mUidBatteryConsumerBuilders.size();
mUidBatteryConsumers = new ArrayList<>(uidBatteryConsumerCount);
for (int i = 0; i < uidBatteryConsumerCount; i++) {
- mUidBatteryConsumers.add(builder.mUidBatteryConsumerBuilders.get(i).build());
+ mUidBatteryConsumers.add(builder.mUidBatteryConsumerBuilders.valueAt(i).build());
+ }
+ int systemBatteryConsumerCount = builder.mSystemBatteryConsumerBuilders.size();
+ mSystemBatteryConsumers = new ArrayList<>(systemBatteryConsumerCount);
+ for (int i = 0; i < systemBatteryConsumerCount; i++) {
+ mSystemBatteryConsumers.add(builder.mSystemBatteryConsumerBuilders.valueAt(i).build());
}
}
@@ -63,6 +70,11 @@
return mUidBatteryConsumers;
}
+ @NonNull
+ public List<SystemBatteryConsumer> getSystemBatteryConsumers() {
+ return mSystemBatteryConsumers;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -71,6 +83,8 @@
private BatteryUsageStats(@NonNull Parcel source) {
mUidBatteryConsumers = new ArrayList<>();
source.readParcelableList(mUidBatteryConsumers, getClass().getClassLoader());
+ mSystemBatteryConsumers = new ArrayList<>();
+ source.readParcelableList(mSystemBatteryConsumers, getClass().getClassLoader());
mConsumedPower = source.readDouble();
mDischargePercentage = source.readInt();
}
@@ -78,6 +92,7 @@
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeParcelableList(mUidBatteryConsumers, flags);
+ dest.writeParcelableList(mSystemBatteryConsumers, flags);
dest.writeDouble(mConsumedPower);
dest.writeInt(mDischargePercentage);
}
@@ -97,10 +112,19 @@
* Builder for BatteryUsageStats.
*/
public static final class Builder {
+ private final int mCustomPowerComponentCount;
+ private final int mCustomTimeComponentCount;
private double mConsumedPower;
private int mDischargePercentage;
- private final ArrayList<UidBatteryConsumer.Builder> mUidBatteryConsumerBuilders =
- new ArrayList<>();
+ private final SparseArray<UidBatteryConsumer.Builder> mUidBatteryConsumerBuilders =
+ new SparseArray<>();
+ private final SparseArray<SystemBatteryConsumer.Builder> mSystemBatteryConsumerBuilders =
+ new SparseArray<>();
+
+ public Builder(int customPowerComponentCount, int customTimeComponentCount) {
+ mCustomPowerComponentCount = customPowerComponentCount;
+ mCustomTimeComponentCount = customTimeComponentCount;
+ }
/**
* Constructs a read-only object using the Builder values.
@@ -113,6 +137,7 @@
/**
* Sets the battery discharge amount since BatteryStats reset as percentage of the full
* charge.
+ *
*/
@SuppressLint("PercentageInt") // See b/174188159
@NonNull
@@ -131,18 +156,40 @@
}
/**
- * Adds a UidBatteryConsumer, which represents battery attribution data for an
- * individual UID.
+ * Creates or returns a exiting UidBatteryConsumer, which represents battery attribution
+ * data for an individual UID.
*/
@NonNull
- public Builder addUidBatteryConsumerBuilder(
- @NonNull UidBatteryConsumer.Builder uidBatteryConsumer) {
- mUidBatteryConsumerBuilders.add(uidBatteryConsumer);
- return this;
+ public UidBatteryConsumer.Builder getOrCreateUidBatteryConsumerBuilder(
+ @NonNull BatteryStats.Uid batteryStatsUid) {
+ int uid = batteryStatsUid.getUid();
+ UidBatteryConsumer.Builder builder = mUidBatteryConsumerBuilders.get(uid);
+ if (builder == null) {
+ builder = new UidBatteryConsumer.Builder(mCustomPowerComponentCount,
+ mCustomTimeComponentCount, batteryStatsUid);
+ mUidBatteryConsumerBuilders.put(uid, builder);
+ }
+ return builder;
+ }
+
+ /**
+ * Creates or returns a exiting UidBatteryConsumer, which represents battery attribution
+ * data for an individual UID.
+ */
+ @NonNull
+ public SystemBatteryConsumer.Builder getOrCreateSystemBatteryConsumerBuilder(
+ @SystemBatteryConsumer.DrainType int drainType) {
+ SystemBatteryConsumer.Builder builder = mSystemBatteryConsumerBuilders.get(drainType);
+ if (builder == null) {
+ builder = new SystemBatteryConsumer.Builder(mCustomPowerComponentCount,
+ mCustomTimeComponentCount, drainType);
+ mSystemBatteryConsumerBuilders.put(drainType, builder);
+ }
+ return builder;
}
@NonNull
- public List<UidBatteryConsumer.Builder> getUidBatteryConsumerBuilders() {
+ public SparseArray<UidBatteryConsumer.Builder> getUidBatteryConsumerBuilders() {
return mUidBatteryConsumerBuilders;
}
}
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index bd18150..8148c45 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -107,12 +107,24 @@
public static final String HARDWARE = getString("ro.hardware");
/**
- * The hardware variant (SKU), if available.
+ * The SKU of the hardware (from the kernel command line). The SKU is reported by the bootloader
+ * to configure system software features.
*/
@NonNull
public static final String SKU = getString("ro.boot.hardware.sku");
/**
+ * The SKU of the device as set by the original design manufacturer (ODM). This is a
+ * runtime-initialized property set during startup to configure device services.
+ *
+ * <p>The ODM SKU may have multiple variants for the same system SKU in case a manufacturer
+ * produces variants of the same design. For example, the same build may be released with
+ * variations in physical keyboard and/or display hardware, each with a different ODM SKU.
+ */
+ @NonNull
+ public static final String ODM_SKU = getString("ro.boot.product.hardware.sku");
+
+ /**
* Whether this build was for an emulator device.
* @hide
*/
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 379d6e6..92fe98c 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -1436,9 +1436,7 @@
public static FileDescriptor convertToModernFd(FileDescriptor fd) {
try {
Context context = AppGlobals.getInitialApplication();
- // TODO(b/169327180): Consider device config.
- if (!SystemProperties.getBoolean("persist.sys.fuse.transcode_enabled", false)
- || !SystemProperties.getBoolean("persist.sys.fuse.transcode_optimize", true)
+ if (!SystemProperties.getBoolean("sys.fuse.transcode_enabled", false)
|| UserHandle.getAppId(Process.myUid()) == getMediaProviderAppId(context)) {
// If transcode is enabled we optimize by default, unless explicitly disabled.
// Never convert modern fd for MediaProvider, because this requires
diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS
index 3b334a7..49451d9 100644
--- a/core/java/android/os/OWNERS
+++ b/core/java/android/os/OWNERS
@@ -29,3 +29,6 @@
per-file *Power* = file:/services/core/java/com/android/server/power/OWNERS
per-file *Telephony* = file:/telephony/OWNERS
per-file *Zygote* = file:/ZYGOTE_OWNERS
+
+# RecoverySystem
+per-file *Recovery* = file:/services/core/java/com/android/server/recoverysystem/OWNERS
diff --git a/core/java/android/os/SystemBatteryConsumer.java b/core/java/android/os/SystemBatteryConsumer.java
new file mode 100644
index 0000000..570a2dc
--- /dev/null
+++ b/core/java/android/os/SystemBatteryConsumer.java
@@ -0,0 +1,136 @@
+/*
+ * 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.os;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+
+/**
+ * Contains power consumption data attributed to a system-wide drain type.
+ *
+ * {@hide}
+ */
+public class SystemBatteryConsumer extends BatteryConsumer implements Parcelable {
+
+ // ****************
+ // This list must be kept current with atoms.proto (frameworks/base/cmds/statsd/src/atoms.proto)
+ // so the constant values must never change.
+ // ****************
+ @IntDef(prefix = {"DRAIN_TYPE_"}, value = {
+ DRAIN_TYPE_AMBIENT_DISPLAY,
+ // Reserved: APP
+ DRAIN_TYPE_BLUETOOTH,
+ DRAIN_TYPE_CAMERA,
+ DRAIN_TYPE_CELL,
+ DRAIN_TYPE_FLASHLIGHT,
+ DRAIN_TYPE_IDLE,
+ DRAIN_TYPE_MEMORY,
+ DRAIN_TYPE_OVERCOUNTED,
+ DRAIN_TYPE_PHONE,
+ DRAIN_TYPE_SCREEN,
+ DRAIN_TYPE_UNACCOUNTED,
+ // Reserved: USER,
+ DRAIN_TYPE_WIFI,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public static @interface DrainType {
+ }
+
+ public static final int DRAIN_TYPE_AMBIENT_DISPLAY = 0;
+ public static final int DRAIN_TYPE_BLUETOOTH = 2;
+ public static final int DRAIN_TYPE_CAMERA = 3;
+ public static final int DRAIN_TYPE_CELL = 4;
+ public static final int DRAIN_TYPE_FLASHLIGHT = 5;
+ public static final int DRAIN_TYPE_IDLE = 6;
+ public static final int DRAIN_TYPE_MEMORY = 7;
+ public static final int DRAIN_TYPE_OVERCOUNTED = 8;
+ public static final int DRAIN_TYPE_PHONE = 9;
+ public static final int DRAIN_TYPE_SCREEN = 10;
+ public static final int DRAIN_TYPE_UNACCOUNTED = 11;
+ public static final int DRAIN_TYPE_WIFI = 13;
+
+ @DrainType
+ private final int mDrainType;
+
+ @DrainType
+ public int getDrainType() {
+ return mDrainType;
+ }
+
+ private SystemBatteryConsumer(@NonNull SystemBatteryConsumer.Builder builder) {
+ super(builder.mPowerComponentsBuilder.build());
+ mDrainType = builder.mDrainType;
+ }
+
+ private SystemBatteryConsumer(Parcel in) {
+ super(new PowerComponents(in));
+ mDrainType = in.readInt();
+ }
+
+ /**
+ * Writes the contents into a Parcel.
+ */
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeInt(mDrainType);
+ }
+
+ public static final Creator<SystemBatteryConsumer> CREATOR =
+ new Creator<SystemBatteryConsumer>() {
+ @Override
+ public SystemBatteryConsumer createFromParcel(Parcel in) {
+ return new SystemBatteryConsumer(in);
+ }
+
+ @Override
+ public SystemBatteryConsumer[] newArray(int size) {
+ return new SystemBatteryConsumer[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ * Builder for SystemBatteryConsumer.
+ */
+ public static final class Builder extends BaseBuilder<Builder> {
+ @DrainType
+ private final int mDrainType;
+
+ Builder(int customPowerComponentCount, int customTimeComponentCount,
+ @DrainType int drainType) {
+ super(customPowerComponentCount, customTimeComponentCount);
+ mDrainType = drainType;
+ }
+
+ /**
+ * Creates a read-only object out of the Builder values.
+ */
+ @NonNull
+ public SystemBatteryConsumer build() {
+ return new SystemBatteryConsumer(this);
+ }
+ }
+}
diff --git a/core/java/android/os/UidBatteryConsumer.java b/core/java/android/os/UidBatteryConsumer.java
index d12ccb5..06cf4a6 100644
--- a/core/java/android/os/UidBatteryConsumer.java
+++ b/core/java/android/os/UidBatteryConsumer.java
@@ -80,16 +80,14 @@
/**
* Builder for UidBatteryConsumer.
*/
- public static final class Builder {
- private final PowerComponents.Builder mPowerComponentsBuilder;
+ public static final class Builder extends BaseBuilder<Builder> {
private final BatteryStats.Uid mBatteryStatsUid;
private final int mUid;
private String mPackageWithHighestDrain;
public Builder(int customPowerComponentCount, int customTimeComponentCount,
BatteryStats.Uid batteryStatsUid) {
- mPowerComponentsBuilder = new PowerComponents.Builder(customPowerComponentCount,
- customTimeComponentCount);
+ super(customPowerComponentCount, customTimeComponentCount);
mBatteryStatsUid = batteryStatsUid;
mUid = batteryStatsUid.getUid();
}
@@ -111,69 +109,6 @@
}
/**
- * Sets the amount of drain attributed to the specified drain type, e.g. CPU, WiFi etc.
- *
- * @param componentId The ID of the power component, e.g.
- * {@link BatteryConsumer#POWER_COMPONENT_CPU}.
- * @param componentPower Amount of consumed power in mAh.
- */
- @NonNull
- public Builder setConsumedPower(@PowerComponent int componentId, double componentPower) {
- mPowerComponentsBuilder.setConsumedPower(componentId, componentPower);
- return this;
- }
-
- /**
- * Sets the amount of drain attributed to the specified custom drain type.
- *
- * @param componentId The ID of the custom power component.
- * @param componentPower Amount of consumed power in mAh.
- */
- @NonNull
- public Builder setConsumedPowerForCustomComponent(int componentId, double componentPower) {
- mPowerComponentsBuilder.setConsumedPowerForCustomComponent(componentId, componentPower);
- return this;
- }
-
- /**
- * Sets the amount of power consumed since BatteryStats reset, mAh.
- */
- @NonNull
- public Builder setConsumedPower(double consumedPower) {
- mPowerComponentsBuilder.setTotalPowerConsumed(consumedPower);
- return this;
- }
-
- /**
- * Sets the amount of time used by the specified component, e.g. CPU, WiFi etc.
- *
- * @param componentId The ID of the time component, e.g.
- * {@link UidBatteryConsumer#TIME_COMPONENT_CPU}.
- * @param componentUsageDurationMillis Amount of time in milliseconds.
- */
- @NonNull
- public Builder setUsageDurationMillis(@UidBatteryConsumer.TimeComponent int componentId,
- long componentUsageDurationMillis) {
- mPowerComponentsBuilder.setUsageDurationMillis(componentId,
- componentUsageDurationMillis);
- return this;
- }
-
- /**
- * Sets the amount of time used by the specified custom component.
- *
- * @param componentId The ID of the custom power component.
- * @param componentUsageDurationMillis Amount of time in milliseconds.
- */
- @NonNull
- public Builder setUsageDurationForCustomComponentMillis(int componentId,
- long componentUsageDurationMillis) {
- mPowerComponentsBuilder.setUsageDurationForCustomComponentMillis(componentId,
- componentUsageDurationMillis);
- return this;
- }
-
- /**
* Sets the name of the package owned by this UID that consumed the highest amount
* of power since BatteryStats reset.
*/
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index f58fa15..ec4d81c 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -444,6 +444,14 @@
public static final String NAMESPACE_PERMISSIONS = "permissions";
/**
+ * Namespace for ota related features.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String NAMESPACE_OTA = "ota";
+
+ /**
* Namespace for all widget related features.
*
* @hide
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index daa17aa..2dbd3ed 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1848,7 +1848,7 @@
/**
* Activity Action: Show notification bubble settings for a single app.
- * See {@link NotificationManager#areBubblesAllowed()}.
+ * See {@link NotificationManager#getBubblePreference()}.
* <p>
* Input: {@link #EXTRA_APP_PACKAGE}, the package to display.
* <p>
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index 0b6d371..c1b66c7 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -1220,7 +1220,7 @@
* your UI, which will eventually culminate in {@link #onShow}. This is similar to calling
* {@link VoiceInteractionService#showSession VoiceInteractionService.showSession}.
* @param args Arbitrary arguments that will be propagated {@link #onShow}.
- * @param flags Indicates additional optional behavior that should be performed. May
+ * @param flags Indicates additional optional behavior that should be performed. May
* be any combination of
* {@link VoiceInteractionSession#SHOW_WITH_ASSIST VoiceInteractionSession.SHOW_WITH_ASSIST} and
* {@link VoiceInteractionSession#SHOW_WITH_SCREENSHOT
@@ -1583,6 +1583,11 @@
*
* @param args The arguments that were supplied to
* {@link VoiceInteractionService#showSession VoiceInteractionService.showSession}.
+ * Some example keys include : "invocation_type", "invocation_phone_state",
+ * "invocation_time_ms", Intent.EXTRA_TIME ("android.intent.extra.TIME") indicating timing
+ * in milliseconds of the KeyEvent that triggered Assistant and
+ * Intent.EXTRA_ASSIST_INPUT_DEVICE_ID (android.intent.extra.ASSIST_INPUT_DEVICE_ID)
+ * referring to the device that sent the request.
* @param showFlags The show flags originally provided to
* {@link VoiceInteractionService#showSession VoiceInteractionService.showSession}.
*/
diff --git a/core/java/android/timezone/OWNERS b/core/java/android/timezone/OWNERS
index 09447a9..8f80897 100644
--- a/core/java/android/timezone/OWNERS
+++ b/core/java/android/timezone/OWNERS
@@ -1 +1,3 @@
-include /core/java/android/app/timezone/OWNERS
+# Bug component: 847766
+mingaleev@google.com
+include /core/java/android/app/timedetector/OWNERS
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 41b2fb4..b66dd29 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -116,20 +116,22 @@
public static final int ITYPE_LEFT_MANDATORY_GESTURES = 9;
public static final int ITYPE_RIGHT_MANDATORY_GESTURES = 10;
- public static final int ITYPE_TOP_TAPPABLE_ELEMENT = 11;
- public static final int ITYPE_BOTTOM_TAPPABLE_ELEMENT = 12;
+ public static final int ITYPE_LEFT_TAPPABLE_ELEMENT = 11;
+ public static final int ITYPE_TOP_TAPPABLE_ELEMENT = 12;
+ public static final int ITYPE_RIGHT_TAPPABLE_ELEMENT = 13;
+ public static final int ITYPE_BOTTOM_TAPPABLE_ELEMENT = 14;
- public static final int ITYPE_LEFT_DISPLAY_CUTOUT = 13;
- public static final int ITYPE_TOP_DISPLAY_CUTOUT = 14;
- public static final int ITYPE_RIGHT_DISPLAY_CUTOUT = 15;
- public static final int ITYPE_BOTTOM_DISPLAY_CUTOUT = 16;
+ public static final int ITYPE_LEFT_DISPLAY_CUTOUT = 15;
+ public static final int ITYPE_TOP_DISPLAY_CUTOUT = 16;
+ public static final int ITYPE_RIGHT_DISPLAY_CUTOUT = 17;
+ public static final int ITYPE_BOTTOM_DISPLAY_CUTOUT = 18;
/** Input method window. */
- public static final int ITYPE_IME = 17;
+ public static final int ITYPE_IME = 19;
/** Additional system decorations inset type. */
- public static final int ITYPE_CLIMATE_BAR = 18;
- public static final int ITYPE_EXTRA_NAVIGATION_BAR = 19;
+ public static final int ITYPE_CLIMATE_BAR = 20;
+ public static final int ITYPE_EXTRA_NAVIGATION_BAR = 21;
static final int LAST_TYPE = ITYPE_EXTRA_NAVIGATION_BAR;
public static final int SIZE = LAST_TYPE + 1;
@@ -542,7 +544,9 @@
case ITYPE_LEFT_GESTURES:
case ITYPE_RIGHT_GESTURES:
return Type.SYSTEM_GESTURES;
+ case ITYPE_LEFT_TAPPABLE_ELEMENT:
case ITYPE_TOP_TAPPABLE_ELEMENT:
+ case ITYPE_RIGHT_TAPPABLE_ELEMENT:
case ITYPE_BOTTOM_TAPPABLE_ELEMENT:
return Type.TAPPABLE_ELEMENT;
case ITYPE_LEFT_DISPLAY_CUTOUT:
@@ -615,8 +619,12 @@
return "ITYPE_LEFT_MANDATORY_GESTURES";
case ITYPE_RIGHT_MANDATORY_GESTURES:
return "ITYPE_RIGHT_MANDATORY_GESTURES";
+ case ITYPE_LEFT_TAPPABLE_ELEMENT:
+ return "ITYPE_LEFT_TAPPABLE_ELEMENT";
case ITYPE_TOP_TAPPABLE_ELEMENT:
return "ITYPE_TOP_TAPPABLE_ELEMENT";
+ case ITYPE_RIGHT_TAPPABLE_ELEMENT:
+ return "ITYPE_RIGHT_TAPPABLE_ELEMENT";
case ITYPE_BOTTOM_TAPPABLE_ELEMENT:
return "ITYPE_BOTTOM_TAPPABLE_ELEMENT";
case ITYPE_LEFT_DISPLAY_CUTOUT:
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 9943e02..de320b8 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -154,6 +154,7 @@
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
+import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
@@ -29442,6 +29443,16 @@
}
return mScrollCaptureInternal;
}
+
+ public void dump(String prefix, PrintWriter writer) {
+ String innerPrefix = prefix + " ";
+ writer.println(prefix + "AttachInfo:");
+ writer.println(innerPrefix + "mHasWindowFocus=" + mHasWindowFocus);
+ writer.println(innerPrefix + "mWindowVisibility=" + mWindowVisibility);
+ writer.println(innerPrefix + "mInTouchMode=" + mInTouchMode);
+ writer.println(innerPrefix + "mUnbufferedDispatchRequested="
+ + mUnbufferedDispatchRequested);
+ }
}
/**
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 863ee7b..37c18b5 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -200,7 +200,6 @@
import com.android.internal.view.RootViewSurfaceTaker;
import com.android.internal.view.SurfaceCallbackHelper;
-import java.io.FileDescriptor;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
@@ -7687,12 +7686,18 @@
mImeFocusController.dumpDebug(proto, IME_FOCUS_CONTROLLER);
}
- public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+ /**
+ * Dump information about this ViewRootImpl
+ * @param prefix the prefix that will be prepended to each line of the produced output
+ * @param writer the writer that will receive the resulting text
+ */
+ public void dump(String prefix, PrintWriter writer) {
String innerPrefix = prefix + " ";
writer.println(prefix + "ViewRoot:");
writer.println(innerPrefix + "mAdded=" + mAdded);
writer.println(innerPrefix + "mRemoved=" + mRemoved);
writer.println(innerPrefix + "mStopped=" + mStopped);
+ writer.println(innerPrefix + "mPausedForTransition=" + mPausedForTransition);
writer.println(innerPrefix + "mConsumeBatchedInputScheduled="
+ mConsumeBatchedInputScheduled);
writer.println(innerPrefix + "mConsumeBatchedInputImmediatelyScheduled="
@@ -7707,6 +7712,12 @@
writer.println(innerPrefix + "mIsAmbientMode=" + mIsAmbientMode);
writer.println(innerPrefix + "mUnbufferedInputSource="
+ Integer.toHexString(mUnbufferedInputSource));
+ if (mAttachInfo != null) {
+ writer.print(innerPrefix + "mAttachInfo= ");
+ mAttachInfo.dump(innerPrefix, writer);
+ } else {
+ writer.println(innerPrefix + "mAttachInfo=<null>");
+ }
mFirstInputStage.dump(innerPrefix, writer);
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index 673073e..149338c 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -126,6 +126,10 @@
}
}
+ protected void attachToParentSurface(SurfaceControl.Builder b) {
+ b.setParent(mRootSurface);
+ }
+
/**
* IWindowSession implementation.
*/
@@ -135,11 +139,11 @@
DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
InsetsState outInsetsState, InsetsSourceControl[] outActiveControls) {
final SurfaceControl.Builder b = new SurfaceControl.Builder(mSurfaceSession)
- .setParent(mRootSurface)
.setFormat(attrs.format)
.setBufferSize(getSurfaceWidth(attrs), getSurfaceHeight(attrs))
.setName(attrs.getTitle().toString())
.setCallsite("WindowlessWindowManager.addToDisplay");
+ attachToParentSurface(b);
final SurfaceControl sc = b.build();
if (((attrs.inputFeatures &
diff --git a/core/java/android/window/DisplayAreaOrganizer.java b/core/java/android/window/DisplayAreaOrganizer.java
index 1ac188c..8a1d4a0 100644
--- a/core/java/android/window/DisplayAreaOrganizer.java
+++ b/core/java/android/window/DisplayAreaOrganizer.java
@@ -24,6 +24,7 @@
import android.view.SurfaceControl;
import java.util.List;
+import java.util.concurrent.Executor;
/**
* Interface for WindowManager to delegate control of display areas.
@@ -113,6 +114,24 @@
*/
public static final int FEATURE_RUNTIME_TASK_CONTAINER_FIRST = FEATURE_VENDOR_LAST + 1;
+ // Callbacks WM Core are posted on this executor if it isn't null, otherwise direct calls are
+ // made on the incoming binder call.
+ private final Executor mExecutor;
+
+ /** @hide */
+ public DisplayAreaOrganizer(@NonNull Executor executor) {
+ mExecutor = executor;
+ }
+
+ /**
+ * Gets the executor to run callbacks on.
+ * @hide
+ */
+ @NonNull
+ public Executor getExecutor() {
+ return mExecutor;
+ }
+
/**
* Registers a DisplayAreaOrganizer to manage display areas for a given feature. A feature can
* not be registered by multiple organizers at the same time.
@@ -208,17 +227,20 @@
@Override
public void onDisplayAreaAppeared(@NonNull DisplayAreaInfo displayAreaInfo,
@NonNull SurfaceControl leash) {
- DisplayAreaOrganizer.this.onDisplayAreaAppeared(displayAreaInfo, leash);
+ mExecutor.execute(
+ () -> DisplayAreaOrganizer.this.onDisplayAreaAppeared(displayAreaInfo, leash));
}
@Override
public void onDisplayAreaVanished(@NonNull DisplayAreaInfo displayAreaInfo) {
- DisplayAreaOrganizer.this.onDisplayAreaVanished(displayAreaInfo);
+ mExecutor.execute(
+ () -> DisplayAreaOrganizer.this.onDisplayAreaVanished(displayAreaInfo));
}
@Override
public void onDisplayAreaInfoChanged(@NonNull DisplayAreaInfo displayAreaInfo) {
- DisplayAreaOrganizer.this.onDisplayAreaInfoChanged(displayAreaInfo);
+ mExecutor.execute(
+ () -> DisplayAreaOrganizer.this.onDisplayAreaInfoChanged(displayAreaInfo));
}
};
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index 777534e..13358daf 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -47,6 +47,21 @@
*/
public static final String NAS_MAX_SUGGESTIONS = "nas_max_suggestions";
+ /**
+ * Whether the Notification Assistant can change ranking.
+ */
+ public static final String ENABLE_NAS_RANKING = "enable_nas_ranking";
+
+ /**
+ * Whether the Notification Assistant can prioritize notification.
+ */
+ public static final String ENABLE_NAS_PRIORITIZER = "enable_nas_prioritizer";
+
+ /**
+ * Whether to enable feedback UI for Notification Assistant
+ */
+ public static final String ENABLE_NAS_FEEDBACK = "enable_nas_feedback";
+
// Flags related to screenshot intelligence
/**
diff --git a/core/java/com/android/internal/jank/FrameTracker.java b/core/java/com/android/internal/jank/FrameTracker.java
index 571ac1b..36514ff 100644
--- a/core/java/com/android/internal/jank/FrameTracker.java
+++ b/core/java/com/android/internal/jank/FrameTracker.java
@@ -51,6 +51,7 @@
private boolean mCancelled = false;
private int mTotalFramesCount = 0;
private int mMissedFramesCount = 0;
+ private int mSfMissedFramesCount = 0;
private long mMaxFrameTimeNanos = 0;
private Session mSession;
@@ -132,6 +133,8 @@
mRendererWrapper.removeObserver(mObserver);
// Log the frame stats as counters to make them easily accessible in traces.
+ Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#sfMissedFrames",
+ mSfMissedFramesCount);
Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#missedFrames",
mMissedFramesCount);
Trace.traceCounter(Trace.TRACE_TAG_APP, mSession.getName() + "#totalFrames",
@@ -141,7 +144,7 @@
// Trigger perfetto if necessary.
boolean overMissedFramesThreshold = mTraceThresholdMissedFrames != -1
- && mMissedFramesCount >= mTraceThresholdMissedFrames;
+ && (mMissedFramesCount + mSfMissedFramesCount) >= mTraceThresholdMissedFrames;
boolean overFrameTimeThreshold = mTraceThresholdFrameTimeMillis != -1
&& mMaxFrameTimeNanos >= mTraceThresholdFrameTimeMillis * NANOS_IN_MILLISECOND;
if (overMissedFramesThreshold || overFrameTimeThreshold) {
@@ -153,7 +156,8 @@
mSession.getStatsdInteractionType(),
mTotalFramesCount,
mMissedFramesCount,
- mMaxFrameTimeNanos);
+ mMaxFrameTimeNanos,
+ mSfMissedFramesCount);
}
return;
}
@@ -168,6 +172,7 @@
mMaxFrameTimeNanos = Math.max(totalDurationNanos, mMaxFrameTimeNanos);
}
+ // TODO(b/171049584): Also update mSfMissedFramesCount once the data is available.
if (isJankyFrame) {
mMissedFramesCount += 1;
}
diff --git a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
index e1d0a15..b97fdc9 100644
--- a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
+++ b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
@@ -23,7 +23,6 @@
import android.os.BatteryUsageStats;
import android.os.Bundle;
import android.os.SystemClock;
-import android.os.UidBatteryConsumer;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.SparseArray;
@@ -110,19 +109,18 @@
// TODO(b/174186358): read extra power component number from configuration
final int customPowerComponentCount = 0;
final int customTimeComponentCount = 0;
- final BatteryUsageStats.Builder batteryUsageStatsBuilder = new BatteryUsageStats.Builder()
- .setDischargePercentage(batteryStatsHelper.getStats().getDischargeAmount(0))
- .setConsumedPower(batteryStatsHelper.getTotalPower());
+ final BatteryUsageStats.Builder batteryUsageStatsBuilder =
+ new BatteryUsageStats.Builder(customPowerComponentCount, customTimeComponentCount)
+ .setDischargePercentage(batteryStatsHelper.getStats().getDischargeAmount(0))
+ .setConsumedPower(batteryStatsHelper.getTotalPower());
final List<BatterySipper> usageList = batteryStatsHelper.getUsageList();
for (int i = 0; i < usageList.size(); i++) {
final BatterySipper sipper = usageList.get(i);
if (sipper.drainType == BatterySipper.DrainType.APP) {
- batteryUsageStatsBuilder.addUidBatteryConsumerBuilder(
- new UidBatteryConsumer.Builder(customPowerComponentCount,
- customTimeComponentCount, sipper.uidObj)
- .setPackageWithHighestDrain(sipper.packageWithHighestDrain)
- .setConsumedPower(sipper.sumPower()));
+ batteryUsageStatsBuilder.getOrCreateUidBatteryConsumerBuilder(sipper.uidObj)
+ .setPackageWithHighestDrain(sipper.packageWithHighestDrain)
+ .setConsumedPower(sipper.sumPower());
}
}
diff --git a/core/java/com/android/internal/os/CpuPowerCalculator.java b/core/java/com/android/internal/os/CpuPowerCalculator.java
index 732d291..0f0839c 100644
--- a/core/java/com/android/internal/os/CpuPowerCalculator.java
+++ b/core/java/com/android/internal/os/CpuPowerCalculator.java
@@ -114,9 +114,10 @@
cpuTimeMs = cpuFgTimeMs;
}
- app.setConsumedPower(UidBatteryConsumer.POWER_COMPONENT_CPU, cpuPowerMah);
- app.setUsageDurationMillis(UidBatteryConsumer.TIME_COMPONENT_CPU, cpuTimeMs);
- app.setUsageDurationMillis(UidBatteryConsumer.TIME_COMPONENT_CPU_FOREGROUND, cpuFgTimeMs);
- app.setPackageWithHighestDrain(packageWithHighestDrain);
+ app.setConsumedPower(UidBatteryConsumer.POWER_COMPONENT_CPU, cpuPowerMah)
+ .setUsageDurationMillis(UidBatteryConsumer.TIME_COMPONENT_CPU, cpuTimeMs)
+ .setUsageDurationMillis(UidBatteryConsumer.TIME_COMPONENT_CPU_FOREGROUND,
+ cpuFgTimeMs)
+ .setPackageWithHighestDrain(packageWithHighestDrain);
}
}
diff --git a/core/java/com/android/internal/os/PhonePowerCalculator.java b/core/java/com/android/internal/os/PhonePowerCalculator.java
index b68899e..27f19c0 100644
--- a/core/java/com/android/internal/os/PhonePowerCalculator.java
+++ b/core/java/com/android/internal/os/PhonePowerCalculator.java
@@ -16,7 +16,10 @@
package com.android.internal.os;
+import android.os.BatteryConsumer;
import android.os.BatteryStats;
+import android.os.BatteryUsageStats;
+import android.os.SystemBatteryConsumer;
import android.os.UserHandle;
import android.util.SparseArray;
@@ -33,6 +36,19 @@
}
@Override
+ public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
+ long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) {
+ long phoneOnTimeMs = batteryStats.getPhoneOnTime(rawRealtimeUs, statsType) / 1000;
+ double phoneOnPower = mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ACTIVE)
+ * phoneOnTimeMs / (60 * 60 * 1000);
+ if (phoneOnPower != 0) {
+ builder.getOrCreateSystemBatteryConsumerBuilder(SystemBatteryConsumer.DRAIN_TYPE_PHONE)
+ .setConsumedPower(BatteryConsumer.POWER_COMPONENT_USAGE, phoneOnPower)
+ .setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_USAGE, phoneOnTimeMs);
+ }
+ }
+
+ @Override
public void calculate(List<BatterySipper> sippers, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) {
long phoneOnTimeMs = batteryStats.getPhoneOnTime(rawRealtimeUs, statsType) / 1000;
diff --git a/core/java/com/android/internal/os/PowerCalculator.java b/core/java/com/android/internal/os/PowerCalculator.java
index a57339b..23f96d9 100644
--- a/core/java/com/android/internal/os/PowerCalculator.java
+++ b/core/java/com/android/internal/os/PowerCalculator.java
@@ -76,10 +76,10 @@
*/
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) {
- final List<UidBatteryConsumer.Builder> uidBatteryConsumerBuilders =
+ final SparseArray<UidBatteryConsumer.Builder> uidBatteryConsumerBuilders =
builder.getUidBatteryConsumerBuilders();
for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {
- final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.get(i);
+ final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i);
calculateApp(app, app.getBatteryStatsUid(), rawRealtimeUs, rawUptimeUs, statsType);
}
}
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index f89e52d..141dc79 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -3140,6 +3140,7 @@
// On TVs, if the app doesn't implement search, we want to launch assist.
Bundle args = new Bundle();
args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, event.getDeviceId());
+ args.putLong(Intent.EXTRA_TIME, event.getEventTime());
((SearchManager) getContext().getSystemService(Context.SEARCH_SERVICE))
.launchAssist(args);
return true;
diff --git a/core/java/com/android/internal/view/OWNERS b/core/java/com/android/internal/view/OWNERS
index 99a7686..851d1f3 100644
--- a/core/java/com/android/internal/view/OWNERS
+++ b/core/java/com/android/internal/view/OWNERS
@@ -2,4 +2,19 @@
file:/core/java/android/view/OWNERS
-per-file *Input* = file:/services/core/java/com/android/server/inputmethod/OWNERS
\ No newline at end of file
+# Autofill
+per-file IInlineSuggestions*.aidl = file:/core/java/android/service/autofill/OWNERS
+per-file InlineSuggestions*.java = file:/core/java/android/service/autofill/OWNERS
+
+# Ime
+per-file *Input* = file:/services/core/java/com/android/server/inputmethod/OWNERS
+
+# Surface
+per-file *Surface* = file:/graphics/java/android/graphics/OWNERS
+per-file *Surface* = file:/services/core/java/com/android/server/wm/OWNERS
+
+# WindowManager
+per-file AppearanceRegion = file:/services/core/java/com/android/server/wm/OWNERS
+per-file BaseIWIndow.java = file:/services/core/java/com/android/server/wm/OWNERS
+per-file RotationPolicy.java = file:/services/core/java/com/android/server/wm/OWNERS
+per-file WindowManagerPolicyThread.java = file:/services/core/java/com/android/server/wm/OWNERS
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index 8048298..54b0340 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -20,11 +20,17 @@
per-file android_graphics_BLASTBufferQueue.cpp = file:/services/core/java/com/android/server/wm/OWNERS
per-file android_view_Surface* = file:/services/core/java/com/android/server/wm/OWNERS
+# Resources
+per-file android_content_res_* = file:/core/java/android/content/res/OWNERS
+per-file android_util_AssetManager* = file:/core/java/android/content/res/OWNERS
+per-file android_util_StringBlock* = file:/core/java/android/content/res/OWNERS
+per-file android_util_XmlBlock* = file:/core/java/android/content/res/OWNERS
+per-file com_android_internal_content_om_OverlayConfig* = file:/core/java/android/content/res/OWNERS
+
per-file *Zygote* = file:/ZYGOTE_OWNERS
per-file Android.bp = file:platform/build/soong:/OWNERS
per-file android_animation_* = file:/core/java/android/animation/OWNERS
per-file android_app_admin_* = file:/core/java/android/app/admin/OWNERS
-per-file android_content_res_* = file:/core/java/android/content/res/OWNERS
per-file android_graphics_* = file:/graphics/java/android/graphics/OWNERS
per-file android_hardware_Usb* = file:/services/usb/OWNERS
per-file android_hardware_display_* = file:/core/java/android/hardware/display/OWNERS
diff --git a/core/res/res/drawable/ic_feedback_alerted.xml b/core/res/res/drawable/ic_feedback_alerted.xml
new file mode 100644
index 0000000..550500a
--- /dev/null
+++ b/core/res/res/drawable/ic_feedback_alerted.xml
@@ -0,0 +1,30 @@
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="16dp"
+ android:height="16dp"
+ android:viewportWidth="16"
+ android:viewportHeight="16">
+ <path
+ android:pathData="M3.3333,5.6667H6V9.6667H10V5.6667H12.6667L8,1L3.3333,5.6667Z"
+ android:fillColor="#EA4335"/>
+ <path
+ android:strokeWidth="1"
+ android:pathData="M2.9798,8.9798L2.1262,9.8333H3.3333H5.5V13.3333V13.8333H6H10H10.5V13.3333V9.8333H12.6667H13.8738L13.0202,8.9798L8.3536,4.3131L8,3.9596L7.6465,4.3131L2.9798,8.9798Z"
+ android:fillColor="#EA4335"
+ android:strokeColor="#ffffff"/>
+</vector>
diff --git a/core/res/res/drawable/ic_feedback_downrank.xml b/core/res/res/drawable/ic_feedback_downrank.xml
new file mode 100644
index 0000000..c48505e
--- /dev/null
+++ b/core/res/res/drawable/ic_feedback_downrank.xml
@@ -0,0 +1,24 @@
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="16dp"
+ android:height="16dp"
+ android:viewportWidth="16"
+ android:viewportHeight="16">
+ <path
+ android:pathData="M12.6667,8H10V4H6V8H3.3333L8,12.6667L12.6667,8Z"
+ android:fillColor="#4285F4"/>
+</vector>
diff --git a/core/res/res/drawable/ic_feedback_silenced.xml b/core/res/res/drawable/ic_feedback_silenced.xml
new file mode 100644
index 0000000..aa221b2
--- /dev/null
+++ b/core/res/res/drawable/ic_feedback_silenced.xml
@@ -0,0 +1,34 @@
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="16dp"
+ android:height="16dp"
+ android:viewportWidth="16"
+ android:viewportHeight="16">
+ <group>
+ <clip-path
+ android:pathData="M16,16l-16,-0l-0,-16l16,-0z"/>
+ <path
+ android:pathData="M12.6667,10.3333H10V6.3333H6V10.3333H3.3333L8,15L12.6667,10.3333Z"
+ android:fillColor="#4285F4"/>
+ <path
+ android:strokeWidth="1"
+ android:pathData="M13.0202,7.0202L13.8738,6.1667H12.6667H10.5V2.6667L10.5,2.1667H10H6H5.5V2.6667V6.1667H3.3333H2.1262L2.9798,7.0202L7.6464,11.6869L8,12.0405L8.3535,11.6869L13.0202,7.0202Z"
+ android:fillColor="#4285F4"
+ android:strokeColor="#ffffff"/>
+ </group>
+</vector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_feedback_uprank.xml b/core/res/res/drawable/ic_feedback_uprank.xml
new file mode 100644
index 0000000..340780c
--- /dev/null
+++ b/core/res/res/drawable/ic_feedback_uprank.xml
@@ -0,0 +1,24 @@
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="16dp"
+ android:height="16dp"
+ android:viewportWidth="16"
+ android:viewportHeight="16">
+ <path
+ android:pathData="M3.3333,8H6V12H10V8H12.6667L8,3.3333L3.3333,8Z"
+ android:fillColor="#EA4335"/>
+</vector>
diff --git a/core/res/res/layout/notification_top_line_views.xml b/core/res/res/layout/notification_top_line_views.xml
index 60507ed..361b7a3 100644
--- a/core/res/res/layout/notification_top_line_views.xml
+++ b/core/res/res/layout/notification_top_line_views.xml
@@ -112,9 +112,8 @@
android:id="@+id/feedback"
android:layout_width="@dimen/notification_feedback_size"
android:layout_height="@dimen/notification_feedback_size"
- android:layout_marginStart="6dp"
- android:layout_marginEnd="6dp"
- android:baseline="10dp"
+ android:layout_marginStart="4dp"
+ android:layout_marginEnd="4dp"
android:scaleType="fitCenter"
android:src="@drawable/ic_feedback_indicator"
android:background="?android:selectableItemBackgroundBorderless"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index d41acda..9f92d72 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Laat die program toe om MMS-boodskappe te ontvang en te verwerk. Dit beteken dat die program boodskappe wat na jou toestel gestuur is kan monitor of uitvee, sonder dat jy dit gesien het."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Stuur seluitsendingboodskappe aan"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Laat die program toe om die seluitsendingmodule te bind om seluitsendingboodskappe aan te stuur wanneer hulle ontvang word. Seluitsendingwaarskuwings word in sommige liggings gelewer om jou oor noodsituasies te waarsku. Kwaadwillige programme kan met die werkverrigting of werking van jou toestel inmeng wanneer \'n noodseluitsending ontvang word."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Bestuur voortgaande oproepe"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Stel \'n program in staat om besonderhede oor voortgaande oproepe op jou toestel te sien, en hierdie oproepe te beheer."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"lees seluitsending-boodskappe"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Laat die program toe om seluitsending-boodskappe te lees wat deur jou toestel ontvang word. Seluitsending-waarskuwings word in sommige plekke afgelewer om jou van noodsituasies te waarsku. Kwaadwillige programme mag inmeng met die prestasie of die werking van jou toestel wanneer \'n noodgeval se seluitsending ontvang word."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lees ingetekende nuus"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index fe45f9e..dea4aa6 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"መተግበሪያው የኤም.ኤም.ኤስ. መልዕክቶችን እንዲያነብ እና እንዲያካሂድ ይፈቅዳል። ይህ ማለት መተግበሪያው ወደ መሳሪያህ የተላኩ መልዕክቶችን ላንተ ሳያሳይህ ሊቆጣጠር ወይም ሊሰርዝ ይችላል።"</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"የሕዋስ ስርጭት መልዕክቶችን ማስተላለፍ"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"የሕዋስ ስርጭት መልዕክቶች እንደመጡ ለማስተላለፍ መተግበሪያው ከሕዋስ ስርጭት ሞዱሉ ጋር እንዲተሳሰር ያስችለዋል። የሕዋስ ስርጭት ማንቂያዎች አስቸኳይ ሁኔታዎች ሲያጋጥሙ አንዳንድ አካባቢዎች ላይ የሚላኩ ናቸው። የሕዋስ ስርጭት ሲደርስ ተንኮል-አዘል መተግበሪያዎች በመሣሪያዎ አፈጻጸም ወይም አሰራር ላይ ጣልቃ ሊገቡ ይችላሉ።"</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"በመካሄድ ላይ ያሉ ጥሪዎችን አስተዳድር"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"አንድ መተግበሪያ በመካሄድ ላይ ስላሉ ጥሪዎች ዝርዝሮችን እንዲመለከት ያስችለዋል።"</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"የህዋስ ስርጭት መልዕክቶችን አንብብ"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"መሣሪያህ የህዋስ ስርጭት መልዕክቶች ሲቀበል መተግበሪያው እንዲያነበው ይፈቅድለታል። የህዋስ ስርጭት ማንቂያዎች አስቸኳይ ሁኔታዎች ሲያጋጥሙ አንዳንድ አካባቢዎች ላይ የሚላኩ ናቸው። የህዋስ ስርጭት ሲደርስ ተንኮል አዘል መተግበሪያዎች በመሣሪያህ አፈጻጸም ወይም አሰራር ላይ ጣልቃ ሊገቡ ይችላሉ።"</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"የምዝገባ መግቦች አንበብ"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 89c4fea..7ad157c 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -365,6 +365,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"للسماح للتطبيق بتلقي ومعالجة رسائل الوسائط المتعددة. وهذا يعني أنه يمكن للتطبيق مراقبة الرسائل التي يتم إرسالها لجهازك أو حذفها بدون عرضها لك."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"إعادة توجيه رسائل البث الخلوي"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"يسمح للتطبيق بالارتباط بوحدة البث الخلوي لإعادة توجيه رسائل البث الخلوي بينما يتم استقبالها. ويتم تسليم تنبيهات البث الخلوي في بعض المواقع لتحذيرك في حالات الطوارئ. ويمكن أن تؤثر التطبيقات الضارة على أداء الجهاز أو تشغيله عندما يتم تلقي بث خلوي في حالات الطوارئ."</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"قراءة رسائل بث الخلية"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"السماح للتطبيق بقراءة رسائل بث الخلية التي يتلقاها هذا الجهاز. يتم تسليم اشعارات بث الخلية في بعض المواقع لتحذيرك من حالات طارئة. يمكن أن تتداخل التطبيقات الضارة مع أداء أو تشغيل الجهاز عندما يتم تلقي بث خلية طارئ."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"قراءة الخلاصات المشتركة"</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 7dac9a2..e6ab01a 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -353,6 +353,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"এমএমএছ বার্তাবোৰ লাভ আৰু ইয়াৰ প্ৰক্ৰিয়া সম্পন্ন কৰিবলৈ এপক অনুমতি দিয়ে। ইয়াৰ অৰ্থ হৈছে এই এপে আপোনাৰ ডিভাইচলৈ প্ৰেৰণ কৰা বার্তাসমূহ আপোনাক নেদেখুৱাকৈয়ে পৰ্যবেক্ষণ আৰু মচিব পাৰে।"</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"চেল সম্প্ৰচাৰ বাৰ্তাসমূহ ফৰৱাৰ্ড কৰক"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"চেল সম্প্ৰচাৰ বাৰ্তাসমূহ লাভ কৰিলে সেইবোৰ ফৰৱাৰ্ড কৰিবলৈ এপ্টোক চেল সম্প্ৰচাৰ মডিউলটোৰ সৈতে সংযুক্ত হ\'বলৈ অনুমতি দিয়ে। আপোনাক জৰুৰীকালীন পৰিস্থিতিসমূহৰ বিষয়ে সতৰ্ক কৰিবলৈ কিছুমান অৱস্থানত চেল সম্প্ৰচাৰ সতৰ্কবাৰ্তাসমূহ ডেলিভাৰ কৰা হয়। কোনো জৰুৰীকালীন চেল সম্প্ৰচাৰ লাভ কৰিলে ক্ষতিকাৰক এপ্সমূহে আপোনাৰ ডিভাইচটোৰ কাৰ্যক্ষমতা অথবা কাৰ্যপ্ৰণালীত হস্তক্ষেপ কৰিব পাৰে।"</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"চেল সম্প্ৰচাৰৰ বার্তাবোৰ পঢ়ক"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"আপোনাৰ ডিভাইচে লাভ কৰা চেল সম্প্ৰচাৰৰ বার্তাবোৰ পঢ়িবলৈ এপক অনুমতি দিয়ে। আপোনাক জৰুৰীকালীন পৰিস্থিতিবোৰত সর্তক কৰিবলৈ চেল সম্প্ৰচাৰৰ বার্তাবোৰ প্ৰেৰণ কৰা হয়। জৰুৰীকালীন চেল সম্প্ৰচাৰ লাভ কৰাৰ সময়ত আপোনাৰ ডিভাইচৰ কাৰ্যদক্ষতা বা কাৰ্যপ্ৰণালীত ক্ষতিকাৰক এপবোৰে হস্তক্ষেপ কৰিব পাৰে।"</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"আপুনি সদস্যভুক্ত হোৱা ফীডসমূহ পঢ়ক"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 9fdc754..763bd2a 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -353,6 +353,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Tətbiqə MMS mesajlarını qəbul və emal üçün imkan verir. Bu o deməkdir ki, bu tətbiq sizə göstərmədən cihazınıza göndərilən mesajları silə bilər."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Şəbəkə yayımı mesajlarını yönləndirin"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Tətbiqə şəbəkə yayım mesajlarını əldə edildiyi anda yönləndirmək üçün şəbəkə yayımı moduluna bağlanmaq icazəsi verir. Şəbəkə yayımı bəzi məkanlarda olan fövqəladə hadisələrlə bağlı Sizi xəbərdar etmək üçün qəbul edilir. Zərərli tətbiqlər fövqəladə şəbəkə yayımı əldə edildiyi zaman cihazın performansına və əməliyyatına müdaxilə edə bilər."</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"mobil yayım mesajlarını oxuyur"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Tətbiqə telefonunuz tərəfindən alınmış yayım mesajlarını oxuma icazəsi verir. Telefon yayımı bəzi məkanlarda olan fövqəladə hadisələrlə bağlı sizi xəbərdar etmək üçün qəbul edilir. Zərərli tətbiqlər təcili mobil yayım qəbul edildiyi zaman telefonunun performansına və əməliyyatına müdaxilə edə bilər."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"abunə olunmuş xəbərləri oxuyur"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 3be770c..77220b2 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -356,6 +356,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Dozvoljava aplikaciji da prima i obrađuje MMS poruke. To znači da aplikacija može da nadgleda ili briše poruke koje se šalju uređaju, a da vam ih ne prikaže."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Prosleđivanje poruka za mobilne uređaje na lokalitetu"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Dozvoljava aplikaciji da se vezuje za modul poruka za mobilne uređaje na lokalitetu da bi prosleđivala poruke za mobilne uređaje na lokalitetu onako kako su primljene. Obaveštenja poruka za mobilne uređaje na lokalitetu se na nekim lokacijama primaju kao upozorenja na hitne slučajeve. Zlonamerne aplikacije mogu da utiču na učinak ili ometaju rad uređaja kada se primi poruka o hitnom slučaju za mobilne uređaje na lokalitetu."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Upravljanje odlaznim pozivima"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Omogućava aplikaciji da vidi detalje o odlaznim pozivima na uređaju i da kontroliše te pozive."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"čitanje poruka info servisa"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Omogućava aplikaciji da čita poruke info servisa koje uređaj prima. Upozorenja info servisa se na nekim lokacijama primaju kao upozorenja na hitne slučajeve. Zlonamerne aplikacije mogu da utiču na učinak ili ometaju funkcionisanje uređaja kada se primi poruka info servisa o hitnom slučaju."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"čitanje prijavljenih fidova"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index fc2849e..d092ad6 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -359,6 +359,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Дазваляе прыкладанням атрымліваць і апрацоўваць MMS-паведамленнi. Гэта значыць, што прыкладанне можа кантраляваць або выдаляць паведамленні, адпраўленыя на прыладу, не паказваючы іх вам."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Пераадрасоўваць паведамленні сотавай трансляцыі"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Дазваляе праграме звязвацца з модулем сотавай трансляцыі, каб пераадрасоўваць атрыманыя там паведамленні. Абвесткі сотавай трансляцыі дасылаюцца ў некаторыя месцы, каб папярэджваць вас пра надзвычайныя сітуацыі. Шкодныя праграмы могуць негатыўна ўплываць на прадукцыйнасць або працу прылады падчас атрымання паведамленняў сотавай трансляцыі пра надзвычайныя сітуацыі."</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"чытаць паведамленні базавай станцыі"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Дазваляе прыкладанню чытаць паведамленні базавай станцыі, атрыманыя прыладай. Папярэджанні базавай станцыі дасылаюцца ў некаторыя месцы, каб папярэдзіць вас аб надзвычайных сітуацыях. Шкоднасныя прыкладанні могуць уплываць на прадукцыйнасць ці працу прылады пры атрыманні паведамлення базавай станцыі аб надзвычайнай сітуацыі."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"чытаць падпісаныя каналы"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index a6321f5..c648398 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Разрешава на приложението да получава и обработва MMS съобщения. Това означава, че то може да наблюдава или изтрива изпратените до устройството ви, без да ви ги покаже."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Препращане на съобщения с клетъчно излъчване"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Разрешава на приложението да се обвърже с модула за клетъчно излъчване, за да препраща получените съобщения с клетъчно излъчване. Сигналите с клетъчно излъчване се получават на някои местоположения, за да ви предупредят за спешни случаи. Злонамерените приложения могат да възпрепятстват изпълнението или работата на устройството ви при получаване на такова спешно излъчване."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Управление на текущите обаждания"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Разрешава на приложението да вижда подробности за текущите обаждания на устройството ви и да ги управлява."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"четене на съобщения с клетъчно излъчване"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Разрешава на приложението да чете съобщения с клетъчно излъчване, получени от устройството ви. Сигналите с клетъчно излъчване се получават на някои местоположения, за да ви предупредят за спешни ситуации. Злонамерените приложения могат да възпрепятстват изпълнението или работата на устройството ви при получаване на такова спешно излъчване."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"четене на емисиите с абонамент"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index 269d2c7..6de7e2d 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -353,6 +353,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"অ্যাপ্লিকেশানটিকে MMS মেসেজ প্রাপ্ত করার এবং প্রক্রিয়া করার অনুমতি দেয়৷ এর মানে হল অ্যাপ্লিকেশানটি আপনার ডিভাইস থেকে পাঠানো মেসেজগুলিকে পর্যবেক্ষণ করতে পারে এবং মুছতে পারে সেগুলিকে আপনাকে না দেখিয়ে৷"</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"সেল ব্রডকাস্টের মাধ্যমে মেসেজ ফরওয়ার্ড করুন"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"সেল ব্রডকাস্ট মেসেজ পেলে এটি সেল ব্রডকাস্ট মডিউলের সাথে তা যুক্ত করে যাতে সেই মেসেজ ফরওয়ার্ড করা যায়। আপনাকে জরুরি অবস্থা সম্পর্কে সাবধান করতে কিছু লোকেশনে সেল ব্রডকাস্ট অ্যালার্ট মেসেজ ডেলিভার করা হয়। জরুরি সেল ব্রডকাস্ট পাওয়া গেলে ক্ষতিকারক অ্যাপ আপনার ডিভাইসের পারফর্ম্যান্স ও অপারেশনে বাধা সৃষ্টি করতে পারে।"</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"সেল সম্প্রচার মেসেজ পড়ুন"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"আপনার ডিভাইস দ্বারা প্রাপ্ত সেল সম্প্রচার পড়তে অ্যাপ্লিকেশানটিকে অনুমতি দেয়৷ কয়েকটি স্থানে আপনাকে জরুরি অবস্থার জন্য সতর্ক করতে জরুরি সতর্কতাগুলি বিতরণ করা হয়৷ যখন একটি জরুরি সেল সম্প্রচার প্রাপ্ত হয় তখন ক্ষতিকারক অ্যাপ্লিকেশানগুলি আপনার ডিভাইসের কার্য সম্পাদনা বা কার্যকলাপে প্রতিবন্ধকতার সৃষ্টি করতে পারে৷"</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"গ্রাহক হিসেবে নেওয়া ফিডগুলি পড়ে"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 6ecad70..53a03a7 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -356,6 +356,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Omogućava aplikaciji prijem i obradu MMS poruka. Ovo znači da aplikacija može pratiti ili brisati poruke poslane na vaš uređaj, a da vam ih pritom ne prikazuje."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Prosljeđivanje poruka info servisa"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Dopušta aplikaciji da se veže za modul info servisa kako bi prosljeđivala poruke info servisa. Upozorenja koja emitira info servis se isporučuju na nekim lokacijama kako bi vas upozorila na vanredne situacije. Zlonamjerne aplikacije mogu ometati performanse ili rad vašeg uređaja kada primite informacije o vanrednoj situaciji od info servisa."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Upravljanje pozivima u toku"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Omogućava aplikaciji da vidi detalje o pozivima u toku na vašem uređaju i da ih kontrolira."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"čitanje poruka info servisa"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Omogućava aplikaciji čitanje poruka info servisa koje je primio vaš uređaj. Upozorenja koja emitira info servis se isporučuju na nekim lokacijama kako bi vas upozorila na vanredne situacije. Zlonamjerne aplikacije mogu ometati performanse ili rad vašeg uređaja kada primite informaciju o vanrednoj situaciji od info servisa."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"čitanje sadržaja na koje ste pretplaćeni"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index c72ca74..5ce2ff2 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Permet que l\'aplicació rebi i processi missatges MMS. Això vol dir que l\'aplicació pot controlar o suprimir missatges que s\'han enviat al teu dispositiu sense mostrar-te\'ls."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Reenviar els missatges de difusió mòbil"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Permet que l\'aplicació es vinculi al mòdul de difusió mòbil per poder reenviar els missatges de difusió mòbil a mesura que es reben. Les alertes de difusió mòbil s\'entreguen en algunes ubicacions per alertar de situacions d\'emergència. És possible que les aplicacions malicioses interfereixin en el rendiment o en el funcionament del dispositiu quan es rebi una difusió mòbil d\'emergència."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Gestiona les trucades en curs"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Permet que una aplicació vegi els detalls sobre les trucades en curs al dispositiu i que controli aquestes trucades."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"llegir missatges de difusió mòbil"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Permet que l\'aplicació llegeixi missatges de difusió mòbil rebuts pel dispositiu. Les alertes de difusió mòbil s\'entreguen en algunes ubicacions per alertar de situacions d\'emergència. És possible que les aplicacions malicioses interfereixin en el rendiment o en el funcionament del dispositiu quan es rep una difusió mòbil d\'emergència."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"llegir els feeds als quals esteu subscrit"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 8174a6e..6840e2d 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -359,6 +359,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Umožňuje aplikaci přijmout a zpracovat zprávy MMS. Znamená to, že aplikace může sledovat zprávy odeslané do vašeho zařízení nebo je smazat, aniž by se vám zobrazily."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Přesměrování zpráv informačních služeb"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Umožňuje aplikaci vytvořit vazbu s modulem informačních služeb za účelem přesměrovávání přijatých zpráv informačních služeb. Výstražná upozornění informačních služeb jsou v některých oblastech odesílána za účelem varování před výjimečnými událostmi. Škodlivé aplikace mohou narušit výkon či provoz vašeho zařízení během přijímání zpráv informačních služeb."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Správa probíhajících hovorů"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Umožňuje aplikaci zobrazit podrobnosti o probíhajících hovorech v zařízení a tyto hovory ovládat."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"čtení zpráv informačních služeb"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Umožňuje aplikaci číst zprávy informačních služeb přijaté ve vašem zařízení. Výstražná upozornění informačních služeb jsou v některých oblastech odesílána za účelem varování před výjimečnými událostmi. Škodlivé aplikace mohou narušit výkon či provoz vašeho zařízení během přijímání zpráv informačních služeb."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"čtení zdrojů přihlášených k odběru"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 0bd9657..d7ff335 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -353,6 +353,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Tillader, at appen kan modtage og behandle mms-beskeder. Det betyder, at appen kan overvåge eller slette de beskeder, der sendes til din enhed, uden at vise dem til dig."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Videresend Cell Broadcast-meddelelser"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Tillader, at appen bindes til Cell Broadcast-modulet, så Cell Broadcast-meddelelser kan videresendes, når de modtages. I nogle områder sendes der Cell Broadcast-underretninger for at advare dig om nødsituationer. Ondsindede apps kan forstyrre effektiviteten eller driften af din enhed, når den modtager en Cell Broadcast-meddelelse om en nødsituation."</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"læse Cell Broadcast-meddelelser"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Tillader, at appen læser Cell Broadcast-underretninger, der modtages af din enhed. I nogle områder sendes der Cell Broadcast-underretninger for at advare om nødsituationer. Ondsindede apps kan forstyrre ydelsen eller driften af din enhed, når der modtages en Cell Broadcast-meddelelse om en nødsituation."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"læse feeds, jeg abonnerer på"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index b51ce5d..41f4f8a 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -353,6 +353,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Ermöglicht der App, MMS zu empfangen und zu verarbeiten. Das bedeutet, dass die App an dein Gerät gesendete Nachrichten überwachen und löschen kann, ohne sie dir anzuzeigen."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Cell-Broadcast-Nachrichten weiterleiten"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Ermöglicht der App, sich mit dem Cell-Broadcast-Modul zu verbinden, um empfangene Cell-Broadcast-Nachrichten weiterzuleiten. Cell-Broadcast-Benachrichtigungen können in einigen Ländern oder Regionen gesendet werden, um dich bei Notfallsituationen zu warnen. Schädliche Apps können die Leistung oder den Betrieb deines Geräts beeinträchtigen, wenn eine Cell-Broadcast-Notfallbenachrichtigung eingeht."</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"Cell Broadcast-Nachrichten lesen"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Ermöglicht der App, von deinem Gerät empfangene Cell Broadcast-Nachrichten zu lesen. Cell Broadcast-Benachrichtigungen werden an einigen Standorten gesendet, um dich über Notfallsituationen zu informieren. Schädliche Apps können die Leistung oder den Betrieb deines Geräts beeinträchtigen, wenn eine Cell Broadcast-Notfallbenachrichtigung eingeht."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"Abonnierte Feeds lesen"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index a794e48..aa2ee69 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Επιτρέπει στην εφαρμογή τη λήψη και την επεξεργασία μηνυμάτων MMS. Αυτό σημαίνει ότι η εφαρμογή θα μπορούσε να παρακολουθήσει ή να διαγράψει τα μηνύματα που αποστέλλονται στη συσκευή σας χωρίς αυτά να εμφανιστούν σε εσάς."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Προώθηση μηνυμάτων εκπομπής κινητής τηλεφωνίας"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Επιτρέπει στην εφαρμογή να συνδέεται στη λειτουργική μονάδα εκπομπής κινητής τηλεφωνίας, προκειμένου να προωθεί τα μηνύματα εκπομπής κινητής τηλεφωνίας κατά τη λήψη τους. Οι ειδοποιήσεις εκπομπής κινητής τηλεφωνίας προβάλλονται σε ορισμένες τοποθεσίες, για να σας προειδοποιήσουν σχετικά με καταστάσεις έκτακτης ανάγκης. Οι κακόβουλες εφαρμογές μπορεί να επηρεάσουν την απόδοση ή τη λειτουργία της συσκευής σας κατά τη λήψη μιας εκπομπής κινητής τηλεφωνίας έκτακτης ανάγκης."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Διαχείριση κλήσεων σε εξέλιξη"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Επιτρέπει σε μια εφαρμογή να βλέπει λεπτομέρειες σχετικά με τις κλήσεις σε εξέλιξη στη συσκευή σας και να τις ελέγχει."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"διαβάζει μηνύματα που έχουν μεταδοθεί μέσω κινητού τηλεφώνου"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Επιτρέπει στην εφαρμογή την ανάγνωση μηνυμάτων που έχουν μεταδοθεί μέσω κινητού τηλεφώνου και έχουν ληφθεί από τη συσκευή σας. Ειδοποιήσεις που μεταδίδονται μέσω κινητού παραδίδονται σε ορισμένες τοποθεσίες για να σας προειδοποιήσουν για καταστάσεις έκτακτης ανάγκης. Κακόβουλες εφαρμογές ενδέχεται να παρεμποδίσουν την απόδοση ή τη λειτουργία της συσκευής σας κατά τη λήψη μετάδοσης μέσω κινητού σχετικά με μια επείγουσα κατάσταση."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"διαβάζει ροές δεδομένων στις οποίες έχετε εγγραφεί"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 74b835e..de5dba2 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Allows the app to receive and process MMS messages. This means that the app could monitor or delete messages sent to your device without showing them to you."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Forward cell broadcast messages"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Allows the app to bind to the cell broadcast module in order to forward cell broadcast messages as they are received. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency cell broadcast is received."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Manage ongoing calls"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Allows an app to see details about ongoing calls on your device and to control these calls."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"read mobile broadcast messages"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Allows the app to read mobile broadcast messages received by your device. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency mobile broadcast is received."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"read subscribed feeds"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 8f8972c..7bd62aa 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Allows the app to receive and process MMS messages. This means that the app could monitor or delete messages sent to your device without showing them to you."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Forward cell broadcast messages"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Allows the app to bind to the cell broadcast module in order to forward cell broadcast messages as they are received. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency cell broadcast is received."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Manage ongoing calls"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Allows an app to see details about ongoing calls on your device and to control these calls."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"read mobile broadcast messages"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Allows the app to read mobile broadcast messages received by your device. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency mobile broadcast is received."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"read subscribed feeds"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 2421e2a..b21b67d 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Allows the app to receive and process MMS messages. This means that the app could monitor or delete messages sent to your device without showing them to you."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Forward cell broadcast messages"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Allows the app to bind to the cell broadcast module in order to forward cell broadcast messages as they are received. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency cell broadcast is received."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Manage ongoing calls"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Allows an app to see details about ongoing calls on your device and to control these calls."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"read mobile broadcast messages"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Allows the app to read mobile broadcast messages received by your device. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency mobile broadcast is received."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"read subscribed feeds"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index dd7b151..69acec6 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Allows the app to receive and process MMS messages. This means that the app could monitor or delete messages sent to your device without showing them to you."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Forward cell broadcast messages"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Allows the app to bind to the cell broadcast module in order to forward cell broadcast messages as they are received. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency cell broadcast is received."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Manage ongoing calls"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Allows an app to see details about ongoing calls on your device and to control these calls."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"read mobile broadcast messages"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Allows the app to read mobile broadcast messages received by your device. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency mobile broadcast is received."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"read subscribed feeds"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 0e14345..ae57206 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Allows the app to receive and process MMS messages. This means the app could monitor or delete messages sent to your device without showing them to you."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Forward cell broadcast messages"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Allows the app to bind to the cell broadcast module in order to forward cell broadcast messages as they are received. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency cell broadcast is received."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Manage ongoing calls"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Allows an app to see details about ongoing calls on your device and to control these calls."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"read cell broadcast messages"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Allows the app to read cell broadcast messages received by your device. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency cell broadcast is received."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"read subscribed feeds"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 780e481..f5bd810 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Permite que la aplicación reciba y procese mensajes MMS, lo que significa que podría controlar o eliminar mensajes enviados al dispositivo sin mostrártelos."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Reenviar mensajes de emisión móvil"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Permite que la app se vincule al módulo de emisión móvil para reenviar los mensajes de este tipo a medida que se reciben. En algunas ubicaciones, se envían alertas de emisión móvil para advertirte en situaciones de emergencia. Es posible que las apps maliciosas interfieran con el rendimiento o el funcionamiento de tu dispositivo cuando recibes una emisión móvil de emergencia."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Administrar llamadas en curso"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Permite que una app vea detalles sobre las llamadas en curso del dispositivo y las controle."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"Leer mensajes de difusión móvil"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Permite a la aplicación leer los mensajes de difusión móvil que recibe tu dispositivo. En algunas ubicaciones, las alertas de difusión móvil se envían para informar situaciones de emergencia. Las aplicaciones maliciosas pueden afectar el rendimiento o funcionamiento de tu dispositivo cuando se recibe un un mensaje de difusión móvil de emergencia."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"leer canales suscritos"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 3c6b9e2..e234efbf 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Permite que la aplicación reciba y procese mensajes MMS, lo que significa que podría utilizar este permiso para controlar o eliminar mensajes enviados al dispositivo sin mostrárselos al usuario."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Reenviar mensajes de difusión móvil"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Permite que la aplicación se vincule con el módulo de difusión móvil para reenviar los mensajes de ese tipo en cuanto se reciben. En ciertas ubicaciones se envían alertas de difusión móvil para avisar de situaciones de emergencia. Cuando se recibe una alerta de difusión móvil de emergencia, ciertas aplicaciones malintencionadas podrían interferir en el rendimiento o en el funcionamiento del dispositivo."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Gestionar llamadas en curso"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Permite que una aplicación consulte datos de llamadas que estén en curso en tu dispositivo y controle esas llamadas."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"leer mensajes de difusión móvil"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Permite que la aplicación lea mensajes de difusión móvil que haya recibido el dispositivo. Las alertas de difusión móvil se envían en algunas ubicaciones para avisar de situaciones de emergencia. Es posible que las aplicaciones malintencionadas interfieran en el rendimiento o en el funcionamiento del dispositivo si se recibe una alerta de difusión móvil de emergencia."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"leer feeds a los que está suscrito el usuario"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index 152a35e..543b5a1 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Võimaldab rakendusel vastu võtta ja töödelda multimeediumsõnumeid. See tähendab, et rakendus võib jälgida või kustutada teie seadmele saadetud sõnumeid neid teile näitamata."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Kärjeteadete edasisaatmine"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Võimaldab rakendusel luua ühenduse kärjeteadete mooduliga, et saabunud kärjeteateid edasi saata. Kärjeteateid edastatakse mõnes asukohas eriolukorrast teavitamiseks. Pahatahtlikud rakendused võivad seadme toimivust või tööd eriolukorra kärjeteate vastuvõtmisel segada."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Käimasolevate kõnede haldamine"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Võimaldab rakendusel näha teie seadmes käimasolevate kõnede üksikasju ja neid kõnesid hallata."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"mobiilsidesõnumite lugemine"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Võimaldab rakendusel lugeda seadme vastu võetud mobiilsidesõnumeid. Mobiilsidemärguandeid edastatakse mõnes asukohas eriolukorrast teavitamiseks. Pahatahtlikud rakendused võivad segada seadme toimivust või tööd eriolukorra sõnumi vastuvõtmisel."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"loe tellitud kanaleid"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 4fa4d06..c552e8f 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"MMS mezuak jasotzeko eta prozesatzeko baimena ematen die aplikazioei. Horrela, aplikazioak gailura bidalitako mezuak kontrola eta ezaba ditzake zuri erakutsi gabe."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"desbideratu sare mugikor bidezko igorpen-mezuak"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Sare mugikor bidezko igorpen-modulura lotzeko baimena ematen dio aplikazioari, sare mugikor bidezko igorpen-mezuak jaso ahala desbideratu ahal izateko. Sare mugikor bidezko igorpen-alertak kokapen batzuetan entregatzen dira larrialdi-egoeren berri emateko. Sare mugikor bidezko larrialdi-igorpenak jasotzean, aplikazio gaiztoek gailuaren errendimenduari edota funtzionamenduari eragin diezaiokete."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Kudeatu abian dauden deiak"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Gailuak jasotzen dituen deiei buruzko xehetasunak ikusteko eta dei horiek kontrolatzeko baimena ematen die aplikazioei."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"irakurri sare mugikor bidezko igorpen-mezuak"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Gailuak jasotako sare mugikor bidezko igorpenen mezuak irakurtzeko baimena ematen die aplikazioei. Sare mugikor bidezko igorpen-alertak kokapen batzuetan ematen dira larrialdi-egoeren berri emateko. Aplikazio gaiztoek gailuaren errendimendua edo funtzionamendua oztopa dezakete larrialdi-igorpen horietako bat jasotzen denean."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"irakurri harpidetutako jarioak"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 9efe16b..3d523fd 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"به برنامه اجازه میدهد پیامهای فراپیام را دریافت و پردازش کند. این یعنی برنامه میتواند پیامهای ارسالی به دستگاه شما را بدون نمایش آنها به شما حذف یا کنترل کند."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"بازارسال پیامهای پخش سلولی"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"به برنامه امکان میدهد به مدول پخش سلولی متصل شود تا پیامهای پخش سلولی را به محض دریافت بازارسال کند. هشدارهای پخش سلولی در برخی از موقعیتهای مکانی ارسال میشوند تا موقعیتهای اضطراری را به شما اعلام کنند. وقتی پخش سلولی دریافت میشود، ممکن است برنامههای مخرب در عملکرد یا کارکرد دستگاه شما اختلال ایجاد کنند."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"مدیریت تماسهای درحال انجام"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"به برنامه اجازه میدهد جزئیات تماسهای درحال انجام در دستگاه را ببیند و این تماسها را کنترل کند."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"خواندن پیامهای پخش سلولی"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"به برنامه اجازه میدهد پیامهای پخش سلولی دستگاه شما را بخواند. هشدارهای پخش سلولی در برخی از موقعیتهای مکانی تحویل داده میشوند تا موقعیتهای اضطراری را به شما اعلام کنند. وقتی پخش سلولی دریافت میشود، ممکن است برنامههای مخرب در عملکرد یا کارکرد دستگاه شما اختلال ایجاد کنند."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"خواندن فیدهای مشترک"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 80c8ebe..81546d9 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Antaa sovelluksen vastaanottaa ja käsitellä multimediaviestejä. Sovellus voi valvoa tai poistaa laitteeseesi lähetettyjä viestejä näyttämättä niitä sinulle."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Lähetä solulähetysviestit edelleen"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Sallii sovelluksen sitoutua solulähetysmoduuliin lähettääkseen solulähetysviestejä edelleen sitä mukaa kun ne saapuvat. Solulähetysilmoitusten avulla ilmoitetaan hätätilanteista joissakin paikoissa. Haitalliset sovellukset voivat häiritä laitteen toimintaa laitteen vastaanottaessa hätätilanteeseen liittyvän solulähetysviestin."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Ylläpidä käynnissä olevia puheluita"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Sovellus voi nähdä tietoja laitteella käynnissä olevista puheluista ja ohjata näitä puheluita."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"lue tiedotteita"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Antaa sovelluksen lukea laitteesi vastaanottamia tiedotteita. Tiedotteiden avulla ilmoitetaan hätätilanteista joissakin paikoissa. Haitalliset sovellukset voivat häiritä laitteen toimintaa laitteen vastaanottaessa hätätiedotteen."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lukea tilattuja syötteitä"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 8bc6d37..cdfa15d 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -356,6 +356,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Permet à l\'application de recevoir et de traiter les messages multimédias. Cette autorisation lui donne la possibilité de surveiller ou de supprimer les messages envoyés à votre appareil sans vous les montrer."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Transférer les messages de diffusion cellulaire"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Permet à l\'application d\'établir un lien avec le module de diffusion cellulaire afin de transférer les messages de diffusion cellulaire à mesure de leur réception. Dans certaines régions, des alertes de diffusion cellulaire sont envoyées afin de vous avertir de situations d\'urgence. Des applications malveillantes peuvent interférer avec les performances ou le fonctionnement de votre appareil lors de la réception d\'une alerte d\'urgence par diffusion cellulaire."</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"lire les messages de diffusion cellulaire"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Permet à l\'application de lire les messages de diffusion cellulaire que votre appareil reçoit. Dans certaines zones géographiques, des alertes vous sont envoyées afin de vous prévenir en cas de situation d\'urgence. Des applications malveillantes peuvent venir perturber les performances ou le fonctionnement de votre appareil lors de la réception d\'un message de diffusion cellulaire."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lire les flux auxquels vous êtes abonné"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 7d5e10b..9e0f60c 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -356,6 +356,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Permet à l\'application de recevoir et de traiter les MMS. Cette autorisation lui donne la possibilité de surveiller ou supprimer les messages envoyés à votre appareil sans vous les montrer."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Transférer les messages reçus via un canal de diffusion cellulaire"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Autorise l\'application à établir une connexion avec le module de diffusion cellulaire afin de transférer les messages reçus via un canal de diffusion cellulaire. Des alertes de diffusion cellulaire sont générées dans certaines régions afin de vous avertir de situations d\'urgence. Des applications malveillantes peuvent interférer avec les performances ou le fonctionnement de votre appareil lors de la réception d\'une alerte d\'urgence par diffusion cellulaire."</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"lire les messages reçus via un canal de diffusion cellulaire"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Permet à l\'application de lire les messages que votre appareil reçoit via un canal de diffusion cellulaire. Dans certaines zones géographiques, des alertes vous sont envoyées afin de vous prévenir en cas de situation d\'urgence. Les applications malveillantes peuvent venir perturber les performances ou le fonctionnement de votre appareil lorsqu\'un message est reçu via un canal de diffusion cellulaire."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lire les flux auxquels vous êtes abonné"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index c1d8703..423b97f 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -353,6 +353,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Permite á aplicación recibir e procesar mensaxes MMS. Isto significa que a aplicación pode supervisar ou eliminar mensaxes enviadas ao teu dispositivo sen mostrarchas."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Reenviar mensaxes de difusión móbil"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Permite que a aplicación se vincule ao módulo de difusión móbil para reenviar as mensaxes deste tipo segundo se reciban. As alertas de difusión móbil envíanse nalgunhas localizacións para avisar de situacións de emerxencia. As aplicacións maliciosas poden interferir no rendemento ou funcionamento do teu dispositivo cando se reciba unha difusión móbil de emerxencia."</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"ler mensaxes de difusión móbil"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Permite á aplicación ler mensaxes de difusión móbil recibidas polo teu dispositivo. As alertas de difusión móbil envíanse nalgunhas localizacións para avisar de situacións de emerxencia. É posible que aplicacións maliciosas afecten ao rendemento ou funcionamento do teu dispositivo cando se recibe unha difusión móbil de emerxencia."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"ler feeds subscritos"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 794b7a7..14347ee 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -353,6 +353,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"ઍપ્લિકેશનને MMS સંદેશા પ્રાપ્ત કરવાની અને તેના પર પ્રક્રિયા કરવાની મંજૂરી આપે છે. આનો અર્થ એ કે ઍપ્લિકેશન તમને દર્શાવ્યા વિના તમારા ઉપકરણ પર મોકલેલ સંદેશાઓનું નિરીક્ષણ કરી શકે છે અથવા કાઢી નાખી શકે છે."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"સેલ બ્રોડકાસ્ટ સંદેશા ફૉરવર્ડ કરો"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"સેલ બ્રોડકાસ્ટ સંદેશા પ્રાપ્ત થાય કે તરત ફૉરવર્ડ કરવા માટે સેલ બ્રોડકાસ્ટ મૉડ્યૂલ સાથે પ્રતિબદ્ધ થવા બાબતે ઍપને મંજૂરી આપે છે. તમને કટોકટીની પરિસ્થિતિની ચેતવણી આપવા માટે સેલ બ્રોડકાસ્ટ અલર્ટ અમુક સ્થાનોમાં ડિલિવર કરવામાં આવે છે. કટોકટી અંગેનો સેલ બ્રોડકાસ્ટ પ્રાપ્ત થાય, ત્યારે દુર્ભાવનાપૂર્ણ ઍપ તમારા ડિવાઇસના કાર્યપ્રદર્શન અથવા ઑપરેશનમાં વિક્ષેપ પાડે તેમ બની શકે છે."</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"સેલ બ્રોડકાસ્ટ સંદેશા વાંચો"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"એપ્લિકેશનને તમારા ઉપકરણ દ્વારા પ્રાપ્ત થયેલ સેલ બ્રોડકાસ્ટ સંદેશાને વાંચવાની મંજૂરી આપે છે. સેલ બ્રોડકાસ્ટ ચેતવણીઓ તમને કટોકટીની સ્થિતિઓ અંગે ચેતવવા માટે કેટલાક સ્થાનોમાં વિતરિત થાય છે. જ્યારે કટોકટીનો સેલ બ્રોડકાસ્ટ પ્રાપ્ત થાય ત્યારે દુર્ભાવનાપૂર્ણ ઍપ્લિકેશનો તમારા ઉપકરણના પ્રદર્શન અથવા ઓપરેશનમાં હસ્તક્ષેપ કરી શકે છે."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"સબ્સ્ક્રાઇબ કરેલ ફીડ્સ વાંચો"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index dc44fba..e63e502 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"ऐप को मल्टीमीडिया मैसेज (एमएमएस) को पाने और उन पर कार्रवाई करने देता है. इसका मतलब है कि ऐप आपके डिवाइस पर भेजे गए मैसेज की निगरानी आपको दिखाए बिना कर सकता है और उन्हें हटा सकता है."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"सेल ब्रॉडकास्ट (CBC) मैसेज दूसरे नंबर पर भेजें"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"सेल ब्रॉडकास्ट (CBC) मैसेज आते ही उसे दूसरे नंबर पर भेजने के लिए, ऐप्लिकेशन को सेल ब्रॉडकास्ट (CBC) मॉड्यूल पर बाइंड करने की अनुमति देता है. कुछ जगहों में सेल ब्रॉडकास्ट (CBC) अलर्ट आपातकालीन स्थितियों के बारे में चेतावनी देने के लिए भेजा जाता है. नुकसान पहुंचाने वाले ऐप्लिकेशन, आपातकाल में सेल ब्रॉडकास्ट (CBC) मैसेज मिलने पर आपके डिवाइस के काम करते समय या इसके परफ़ॉर्मेंस में रुकावट पैदा कर सकते हैं."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"चल रहे कॉल प्रबंधित करें"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"इससे, ऐप्लिकेशन को आपके डिवाइस पर चल रहे कॉल की जानकारी देखने और उन्हें कंट्रोल करने की अनुमति मिलती है."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"सेल ब्रॉडकास्ट (CBC) मैसेज पढ़ें"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"ऐप को, वो सेल ब्रॉडकास्ट (CBC) मैसेज पढ़ने देता है जो आपके डिवाइस को मिले हैं. सेल ब्रॉडकास्ट (CBC) अलर्ट कुछ स्थानों (लोकेशन) पर आपको आपातकालीन स्थितियों की चेतावनी देने के लिए दिए जाते हैं. आपातकालीन सेल ब्रॉडकास्ट (CBC) मिलने पर, धोखा देने वाले ऐप आपके डिवाइस के परफ़ॉर्मेंस या कार्यवाही में दखल दे सकते हैं."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"सदस्यता वाली फ़ीड पढ़ें"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index deaac3f..45c89a6 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -356,6 +356,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Aplikaciji omogućuje primanje i obradu MMS poruka. To znači da aplikacija može nadzirati ili izbrisati poruke poslane na vaš uređaj, a da vam ih ne prikaže."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Prosljeđivanje poruka emitiranja na mobitele"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Omogućuje aplikaciji da se poveže s modulom za emitiranje na mobitele kako bi prosljeđivala poruke koje se emitiraju na mobitele po njihovom primitku. Upozorenja značajke emitiranja na mobitele dostavljaju se na nekim lokacijama kako bi upozorila korisnike na hitne situacije. Zlonamjerne aplikacije mogu ometati izvršavanje ili rad vašeg uređaja kada stigne hitno emitiranje na mobitele."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Upravljanje tekućim pozivima"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Omogućuje aplikaciji pregled pojedinosti o tekućim pozivima na uređaju i upravljanje tim pozivima."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"čitaj poruke koje se emitiraju unutar mobilne mreže"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Omogućuje aplikaciji čitanje poruka emitiranih unutar mobilne mreže koje prima vaš uređaj. Upozorenja koja se emitiraju na području mobilne mreže dostavljaju se na nekim lokacijama kako bi upozorila korisnike na hitne situacije. Zlonamjerne aplikacije mogu ometati izvršavanje ili rad vašeg uređaja kada stigne hitno upozorenje koje se emitira unutar mobilne mreže."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"čitanje pretplaćenih feedova"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index c408395..ec0715b 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -353,6 +353,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Lehetővé teszi az alkalmazás számára, hogy MMS-eket fogadjon és dolgozzon fel. Ez azt jelenti, hogy az alkalmazás megfigyelheti vagy törölheti a beérkező üzeneteket anélkül, hogy Ön látná azokat."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Cellán belüli üzenetek továbbítása"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Az alkalmazás összekapcsolódhat a cellán belüli üzenetszórás moduljával, hogy az érkezésükkor továbbítani tudja a cellán belüli üzeneteket. Bizonyos helyeken figyelmeztető üzeneteket kaphat a cellán belül a vészhelyzetekről. A rosszindulatú alkalmazások vészhelyzeti cellaüzenet érkezésekor befolyásolhatják az eszköz teljesítményét és működését."</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"cellán belüli üzenetek olvasása"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Lehetővé teszi az alkalmazás számára az eszközre érkező cellán belüli üzenetek olvasását. Bizonyos helyeken figyelmeztető üzeneteket kaphat a cellán belül a vészhelyzetekről. A rosszindulatú alkalmazások befolyásolhatják az eszköz teljesítményét vagy működését vészhelyzeti cellaüzenet érkezésekor."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"feliratkozott hírcsatornák olvasása"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index b1db764..b28e5fd 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Թույլ է տալիս հավելվածին ստանալ և մշակել MMS հաղորդագրությունները: Սա նշանակում է, որ հավելվածը կարող է ստուգել կամ ջնջել ձեր սարքին ուղարկված հաղորդագրությունները` առանց դրանք ձեզ ցուցադրելու:"</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Բջջային հեռարձակման հաղորդագրությունների վերահասցեավորում"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Թույլ է տալիս հավելվածին կապ հաստատել բջջային հեռարձակման մոդուլի հետ՝ բնակչությանը ծանուցող հաղորդագրությունները վերահասցեավորելու համար։ Որոշ երկրներում այս հաղորդագրություններն օգտագործվում են բնակչությանը արտակարգ իրավիճակների մասին զգուշացնելու համար: Վնասարար հավելվածները կարող են խանգարել ձեր սարքի աշխատանքին, որին ուղարկվում են այս հաղորդագրությունները:"</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Ընթացիկ զանգերի կառավարում"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Թույլ է տալիս հավելվածին ձեր սարքում տեսնել ընթացիկ զանգերի մասին տեղեկությունները և կառավարել այդ զանգերը։"</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"կարդալ բջջային զեկուցվող հաղորդագրությունները"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Թույլ է տալիս հավելվածին կարդալ ձեր սարքի կողմից ստացված բջջային հեռարձակվող հաղորդագրությունները: Բջջային հեռարձակվող զգուշացումները ուղարկվում են որոշ վայրերում` արտակարգ իրավիճակների մասին ձեզ զգուշացնելու համար: Վնասարար հավելվածները կարող են խանգարել ձեր սարքի արդյունավետությանը կամ շահագործմանը, երբ ստացվում է արտակարգ իրավիճակի մասին բջջային հաղորդում:"</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"կարդալ բաժանորդագրված հոսքերը"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index fc82c22..099f819 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -353,6 +353,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Memungkinkan aplikasi menerima dan memproses pesan MMS. Ini artinya aplikasi dapat memantau atau menghapus pesan yang dikirim ke perangkat Anda tanpa menunjukkannya kepada Anda."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Teruskan pesan cell broadcast"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Mengizinkan aplikasi mem-binding ke modul cell broadcast untuk meneruskan pesan cell broadcast saat pesan tersebut diterima. Notifikasi cell broadcast dikirim di beberapa lokasi untuk memperingatkan Anda tentang situasi darurat. Aplikasi berbahaya dapat mengganggu performa atau operasi perangkat saat cell broadcast darurat diterima."</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"membaca pesan siaran seluler"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Mengizinkan aplikasi membaca pesan siaran seluler yang diterima perangkat Anda. Notifikasi siaran seluler dikirimkan di beberapa lokasi untuk memperingatkan Anda tentang situasi darurat. Aplikasi berbahaya dapat mengganggu kinerja atau operasi perangkat Anda saat siaran seluler darurat diterima."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"baca feed langganan"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index 456f518..867fca8 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Leyfir forriti að taka á móti og vinna úr MMS-skilaboðum. Þetta þýðir að forritið getur fylgst með eða eytt skilaboðum sem send eru í tækið án þess að birta þér þau."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Framsenda skilaboð frá endurvarpa"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Heimilar forritinu að bindast endurvarpseiningunni til að framsenda skilaboð frá endurvarpa þegar þau berast. Viðvaranir frá endurvarpa berast á tilteknum stöðum til að vara þig við neyðarástandi. Spilliforrit geta truflað afköst eða virkni tækisins þegar neyðarboð berast frá endurvarpa."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Stjórna símtölum sem eru í gangi"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Leyfir forriti að sjá upplýsingar um og stjórna símtölum sem eru í gangi í tækinu þínu."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"lesa skilaboð frá endurvarpa"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Leyfir forriti að lesa skilaboð frá endurvarpa sem tækið móttekur. Viðvaranir frá endurvarpa berast á tilteknum stöðum til að vara þig við neyðarástandi. Spilliforrit geta truflað afköst eða virkni tækisins þegar neyðarboð berast frá endurvarpa."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lesa strauma í áskrift"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index e89145b..6f2e158 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Consente all\'applicazione di ricevere ed elaborare messaggi MMS. Significa che l\'applicazione potrebbe monitorare o eliminare i messaggi inviati al tuo dispositivo senza mostrarteli."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Inoltro di messaggi cell broadcast"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Consente all\'app di essere associata al modulo di cell broadcast al fine di inoltrare i messaggi di cell broadcast man mano che arrivano. Gli avvisi cell broadcast vengono trasmessi in alcune località per avvertire di situazioni di emergenza. Le app dannose potrebbero interferire con le prestazioni o con il funzionamento del dispositivo quando si riceve un messaggio cell broadcast di emergenza."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Gestione delle chiamate in corso"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Consente a un\'app di accedere a dettagli relativi alle chiamate in corso sul tuo dispositivo e di controllare tali chiamate."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"lettura di messaggi cell broadcast"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Consente all\'applicazione di leggere i messaggi cell broadcast ricevuti dal dispositivo. Gli avvisi cell broadcast vengono trasmessi in alcune località per avvertire di eventuali situazioni di emergenza. Le app dannose potrebbero interferire con le prestazioni o con il funzionamento del dispositivo quando si riceve un messaggio cell broadcast di emergenza."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lettura feed sottoscritti"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index a8810ab..2846508 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -359,6 +359,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"מאפשר לאפליקציה לקבל ולעבד הודעות MMS. משמעות הדבר היא שהאפליקציה יכולה לעקוב אחר הודעות שנשלחו למכשיר או למחוק אותן מבלי להציג לך אותן."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"העברת הודעות של שידור סלולרי"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"מאפשרת לאפליקציה להתחייב למודול של השידור הסלולרי כדי להעביר הודעות של שידור סלולרי כשהן מתקבלות. התראות שידור סלולרי נשלחות במקומות מסוימים כדי להזהיר אותך מפני מצבי חירום. אפליקציות זדוניות עשויות להפריע לביצועים או לפעולה של המכשיר כאשר מתקבל שידור חירום סלולרי."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"ניהול שיחות שנערכות"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"לאפליקציה תהיה אפשרות לראות פרטים על שיחות שנערכות במכשיר ולשלוט בשיחות האלה."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"קריאת הודעות שידור סלולרי"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"מאפשר לאפליקציה לקרוא הודעות שידור סלולרי שהתקבלו במכשיר שלך. התראות שידור סלולרי נשלחות במקומות מסוימים על מנת להזהיר אותך מפני מצבי חירום. אפליקציות זדוניות עשויות להפריע לביצועים או לפעולה של המכשיר שלך כאשר מתקבל שידור חירום סלולרי."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"קרא עדכוני מנויים"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 079598b..c6e8a14 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"MMSメッセージの受信と処理をアプリに許可します。これにより、アプリがデバイスに届いたメッセージを表示することなく監視または削除できるようになります。"</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"緊急速報メールの転送"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"受信した緊急速報メールを転送するために、緊急速報メール モジュールにバインドすることをこのアプリに許可します。緊急速報メールは、緊急事態を警告する目的で一部の地域に配信されます。緊急速報メールの受信時に、悪意のあるアプリによってデバイスの動作や処理が妨害される恐れがあります。"</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"通話の管理"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"デバイスでの通話に関する詳細の参照と、通話の操作をアプリに許可します。"</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"緊急速報メール SMS の読み取り"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"デバイスで受信した緊急速報メール SMS の読み取りをアプリに許可します。緊急速報メールは、緊急事態を警告する目的で一部の地域に配信されます。緊急速報メールの受信時に、悪意のあるアプリによってデバイスの動作や処理が妨害される恐れがあります。"</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"登録したフィードの読み取り"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index 22d69d6..912930f 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"აპს შეეძლება MMS შეტყობინებების მიღება და დამუშავება. ეს ნიშნავს, რომ აპს შეეძლება შეტყობინებების მონიტორინგი და მათი წაშლა თქვენთვის ჩვენების გარეშე."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Cell broadcast შეტყობინებების გადამისამართება"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"საშუალებას აძლევს აპს, დაუკავშირდეს cell broadcast მოდულს იმისთვის, რომ გადაამისამართოს cell broadcast შეტყობინებები მათი მიღებისთანავე. Cell broadcast გაფრთხილებები მიეწოდება ზოგიერთ მდებარეობაზე საგანგებო სიტუაციების შესახებ გაფრთხილების მიზნით. საგანგებო cell broadcast-ის მიღების დროს, მავნე აპებმა შეიძლება ხელი შეუშალონ თქვენი მოწყობილობის ფუნქციონირებას ან ოპერაციებს."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"მიმდინარე ზარების მართვა"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"საშუალებას აძლევს აპს, ნახოს თქვენს მოწყობილობაზე მიმდინარე ზარების დეტალები და აკონტროლოს ეს ზარები."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"მასიური დაგზავნის შეტყობინებების წაკითხვა"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"აპს შეეძლება, წაიკითხოს თქვენს მოწყობილობაზე გამოგზავნილი ქსელის სამაუწყებლო შეტყობინებები. სამაუწყებლო გაფრთხილებები მოგეწოდებათ ზოგიერთ ადგილზე ექსტრემალური სიტუაციების შესახებ გასაფრთხილებლად. ქსელის გადაუდებელი შეტყონიბენის მიღების დროს მავნე აპებმა შეიძლება ხელი შეუშალონ თქვენი მოწყობილობის ფუნქციონირებას ან ოპერაციებს."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"გამოწერილი არხების წაკითხვა"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 464b798..d615538 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Қолданбаға MMS хабарларын алу және өңдеу мүмкіндігін береді. Бұл қолданба құрылғыңызға жіберілген хабарларды сізге көрсетпестен қабылдай және жоя алады дегенді білдіреді."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Ұялы таратылым хабарларының бағытын өзгерту"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Ұялы таратылым хабарлары алынғаннан кейін, олардың бағытын өзгерту үшін қолданбаға ұялы таратылым модулімен байланыстыруға мүмкіндік береді. Ұялы таратылым ескертулері кей аймақтарда төтенше жағдайлар туралы хабарлау үшін беріледі. Төтенше жағдай туралы ұялы таратылым хабары алынғаннан кейін, зиянды қолданбалар құрылғы жұмысына кедергі келтіруі мүмкін."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Қазіргі қоңырауларды басқару"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Қолданбаға құрылғыдағы қазіргі қоңыраулар туралы мәліметтерді көруге және басқаруға мүмкіндік береді."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"ұялы хабар тарату хабарларын оқу"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Қолданбаға ұялы таратылым хабарларын оқу мүмкіндігін береді. Ұялы таратылым дабылдары кейбір аймақтарда төтенше жағдай туралы ескерту үшін қолданылады. Төтенше ұялы хабарлар келгенде залалды қолданбалар құрылғының жұмысына кедергі жасауы мүмкін."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"жазылған ағындарды оқу"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 823a574..075a652 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"ឲ្យកម្មវិធីទទួល និងដំណើរការសារ MMS ។ វាមានន័យថា កម្មវិធីអាចតាមដាន ឬលុបសារដែលបានផ្ញើទៅឧបករណ៍របស់អ្នកដោយមិនបង្ហាញពួកវា។"</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"បញ្ជូនសារផ្សាយចល័តបន្ត"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"អនុញ្ញាតឱ្យកម្មវិធីភ្ជាប់ទៅម៉ូឌុលការផ្សាយចល័ត ដើម្បីបញ្ជូនសារផ្សាយចល័តបន្ត នៅពេលទទួលបានសារទាំងនោះ។ ការជូនដំណឹងអំពីការផ្សាយចល័តត្រូវបានបញ្ជូនទៅទីតាំងមួយចំនួន ដើម្បីព្រមានអ្នកអំពីស្ថានភាពអាសន្ន។ កម្មវិធីគ្រោះថ្នាក់អាចរំខានដល់ដំណើរការ ឬប្រតិបត្តិការឧបករណ៍របស់អ្នក នៅពេលទទួលបានការផ្សាយចល័តពេលមានអាសន្ន។"</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"គ្រប់គ្រងការហៅទូរសព្ទដែលកំពុងដំណើរការ"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"អនុញ្ញាតឱ្យកម្មវិធីមើលព័ត៌មានលម្អិតអំពីការហៅទូរសព្ទដែលកំពុងដំណើរការនៅលើឧបករណ៍របស់អ្នក និងគ្រប់គ្រងការហៅទូរសព្ទទាំងនេះ។"</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"អានសារប្រកាសចល័ត"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"ឲ្យកម្មវិធីអានសារប្រកាសការហៅដែលឧបករណ៍របស់អ្នកបានទទួល។ ការជូនដំណឹងប្រកាសចល័តត្រូវបានបញ្ជូនទៅទីតាំងមួយចំនួន ដើម្បីព្រមានអ្នកអំពីស្ថានភាពអាសន្ន។ កម្មវិធីព្យាបាទអាចជ្រៀតជ្រែកការអនុវត្ត ឬប្រតិបត្តិការឧបករណ៍របស់អ្នកពេលទទួលការប្រកាសចល័តពេលអាសន្ន។"</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"អានអត្ថបទព័ត៌មានបានជាវ"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index bac30ef..61ed9b3 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -353,6 +353,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"MMS ಸಂದೇಶಗಳನ್ನು ಸ್ವೀಕರಿಸಲು ಮತ್ತು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ. ಇದರರ್ಥ, ನಿಮ್ಮ ಸಾಧನಕ್ಕೆ ಕಳುಹಿಸಲಾಗಿರುವ ಸಂದೇಶಗಳನ್ನು ನಿಮಗೆ ತೋರಿಸದೆಯೇ, ಅಪ್ಲಿಕೇಶನ್ ಅವುಗಳನ್ನು ಮಾನಿಟರ್ ಮಾಡಬಹುದು ಅಥವಾ ಅಳಿಸಬಹುದು."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"ಸೆಲ್ ಪ್ರಸಾರ ಸಂದೇಶಗಳನ್ನು ಫಾರ್ವರ್ಡ್ ಮಾಡಿ"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"ಸೆಲ್ ಪ್ರಸಾರವು ಸಂದೇಶಗಳನ್ನು ಸ್ವೀಕರಿಸಿದ ರೀತಿಯಲ್ಲಿಯೇ ಫಾರ್ವರ್ಡ್ ಮಾಡಲು, ಸೆಲ್ ಪ್ರಸಾರ ಮಾಡ್ಯುಲ್ ಅನ್ನು ಪ್ರತಿಬಂಧಿಸಲು ಆ್ಯಪ್ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಕೆಲವು ಸ್ಥಳಗಳಲ್ಲಿ ತುರ್ತು ಸ್ಥಿತಿಗಳ ಕುರಿತು ನಿಮಗೆ ಎಚ್ಚರಿಸಲು ಸೆಲ್ ಪ್ರಸಾರದ ಎಚ್ಚರಿಕೆಗಳನ್ನು ಕಳುಹಿಸಲಾಗುತ್ತದೆ. ತುರ್ತು ಸೆಲ್ ಪ್ರಸಾರವನ್ನು ಸ್ವೀಕರಿಸಿದಾಗ ನಿಮ್ಮ ಸಾಧನದ ಕಾರ್ಯಾಚರಣೆ ಅಥವಾ ಕಾರ್ಯಕ್ಷಮತೆಗೆ ದುರುದ್ದೇಶಪೂರಿತ ಆ್ಯಪ್ಗಳು ಹಸ್ತಕ್ಷೇಪ ಮಾಡಬಹುದು."</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"ಸೆಲ್ ಪ್ರಸಾರದ ಸಂದೇಶಗಳನ್ನು ಓದಿರಿ"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"ನಿಮ್ಮ ಸಾಧನದಿಂದ ಸ್ವೀಕರಿಸಿದ ಸೆಲ್ ಪ್ರಸಾರ ಸಂದೇಶಗಳನ್ನು ರೀಡ್ ಮಾಡಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಸೆಲ್ ಪ್ರಸಾರ ಎಚ್ಚರಿಕೆಗಳನ್ನು ತುರ್ತು ಸಂದರ್ಭಗಳಲ್ಲಿ ನಿಮಗೆ ಎಚ್ಚರಿಸುವ ಸಲುವಾಗಿ ಕೆಲವು ಸ್ಥಳಗಳಲ್ಲಿ ವಿತರಿಸಲಾಗುತ್ತದೆ. ದುರುದ್ದೇಶಪೂರಿತ ಅಪ್ಲಿಕೇಶನ್ಗಳು ತುರ್ತು ಸೆಲ್ ಪ್ರಸಾರವನ್ನು ಸ್ವೀಕರಿಸುವಾಗ, ನಿಮ್ಮ ಸಾಧನದ ಕಾರ್ಯಕ್ಷಮತೆ ಇಲ್ಲವೇ ಕಾರ್ಯಾಚರಣೆಯಲ್ಲಿ ಹಸ್ತಕ್ಷೇಪ ಮಾಡಬಹುದು."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"ಚಂದಾದಾರ ಫೀಡ್ಗಳನ್ನು ಓದಿ"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 00eb66f..dfa3770 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -353,6 +353,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"앱이 MMS 메시지를 수신하고 처리할 수 있도록 허용합니다. 앱이 사용자에게 표시하지 않고 기기로 전송된 메시지를 확인 또는 삭제할 수도 있습니다."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"셀 브로드캐스트 메시지 전달"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"셀 브로드캐스트 메시지를 수신하자마자 전달하기 위해 앱이 셀 브로드캐스트 모듈에 연결하도록 허용합니다. 비상 상황임을 알리기 위해 일부 지역에서 셀 브로드캐스트 경고가 전달됩니다. 비상 셀 브로드캐스트를 수신할 때 악성 앱이 기기의 성능이나 작동을 방해할 수 있습니다."</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"셀 브로드캐스트 메시지 읽기"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"앱이 기기가 수신한 셀 브로드캐스트 메시지를 읽을 수 있도록 합니다. 비상 상황임을 알리기 위해 일부 지역에서 셀 브로드캐스트 경고가 전달됩니다. 비상 셀 브로드캐스트를 수신할 때 악성 앱이 기기의 성능이나 작동을 방해할 수 있습니다."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"가입된 피드 읽기"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 7c1fb98..bd6ecef 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -353,6 +353,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Колдонмого MMS билдирүүлөрүн кабыл алууга жана аларды иштетип чыгууга уруксат берет. Бул, колдонмо сизге билгизбестен түзмөгүңүзгө жөнөтүлгөн билдирүүлөрдү мониторлой же жок кыла алат дегенди билдирет."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Уюк жөнөтүүлөрүнүн билдирүүлөрүн башка номерге багыттоо"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Уюк жөнөтүүлөрүнүн билдирүүлөрү келген сайын башка номерге багыттап туруу үчүн колдонмого уюк жөнөтүүлөрүнүн модулу менен байланышууга уруксат берет. Шашылыш уюк жөнөтүүлөрү кээ бир жерлердеги өзгөчө кырдаалдар тууралуу сизге эскертүү үчүн жөнөтүлөт. Зыянкеч колдонмолор шашылыш уюк жөнөтүүлөрү кабыл алынганда түзмөктүн майнаптуулугуна же иштешине жолтоо болушу мүмкүн."</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"уюктук берүү билдирүүлөрүн окуу"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Колдонмого түзмөгүңүз кабыл алган уюк берүүнүн билдирүүлөрүн окууга жол берет. Шашылыш эскертүү билдирүүлөрү кээ бир жерлердеги өзгөчө кырдаалдар тууралу сизди эскертүү үчүн жөнөтүлөт. Зыяндуу колдономолор шашылыш эскертүүлөр берилип жатканда, сиздин түзмөктүн иштешине жолтоо болушу мүмкүн."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"жазылган түрмөктөрдү окуу"</string>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 72bd141..c60d594 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"ອະນຸຍາດໃຫ້ແອັບຯ ຮັບແລະປະມວນຜົນຂໍ້ຄວາມ MMS. ນີ້ໝາຍຄວາມວ່າແອັບຯສາມາດຕິດຕາມ ຫຼືລຶບຂໍ້ຄວາມທີ່ສົ່ງເຂົ້າອຸປະກອນຂອງທ່ານ ໂດຍທີ່ບໍ່ສະແດງພວກມັນໃຫ້ທ່ານເຫັນ."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"ສົ່ງຕໍ່ຂໍ້ຄວາມການກະຈາຍສັນຍານໂທລະສັບ"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"ອະນຸຍາດໃຫ້ແອັບຜູກມັດກັບໂມດູນການກະຈາຍສັນຍານໂທລະສັບເພື່ອສົ່ງຕໍ່ຂໍ້ຄວາມການກະຈາຍສັນຍານໂທລະສັບເມື່ອໄດ້ຮັບມາ. ການເຕືອນການກະຈາຍສັນຍານໂທລະສັບແມ່ນຖືກຈັດສົ່ງໃນບາງສະຖານທີ່ເພື່ອເຕືອນທ່ານໃນກໍລະນີມີເຫດການສຸກເສີນເກີດຂຶ້ນ. ແອັບທີ່ເປັນອັນຕະລາຍອາດລົບກວນປະສິດທິພາບ ຫຼື ການເຮັດວຽກຂອງອຸປະກອນທ່ານເມື່ອໄດ້ຮັບການກະຈາຍສັນຍານໂທລະສັບສຸກເສີນ."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"ຈັດການສາຍໂທອອກ"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"ອະນຸຍາດໃຫ້ແອັບໃດໜຶ່ງເບິ່ງເຫັນລາຍລະອຽດກ່ຽວກັບສາຍໂທອອກຢູ່ອຸປະກອນຂອງທ່ານ ແລະ ເພື່ອຄວບຄຸມການໂທເຫຼົ່ານີ້."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"ອ່ານຂໍ້ຄວາມກະຈາຍສັນຍານຂອງເສົາສັນຍານ"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"ອະນຸຍາດໃຫ້ແອັບຯ ສາມາດອ່ານຂໍ້ຄວາມແຈ້ງເຕືອນເຫດສຸກເສີນ ທີ່ໄດ້ຮັບໂດຍອຸປະກອນຂອງທ່ານ. ການແຈ້ງເຕືອນສຸກເສີນທີ່ມີໃຫ້ບໍລິການໃນບາງພື້ນທີ່ ເພື່ອແຈ້ງເຕືອນໃຫ້ທ່ານຮູ້ເຖິງສະຖານະການສຸກເສີນ. ແອັບພລິເຄຊັນທີ່ເປັນອັນຕະລາຍອາດລົບກວນປະສິດທິພາບ ຫຼືການດຳເນີນງານຂອງອຸປະກອນຂອງທ່ານ ເມື່ອໄດ້ການຮັບແຈ້ງເຕືອນສຸກເສີນຈາກສະຖານີມືຖື."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"ອ່ານຂໍ້ມູນຟີດທີ່ສະໝັກໄວ້"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index a4e1756..39cbbe1 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -359,6 +359,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Leidžiama programai gauti ir apdoroti MMS pranešimus. Tai reiškia, kad programa gali stebėti ir ištrinti į jūsų įrenginį siunčiamus pranešimus jums jų neparodžiusi."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Persiųsti mobiliuoju transliuojamus pranešimus"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Programai leidžiama susaistyti transliacijos mobiliuoju modulį, kad būtų galima persiųsti mobiliuoju transliuojamus pranešimus, kai jie gaunami. Transliacijos mobiliuoju įspėjimai pristatomi kai kuriose vietovėse, kad būtų galima įspėti apie kritines situacijas. Kai gaunamas mobiliuoju transliuojamas pranešimas apie kritinę situaciją, kenkėjiškos programos gali trukdyti įrenginiui veikti ar jį naudoti."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Tvarkyti vykstančius skambučius"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Programai leidžiama peržiūrėti išsamią informaciją apie vykstančius skambučius įrenginyje ir valdyti šiuos skambučius."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"skaityti mobiliuoju transliuojamus pranešimus"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Programai leidžiama skaityti mobiliuoju transliuojamus pranešimus, gaunamus jūsų įrenginyje. Mobiliuoju transliuojami įspėjimai pristatomi kai kuriose vietose, kad įspėtų apie kritines situacijas. Kai gaunamas mobiliuoju transliuojamas pranešimas apie kritinę situaciją, kenkėjiškos programos gali trukdyti įrenginiui veikti ar jį naudoti."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"skaityti prenumeruojamus tiekimus"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 088e78d..49d3f44 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -356,6 +356,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Ļauj lietotnei saņemt un apstrādāt multiziņas. Tas nozīmē, ka lietotne var pārraudzīt vai dzēst uz jūsu ierīci nosūtītos ziņojumus, neparādot tos jums."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Pārsūtīt šūnu apraides ziņojumus"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Ļauj piesaistīt lietotni šūnu apraides modulim, lai pārsūtītu šūnu apraides ziņojumus, tiklīdz tie tiek saņemti. Šūnu apraides brīdinājumi tiek piegādāti noteiktās atrašanās vietās, lai brīdinātu jūs par ārkārtas situācijām. Ļaunprātīgas lietotnes var traucēt ierīces veiktspēju vai darbības, kad ir saņemts ārkārtas šūnas apraides ziņojums."</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"šūnu apraides ziņojumu lasīšana"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Ļauj lietotnei lasīt ierīcē saņemtos šūnu apraides ziņojumus. Šūnu apraides brīdinājumi tiek piegādāti dažās atrašanās vietās, lai brīdinātu jūs par ārkārtas situācijām. Ļaunprātīgas lietotnes var traucēt ierīces veiktspēju vai darbības, kad ir saņemts ārkārtas šūnas apraides ziņojums."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lasīt abonētās plūsmas"</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 23a84c6..63375f5 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Овозможува апликацијата да прима и да обработува MMS пораки. Тоа значи дека апликацијата може да следи или да брише пораки испратени до вашиот уред без да ви ги прикаже вам."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Проследување пораки за мобилен пренос"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Дозволува апликацијата да се врзе со модулот за мобилен пренос за да проследува пораки за мобилен пренос штом ќе се примат. Предупредувањата за мобилно емитување се доставуваат на некои локации за да ве предупредат на итни ситуации. Злонамерните апликации може да пречат во ефикасноста или работењето на вашиот уред кога се прима емитување за итен случај."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Управување со тековни повици"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Дозволува апликацијата да гледа детали за тековните повици на уредот и да ги контролира овие повици."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"прочитај пораки за мобилно емитување"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Овозможува апликациите да ги читаат пораките за мобилно емитување што ги прима вашиот уред. Предупредувањата за мобилно емитување се доставуваат на некои локации, за да ве предупредат на итни ситуации. Злонамерните апликации може да пречат во ефикасноста или работењето на вашиот уред кога се прима емитување за итен случај."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"читај претплатени навестувања на содржина"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 1c89b33..3eca56c 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -353,6 +353,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"MMS സന്ദേശങ്ങൾ നേടാനും പ്രോസസ്സുചെയ്യാനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. നിങ്ങളുടെ ഉപകരണത്തിലേക്ക് അയയ്ക്കുന്ന സന്ദേശങ്ങൾ നിങ്ങൾക്ക് ദൃശ്യമാക്കാതെ തന്നെ അപ്ലിക്കേഷന് നിരീക്ഷിക്കാനോ ഇല്ലാതാക്കാനോ കഴിയുമെന്നാണ് ഇതിനർത്ഥം."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"ബ്രോഡ്കാസ്റ്റ് സന്ദേശങ്ങൾ കൈമാറുക"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"സ്വീകരിക്കുന്ന മുറയ്ക്ക് ബ്രോഡ്കാസ്റ്റ് സന്ദേശങ്ങൾ കൈമാറുന്നതിന് സെൽ ബ്രോഡ്കാസ്റ്റ് മോഡ്യൂളിലേക്ക് ബൈൻഡ് ചെയ്യാൻ ആപ്പിനെ അനുവദിക്കുന്നു. അടിയന്തര സാഹചര്യങ്ങളെ കുറിച്ച് നിങ്ങൾക്ക് മുന്നറിയിപ്പ് നൽകുന്നതിന് ചില ലൊക്കേഷനുകളിൽ സെൽ ബ്രോഡ്കാസ്റ്റ് അലേർട്ടുകൾ ഡെലിവറി ചെയ്യപ്പെടുന്നു. ഒരു അടിയന്തര സെൽ ബ്രോഡ്കാസ്റ്റ് ലഭിക്കുമ്പോൾ ക്ഷുദ്രകരമായ അപ്ലിക്കേഷനുകൾ നിങ്ങളുടെ ഉപകരണത്തിന്റെ പ്രകടനത്തെയോ പ്രവർത്തനത്തെയോ തടസപ്പെടുത്താനിടയുണ്ട്."</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"സെൽ പ്രക്ഷേപണ സന്ദേശങ്ങൾ റീഡുചെയ്യുക"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"നിങ്ങളുടെ ഉപകരണത്തിൽ ലഭിച്ച സെൽ പ്രക്ഷേപണ സന്ദേശങ്ങൾ റീഡുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. അടിയന്തര സാഹചര്യങ്ങളെക്കുറിച്ച് നിങ്ങൾക്ക് മുന്നറിയിപ്പ് നൽകാനായി ചില ലൊക്കേഷനുകളിൽ നൽകപ്പെടുന്നവയാണ് സെൽ പ്രക്ഷേപണ അലേർട്ടുകൾ. ഒരു അടിയന്തര സെൽ പ്രക്ഷേപണം ലഭിക്കുമ്പോൾ, ക്ഷുദ്രകരമായ അപ്ലിക്കേഷനുകൾ നിങ്ങളുടെ ഉപകരണത്തിന്റെ പ്രകടനമോ പ്രവർത്തനമോ തടസ്സപ്പെടുത്താനിടയുണ്ട്."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"സബ്സ്ക്രൈബ് ചെയ്ത ഫീഡുകൾ വായിക്കുക"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 919112a..366a5b7 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Апп нь MMS мессежийг хүлээн авах болон гүйцэтгэх боломжтой. Ингэснээр апп нь таны төхөөрөмжрүү илгээсэн мессежийг танд үзүүлэхгүйгээр хянах болон устгаж чадна."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Гар утсанд масс мессеж түгээх онцлогийн мессежийг шилжүүлэх"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Гар утсанд масс мессеж түгээх онцлогийн мессежийг хүлээн авах үед түүнийг шилжүүлэх зорилгоор аппад гар утсанд масс мессеж түгээх модультай холбогдохыг зөвшөөрөх Гар утсанд масс мессеж түгээх онцлогийн сэрэмжлүүлэг нь онцгой нөхцөл байдлын тухай танд анхааруулахын тулд зарим байршилд хүрдэг. Гар утсанд масс мессеж түгээх онцлогийн илгээх онцгой нөхцөл байдлын тухай мессежийг хүлээн авах үед хортой апп таны төхөөрөмжийн гүйцэтгэл эсвэл ажиллагаанд саад учруулж болзошгүй."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Үргэлжилж буй дуудлагыг удирдах"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Аппад таны төхөөрөмж дээрх үргэлжилж буй дуудлагын талаарх дэлгэрэнгүйг харах болон эдгээр дуудлагыг хянахыг зөвшөөрнө."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"үүрэн өргөн дамжууллын мессеж унших"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Апп нь таны төхөөрөмжийн хүлээн авсан үүрэн өргөн дамжуулах мессежийг унших боломжтой. Үүрэн өргөн дамжууллын мэдэгдэл нь яаралтай нөхцөл байдлыг анхааруулах зорилгоор зарим байршлуудад хүрдэг. Хортой апп нь яаралтай үүрэн өргөн дамжууллыг хүлээн авсан үед таны төхөөрөмжийн ажиллагаа болон чадамжид нөлөөлөх боломжтой."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"бүртгүүлсэн хангамжийг унших"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 7a8fd1a..197797f 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -353,6 +353,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"MMS मेसेज प्राप्त करण्यास आणि त्यावर प्रक्रिया करण्यास अॅप ला अनुमती देते. म्हणजेच अॅप आपल्या डिव्हाइसवर पाठविलेले मेसेज तुम्हाला न दर्शवता त्यांचे परीक्षण करू किंवा ते हटवू शकतो."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"सेल प्रसारण मेसेज फॉरवर्ड करा"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"सेल प्रसारण मेसेज मिळाल्यानंतर ते फॉरवर्ड करण्यासाठी ॲपला सेल प्रसारण मॉड्यूलमध्ये प्रतिबद्ध करण्याची अनुमती देते. काही स्थानांमध्ये तुम्हाला आणीबाणीच्या परिस्थीतींची चेतावणी देण्यासाठी सेल प्रसारण सूचना वितरित केल्या जातात. दुर्भावनापूर्ण अॅप्स आणीबाणी सेल प्रसारण मिळवतात तेव्हा ती तुमच्या डिव्हाइसच्या परफॉर्मन्समध्ये किंवा कामामध्ये कदाचित व्यत्यय आणू शकतात."</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"सेल प्रसारण मेसेज वाचा"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"आपल्या डिव्हाइसद्वारे प्राप्त केलेले सेल प्रसारण मेसेज वाचण्यासाठी अॅप ला अनुमती देते. काही स्थानांमध्ये तुम्हाला आणीबाणीच्या परिस्थितीची चेतावणी देण्यासाठी सेल प्रसारण सूचना वितरीत केल्या जातात. आणीबाणी सेल प्रसारण प्राप्त होते तेव्हा आपल्या डिव्हाइसच्या कार्यप्रदर्शनात किंवा कार्यात दुर्भावनापूर्ण अॅप्स व्यत्यय आणू शकतात."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"सदस्यता घेतलेली फीड वाचा"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index e94dcde..635c5b7 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -353,6 +353,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Membenarkan apl menerima dan memproses mesej MMS. Ini bermakna apl boleh memantau atau memadam mesej yang dihantar ke peranti anda tanpa menunjukkannya kepada anda."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Kirim semula mesej siaran sel"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Membenarkan apl terikat pada modul siaran sel untuk mengirim semula mesej siaran sel apabila diterima. Makluman siaran sel dihantar di sesetengah lokasi untuk memberi amaran kepada anda tentang situasi kecemasan. Apl hasad boleh mengganggu prestasi atau operasi peranti anda apabila siaran sel kecemasan diterima."</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"baca mesej siaran sel"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Membolehkan apl membaca mesej siaran sel yang diterima oleh peranti anda. Isyarat siaran sel dihantar di beberapa lokasi untuk memberi amaran kepada anda tentang situasi kecemasan. Apl hasad boleh mengganggu prestasi atau operasi peranti anda apabila siaran sel kecemasan diterima."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"baca suapan langganan"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index c31b7b2..96d4417 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"အပလီကေးရှင်းအား ရုပ်သံစာများ လက်ခံခြင်း၊ ဆောင်ရွက်ခြင်း ခွင့်ပြုပါ။ ဤခွင့်ပြုချက်တွင် အပလီကေးရှင်းအနေဖြင့် သင် လက်ခံရရှိသော စာများအား သင့်အား မပြပဲစောင့်ကြည့်ခွင့်နှင့် ဖျက်ပစ်ခွင့်များ ပါဝင်ပါသည်။"</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"စာတို ဖြန့်ဝေခြင်းစနစ်သုံး မက်ဆေ့ဂျ်များကို ထပ်ဆင့်ပို့ခြင်း"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"စာတို ဖြန့်ဝေခြင်းစနစ် မော်ဂျူးကိုပေါင်းရန် အက်ပ်များအား ခွင့်ပြုသည်။ ၎င်းမှာ စာတို ဖြန့်ဝေခြင်းစနစ်သုံး မက်ဆေ့ဂျ်များကို လက်ခံရရှိသည့်အတိုင်း ထပ်ဆင့်ပို့ရန် ဖြစ်သည်။ အချို့တည်နေရာများတွင် သင့်အား အရေးပေါ်အခြေအနေများကို သတိပေးရန် စာတို ဖြန့်ဝေခြင်းစနစ်သုံး သတိပေးချက်များကို ပေးပို့သည်။ အရေးပေါ် စာတို ဖြန့်ဝေခြင်းကို ရရှိသည့်အခါ သံသယဖြစ်နိုင်ဖွယ်ရှိသည့် အက်ပ်များက သင့်စက်၏ စွမ်းဆောင်ရည်နှင့် အော်ပရေးရှင်းတို့ကို အနှောင့်အယှက်ပေးနိုင်သည်။"</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"လက်ရှိခေါ်ဆိုမှုများကို စီမံခြင်း"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"သင့်စက်ပစ္စည်းပေါ်ရှိ လက်ရှိခေါ်ဆိုမှုများအကြောင်း အသေးစိတ်များကို ကြည့်ရှုရန်နှင့် ဤခေါ်ဆိုမှုများကို ထိန်းချုပ်ရန် အက်ပ်အား ခွင့်ပြုသည်။"</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"စာတိုများ ဖြန့်ဝေခြင်းစနစ်အား ဖတ်ခြင်း"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"အပလီကေးရှင်းကို သင်၏ စက်ပစ္စည်းမှ လက်ခံရရှိသော အများလွှင့်ထုတ်ချက်များကို ဖတ်ရန် ခွင့်ပြုသည်။ အများလွှင့်ထုတ်ချက်များသည် အရေးပေါ်အခြေအနေများကို သင့်အား သတိပေးရန် အချို့ နေရာများတွင် ပို့ပေးသည်။ အရေးပေါ်သတိပေးချက် ထုတ်လွှင့်ချက်ကို လက်ခံရရှိချိန်တွင်အန္တရာယ် ဖြစ်စေနိုင်သော အပလီကေးရှင်းများသည် သင့်စက်ပစ္စည်း၏ လုပ်ငန်းလည်ပတ်မှုနှင့် စွမ်းဆောင်မှုကို ဝင်စွက်ဖက်နိုင်သည်။"</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"အမည်သွင်းထားသောဖိဖ့်များကို ဖတ်ခြင်း"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 7f2c6aa..c85626f 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Lar appen motta og behandle multimediemeldinger. Dette betyr at appen kan overvåke eller slette meldinger som er sendt til enheten din uten at du har sett dem."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Videresend kringkastede meldinger"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Tillat at denne appen binder seg til modulen for kringkastede meldinger for å videresende kringkastede meldinger når de mottas. Kringkastede varsler leveres noen steder for å advare deg om nødssituasjoner. Skadelige apper kan forstyrre ytelsen eller funksjonen til enheten din når en kringkastet nødmelding mottas."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Administrer pågående anrop"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Gir en app tillatelse til å se informasjon om pågående anrop på enheten og til å kontrollere disse anropene."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"lese kringkastede meldinger"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Tillater at appen kan lese kringkastede meldinger enheten din mottar. Kringkastede varsler leveres noen steder for å advare deg om nødssituasjoner. Skadelige apper kan forstyrre ytelsen eller funksjonen til enheten din når en kringkastet nødmelding mottas."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lese abonnement på nyhetskilder"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index d555b7c..d1ae9ab 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -353,6 +353,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"एपलाई MMS सन्देशहरू प्राप्त गर्न र प्रकृया गर्न अनुमति दिन्छ। यसको मतलब अनुप्रयोगले तपाईंको उपकरणमा पठाइएको सन्देशहरू तपाईंलाई नदेखाईनै मोनिटर गर्न वा मेटाउन सक्दछ।"</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"मोबाइल प्रसारणसम्बन्धी सन्देशहरू फर्वार्ड गर्नुहोस्"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"मोबाइल प्रसारणसम्बन्धी सन्देशहरू प्राप्त हुनासाथै तिनीहरूलाई फर्वार्ड गर्नका लागि यसले एपलाई मोबाइल प्रसारण मोड्युलमा जोडिने अनुमति दिन्छ। तपाईंलाई कतिपय स्थानमा आपत्कालीन अवस्थाका बारेमा जानकारी दिनका लागि मोबाइल प्रसारणसम्बन्धी अलर्टहरू पठाइन्छ। हानिकारक एपहरूले आपत्कालीन मोबाइल प्रसारण प्राप्त हुँदा तपाईंको यन्त्रलाई कार्य सम्पादन गर्ने वा सञ्चालित हुने क्रममा हस्तक्षेप गर्न सक्छन्।"</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"सेल प्रसारित सन्देशहरू पढ्नुहोस्"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"तपाईंको उपकरणद्वारा प्राप्त सेल प्रसारण सन्देशहरू एपलाई पढ्न अनुमति दिन्छ। सेल प्रसारण चेतावनीहरू केही स्थानहरूमा तपाईंलाई आपत्कालीन गतिविधिहरूको बारेमा सचेत गराउन गरिएका छन्। खराब एपहरूले एउटा आपत्कालीन सेल प्रसारण प्राप्त गर्दछ जब तपाईंको उपकरणको प्रदर्शन वा अपरेशनको साथ हस्तक्षेप गर्न सक्दछन्।"</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"सदस्य बनाइका फिडहरू पढ्नुहोस्"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 04f598d..9d470b8 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Hiermee kan de app MMS-berichten ontvangen en verwerken. Dit betekent dat de app berichten die naar je apparaat zijn verzonden, kan bijhouden of verwijderen zonder deze aan u weer te geven."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Cell broadcast-berichten doorsturen"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Hiermee kan de app de module voor cell broadcasts binden om cell broadcast-berichten door te sturen als die worden ontvangen. Cell broadcast-waarschuwingen worden op bepaalde locaties verzonden om je te waarschuwen voor noodsituaties. Schadelijke apps kunnen de prestaties of verwerking van je apparaat verstoren als een bericht met een noodmelding wordt ontvangen."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Actieve gesprekken beheren"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Hiermee kan een app informatie over actieve gesprekken op je apparaat bekijken en deze gesprekken beheren."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"infodienstberichten lezen"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Toestaan dat de app infodienstberichten leest die worden ontvangen op je apparaat. Infodienstberichten worden verzonden naar bepaalde locaties om u te waarschjeen voor noodsituaties. Schadelijke apps kunnen de prestaties of verwerking van je apparaat verstoren wanneer een infodienstbericht wordt ontvangen."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"Geabonneerde feeds lezen"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index bccb824..df72172 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -353,6 +353,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"MMS ମେସେଜ୍ ପ୍ରାପ୍ତ କରିବାକୁ ତଥା ପ୍ରକ୍ରିୟା କରାଇବାକୁ ଆପ୍ଟିକୁ ଅନୁମତି ଦିଏ। ଏହାର ଅର୍ଥ, ଆପଣଙ୍କ ଡିଭାଇସ୍କୁ ପଠାଯାଇଥିବା ମେସେଜ୍ ଆପଣଙ୍କୁ ନଦେଖାଇ ଆପ୍ଟି ମନିଟର୍ କିମ୍ବା ଡିଲିଟ୍ କରିପାରେ।"</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"ସେଲ୍ ପ୍ରସାରଣ ମେସେଜ୍ ଫର୍ୱାର୍ଡ କରନ୍ତୁ"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"ସେଲ୍ ପ୍ରସାରଣ ମେସେଜ୍ ପ୍ରାପ୍ତ ହେବା ପରେ ସେଗୁଡ଼ିକୁ ଫର୍ୱାର୍ଡ କରିବା ପାଇଁ ଆପ୍କୁ ସେଲ୍ ପ୍ରସାରଣ ମଡ୍ୟୁଲ୍ ସହିତ ସଂଯୁକ୍ତ କରିବାକୁ ଅନୁମତି ଦିଏ। ଜରୁରୀକାଳୀନ ପରିସ୍ଥିତିରେ ଆପଣଙ୍କୁ ଚେତାବନୀ ଦେବା ପାଇଁ କିଛି ଲୋକେସନ୍ରେ ସେଲ୍ ପ୍ରସାରଣ ଆଲର୍ଟ ବିତରଣ କରାଯାଇଥାଏ। ଏକ ଜରୁରୀକାଳୀନ ସେଲ୍ ପ୍ରସାରଣ ପ୍ରାପ୍ତ ହେବା ସମୟରେ କିଛି କ୍ଷତିକାରକ ଆପ୍ସ ହୁଏତ ଆପଣଙ୍କର ଡିଭାଇସ୍ର କାର୍ଯ୍ୟଦକ୍ଷତା କିମ୍ବା କାର୍ଯ୍ୟ ପ୍ରକ୍ରିୟାରେ ହସ୍ତକ୍ଷେପ କରିପାରେ।"</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"ସେଲ୍ ବ୍ରଡ୍କାଷ୍ଟ ମେସେଜ୍ ପଢ଼ନ୍ତୁ"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"ଆପଣଙ୍କ ଡିଭାଇସ୍ରେ ପ୍ରାପ୍ତ ହୋଇଥିବା ସେଲ୍ ବ୍ରଡ୍କାଷ୍ଟ ମେସେଜ୍ ପଢିବାକୁ ଆପ୍କୁ ଅନୁମତି ଦିଏ। ଜରୁରୀକାଳୀନ ଅବସ୍ଥା ବିଷୟରେ ଆପଣଙ୍କୁ ସତର୍କ କରାଇବାକୁ କିଛି ଲୋକେଶନ୍ରେ ସେଲ୍ ବ୍ରଡ୍କାଷ୍ଟ ସତର୍କ ଡେଲିଭର୍ କରାଯାଇଥାଏ। ଏକ ଜରୁରୀକାଳୀନ ସେଲ୍ ବ୍ରଡ୍କାଷ୍ଟ ପ୍ରାପ୍ତ ହେବାପରେ ହାନୀକାରକ ଆପ୍ ଆପଣଙ୍କ ଡିଭାଇସ୍ର କାର୍ଯ୍ୟକ୍ଷମତା କିମ୍ବା ସଞ୍ଚାଳନାରେ ବାଧା ପହଞ୍ଚାଇପାରନ୍ତି।"</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"ସବସ୍କ୍ରାଇବ୍ ହୋଇଥିବା ଫୀଡ୍କୁ ପଢ଼ନ୍ତୁ"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 2d16de8..9736e57 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -353,6 +353,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"ਐਪ ਨੂੰ MMS ਸੁਨੇਹੇ ਪ੍ਰਾਪਤ ਕਰਨ ਅਤੇ ਉਹਨਾਂ ਦੀ ਪ੍ਰਕਿਰਿਆ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਸਦਾ ਮਤਲਬ ਹੈ ਕਿ ਐਪ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਤੇ ਭੇਜੇ ਗਏ ਸੁਨੇਹਿਆਂ ਨੂੰ ਤੁਹਾਨੂੰ ਦਿਖਾਏ ਬਿਨਾਂ ਨਿਰੀਖਣ ਕਰ ਸਕਦੀ ਹੈ ਜਾਂ ਮਿਟਾ ਸਕਦੀ ਹੈ।"</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"ਸੈੱਲ ਪ੍ਰਸਾਰਨ ਸੁਨੇਹਿਆਂ ਨੂੰ ਅੱਗੇ ਭੇਜੋ"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"ਐਪ ਨੂੰ ਸੈੱਲ ਪ੍ਰਸਾਰਨ ਸੁਨੇਹਿਆਂ ਦੇ ਪ੍ਰਾਪਤ ਹੁੰਦੇ ਹੀ ਉਹਨਾਂ ਨੂੰ ਅੱਗੇ ਭੇਜਣ ਲਈ ਸੈੱਲ ਪ੍ਰਸਾਰਨ ਮਾਡਿਊਲ ਨਾਲ ਜੋੜਨ ਦੀ ਇਜਾਜ਼ਤ ਦਿੱਤੀ ਜਾਂਦੀ ਹੈ। ਸੈੱਲ ਪ੍ਰਸਾਰਨ ਸੁਚੇਤਨਾਵਾਂ ਤੁਹਾਨੂੰ ਸੰਕਟਕਾਲੀ ਸਥਿਤੀਆਂ ਦੀ ਚਿਤਾਵਨੀ ਦੇਣ ਲਈ ਕੁਝ ਟਿਕਾਣਿਆਂ \'ਤੇ ਪ੍ਰਦਾਨ ਕੀਤੀਆਂ ਜਾਂਦੀਆਂ ਹਨ। ਭੈੜੀਆਂ ਐਪਾਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੀ ਕਾਰਗੁਜ਼ਾਰੀ ਜਾਂ ਓਪਰੇਸ਼ਨ ਵਿੱਚ ਵਿਘਨ ਪਾ ਸਕਦੀਆਂ ਹਨ ਜਦੋਂ ਇੱਕ ਸੰਕਟਕਾਲੀ ਸੈੱਲ ਪ੍ਰਸਾਰਨ ਪ੍ਰਾਪਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।"</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"ਸੈਲ ਪ੍ਰਸਾਰਨ ਸੁਨੇਹੇ ਪੜ੍ਹੋ"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"ਐਪ ਨੂੰ ਤੁਹਾਡੀ ਡੀਵਾਈਸ ਵੱਲੋਂ ਪ੍ਰਾਪਤ ਕੀਤੇ ਸੈੱਲ ਪ੍ਰਸਾਰਣ ਸੁਨੇਹੇ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਸੈੱਲ ਪ੍ਰਸਾਰਣ ਚਿਤਾਵਨੀਆਂ ਤੁਹਾਨੂੰ ਸੰਕਟਕਾਲੀਨ ਸਥਿਤੀਆਂ ਦੀ ਚਿਤਾਵਨੀ ਦੇਣ ਲਈ ਕੁਝ ਨਿਰਧਾਰਤ ਟਿਕਾਣਿਆਂ ਤੇ ਪ੍ਰਦਾਨ ਕੀਤੀਆਂ ਜਾਂਦੀਆਂ ਹਨ। ਖਰਾਬ ਐਪਾਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੇ ਪ੍ਰਦਰਸ਼ਨ ਜਾਂ ਓਪਰੇਸ਼ਨ ਵਿੱਚ ਵਿਘਨ ਪਾ ਸਕਦੀਆਂ ਹਨ ਜਦੋਂ ਇੱਕ ਸੰਕਟਕਾਲੀਨ ਸੈੱਲ ਪ੍ਰਸਾਰਣ ਪ੍ਰਾਪਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।"</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"ਸਬਸਕ੍ਰਾਈਬ ਕੀਤੇ ਫੀਡਸ ਪੜ੍ਹੋ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 9534359..295a54e 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -359,6 +359,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Pozwala aplikacji na odbieranie i przetwarzanie MMS-ów. To oznacza, że aplikacja będzie mogła bez Twojej wiedzy monitorować i usuwać wiadomości wysyłane do Twojego urządzenia."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Przekaż komunikaty z sieci komórkowej"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Zezwala aplikacji powiązać się z modułem komunikatów z sieci komórkowej, aby przekazywać je w momencie, w którym są otrzymywane. W niektórych lokalizacjach komunikaty alarmowe z sieci komórkowej są dostarczane, aby ostrzec Cię o sytuacjach zagrożenia. Złośliwe aplikacje mogą wpływać na działanie urządzenia lub zakłócać je po nadejściu komunikatu alarmowego z sieci komórkowej."</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"odczyt komunikatów z sieci komórkowej"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Zezwala aplikacji na odczyt komunikatów z sieci komórkowej odebranych na urządzeniu. Komunikaty alarmowe z sieci komórkowej są dostarczane w niektórych lokalizacjach w celu ostrzeżenia Cię o sytuacjach zagrożenia. Złośliwe aplikacje mogą wpływać na wydajność lub zakłócać działanie urządzenia po odebraniu komunikatu alarmowego z sieci komórkowej."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"czytanie subskrybowanych źródeł"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 8198a62..d9050bf 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Permite que o app receba e processe mensagens MMS. Isso significa que o app pode monitorar ou excluir as mensagens enviadas para o dispositivo sem mostrá-las para você."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Encaminhar mensagens de transmissão celular"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Permite que o app se vincule ao módulo de transmissão celular para encaminhar mensagens de transmissão celular assim que elas forem recebidas. Alertas de transmissão celular são recebidos em alguns locais para avisar sobre situações de emergência. Apps maliciosos podem interferir no desempenho ou funcionamento do dispositivo quando uma transmissão celular de emergência é recebida."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Gerenciar chamadas em andamento"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Permite que um app veja detalhes sobre chamadas em andamento no seu dispositivo e as controle."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"ler mensagens de difusão celular"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Permite que o app leia mensagens de difusão celular recebidas por seu dispositivo. Alertas de difusão celular são recebidos em alguns locais para avisar você de situações de emergência. Apps maliciosos podem interferir no desempenho ou funcionamento de seu dispositivo quando uma difusão celular de emergência é recebida."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"ler feeds inscritos"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 71dd2b9..3de02ab 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Permite que a app receba e processe mensagens MMS. Isto significa que a app poderá monitorizar ou eliminar mensagens enviadas para o seu dispositivo sem as apresentar."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Encaminhar mensagens de difusão celular"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Permite que a app se vincule ao módulo de difusão celular para encaminhar mensagens de difusão celular à medida que são recebidas. Os alertas de difusão celular são fornecidos em algumas localizações para avisar sobre situações de emergência. As aplicações maliciosas podem interferir com o desempenho ou funcionamento do seu dispositivo quando for recebida uma difusão celular de emergência."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Gerir chamadas em curso"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Permite que uma app veja detalhes acerca das chamadas em curso no seu dispositivo e controle essas chamadas."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"ler mensagens de transmissão celular"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Permite que a app leia mensagens de transmissão celular recebidas pelo seu dispositivo. Os alertas de transmissão celular são fornecidos em algumas localizações para avisá-lo sobre situações de emergência. As aplicações maliciosas podem interferir com o desempenho ou funcionamento do seu dispositivo quando for recebida uma transmissão celular de emergência."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"ler feeds subscritos"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 8198a62..d9050bf 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Permite que o app receba e processe mensagens MMS. Isso significa que o app pode monitorar ou excluir as mensagens enviadas para o dispositivo sem mostrá-las para você."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Encaminhar mensagens de transmissão celular"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Permite que o app se vincule ao módulo de transmissão celular para encaminhar mensagens de transmissão celular assim que elas forem recebidas. Alertas de transmissão celular são recebidos em alguns locais para avisar sobre situações de emergência. Apps maliciosos podem interferir no desempenho ou funcionamento do dispositivo quando uma transmissão celular de emergência é recebida."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Gerenciar chamadas em andamento"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Permite que um app veja detalhes sobre chamadas em andamento no seu dispositivo e as controle."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"ler mensagens de difusão celular"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Permite que o app leia mensagens de difusão celular recebidas por seu dispositivo. Alertas de difusão celular são recebidos em alguns locais para avisar você de situações de emergência. Apps maliciosos podem interferir no desempenho ou funcionamento de seu dispositivo quando uma difusão celular de emergência é recebida."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"ler feeds inscritos"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 4d091e9..340b752 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -356,6 +356,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Permite aplicației să primească și să proceseze mesaje MMS. Acest lucru înseamnă că aplicația ar putea monitoriza sau șterge mesajele trimise pe dispozitivul dvs. fără a vi le arăta."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Redirecționează mesajele cu transmisie celulară"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Permite aplicației să se conecteze la modulul de transmisie celulară pentru a redirecționa mesajele cu transmisie celulară pe măsură ce le primește. Alertele cu transmisie celulară sunt difuzate în unele locații pentru a vă avertiza cu privire la situațiile de urgență. Aplicațiile rău intenționate pot afecta performanța sau funcționarea dispozitivului dvs. când este primită o transmisie celulară de urgență."</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"citește mesajele cu transmisie celulară"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Permite aplicației să citească mesajele primite prin transmisie celulară de dispozitivul dvs. Alertele cu transmisie celulară sunt difuzate în unele locații pentru a vă avertiza cu privire la situațiile de urgență. Aplicațiile rău intenționate pot afecta performanța sau funcționarea dispozitivului dvs. când este primită o transmisie celulară de urgență."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"citire feeduri abonat"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 783ec9a..74d5bf9 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -359,6 +359,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Приложение сможет получать и обрабатывать MMS. Это значит, что оно сможет отслеживать и удалять отправленные на ваше устройство сообщения, не показывая их."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Пересылка сообщений для оповещения населения"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Приложение сможет выполнить привязку к модулю оповещения населения, чтобы пересылать сообщения широковещательных SMS-служб сразу после их получения. В некоторых странах эти сообщения используются для информирования об экстренных ситуациях. Вредоносное ПО может помешать работе устройства, на которое поступают такие сообщения."</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"Читать сообщения массовой рассылки"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Приложение получит доступ к сообщениям широковещательных SMS-служб, которые в некоторых странах используются для информирования населения об экстренных ситуациях. Вредоносные программы могут помешать работе устройства, на которое поступают такие сообщения."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"Просмотр фидов пользователя"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 74b4008..6c1c777 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"MMS පණිවිඩ සොයා ලබාගැනීමට සහ ක්රියාත්මක කිරීමට යෙදුමට අවසර දෙන්න. යෙදුම නිරීක්ෂණය කරනු ලබන අතර ඔබට ලැබුන පණිවිඩ පෙන්වීමෙන් තොරවම මකා දැමිය හැකි බව මෙමඟින් අදහස් කරයි."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"සෙල් විකාශන පණිවිඩ යොමු කිරීම"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"සෙල් විකාශන පණිවිඩ ලැබුණු විට ඒවා යොමු කිරීම සඳහා සෙල් විකාශන මොඩියුලයට බැඳීමට යෙදුමට ඉඩ දෙයි. හදිසි අවස්ථා පිළිබඳව ඔබට අනතුරු ඇඟවීම සඳහා සෙල් විකාශන ඇඟවීම් සමහර ස්ථානවල ලබා දෙනු ලැබේ. හදිසි සෙල් විකාශනයක් ලැබෙන අවස්ථාවකදී, අනිෂ්ට යෙදුම්වලින් ඔබගේ උපාංග කාර්ය සාධනයට හෝ මෙහෙයුමට බාධා සිදු විය හැකිය."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"සිදු වෙමින් පවතින ඇමතුම් කළමනාකරණය කරන්න"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"ඔබගේ උපාංගයේ සිදු වෙමින් පවතින ඇමතුම් පිළිබඳ විස්තර බැලීමට සහ මෙම ඇමතුම් පාලනය කිරීමට යෙදුමකට ඉඩ දෙයි."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"සෙල් ප්රචාරණ පණිවිඩ කියවීම"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"ඔබගේ උපාංගයට ලැබුණු සෙල් විකාශන පණිවිඩ කියවීමට යෙදුමට අවසර දෙන්න. ඔබට හදිසි අවස්ථාවන් පිළිබඳ අනතුරු ඇඟවීමට සෙල් විකාශන පණිවිඩ ඇතැම් ස්ථානවල සිට යවනු ලබයි. හදිසි සෙල් විකාශන ලැබෙන අවස්ථාවකදී, අනිෂ්ට යෙදුම් මඟින් ඔබගේ උපාංගයට කාර්ය සාධනයට හෝ ක්රියකරණයට බාධා සිදුවිය හැක."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"දායක වූ සංග්රහ කියවීම"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 74e2b69..cfffb86 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -162,7 +162,7 @@
<string name="httpErrorAuth" msgid="469553140922938968">"Nepodarilo sa overiť totožnosť."</string>
<string name="httpErrorProxyAuth" msgid="7229662162030113406">"Overenie pomocou servera proxy bolo neúspešné."</string>
<string name="httpErrorConnect" msgid="3295081579893205617">"K serveru sa nepodarilo pripojiť."</string>
- <string name="httpErrorIO" msgid="3860318696166314490">"Nepodarilo sa nadviazať komunikáciu so serverom. Skúste to znova neskôr."</string>
+ <string name="httpErrorIO" msgid="3860318696166314490">"Nepodarilo sa nadviazať komunikáciu so serverom. Skúste to neskôr."</string>
<string name="httpErrorTimeout" msgid="7446272815190334204">"Časový limit pripojenia na server vypršal."</string>
<string name="httpErrorRedirectLoop" msgid="8455757777509512098">"Stránka obsahuje príliš veľa presmerovaní servera."</string>
<string name="httpErrorUnsupportedScheme" msgid="2664108769858966374">"Protokol nie je podporovaný."</string>
@@ -359,6 +359,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Umožňuje aplikácii prijímať a spracovávať správy MMS. Znamená to, že aplikácia môže sledovať správy odoslané na vaše zariadenie alebo ich odstrániť bez toho, aby sa vám zobrazili."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Preposielanie správ informačných služieb"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Umožňuje aplikácii spojiť sa s modulom správ informačných služieb s cieľom preposielať prichádzajúce správy informačných služieb. Správy informačných služieb sa doručujú na určitých miestach a upozorňujú na tiesňové situácie. Škodlivé aplikácie môžu pri prijatí správy informačnej služby narušiť výkonnosť alebo prevádzku vášho zariadenia."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Správa prebiehajúcich hovorov"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Povolí aplikácii čítať podrobnosti o prebiehajúcich hovoroch v zariadení a ovládať ich."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"čítať správy informačných služieb"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Umožňuje aplikácii čítať správy informačných služieb prijaté vaším zariadením. Správy informačných služieb sa doručujú na určitých miestach a upozorňujú na tiesňové situácie. Škodlivé aplikácie môžu pri prijatí správy informačnej služby narušiť výkonnosť alebo prevádzku vášho zariadenia."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"čítať odoberané informačné kanály"</string>
@@ -572,7 +574,7 @@
<string name="fingerprint_error_timeout" msgid="2946635815726054226">"Časový limit rozpoznania odtlačku prsta vypršal. Skúste to znova."</string>
<string name="fingerprint_error_canceled" msgid="540026881380070750">"Operácia týkajúca sa odtlačku prsta bola zrušená"</string>
<string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Overenie odtlačku prsta zrušil používateľ."</string>
- <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Príliš veľa pokusov. Skúste to znova neskôr."</string>
+ <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Príliš veľa pokusov. Skúste to neskôr."</string>
<string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Príliš veľa pokusov. Senzor odtlačkov prstov bol deaktivovaný."</string>
<string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Skúste to znova"</string>
<string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Neregistrovali ste žiadne odtlačky prstov."</string>
@@ -616,7 +618,7 @@
<string name="face_error_no_space" msgid="5649264057026021723">"Nové údaje o tvári sa nedajú uložiť. Najprv odstráňte jeden zo starých záznamov."</string>
<string name="face_error_canceled" msgid="2164434737103802131">"Operácia týkajúca sa tváre bola zrušená"</string>
<string name="face_error_user_canceled" msgid="8553045452825849843">"Odomknutie tvárou zrušil používateľ."</string>
- <string name="face_error_lockout" msgid="7864408714994529437">"Príliš veľa pokusov. Skúste to znova neskôr."</string>
+ <string name="face_error_lockout" msgid="7864408714994529437">"Príliš veľa pokusov. Skúste to neskôr."</string>
<string name="face_error_lockout_permanent" msgid="8277853602168960343">"Príliš veľa pokusov. Odomknutie tvárou bolo zakázané."</string>
<string name="face_error_unable_to_process" msgid="5723292697366130070">"Nedá sa overiť tvár. Skúste to znova."</string>
<string name="face_error_not_enrolled" msgid="7369928733504691611">"Nenastavili ste odomknutie tvárou."</string>
@@ -1824,7 +1826,7 @@
<item quantity="other">Skúste to znova o <xliff:g id="COUNT">%d</xliff:g> sekúnd</item>
<item quantity="one">Skúste to znova o 1 sekundu</item>
</plurals>
- <string name="restr_pin_try_later" msgid="5897719962541636727">"Skúste to znova neskôr"</string>
+ <string name="restr_pin_try_later" msgid="5897719962541636727">"Skúste to neskôr"</string>
<string name="immersive_cling_title" msgid="2307034298721541791">"Zobrazenie na celú obrazovku"</string>
<string name="immersive_cling_description" msgid="7092737175345204832">"Ukončíte potiahnutím zhora nadol."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Dobre"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 755db5c..2a027b2 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -359,6 +359,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Aplikaciji omogoča prejemanje in obdelavo MMS-ov. S tem lahko aplikacija nadzoruje ali izbriše sporočila, poslana v napravo, ne da bi vam jih pokazala."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Posredovanje sporočil oddaj v celici"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Aplikaciji omogoča povezovanje z modulom za oddaje v celici, da posreduje sporočila oddaj v celici, takoj ko jih prejme. Na nekaterih lokacijah so opozorila oddaj v celici dostavljena, da vas opozorijo na izredne razmere. Zlonamerne aplikacije lahko vplivajo na delovanje naprave, ko prejme sporočilo oddaje v celici."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Upravljanje aktivnih klicev"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Aplikaciji dovoljuje ogled podrobnosti o aktivnih klicih v napravi in upravljanje s temi klici."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"branje sporočil oddaje v celici"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Omogoča aplikaciji branje sporočil oddaje v celici, ki jih prejme naprava. Opozorila oddaje v celici so dostavljena na nekaterih lokacijah, da vas opozorijo na izredne razmere. Zlonamerne aplikacije lahko vplivajo na delovanje naprave, ko dobi sporočilo oddaje v celici."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"branje naročenih virov"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index bd970a0..25989bd9 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -353,6 +353,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Lejon aplikacionin të marrë dhe përpunojë mesazhe MMS. Kjo do të thotë se aplikacioni mund të monitorojë ose fshijë mesazhe të dërguara në pajisjen tënde, pa t\'i treguar ato."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Transmeto mesazhet e transmetimit celular"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Lejon që aplikacioni të lidhet me modulin e transmetimit celular për t\'i transferuar mesazhet e transmetimit celular menjëherë kur merren. Sinjalizimet e transmetimit celular dërgohen në disa vendndodhje për të të paralajmëruar për situata urgjente. Aplikacionet keqdashëse mund të ndërhyjnë në cilësinë e funksionimit ose në veprimin e pajisjes sate kur merret një transmetim celular urgjent."</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"lexo mesazhet e transmetimit të qelizës"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Lejon aplikacionin të lexojë mesazhet e transmetimit të qelizës, të marra nga pajisja jote. Alarmet e transmetimit të qelizës dërgohen në disa vendndodhje për të të paralajmëruar në situata urgjente. Aplikacionet keqdashëse mund të ndërhyjnë në veprimtarinë ose operacionin e pajisjes tënde kur merret një transmetim urgjent i qelizës."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lexo informacione të abonuara"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index a3acb3d..fe12013 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -356,6 +356,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Дозвољава апликацији да прима и обрађује MMS поруке. То значи да апликација може да надгледа или брише поруке које се шаљу уређају, а да вам их не прикаже."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Прослеђивање порука за мобилне уређаје на локалитету"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Дозвољава апликацији да се везује за модул порука за мобилне уређаје на локалитету да би прослеђивала поруке за мобилне уређаје на локалитету онако како су примљене. Обавештења порука за мобилне уређаје на локалитету се на неким локацијама примају као упозорења на хитне случајеве. Злонамерне апликације могу да утичу на учинак или ометају рад уређаја када се прими порука о хитном случају за мобилне уређаје на локалитету."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Управљање одлазним позивима"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Омогућава апликацији да види детаље о одлазним позивима на уређају и да контролише те позиве."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"читање порука инфо сервиса"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Омогућава апликацији да чита поруке инфо сервиса које уређај прима. Упозорења инфо сервиса се на неким локацијама примају као упозорења на хитне случајеве. Злонамерне апликације могу да утичу на учинак или ометају функционисање уређаја када се прими порука инфо сервиса о хитном случају."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"читање пријављених фидова"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index ddd3faa..60b14ff 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Tillåter att appen tar emot och hanterar MMS-meddelanden. Detta innebär att appen kan övervaka eller ta bort meddelanden som skickats till enheten utan att visa dem för dig."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Vidarebefordra massutskick via sms"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Tillåter att appen binds till cellsändningsmodulen så att massutskick via sms kan vidarebefordras vid mottagandet. I vissa områden används massutskick via sms för att varna om nödsituationer. Skadliga appar kan påverka enhetens prestanda eller funktioner när ett massutskick via sms tas emot."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Hantera pågående samtal"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Tillåter att en app får åtkomst till information om pågående samtal på enheten och kan kontrollera dessa samtal."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"läsa SMS-meddelanden"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Appen tillåts läsa SMS som skickas till din enhet. På vissa platser skickas SMS för att varna för nödsituationer. Skadliga appar kan påverka enhetens prestanda eller funktionalitet när du får ett meddelande om en nödsituation via SMS."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"läsa flöden som du prenumererar på"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 62b1c06..0818d80 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -353,6 +353,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Inaruhusu programu kupokea na kuchakata ujumbe medianwai (MMS). Hii inamaanisha uwezo wa kuchunguza na kufuta ujumbe uliotumwa kwa kifaa chako bila ya kukuonyesha."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Sambaza ujumbe wa matangazo ya simu"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Huruhusu programu ipachikwe katika sehemu ya matangazo ya simu ili isambaze ujumbe wa matangazo ya simu unapopokewa. Arifa za matangazo ya simu huwasilishwa katika maeneo mengine ili kukuonya juu ya hali za dharura. Huenda programu hasidi zikatatiza utendaji au shughuli ya kifaa chako matangazo ya simu ya dharura yanapopokewa."</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"soma mawasiliano ya matangazo ya simu"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Huruhusu programu kusoma mawasiliano ya matangazo ya simu yaliyoingia kwenye kifaa chako. Arifa za matangazo ya simu huwasilishwa katika maeneo mengine ili kukuonya juu ya hali za dharura. Huenda programu hasidi zikatatiza utendajikazi au shughuli ya kifaa chako wakati matangazo ya simu ya dharura yameingia."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"kusoma mipasho kutoka vyanzo unavyofuatilia"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index 28a9cb7..0fe5962 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"MMS செய்திகளைப் பெற, செயற்படுத்தப் ஆப்ஸை அனுமதிக்கிறது. இதற்கு அர்த்தம் உங்கள் சாதனத்திற்கு அனுப்பப்படும் செய்திகளை உங்களுக்குக் காட்டாமல் கண்காணிக்கவோ, நீக்கவோ ஆப்ஸால் முடியும் என்பதாகும்."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"செல் பிராட்காஸ்ட் மெசேஜ்களை முன்னனுப்பு"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"செல் பிராட்காஸ்ட் மெசேஜ்களைப் பெறும்போதெல்லாம் அவற்றை முன்னனுப்பும் பொருட்டு, ஆப்ஸை செல் பிராட்காஸ்ட் மாடியூலோடு இணைக்கும். சில இடங்களில் அவசர சூழ்நிலைகளின் போது உங்களை எச்சரிக்க செல் பிராட்காஸ்ட் விழிப்பூட்டல்கள் அனுப்பப்படும். அவசரநிலை செல் பிராட்காஸ்ட்டைப் பெறும்போது, தீங்கிழைக்கும் ஆப்ஸ் உங்கள் சாதனத்தின் செயல்திறனுக்கோ செயல்பாட்டிற்கோ இடையூறு விளைவிக்கக்கூடும்."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"செயலில் உள்ள அழைப்புகளை நிர்வகித்தல்"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"உங்கள் சாதனத்தில், செயலில் உள்ள அழைப்புகள் குறித்த விவரங்களைப் பார்க்கவும் அந்த அழைப்புகளை நிர்வகிக்கவும் ஆப்ஸை அனுமதிக்கும்."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"செல் அலைபரப்புச் செய்திகளைப் படித்தல்"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"உங்கள் சாதனத்தில் பெறப்படும் செல் அலைபரப்புச் செய்திகளைப் படிப்பதற்குப் ஆப்ஸை அனுமதிக்கிறது. அவசரநிலை சூழ்நிலைகளை உங்களுக்கு எச்சரிக்கைச் செய்வதற்கு சில இடங்களில் செல் அலைபரப்பு விழிப்பூட்டல்கள் வழங்கப்படும். அவசரநிலை மொபைல் அலைபரப்புப் பெறப்படும்போது உங்கள் சாதனத்தின் செயல்திறன் அல்லது செயல்பாட்டுடன் தீங்கிழைக்கும் ஆப்ஸ் அதைத் தடுக்கலாம்."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"குழுசேர்ந்த ஊட்டங்களைப் படித்தல்"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index f9e0934..b4d3380 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -353,6 +353,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"MMS సందేశాలను స్వీకరించడానికి మరియు ప్రాసెస్ చేయడానికి యాప్ను అనుమతిస్తుంది. యాప్ మీ డివైజ్కు పంపబడిన సందేశాలను మీకు చూపకుండానే పర్యవేక్షించగలదని లేదా తొలగించగలదని దీని అర్థం."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"సెల్ ప్రసార సందేశాలను ఫార్వర్డ్ చేయడం"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"సెల్ ప్రసార సందేశాలను అందుకుంటే, వాటిని ఫార్వర్డ్ చేసే విధంగా సెల్ ప్రసార మాడ్యూల్కు కట్టుబడి ఉండటానికి యాప్ను అనుమతిస్తుంది. సెల్ ప్రసార హెచ్చరికలు అత్యవసర పరిస్థితుల గురించి మిమ్మల్ని హెచ్చరించడానికి కొన్ని స్థానాల్లో అందించబడతాయి. అత్యవసర సెల్ ప్రసారం అందుకున్నప్పుడు హానికరమైన యాప్లు మీ పరికరం యొక్క పనితీరు లేదా నిర్వహణకు అంతరాయం కలిగించవచ్చు."</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"సెల్ ప్రసార సందేశాలను చదవడం"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"మీ పరికరం స్వీకరించిన సెల్ ప్రసార సందేశాలను చదవడానికి యాప్ను అనుమతిస్తుంది. సెల్ ప్రసార హెచ్చరికలు అత్యవసర పరిస్థితుల గురించి మిమ్మల్ని హెచ్చరించడానికి కొన్ని స్థానాల్లో అందించబడతాయి. అత్యవసర సెల్ ప్రసారం స్వీకరించినప్పుడు హానికరమైన యాప్లు మీ పరికరం యొక్క పనితీరు లేదా నిర్వహణకు అంతరాయం కలిగించవచ్చు."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"చందా చేయబడిన ఫీడ్లను చదవడం"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index c23cf2b..abda062 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"อนุญาตให้แอปพลิเคชันรับและประมวลผลข้อความ MMS ซึ่งหมายความว่าแอปพลิเคชันจะสามารถตรวจสอบหรือลบข้อความที่ส่งมายังอุปกรณ์ของคุณได้โดยไม่ต้องแสดงให้คุณเห็น"</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"ส่งต่อข้อความจากการส่งข้อมูลเตือนภัยทางมือถือ (CB)"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"อนุญาตให้แอปเชื่อมโยงกับโมดูลการส่งข้อมูลเตือนภัยทางมือถือ (CB) เพื่อส่งต่อข้อความจากการส่งข้อมูลเตือนภัยทางมือถือ (CB) ทันทีที่ได้รับ ระบบจะส่งการแจ้งเตือนจากการส่งข้อมูลเตือนภัยทางมือถือ (CB) ในบางตำแหน่งเพื่อแจ้งเตือนคุณเกี่ยวกับสถานการณ์ฉุกเฉิน แอปที่เป็นอันตรายอาจรบกวนประสิทธิภาพหรือการทำงานของอุปกรณ์เมื่อได้รับการส่งข้อมูลเตือนภัยทางมือถือ (CB) ในกรณีฉุกเฉิน"</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"จัดการสายที่สนทนา"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"อนุญาตแอปเพื่อดูรายละเอียดเกี่ยวกับสายที่สนทนาอยู่บนโทรศัพท์และเพื่อควบคุมสายสนทนาเหล่านี้"</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"อ่านข้อความที่ได้รับจากสถานีมือถือ"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"อนุญาตให้แอปอ่านข้อความจากสถานีมือถือที่อุปกรณ์ได้รับ การแจ้งเตือนทางมือถือมีให้บริการในบางพื้นที่ โดยจะแจ้งเตือนคุณเกี่ยวกับสถานการณ์ฉุกเฉิน แอปที่เป็นอันตรายอาจเข้าแทรกแซงการทำงานของอุปกรณ์เมื่อได้รับข้อความแจ้งเตือนฉุกเฉิน"</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"อ่านฟีดข้อมูลที่สมัครไว้"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 8a6ad7e..286d28d 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Pinapayagan ang app na tumanggap at magproseso ng mga mensaheng MMS. Nangangahulugan ito na maaaring sumubaybay o magtanggal ang app ng mga mensaheng ipinapadala sa iyong device nang hindi ipinapakita ang mga ito sa iyo."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Magpasa ng mga mensahe ng cell broadcast"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Nagbibigay-daan sa app na mag-bind sa module ng cell broadcast para makapagpasa ng mga mensahe ng cell broadcast pagkatanggap sa mga ito. Inihahatid ang mga alerto ng cell broadcast sa ilang lokasyon para balaan ka tungkol sa mga emergency na sitwasyon. Posibleng makasagabal ang mga nakakahamak na app sa performance o pagpapatakbo ng iyong device kapag nakatanggap ito ng emergency na cell broadcast."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Pamahalaan ang mga kasalukuyang tawag"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Pinapayagan ang app na makita ang mga detalye tungkol sa mga kasalukuyang tawag sa iyong device at kontrolin ang mga tawag na ito."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"basahin ang mga mensahe ng cell broadcast"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Binibigyang-daan ang app na magbasa ng mga mensahe ng cell broadcast na natanggap ng iyong device. Inihahatid ang mga alerto ng cell broadcast sa ilang lokasyon upang balaan ka tungkol sa mga emergency na sitwasyon. Maaaring makaabala ang nakakahamak na apps sa performance o pagpapatakbo ng iyong device kapag nakatanggap ng emergency na cell broadcast."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"magbasa ng mga na-subscribe na feed"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index d31d7e9..96c15b1 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -353,6 +353,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Uygulamaya MMS iletilerini alma ve işleme izni verir. Bu izin, uygulamanın cihazınıza gönderilen iletileri takip edip size göstermeden silebileceği anlamına gelir."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Hücre yayını mesajlarını yönlendirme"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Uygulamanın hücre yayını mesajları geldiğinde bunları yönlendirmek için hücre yayını modülüne bağlanmasına izin verir. Hücre yayını uyarıları bazı konumlarda acil durumlar hakkında sizi uyarmak için kullanılır. Zararlı uygulamalar acil durum hücre yayını alındığında cihazınızın performansını ve çalışmasını olumsuz etkileyebilir."</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"hücre yayını mesajlarını oku"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Uygulamaya, cihazınız tarafından alınan hücre yayını mesajlarını okuma izni verir. Hücre yayını uyarıları bazı yerlerde acil durumlar konusunda sizi uyarmak için gönderilir. Kötü amaçlı uygulamalar acil hücre yayını alındığında cihazınızın performansına ya da çalışmasına engel olabilir."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"abone olunan yayınları okuma"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 2352584..8511edc 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -359,6 +359,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Дозволяє програмі отримувати й обробляти MMS-повідомлення. Це означає, що програма може відстежувати чи видаляти повідомлення, надіслані на ваш пристрій, навіть не показуючи їх вам."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Переадресувати повідомлення Cell Broadcast"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Дозволяє додатку зв\'язуватися з модулем Cell Broadcast, щоб переадресувати відповідні вхідні повідомлення. У деяких місцеположеннях сповіщення Cell Broadcast надсилаються для попередження про надзвичайні ситуації. Після повідомлення Cell Broadcast шкідливі додатки можуть перешкоджати роботі вашого пристрою."</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"читати широкомовні повідомлення мережі"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Дозволяє програмі читати широкомовні повідомлення мережі, отримані пристроєм. Широкомовні сповіщення мережі надсилаються в деяких країнах для попередження про надзвичайні ситуації. Шкідливі програми можуть втручатися у швидкодію чи роботу пристрою під час отримання широкомовного повідомлення мережі про надзвичайну ситуацію."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"читати підписані канали"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 68572d8..6eabc7b 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -353,6 +353,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"ایپ کو MMS پیغامات حاصل اور ان پر کارروائی کرنے کی اجازت دیتا ہے۔ اس کا مطلب ہے کہ ایپ آپ کے آلے پر مرسلہ پیغامات آپ کو دکھائے بغیر ان پر نگاہ رکھ یا انہیں حذف کرسکتی ہے۔"</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"سیل کے نشریاتی پیغامات فارورڈ کریں"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"سیل کی نشریاتی پیغامات کے موصول ہوتے ہی فارورڈ کرنے کے لیے ایپ کو سیل کے نشریاتی ماڈیول میں پابندی لگانے کی اجازت دیں۔ سیل کی نشریاتی الرٹس آپ کو ہنگامی حالات سے مطلع کرنے کیلئے کچھ مقامات میں مہیا کی جاتی ہیں۔ نقصان دہ ایپس کوئی ہنگامی سیل براڈ کاسٹ موصول ہونے پر آپ کے آلے کی کارکردگی یا عمل میں مداخلت کر سکتی ہیں۔"</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"سیل کے نشریاتی پیغامات پڑھیں"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"ایپ کو آپ کے آلے کو موصولہ سیل کے نشریاتی پیغامات پڑھنے کی اجازت دیتا ہے۔ سیل کی نشریاتی الرٹس آپ کو ہنگامی حالات سے مطلع کرنے کیلئے کچھ مقامات میں مہیا کی جاتی ہیں۔ نقصان دہ ایپس کوئی ہنگامی سیل کا نشریہ موصول ہونے پر آپ کے آلے کی کارکردگی یا عمل میں خلل ڈال سکتی ہیں۔"</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"سبسکرائب کردہ فیڈز پڑھیں"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 423669d..00f2215 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Ilovaga MMS xabarlarini qabul qilish va ularni qayta ishlash uchun ruxsat beradi. Bu sizga yuborilgan xabarlarni ilova sizga ko‘rsatmasdan kuzatishi va o‘chirishi mumkinligini bildiradi."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Aholini ogohlantirish xabarlarini uzatish"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Qabul qilingan aholini ogohlantirish xabarlarini shu holicha uzatish uchun ilovani aholini ogohlantirish moduliga bogʻlash imkonini beradi. Ilovaga ayrim mamlakatlarda aholini favqulodda vaziyatlarda ogohlantirish uchun yuboriladigan tarqatma xabarlarni oʻqish uchun ruxsat beradi. Zararli dasturlar bunday xabarlar kelayotgan qurilmaning ishlashiga xalaqit qilishi mumkin."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Amaldagi chaqiruvlarni boshqarish"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Ilovaga qurilmangizdagi amaldagi chaqiruv tafsilotlarini koʻrish va uni boshqarish huquqini beradi."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"uyali tarmoq operatori xabarlarini o‘qish"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Ilovaga qurilmangiz tomonidan qabul qilingan uyali tarmoq operatori xabarlarini o‘qish uchun ruxsat beradi. Uyali tarmoq operatorining ogohlantiruvchi xabarlari ba’zi manzillarga favqulodda holatlar haqida ogohlantirish uchun jo‘natiladi. Zararli ilovalar uyali tarmoq orqali favqulodda xabar qabul qilinganda qurilmangizning ish faoliyati yoki amallariga xalaqit qilishi mumkin"</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"obunalarni o‘qish"</string>
@@ -1773,7 +1775,7 @@
<string name="restr_pin_confirm_pin" msgid="7143161971614944989">"Yangi PIN kodni tasdiqlash"</string>
<string name="restr_pin_create_pin" msgid="917067613896366033">"Cheklovlarni o‘zgartirish uchun PIN-kod yaratish"</string>
<string name="restr_pin_error_doesnt_match" msgid="7063392698489280556">"PIN-kod mos kelmadi. Qayta urinib ko‘ring."</string>
- <string name="restr_pin_error_too_short" msgid="1547007808237941065">"PIN kod kamida 4 ta raqamdan iborat bo‘lishi shart."</string>
+ <string name="restr_pin_error_too_short" msgid="1547007808237941065">"PIN kod juda qisqa, kamida 4 ta raqam kiriting."</string>
<plurals name="restr_pin_countdown" formatted="false" msgid="4427486903285216153">
<item quantity="other"><xliff:g id="COUNT">%d</xliff:g> soniyadan so‘ng qayta urinib ko‘ring</item>
<item quantity="one">1 soniyadan so‘ng qayta urinib ko‘ring</item>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 7533196..8b27cd0 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -353,6 +353,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Cho phép ứng dụng nhận và xử lý tin nhắn MMS. Điều này có nghĩa là ứng dụng có thể theo dõi hoặc xóa tin nhắn được gửi đến thiết bị của bạn mà không hiển thị chúng cho bạn."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Chuyển tiếp tin nhắn truyền phát trên di động"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Cho phép ứng dụng liên kết với mô-đun truyền phát trên di động để chuyển tiếp tin nhắn truyền phát trên di động ngay khi nhận được. Ở một số vị trí, thông báo truyền phát trên di động sẽ được gửi nhằm cảnh báo cho bạn về các tình huống khẩn cấp. Các ứng dụng độc hại có thể ảnh hưởng đến hiệu suất hoặc hoạt động của thiết bị khi nhận được tin nhắn truyền phát trên di động lúc khẩn cấp."</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"đọc tin nhắn quảng bá"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Cho phép ứng dụng đọc tin nhắn quảng bá mà thiết bị của bạn nhận được. Tin nhắn quảng bá cảnh báo được gửi ở một số địa điểm nhằm cảnh báo cho bạn về các tình huống khẩn cấp. Các ứng dụng độc hại có thể gây ảnh hưởng đến hiệu suất hoặc hoạt động của thiết bị của bạn khi nhận được tin nhắn quảng bá khẩn cấp."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"đọc nguồn cấp dữ liệu đã đăng ký"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 811992e..9826dfb 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -353,6 +353,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"允许该应用接收和处理彩信。这就意味着,该应用可能会监视发送到您设备的彩信,或删除发送到您设备的彩信而不向您显示。"</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"转发小区广播消息"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"允许应用绑定到小区广播模块,以便及时转发收到的小区广播消息。小区广播消息是在某些地区发送的、用于发布紧急情况警告的提醒信息。恶意应用可能会在您的设备收到紧急小区广播时干扰设备的性能或操作。"</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"读取小区广播消息"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"允许应用读取您的设备收到的小区广播消息。小区广播消息是在某些地区发送的、用于发布紧急情况警告的提醒信息。恶意应用可能会在您收到小区紧急广播时干扰您设备的性能或操作。"</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"读取订阅的供稿"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 25807ca..33196c82 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"允許應用程式接收和處理 MMS 訊息。這表示應用程式可監控傳送至您裝置的訊息,或在您閱讀訊息前擅自刪除訊息。"</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"轉寄區域廣播訊息"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"允許應用程式繫結至區域廣播模組,以在收到區域廣播訊息時轉寄訊息。在某些地點,系統會發出區域廣播通知,提示您有緊急狀況發生。惡意應用程式可能會在裝置收到緊急區域廣播時,干擾裝置的效能或運作。"</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"管理正在進行的通話"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"允許應用程式查看裝置上正在進行的通話詳情並控制通話。"</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"讀取區域廣播訊息"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"允許應用程式讀取您裝置接收的區域廣播訊息。某些地點會發出區域廣播警報,警告您發生緊急狀況。惡意應用程式可能會在裝置收到緊急區域廣播時,干擾裝置的性能或運作。"</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"讀取訂閱的資訊提供"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 238a890..a034f0b 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -353,6 +353,10 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"允許應用程式接收和處理多媒體訊息。這項設定可讓應用程式監控傳送至你裝置的訊息,或在你閱讀訊息前擅自刪除訊息。"</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"轉送區域廣播訊息"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"允許應用程式繫結至區域廣播模組,以便轉送收到的區域廣播訊息。某些地點會發出區域廣播警示,警告你有緊急狀況發生。請注意,惡意應用程式可能會在裝置收到緊急區域廣播時,干擾裝置的效能或運作。"</string>
+ <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
+ <skip />
+ <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
+ <skip />
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"讀取區域廣播訊息"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"允許應用程式讀取你裝置收到的區域廣播訊息。某些地點會發出區域廣播警示,警告你有緊急狀況發生。請注意,惡意應用程式可能會在裝置收到緊急區域廣播時,干擾裝置的效能或運作。"</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"讀取訂閱資訊提供"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 6a23502..67eb874 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -353,6 +353,8 @@
<string name="permdesc_receiveMms" msgid="958102423732219710">"Ivumela uhlelo lokusebenza ukuthola nokucubungula imilayezo ye-MMS. Loku kuchaza ukuthi uhlelo lokusebenza lungangamela noma lesuse imilayezo ethunyelwe kudivayisi yakho ngaphandle kokukubonisa yona."</string>
<string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Dlulisela imilayezo yokusakaza kweselula"</string>
<string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Ivumela uhlelo lokusebenza ukuthi luboshezelwe kumojuli yokusakaza kweselula ukuze kudluliselwe imilayezo yokusakaza yeselula njengoba itholwa. Izexwayiso zokusakaza kweselula zilethwa kwezinye izindawo ukuze zikuxwayise ngezimo zesimo esiphuthumayo. Izinhlelo zokusebenza ezinobungozi zingaphazamisa ngokusebenza noma ukusetshenziswa kwedivayisi yakho uma ukusakaza kweselula kwesimo esiphuthumayo kwamukelwa."</string>
+ <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Phatha amakholi aqhubekayo"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Ivumela uhlelo lokusebenza ukubona imininingwane emayelana namakholi aqhubekayo kudivayisi yakho nokulawula lamakholi."</string>
<string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"funda imilayezo yokusakaza yeselula"</string>
<string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Ivumela uhlelo lokusebenza ukufunda imilayezo yokusakaza yeselula etholwe idivayisi yakho. Izaziso zokusakaza zeselula zilethwa kwezinye izindawo ukukuxwayisa ngezimo ezisheshayo. Izinhlelo zokusebenza ezingalungile zingaphazamisana nokusebenza noma umsebenzi wedivayisi yakho uma ukusakaza kweselula kwesimo esisheshayo kutholwa."</string>
<string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"funda izifunzo ezikhokhelwayo"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index cddb8b5..fab65d0 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -654,10 +654,9 @@
The default is false. -->
<bool name="config_lidControlsSleep">false</bool>
- <!-- Indicate whether closing the lid causes the device to enter the folded state which means
- to get a smaller screen and opening the lid causes the device to enter the unfolded state
- which means to get a larger screen. -->
- <bool name="config_lidControlsDisplayFold">false</bool>
+ <!-- The device state (supplied by DeviceStateManager) that should be treated as folded by the
+ display fold controller. Default is DeviceStateManager.INVALID_DEVICE_STATE. -->
+ <integer name="config_foldedDeviceState">-1</integer>
<!-- Indicate the display area rect for foldable devices in folded state. -->
<string name="config_foldedArea"></string>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 05db741..4fd8ef6 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -480,7 +480,7 @@
<dimen name="notification_inbox_item_top_padding">5dp</dimen>
<!-- Size of the feedback indicator for notifications -->
- <dimen name="notification_feedback_size">14dp</dimen>
+ <dimen name="notification_feedback_size">16dp</dimen>
<!-- Size of the profile badge for notifications -->
<dimen name="notification_badge_size">12dp</dimen>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index a2556a1..88a78a8 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1436,6 +1436,10 @@
<java-symbol type="drawable" name="ic_mic" />
<java-symbol type="drawable" name="ic_alert_window_layer" />
<java-symbol type="drawable" name="ic_feedback_indicator" />
+ <java-symbol type="drawable" name="ic_feedback_alerted" />
+ <java-symbol type="drawable" name="ic_feedback_silenced" />
+ <java-symbol type="drawable" name="ic_feedback_uprank" />
+ <java-symbol type="drawable" name="ic_feedback_downrank" />
<java-symbol type="drawable" name="ic_account_circle" />
<java-symbol type="color" name="user_icon_1" />
@@ -3702,7 +3706,7 @@
<java-symbol type="string" name="config_customCountryDetector" />
<!-- For Foldables -->
- <java-symbol type="bool" name="config_lidControlsDisplayFold" />
+ <java-symbol type="integer" name="config_foldedDeviceState" />
<java-symbol type="string" name="config_foldedArea" />
<java-symbol type="array" name="config_disableApksUnlessMatchedSku_apk_list" />
diff --git a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java
index b077ea3..1d9d9e8 100644
--- a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java
+++ b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java
@@ -21,6 +21,7 @@
import android.os.BatteryStats;
import android.os.BatteryUsageStats;
import android.os.Process;
+import android.os.SystemBatteryConsumer;
import android.os.UidBatteryConsumer;
import android.os.UserHandle;
@@ -154,6 +155,15 @@
return;
}
+ if (requestedBatteryConsumer == null) {
+ for (BatteryConsumer consumer : batteryUsageStats.getSystemBatteryConsumers()) {
+ if (batteryConsumerId(consumer).equals(batteryConsumerId)) {
+ requestedBatteryConsumer = consumer;
+ break;
+ }
+ }
+ }
+
mBatteryConsumerInfo = BatteryConsumerInfoHelper.makeBatteryConsumerInfo(
context.getPackageManager(), requestedBatterySipper);
long totalScreenMeasuredEnergyUJ = batteryStats.getScreenOnEnergy();
@@ -185,8 +195,14 @@
requestedBatterySipper.cpuPowerMah, totalCpuPowerMah);
addEntry("System services", EntryType.POWER,
requestedBatterySipper.systemServiceCpuPowerMah, totalSystemServiceCpuPowerMah);
- addEntry("Usage", EntryType.POWER,
- requestedBatterySipper.usagePowerMah, totalUsagePowerMah);
+ if (requestedBatteryConsumer != null) {
+ addEntry("Usage", EntryType.POWER,
+ requestedBatteryConsumer.getConsumedPower(
+ BatteryConsumer.POWER_COMPONENT_USAGE), totalUsagePowerMah);
+ } else {
+ addEntry("Usage (sipper)", EntryType.POWER,
+ requestedBatterySipper.usagePowerMah, totalUsagePowerMah);
+ }
addEntry("Wake lock", EntryType.POWER,
requestedBatterySipper.wakeLockPowerMah, totalWakeLockPowerMah);
addEntry("Mobile radio", EntryType.POWER,
@@ -295,6 +311,8 @@
return BatterySipper.DrainType.APP + "|"
+ UserHandle.getUserId(((UidBatteryConsumer) consumer).getUid()) + "|"
+ ((UidBatteryConsumer) consumer).getUid();
+ } else if (consumer instanceof SystemBatteryConsumer) {
+ return ((SystemBatteryConsumer) consumer).getDrainType() + "|0|0";
} else {
return "";
}
diff --git a/core/tests/coretests/src/android/app/OWNERS b/core/tests/coretests/src/android/app/OWNERS
new file mode 100644
index 0000000..bd7da0c
--- /dev/null
+++ b/core/tests/coretests/src/android/app/OWNERS
@@ -0,0 +1 @@
+per-file Window*.java = file:/services/core/java/com/android/server/wm/OWNERS
diff --git a/core/tests/coretests/src/android/app/activity/OWNERS b/core/tests/coretests/src/android/app/activity/OWNERS
new file mode 100644
index 0000000..0862c05
--- /dev/null
+++ b/core/tests/coretests/src/android/app/activity/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/core/tests/coretests/src/android/app/appsearch/OWNERS b/core/tests/coretests/src/android/app/appsearch/OWNERS
new file mode 100644
index 0000000..24f6b0b
--- /dev/null
+++ b/core/tests/coretests/src/android/app/appsearch/OWNERS
@@ -0,0 +1 @@
+include /apex/appsearch/OWNERS
\ No newline at end of file
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/SetSchemaRequestTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/SetSchemaRequestTest.java
index e03cea3..879aa09 100644
--- a/core/tests/coretests/src/android/app/appsearch/external/app/SetSchemaRequestTest.java
+++ b/core/tests/coretests/src/android/app/appsearch/external/app/SetSchemaRequestTest.java
@@ -16,28 +16,54 @@
package android.app.appsearch;
+import static android.app.appsearch.AppSearchSchema.PropertyConfig.INDEXING_TYPE_PREFIXES;
+import static android.app.appsearch.AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_PLAIN;
+
import static com.google.common.truth.Truth.assertThat;
import static org.testng.Assert.expectThrows;
+import android.util.ArrayMap;
+
import org.junit.Test;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
public class SetSchemaRequestTest {
@Test
- public void testInvalidSchemaReferences() {
+ public void testInvalidSchemaReferences_fromSystemUiVisibility() {
IllegalArgumentException expected =
expectThrows(
IllegalArgumentException.class,
() ->
new SetSchemaRequest.Builder()
- .setSchemaTypeVisibilityForSystemUi(false, "InvalidSchema")
+ .setSchemaTypeVisibilityForSystemUi("InvalidSchema", false)
.build());
assertThat(expected).hasMessageThat().contains("referenced, but were not added");
}
@Test
- public void testSchemaTypeVisibilityForSystemUi_Visible() {
+ public void testInvalidSchemaReferences_fromPackageVisibility() {
+ IllegalArgumentException expected =
+ expectThrows(
+ IllegalArgumentException.class,
+ () ->
+ new SetSchemaRequest.Builder()
+ .setSchemaTypeVisibilityForPackage(
+ "InvalidSchema",
+ /*visible=*/ true,
+ new PackageIdentifier(
+ "com.foo.package",
+ /*certificate=*/ new byte[] {}))
+ .build());
+ assertThat(expected).hasMessageThat().contains("referenced, but were not added");
+ }
+
+ @Test
+ public void testSchemaTypeVisibilityForSystemUi_visible() {
AppSearchSchema schema = new AppSearchSchema.Builder("Schema").build();
// By default, the schema is visible.
@@ -47,19 +73,106 @@
request =
new SetSchemaRequest.Builder()
.addSchema(schema)
- .setSchemaTypeVisibilityForSystemUi(true, "Schema")
+ .setSchemaTypeVisibilityForSystemUi("Schema", true)
.build();
assertThat(request.getSchemasNotPlatformSurfaceable()).isEmpty();
}
@Test
- public void testSchemaTypeVisibilityForSystemUi_NotVisible() {
+ public void testSchemaTypeVisibilityForSystemUi_notVisible() {
AppSearchSchema schema = new AppSearchSchema.Builder("Schema").build();
SetSchemaRequest request =
new SetSchemaRequest.Builder()
.addSchema(schema)
- .setSchemaTypeVisibilityForSystemUi(false, "Schema")
+ .setSchemaTypeVisibilityForSystemUi("Schema", false)
.build();
assertThat(request.getSchemasNotPlatformSurfaceable()).containsExactly("Schema");
}
+
+ @Test
+ public void testSchemaTypeVisibilityForPackage_visible() {
+ AppSearchSchema schema = new AppSearchSchema.Builder("Schema").build();
+
+ // By default, the schema is not visible.
+ SetSchemaRequest request = new SetSchemaRequest.Builder().addSchema(schema).build();
+ assertThat(request.getSchemasPackageAccessible()).isEmpty();
+
+ PackageIdentifier packageIdentifier =
+ new PackageIdentifier("com.package.foo", new byte[] {100});
+ Map<String, Set<PackageIdentifier>> expectedPackageVisibleMap = new ArrayMap<>();
+ expectedPackageVisibleMap.put("Schema", Collections.singleton(packageIdentifier));
+
+ request =
+ new SetSchemaRequest.Builder()
+ .addSchema(schema)
+ .setSchemaTypeVisibilityForPackage(
+ "Schema", /*visible=*/ true, packageIdentifier)
+ .build();
+ assertThat(request.getSchemasPackageAccessible())
+ .containsExactlyEntriesIn(expectedPackageVisibleMap);
+ }
+
+ @Test
+ public void testSchemaTypeVisibilityForPackage_notVisible() {
+ AppSearchSchema schema = new AppSearchSchema.Builder("Schema").build();
+
+ SetSchemaRequest request =
+ new SetSchemaRequest.Builder()
+ .addSchema(schema)
+ .setSchemaTypeVisibilityForPackage(
+ "Schema",
+ /*visible=*/ false,
+ new PackageIdentifier(
+ "com.package.foo", /*certificate=*/ new byte[] {}))
+ .build();
+ assertThat(request.getSchemasPackageAccessible()).isEmpty();
+ }
+
+ @Test
+ public void testSchemaTypeVisibilityForPackage_deduped() throws Exception {
+ AppSearchSchema schema = new AppSearchSchema.Builder("Schema").build();
+
+ PackageIdentifier packageIdentifier =
+ new PackageIdentifier("com.package.foo", new byte[] {100});
+ Map<String, Set<PackageIdentifier>> expectedPackageVisibleMap = new ArrayMap<>();
+ expectedPackageVisibleMap.put("Schema", Collections.singleton(packageIdentifier));
+
+ SetSchemaRequest request =
+ new SetSchemaRequest.Builder()
+ .addSchema(schema)
+ // Set it visible for "Schema"
+ .setSchemaTypeVisibilityForPackage(
+ "Schema", /*visible=*/ true, packageIdentifier)
+ // Set it visible for "Schema" again, which should be a no-op
+ .setSchemaTypeVisibilityForPackage(
+ "Schema", /*visible=*/ true, packageIdentifier)
+ .build();
+ assertThat(request.getSchemasPackageAccessible())
+ .containsExactlyEntriesIn(expectedPackageVisibleMap);
+ }
+
+ @Test
+ public void testSchemaTypeVisibilityForPackage_removed() throws Exception {
+ AppSearchSchema schema = new AppSearchSchema.Builder("Schema").build();
+
+ SetSchemaRequest request =
+ new SetSchemaRequest.Builder()
+ .addSchema(schema)
+ // First set it as visible
+ .setSchemaTypeVisibilityForPackage(
+ "Schema",
+ /*visible=*/ true,
+ new PackageIdentifier(
+ "com.package.foo", /*certificate=*/ new byte[] {100}))
+ // Then make it not visible
+ .setSchemaTypeVisibilityForPackage(
+ "Schema",
+ /*visible=*/ false,
+ new PackageIdentifier(
+ "com.package.foo", /*certificate=*/ new byte[] {100}))
+ .build();
+
+ // Nothing should be visible.
+ assertThat(request.getSchemasPackageAccessible()).isEmpty();
+ }
}
diff --git a/core/tests/coretests/src/android/app/servertransaction/OWNERS b/core/tests/coretests/src/android/app/servertransaction/OWNERS
new file mode 100644
index 0000000..0862c05
--- /dev/null
+++ b/core/tests/coretests/src/android/app/servertransaction/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/core/tests/coretests/src/android/app/time/OWNERS b/core/tests/coretests/src/android/app/time/OWNERS
new file mode 100644
index 0000000..8f80897
--- /dev/null
+++ b/core/tests/coretests/src/android/app/time/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 847766
+mingaleev@google.com
+include /core/java/android/app/timedetector/OWNERS
diff --git a/core/tests/coretests/src/android/app/timedetector/GnssTimeSuggestionTest.java b/core/tests/coretests/src/android/app/timedetector/GnssTimeSuggestionTest.java
new file mode 100644
index 0000000..e248010
--- /dev/null
+++ b/core/tests/coretests/src/android/app/timedetector/GnssTimeSuggestionTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.timedetector;
+
+import static android.app.timezonedetector.ParcelableTestSupport.assertRoundTripParcelable;
+import static android.app.timezonedetector.ParcelableTestSupport.roundTripParcelable;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import android.os.TimestampedValue;
+
+import org.junit.Test;
+
+public class GnssTimeSuggestionTest {
+
+ private static final TimestampedValue<Long> ARBITRARY_TIME =
+ new TimestampedValue<>(1111L, 2222L);
+
+ @Test
+ public void testEquals() {
+ GnssTimeSuggestion one = new GnssTimeSuggestion(ARBITRARY_TIME);
+ assertEquals(one, one);
+
+ GnssTimeSuggestion two = new GnssTimeSuggestion(ARBITRARY_TIME);
+ assertEquals(one, two);
+ assertEquals(two, one);
+
+ TimestampedValue<Long> differentTime = new TimestampedValue<>(
+ ARBITRARY_TIME.getReferenceTimeMillis() + 1,
+ ARBITRARY_TIME.getValue());
+ GnssTimeSuggestion three = new GnssTimeSuggestion(differentTime);
+ assertNotEquals(one, three);
+ assertNotEquals(three, one);
+
+ // DebugInfo must not be considered in equals().
+ one.addDebugInfo("Debug info 1");
+ two.addDebugInfo("Debug info 2");
+ assertEquals(one, two);
+ }
+
+ @Test
+ public void testParcelable() {
+ GnssTimeSuggestion suggestion = new GnssTimeSuggestion(ARBITRARY_TIME);
+ assertRoundTripParcelable(suggestion);
+
+ // DebugInfo should also be stored (but is not checked by equals()
+ suggestion.addDebugInfo("This is debug info");
+ GnssTimeSuggestion rtSuggestion = roundTripParcelable(suggestion);
+ assertEquals(suggestion.getDebugInfo(), rtSuggestion.getDebugInfo());
+ }
+}
diff --git a/core/tests/coretests/src/android/app/timedetector/OWNERS b/core/tests/coretests/src/android/app/timedetector/OWNERS
new file mode 100644
index 0000000..8f80897
--- /dev/null
+++ b/core/tests/coretests/src/android/app/timedetector/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 847766
+mingaleev@google.com
+include /core/java/android/app/timedetector/OWNERS
diff --git a/core/tests/coretests/src/android/app/timezone/OWNERS b/core/tests/coretests/src/android/app/timezone/OWNERS
new file mode 100644
index 0000000..8f80897
--- /dev/null
+++ b/core/tests/coretests/src/android/app/timezone/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 847766
+mingaleev@google.com
+include /core/java/android/app/timedetector/OWNERS
diff --git a/core/tests/coretests/src/android/app/timezonedetector/OWNERS b/core/tests/coretests/src/android/app/timezonedetector/OWNERS
new file mode 100644
index 0000000..8f80897
--- /dev/null
+++ b/core/tests/coretests/src/android/app/timezonedetector/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 847766
+mingaleev@google.com
+include /core/java/android/app/timedetector/OWNERS
diff --git a/core/tests/coretests/src/android/content/OWNERS b/core/tests/coretests/src/android/content/OWNERS
new file mode 100644
index 0000000..911efb2
--- /dev/null
+++ b/core/tests/coretests/src/android/content/OWNERS
@@ -0,0 +1 @@
+per-file ContextTest.java = file:/services/core/java/com/android/server/wm/OWNERS
diff --git a/core/tests/mockingcoretests/src/android/app/activity/OWNERS b/core/tests/mockingcoretests/src/android/app/activity/OWNERS
new file mode 100644
index 0000000..0862c05
--- /dev/null
+++ b/core/tests/mockingcoretests/src/android/app/activity/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/graphics/java/android/graphics/OWNERS b/graphics/java/android/graphics/OWNERS
index c3fb6f8..a8a3631 100644
--- a/graphics/java/android/graphics/OWNERS
+++ b/graphics/java/android/graphics/OWNERS
@@ -6,3 +6,6 @@
sumir@google.com
per-file BLASTBufferQueue.java = file:/services/core/java/com/android/server/wm/OWNERS
+per-file FontFamily.java = file:fonts/OWNERS
+per-file FontListParser.java = file:fonts/OWNERS
+per-file Typeface.java = file:fonts/OWNERS
diff --git a/libs/WindowManager/Shell/res/layout/docked_stack_divider.xml b/libs/WindowManager/Shell/res/layout/docked_stack_divider.xml
index ad87025..ea21eb9 100644
--- a/libs/WindowManager/Shell/res/layout/docked_stack_divider.xml
+++ b/libs/WindowManager/Shell/res/layout/docked_stack_divider.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
-<com.android.wm.shell.splitscreen.DividerView
+<com.android.wm.shell.legacysplitscreen.DividerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent">
@@ -24,15 +24,15 @@
android:id="@+id/docked_divider_background"
android:background="@color/docked_divider_background"/>
- <com.android.wm.shell.splitscreen.MinimizedDockShadow
+ <com.android.wm.shell.legacysplitscreen.MinimizedDockShadow
style="@style/DockedDividerMinimizedShadow"
android:id="@+id/minimized_dock_shadow"
android:alpha="0"/>">
- <com.android.wm.shell.splitscreen.DividerHandleView
+ <com.android.wm.shell.legacysplitscreen.DividerHandleView
style="@style/DockedDividerHandle"
android:id="@+id/docked_divider_handle"
android:contentDescription="@string/accessibility_divider"
android:background="@null"/>
-</com.android.wm.shell.splitscreen.DividerView>
+</com.android.wm.shell.legacysplitscreen.DividerView>
diff --git a/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json b/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
index db9e1af9..4070829 100644
--- a/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
+++ b/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
@@ -1,12 +1,6 @@
{
"version": "1.0.0",
"messages": {
- "-1993693214": {
- "message": "Letterbox Task Changed: #%d",
- "level": "VERBOSE",
- "group": "WM_SHELL_TASK_ORG",
- "at": "com\/android\/wm\/shell\/letterbox\/LetterboxTaskListener.java"
- },
"-1683614271": {
"message": "Existing task: id=%d component=%s",
"level": "VERBOSE",
@@ -37,6 +31,12 @@
"group": "WM_SHELL_DRAG_AND_DROP",
"at": "com\/android\/wm\/shell\/draganddrop\/DragAndDropController.java"
},
+ "-1362429294": {
+ "message": "%s onTaskAppeared Primary taskId=%d",
+ "level": "VERBOSE",
+ "group": "WM_SHELL_TASK_ORG",
+ "at": "com\/android\/wm\/shell\/legacysplitscreen\/LegacySplitScreenTaskListener.java"
+ },
"-1340279385": {
"message": "Remove listener=%s",
"level": "VERBOSE",
@@ -73,12 +73,6 @@
"group": "WM_SHELL_TASK_ORG",
"at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
},
- "-842742255": {
- "message": "%s onTaskAppeared unknown taskId=%d winMode=%d",
- "level": "VERBOSE",
- "group": "WM_SHELL_TASK_ORG",
- "at": "com\/android\/wm\/shell\/splitscreen\/SplitScreenTaskListener.java"
- },
"-742394458": {
"message": "pair task1=%d task2=%d in AppPair=%s",
"level": "VERBOSE",
@@ -91,17 +85,11 @@
"group": "WM_SHELL_DRAG_AND_DROP",
"at": "com\/android\/wm\/shell\/draganddrop\/DragLayout.java"
},
- "-679492476": {
- "message": "%s onTaskAppeared Primary taskId=%d",
+ "-298656957": {
+ "message": "%s onTaskAppeared unknown taskId=%d winMode=%d",
"level": "VERBOSE",
"group": "WM_SHELL_TASK_ORG",
- "at": "com\/android\/wm\/shell\/splitscreen\/SplitScreenTaskListener.java"
- },
- "-342975160": {
- "message": "Letterbox Task Vanished: #%d",
- "level": "VERBOSE",
- "group": "WM_SHELL_TASK_ORG",
- "at": "com\/android\/wm\/shell\/letterbox\/LetterboxTaskListener.java"
+ "at": "com\/android\/wm\/shell\/legacysplitscreen\/LegacySplitScreenTaskListener.java"
},
"-234284913": {
"message": "unpair taskId=%d pair=%s",
@@ -115,12 +103,6 @@
"group": "WM_SHELL_TRANSITIONS",
"at": "com\/android\/wm\/shell\/Transitions.java"
},
- "154313206": {
- "message": "%s onTaskAppeared Secondary taskId=%d",
- "level": "VERBOSE",
- "group": "WM_SHELL_TASK_ORG",
- "at": "com\/android\/wm\/shell\/splitscreen\/SplitScreenTaskListener.java"
- },
"157713005": {
"message": "Task info changed taskId=%d",
"level": "VERBOSE",
@@ -139,6 +121,12 @@
"group": "WM_SHELL_DRAG_AND_DROP",
"at": "com\/android\/wm\/shell\/draganddrop\/DragAndDropController.java"
},
+ "473543554": {
+ "message": "%s onTaskAppeared Supported",
+ "level": "VERBOSE",
+ "group": "WM_SHELL_TASK_ORG",
+ "at": "com\/android\/wm\/shell\/legacysplitscreen\/LegacySplitScreenTaskListener.java"
+ },
"481673835": {
"message": "addListenerForTaskId taskId=%s",
"level": "VERBOSE",
@@ -175,6 +163,12 @@
"group": "WM_SHELL_TASK_ORG",
"at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
},
+ "982027396": {
+ "message": "%s onTaskAppeared Secondary taskId=%d",
+ "level": "VERBOSE",
+ "group": "WM_SHELL_TASK_ORG",
+ "at": "com\/android\/wm\/shell\/legacysplitscreen\/LegacySplitScreenTaskListener.java"
+ },
"1079041527": {
"message": "incrementPool size=%d",
"level": "VERBOSE",
@@ -199,12 +193,6 @@
"group": "WM_SHELL_DRAG_AND_DROP",
"at": "com\/android\/wm\/shell\/draganddrop\/DragAndDropController.java"
},
- "1885882094": {
- "message": "Letterbox Task Appeared: #%d",
- "level": "VERBOSE",
- "group": "WM_SHELL_TASK_ORG",
- "at": "com\/android\/wm\/shell\/letterbox\/LetterboxTaskListener.java"
- },
"1891981945": {
"message": "release entry.taskId=%s listener=%s size=%d",
"level": "VERBOSE",
@@ -228,12 +216,6 @@
"level": "VERBOSE",
"group": "WM_SHELL_DRAG_AND_DROP",
"at": "com\/android\/wm\/shell\/draganddrop\/DragAndDropController.java"
- },
- "2135461748": {
- "message": "%s onTaskAppeared Supported",
- "level": "VERBOSE",
- "group": "WM_SHELL_TASK_ORG",
- "at": "com\/android\/wm\/shell\/splitscreen\/SplitScreenTaskListener.java"
}
},
"groups": {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/RootTaskDisplayAreaOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/RootTaskDisplayAreaOrganizer.java
new file mode 100644
index 0000000..f741a42
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/RootTaskDisplayAreaOrganizer.java
@@ -0,0 +1,169 @@
+/*
+ * 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;
+
+import android.util.SparseArray;
+import android.view.SurfaceControl;
+import android.window.DisplayAreaInfo;
+import android.window.DisplayAreaOrganizer;
+
+import androidx.annotation.NonNull;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Executor;
+
+/** Display area organizer for the root/default TaskDisplayAreas */
+public class RootTaskDisplayAreaOrganizer extends DisplayAreaOrganizer {
+
+ private static final String TAG = RootTaskDisplayAreaOrganizer.class.getSimpleName();
+
+ // Display area info. mapped by displayIds.
+ private final SparseArray<DisplayAreaInfo> mDisplayAreasInfo = new SparseArray<>();
+ // Display area leashes. mapped by displayIds.
+ private final SparseArray<SurfaceControl> mLeashes = new SparseArray<>();
+
+ private final SparseArray<ArrayList<RootTaskDisplayAreaListener>> mListeners =
+ new SparseArray<>();
+
+ public RootTaskDisplayAreaOrganizer(Executor executor) {
+ super(executor);
+ registerOrganizer(FEATURE_DEFAULT_TASK_CONTAINER);
+ }
+
+ public void registerListener(int displayId, RootTaskDisplayAreaListener listener) {
+ ArrayList<RootTaskDisplayAreaListener> listeners = mListeners.get(displayId);
+ if (listeners == null) {
+ listeners = new ArrayList<>();
+ mListeners.put(displayId, listeners);
+ }
+
+ listeners.add(listener);
+
+ final DisplayAreaInfo info = mDisplayAreasInfo.get(displayId);
+ if (info != null) {
+ listener.onDisplayAreaAppeared(info);
+ }
+ }
+
+ public void unregisterListener(RootTaskDisplayAreaListener listener) {
+ for (int i = mListeners.size() - 1; i >= 0; --i) {
+ final List<RootTaskDisplayAreaListener> listeners = mListeners.valueAt(i);
+ if (listeners == null) continue;
+ listeners.remove(listener);
+ }
+ }
+
+ public void attachToDisplayArea(int displayId, SurfaceControl.Builder b) {
+ final SurfaceControl sc = mLeashes.get(displayId);
+ b.setParent(sc);
+ }
+
+ @Override
+ public void onDisplayAreaAppeared(@NonNull DisplayAreaInfo displayAreaInfo,
+ @NonNull SurfaceControl leash) {
+ if (displayAreaInfo.featureId != FEATURE_DEFAULT_TASK_CONTAINER) {
+ throw new IllegalArgumentException(
+ "Unknown feature: " + displayAreaInfo.featureId
+ + "displayAreaInfo:" + displayAreaInfo);
+ }
+
+ final int displayId = displayAreaInfo.displayId;
+ if (mDisplayAreasInfo.get(displayId) != null) {
+ throw new IllegalArgumentException(
+ "Duplicate DA for displayId: " + displayId
+ + " displayAreaInfo:" + displayAreaInfo
+ + " mDisplayAreasInfo.get():" + mDisplayAreasInfo.get(displayId));
+ }
+
+ mDisplayAreasInfo.put(displayId, displayAreaInfo);
+
+ ArrayList<RootTaskDisplayAreaListener> listeners = mListeners.get(displayId);
+ if (listeners != null) {
+ for (int i = listeners.size() - 1; i >= 0; --i) {
+ listeners.get(i).onDisplayAreaAppeared(displayAreaInfo);
+ }
+ }
+ }
+
+ @Override
+ public void onDisplayAreaVanished(@NonNull DisplayAreaInfo displayAreaInfo) {
+ final int displayId = displayAreaInfo.displayId;
+ if (mDisplayAreasInfo.get(displayId) == null) {
+ throw new IllegalArgumentException(
+ "onDisplayAreaVanished() Unknown DA displayId: " + displayId
+ + " displayAreaInfo:" + displayAreaInfo
+ + " mDisplayAreasInfo.get():" + mDisplayAreasInfo.get(displayId));
+ }
+
+ mDisplayAreasInfo.remove(displayId);
+
+ ArrayList<RootTaskDisplayAreaListener> listeners = mListeners.get(displayId);
+ if (listeners != null) {
+ for (int i = listeners.size() - 1; i >= 0; --i) {
+ listeners.get(i).onDisplayAreaVanished(displayAreaInfo);
+ }
+ }
+ }
+
+ @Override
+ public void onDisplayAreaInfoChanged(@NonNull DisplayAreaInfo displayAreaInfo) {
+ final int displayId = displayAreaInfo.displayId;
+ if (mDisplayAreasInfo.get(displayId) == null) {
+ throw new IllegalArgumentException(
+ "onDisplayAreaInfoChanged() Unknown DA displayId: " + displayId
+ + " displayAreaInfo:" + displayAreaInfo
+ + " mDisplayAreasInfo.get():" + mDisplayAreasInfo.get(displayId));
+ }
+
+ mDisplayAreasInfo.put(displayId, displayAreaInfo);
+
+ ArrayList<RootTaskDisplayAreaListener> listeners = mListeners.get(displayId);
+ if (listeners != null) {
+ for (int i = listeners.size() - 1; i >= 0; --i) {
+ listeners.get(i).onDisplayAreaInfoChanged(displayAreaInfo);
+ }
+ }
+ }
+
+ public void dump(@NonNull PrintWriter pw, String prefix) {
+ final String innerPrefix = prefix + " ";
+ final String childPrefix = innerPrefix + " ";
+ pw.println(prefix + this);
+ }
+
+ @Override
+ public String toString() {
+ return TAG + "#" + mDisplayAreasInfo.size();
+ }
+
+ /** Callbacks for when root task display areas change. */
+ public interface RootTaskDisplayAreaListener {
+ default void onDisplayAreaAppeared(DisplayAreaInfo displayAreaInfo) {
+ }
+
+ default void onDisplayAreaVanished(DisplayAreaInfo displayAreaInfo) {
+ }
+
+ default void onDisplayAreaInfoChanged(DisplayAreaInfo displayAreaInfo) {
+ }
+
+ default void dump(@NonNull PrintWriter pw, String prefix) {
+ }
+ }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandler.java
index 2085042..2f2168f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandler.java
@@ -21,7 +21,7 @@
import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout;
import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.pip.Pip;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import java.io.PrintWriter;
import java.util.Optional;
@@ -33,7 +33,7 @@
*/
public final class ShellCommandHandler {
- private final Optional<SplitScreen> mSplitScreenOptional;
+ private final Optional<LegacySplitScreen> mLegacySplitScreenOptional;
private final Optional<Pip> mPipOptional;
private final Optional<OneHanded> mOneHandedOptional;
private final Optional<HideDisplayCutout> mHideDisplayCutout;
@@ -42,13 +42,13 @@
public ShellCommandHandler(
ShellTaskOrganizer shellTaskOrganizer,
- Optional<SplitScreen> splitScreenOptional,
+ Optional<LegacySplitScreen> legacySplitScreenOptional,
Optional<Pip> pipOptional,
Optional<OneHanded> oneHandedOptional,
Optional<HideDisplayCutout> hideDisplayCutout,
Optional<AppPairs> appPairsOptional) {
mShellTaskOrganizer = shellTaskOrganizer;
- mSplitScreenOptional = splitScreenOptional;
+ mLegacySplitScreenOptional = legacySplitScreenOptional;
mPipOptional = pipOptional;
mOneHandedOptional = oneHandedOptional;
mHideDisplayCutout = hideDisplayCutout;
@@ -62,7 +62,7 @@
pw.println();
pw.println();
mPipOptional.ifPresent(pip -> pip.dump(pw));
- mSplitScreenOptional.ifPresent(splitScreen -> splitScreen.dump(pw));
+ mLegacySplitScreenOptional.ifPresent(splitScreen -> splitScreen.dump(pw));
mOneHandedOptional.ifPresent(oneHanded -> oneHanded.dump(pw));
mHideDisplayCutout.ifPresent(hideDisplayCutout -> hideDisplayCutout.dump(pw));
pw.println();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInit.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInit.java
index f895603..f4c617e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInit.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInit.java
@@ -22,7 +22,7 @@
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.annotations.ExternalThread;
import com.android.wm.shell.draganddrop.DragAndDropController;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import java.util.Optional;
@@ -34,7 +34,7 @@
private final DisplayImeController mDisplayImeController;
private final DragAndDropController mDragAndDropController;
private final ShellTaskOrganizer mShellTaskOrganizer;
- private final Optional<SplitScreen> mSplitScreenOptional;
+ private final Optional<LegacySplitScreen> mLegacySplitScreenOptional;
private final Optional<AppPairs> mAppPairsOptional;
private final FullscreenTaskListener mFullscreenTaskListener;
private final Transitions mTransitions;
@@ -42,14 +42,14 @@
public ShellInit(DisplayImeController displayImeController,
DragAndDropController dragAndDropController,
ShellTaskOrganizer shellTaskOrganizer,
- Optional<SplitScreen> splitScreenOptional,
+ Optional<LegacySplitScreen> legacySplitScreenOptional,
Optional<AppPairs> appPairsOptional,
FullscreenTaskListener fullscreenTaskListener,
Transitions transitions) {
mDisplayImeController = displayImeController;
mDragAndDropController = dragAndDropController;
mShellTaskOrganizer = shellTaskOrganizer;
- mSplitScreenOptional = splitScreenOptional;
+ mLegacySplitScreenOptional = legacySplitScreenOptional;
mAppPairsOptional = appPairsOptional;
mFullscreenTaskListener = fullscreenTaskListener;
mTransitions = transitions;
@@ -67,7 +67,7 @@
mAppPairsOptional.ifPresent(AppPairs::onOrganizerRegistered);
// Bind the splitscreen impl to the drag drop controller
- mDragAndDropController.setSplitScreenController(mSplitScreenOptional);
+ mDragAndDropController.setSplitScreenController(mLegacySplitScreenOptional);
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
mTransitions.register(mShellTaskOrganizer);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java
index cfbf845..9754f51 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java
@@ -96,7 +96,7 @@
mTaskInfo2 = task2;
mSplitLayout = new SplitLayout(
mDisplayController.getDisplayContext(mRootTaskInfo.displayId),
- mRootTaskInfo.configuration, this, mRootTaskLeash);
+ mRootTaskInfo.configuration, this, b -> b.setParent(mRootTaskLeash));
final WindowContainerToken token1 = task1.token;
final WindowContainerToken token2 = task2.token;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index 4c70b5d..6b9bf2d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -57,10 +57,12 @@
private int mDividePosition;
public SplitLayout(Context context, Configuration configuration,
- LayoutChangeListener layoutChangeListener, SurfaceControl rootLeash) {
+ LayoutChangeListener layoutChangeListener,
+ SplitWindowManager.ParentContainerCallbacks parentContainerCallbacks) {
mContext = context.createConfigurationContext(configuration);
mLayoutChangeListener = layoutChangeListener;
- mSplitWindowManager = new SplitWindowManager(mContext, configuration, rootLeash);
+ mSplitWindowManager = new SplitWindowManager(
+ mContext, configuration, parentContainerCallbacks);
mDividerWindowWidth = context.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.docked_stack_divider_thickness);
@@ -123,14 +125,16 @@
mBounds1.set(mRootBounds);
mBounds2.set(mRootBounds);
if (isLandscape(mRootBounds)) {
+ position += mRootBounds.left;
mDividerBounds.left = position - mDividerInsets;
mDividerBounds.right = mDividerBounds.left + mDividerWindowWidth;
- mBounds1.right = mBounds1.left + position;
+ mBounds1.right = position;
mBounds2.left = mBounds1.right + mDividerSize;
} else {
+ position += mRootBounds.top;
mDividerBounds.top = position - mDividerInsets;
mDividerBounds.bottom = mDividerBounds.top + mDividerWindowWidth;
- mBounds1.bottom = mBounds1.top + position;
+ mBounds1.bottom = position;
mBounds2.top = mBounds1.bottom + mDividerSize;
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
index e412198..238caef 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
@@ -51,10 +51,17 @@
private Context mContext;
private SurfaceControlViewHost mViewHost;
+ final private ParentContainerCallbacks mParentContainerCallbacks;
- public SplitWindowManager(Context context, Configuration config, SurfaceControl rootSurface) {
- super(config, rootSurface, null /* hostInputToken */);
+ public interface ParentContainerCallbacks {
+ void attachToParentSurface(SurfaceControl.Builder b);
+ }
+
+ public SplitWindowManager(Context context, Configuration config,
+ ParentContainerCallbacks parentContainerCallbacks) {
+ super(config, null /* rootSurface */, null /* hostInputToken */);
mContext = context.createConfigurationContext(config);
+ mParentContainerCallbacks = parentContainerCallbacks;
}
@Override
@@ -73,6 +80,11 @@
mContext = mContext.createConfigurationContext(configuration);
}
+ @Override
+ protected void attachToParentSurface(SurfaceControl.Builder b) {
+ mParentContainerCallbacks.attachToParentSurface(b);
+ }
+
/** Inflates {@link DividerView} on to the root surface. */
void init(SplitLayout splitLayout) {
if (mViewHost == null) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
index a89c8bb..8ae6679 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
@@ -52,7 +52,7 @@
import com.android.wm.shell.R;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import java.util.Optional;
@@ -66,7 +66,7 @@
private final Context mContext;
private final DisplayController mDisplayController;
- private SplitScreen mSplitScreen;
+ private LegacySplitScreen mLegacySplitScreen;
private final SparseArray<PerDisplay> mDisplayDropTargets = new SparseArray<>();
private final SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction();
@@ -77,8 +77,8 @@
mDisplayController.addDisplayWindowListener(this);
}
- public void setSplitScreenController(Optional<SplitScreen> splitscreen) {
- mSplitScreen = splitscreen.orElse(null);
+ public void setSplitScreenController(Optional<LegacySplitScreen> splitscreen) {
+ mLegacySplitScreen = splitscreen.orElse(null);
}
@Override
@@ -104,7 +104,7 @@
R.layout.global_drop_target, null);
rootView.setOnDragListener(this);
rootView.setVisibility(View.INVISIBLE);
- DragLayout dragLayout = new DragLayout(context, mSplitScreen);
+ DragLayout dragLayout = new DragLayout(context, mLegacySplitScreen);
rootView.addView(dragLayout,
new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));
try {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
index 7b3b5db..4043d0b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
@@ -37,7 +37,6 @@
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
-import android.app.IActivityTaskManager;
import android.app.PendingIntent;
import android.app.WindowConfiguration;
import android.content.ActivityNotFoundException;
@@ -60,7 +59,7 @@
import androidx.annotation.VisibleForTesting;
import com.android.wm.shell.common.DisplayLayout;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -78,22 +77,22 @@
private final Context mContext;
private final ActivityTaskManager mActivityTaskManager;
private final Starter mStarter;
- private final SplitScreen mSplitScreen;
+ private final LegacySplitScreen mLegacySplitScreen;
private final ArrayList<DragAndDropPolicy.Target> mTargets = new ArrayList<>();
private DragSession mSession;
- public DragAndDropPolicy(Context context, SplitScreen splitScreen) {
- this(context, ActivityTaskManager.getInstance(), splitScreen,
- new DefaultStarter(context, splitScreen));
+ public DragAndDropPolicy(Context context, LegacySplitScreen legacySplitScreen) {
+ this(context, ActivityTaskManager.getInstance(), legacySplitScreen,
+ new DefaultStarter(context, legacySplitScreen));
}
@VisibleForTesting
DragAndDropPolicy(Context context, ActivityTaskManager activityTaskManager,
- SplitScreen splitScreen, Starter starter) {
+ LegacySplitScreen legacySplitScreen, Starter starter) {
mContext = context;
mActivityTaskManager = activityTaskManager;
- mSplitScreen = splitScreen;
+ mLegacySplitScreen = legacySplitScreen;
mStarter = starter;
}
@@ -151,13 +150,13 @@
new Rect(w / 2, 0, w, h)));
}
} else if (mSession.dragItemSupportsSplitscreen
- && mSplitScreen != null
- && mSplitScreen.isDividerVisible()) {
+ && mLegacySplitScreen != null
+ && mLegacySplitScreen.isDividerVisible()) {
// Already split, allow replacing existing split task
// TODO(b/169894807): For now, only allow replacing the non-primary task until we have
// split pairs
final Rect secondarySplitRawBounds =
- mSplitScreen.getDividerView().getNonMinimizedSplitScreenSecondaryBounds();
+ mLegacySplitScreen.getDividerView().getNonMinimizedSplitScreenSecondaryBounds();
final Rect secondarySplitBounds = new Rect(secondarySplitRawBounds);
secondarySplitBounds.intersect(new Rect(l, t, l + iw, t + ih));
if (isVerticalSplit) {
@@ -212,14 +211,14 @@
boolean deferAppLaunchUntilSplit = false;
if (target.type == TYPE_FULLSCREEN) {
- if (mSplitScreen != null && mSplitScreen.isDividerVisible()) {
+ if (mLegacySplitScreen != null && mLegacySplitScreen.isDividerVisible()) {
// If in split, remove split and launch fullscreen
mStarter.exitSplitScreen(mSession.runningTaskId);
} else {
// Not in split, fall through to launch
}
} else {
- if (mSplitScreen != null && mSplitScreen.isDividerVisible()) {
+ if (mLegacySplitScreen != null && mLegacySplitScreen.isDividerVisible()) {
// Split is already visible, just replace the task
// TODO(b/169894807): Since we only allow replacing the non-primary target above
// just fall through and start the activity
@@ -250,12 +249,12 @@
// into split, and we should wait for home and other tasks to be moved to
// split-secondary before trying to launch the new secondary task. This can be removed
// once we have app-pairs.
- mSplitScreen.registerInSplitScreenListener(new Consumer<Boolean>() {
+ mLegacySplitScreen.registerInSplitScreenListener(new Consumer<Boolean>() {
@Override
public void accept(Boolean inSplit) {
if (inSplit) {
startAppRunnable.run();
- mSplitScreen.unregisterInSplitScreenListener(this);
+ mLegacySplitScreen.unregisterInSplitScreenListener(this);
}
}
});
@@ -333,11 +332,11 @@
*/
private static class DefaultStarter implements Starter {
private final Context mContext;
- private final SplitScreen mSplitScreen;
+ private final LegacySplitScreen mLegacySplitScreen;
- public DefaultStarter(Context context, SplitScreen splitScreen) {
+ public DefaultStarter(Context context, LegacySplitScreen legacySplitScreen) {
mContext = context;
- mSplitScreen = splitScreen;
+ mLegacySplitScreen = legacySplitScreen;
}
@Override
@@ -373,12 +372,12 @@
@Override
public void enterSplitScreen(int taskId, boolean leftOrTop) {
- mSplitScreen.splitPrimaryTask();
+ mLegacySplitScreen.splitPrimaryTask();
}
@Override
public void exitSplitScreen(int taskId) {
- mSplitScreen.dismissSplitToPrimaryTask();
+ mLegacySplitScreen.dismissSplitToPrimaryTask();
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
index 5b7531c..a56fe8d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
@@ -35,7 +35,6 @@
import android.view.View;
import android.view.WindowInsets;
import android.view.WindowInsets.Type;
-import android.view.animation.Interpolator;
import androidx.annotation.NonNull;
@@ -43,10 +42,9 @@
import com.android.wm.shell.R;
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import java.util.ArrayList;
-import java.util.function.Consumer;
/**
* Coordinates the visible drop targets for the current drag.
@@ -63,7 +61,7 @@
private boolean mIsShowing;
private boolean mHasDropped;
- public DragLayout(Context context, SplitScreen splitscreen) {
+ public DragLayout(Context context, LegacySplitScreen splitscreen) {
super(context);
mPolicy = new DragAndDropPolicy(context, splitscreen);
mDisplayMargin = context.getResources().getDimensionPixelSize(
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutController.java
index e4e2546..b92846f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutController.java
@@ -27,6 +27,7 @@
import com.android.wm.shell.common.DisplayController;
import java.io.PrintWriter;
+import java.util.concurrent.Executor;
/**
* Manages the hide display cutout status.
@@ -51,7 +52,7 @@
*/
@Nullable
public static HideDisplayCutoutController create(
- Context context, DisplayController displayController) {
+ Context context, DisplayController displayController, Executor executor) {
// The SystemProperty is set for devices that support this feature and is used to control
// whether to create the HideDisplayCutout instance.
// It's defined in the device.mk (e.g. device/google/crosshatch/device.mk).
@@ -60,7 +61,7 @@
}
HideDisplayCutoutOrganizer organizer =
- new HideDisplayCutoutOrganizer(context, displayController);
+ new HideDisplayCutoutOrganizer(context, displayController, executor);
return new HideDisplayCutoutController(context, organizer);
}
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 4e62ea6..51a35d8 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
@@ -45,6 +45,7 @@
import java.io.PrintWriter;
import java.util.List;
+import java.util.concurrent.Executor;
/**
* Manages the display areas of hide display cutout feature.
@@ -88,7 +89,9 @@
t.apply();
};
- HideDisplayCutoutOrganizer(Context context, DisplayController displayController) {
+ HideDisplayCutoutOrganizer(Context context, DisplayController displayController,
+ Executor executor) {
+ super(executor);
mContext = context;
mDisplayController = displayController;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerHandleView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerHandleView.java
similarity index 98%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerHandleView.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerHandleView.java
index 2cb1fff..17ca110 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerHandleView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerHandleView.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.wm.shell.splitscreen;
+package com.android.wm.shell.legacysplitscreen;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerImeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerImeController.java
similarity index 96%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerImeController.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerImeController.java
index 71710af..2c0cf59 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerImeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerImeController.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.wm.shell.splitscreen;
+package com.android.wm.shell.legacysplitscreen;
import static android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED;
import static android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED;
@@ -37,11 +37,11 @@
class DividerImeController implements DisplayImeController.ImePositionProcessor {
private static final String TAG = "DividerImeController";
- private static final boolean DEBUG = SplitScreenController.DEBUG;
+ private static final boolean DEBUG = LegacySplitScreenController.DEBUG;
private static final float ADJUSTED_NONFOCUS_DIM = 0.3f;
- private final SplitScreenTaskListener mSplits;
+ private final LegacySplitScreenTaskListener mSplits;
private final TransactionPool mTransactionPool;
private final Handler mHandler;
private final TaskOrganizer mTaskOrganizer;
@@ -93,8 +93,8 @@
private boolean mPausedTargetAdjusted = false;
private boolean mAdjustedWhileHidden = false;
- DividerImeController(SplitScreenTaskListener splits, TransactionPool pool, Handler handler,
- TaskOrganizer taskOrganizer) {
+ DividerImeController(LegacySplitScreenTaskListener splits, TransactionPool pool,
+ Handler handler, TaskOrganizer taskOrganizer) {
mSplits = splits;
mTransactionPool = pool;
mHandler = handler;
@@ -105,7 +105,7 @@
return mSplits.mSplitScreenController.getDividerView();
}
- private SplitDisplayLayout getLayout() {
+ private LegacySplitDisplayLayout getLayout() {
return mSplits.mSplitScreenController.getSplitLayout();
}
@@ -202,7 +202,7 @@
// Reposition the server's secondary split position so that it evaluates
// insets properly.
WindowContainerTransaction wct = new WindowContainerTransaction();
- final SplitDisplayLayout splitLayout = getLayout();
+ final LegacySplitDisplayLayout splitLayout = getLayout();
if (mTargetAdjusted) {
splitLayout.updateAdjustedBounds(mShownTop, mHiddenTop, mShownTop);
wct.setBounds(mSplits.mSecondary.token, splitLayout.mAdjustedSecondary);
@@ -285,7 +285,7 @@
private void onProgress(float progress, SurfaceControl.Transaction t) {
final DividerView view = getView();
if (mTargetAdjusted != mAdjusted && !mPaused) {
- final SplitDisplayLayout splitLayout = getLayout();
+ final LegacySplitDisplayLayout splitLayout = getLayout();
final float fraction = mTargetAdjusted ? progress : 1.f - progress;
mLastAdjustTop = (int) (fraction * mShownTop + (1.f - fraction) * mHiddenTop);
splitLayout.updateAdjustedBounds(mLastAdjustTop, mHiddenTop, mShownTop);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerState.java
similarity index 94%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerState.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerState.java
index 23d86a0..af2ab15 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerState.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerState.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.wm.shell.splitscreen;
+package com.android.wm.shell.legacysplitscreen;
/**
* Class to hold state of divider that needs to persist across configuration changes.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java
similarity index 98%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerView.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java
index ba07166..16c966f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.wm.shell.splitscreen;
+package com.android.wm.shell.legacysplitscreen;
import static android.view.PointerIcon.TYPE_HORIZONTAL_DOUBLE_ARROW;
import static android.view.PointerIcon.TYPE_VERTICAL_DOUBLE_ARROW;
@@ -75,7 +75,7 @@
public class DividerView extends FrameLayout implements OnTouchListener,
OnComputeInternalInsetsListener {
private static final String TAG = "DividerView";
- private static final boolean DEBUG = SplitScreenController.DEBUG;
+ private static final boolean DEBUG = LegacySplitScreenController.DEBUG;
interface DividerCallbacks {
void onDraggingStart();
@@ -137,12 +137,12 @@
private final Rect mOtherInsetRect = new Rect();
private final Rect mLastResizeRect = new Rect();
private final Rect mTmpRect = new Rect();
- private SplitScreenController mSplitScreenController;
+ private LegacySplitScreenController mSplitScreenController;
private WindowManagerProxy mWindowManagerProxy;
private DividerWindowManager mWindowManager;
private VelocityTracker mVelocityTracker;
private FlingAnimationUtils mFlingAnimationUtils;
- private SplitDisplayLayout mSplitLayout;
+ private LegacySplitDisplayLayout mSplitLayout;
private DividerImeController mImeController;
private DividerCallbacks mCallback;
private final AnimationHandler mAnimationHandler = new AnimationHandler();
@@ -156,7 +156,7 @@
private boolean mAdjustedForIme;
private DividerState mState;
- private SplitScreenTaskListener mTiles;
+ private LegacySplitScreenTaskListener mTiles;
boolean mFirstLayout = true;
int mDividerPositionX;
int mDividerPositionY;
@@ -353,10 +353,11 @@
}
}
- void injectDependencies(SplitScreenController splitScreenController,
+ void injectDependencies(LegacySplitScreenController splitScreenController,
DividerWindowManager windowManager, DividerState dividerState,
- DividerCallbacks callback, SplitScreenTaskListener tiles, SplitDisplayLayout sdl,
- DividerImeController imeController, WindowManagerProxy wmProxy) {
+ DividerCallbacks callback, LegacySplitScreenTaskListener tiles,
+ LegacySplitDisplayLayout sdl, DividerImeController imeController,
+ WindowManagerProxy wmProxy) {
mSplitScreenController = splitScreenController;
mWindowManager = windowManager;
mState = dividerState;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerWindowManager.java
similarity index 98%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerWindowManager.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerWindowManager.java
index 5078371..2c3ae68 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerWindowManager.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.wm.shell.splitscreen;
+package com.android.wm.shell.legacysplitscreen;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ForcedResizableInfoActivity.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/ForcedResizableInfoActivity.java
similarity index 98%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ForcedResizableInfoActivity.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/ForcedResizableInfoActivity.java
index 7a16335..abff69c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ForcedResizableInfoActivity.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/ForcedResizableInfoActivity.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.wm.shell.splitscreen;
+package com.android.wm.shell.legacysplitscreen;
import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY;
import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SPLIT_SCREEN;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ForcedResizableInfoActivityController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/ForcedResizableInfoActivityController.java
similarity index 95%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ForcedResizableInfoActivityController.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/ForcedResizableInfoActivityController.java
index 1ef142d..ee5c9bc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ForcedResizableInfoActivityController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/ForcedResizableInfoActivityController.java
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-package com.android.wm.shell.splitscreen;
+package com.android.wm.shell.legacysplitscreen;
-import static com.android.wm.shell.splitscreen.ForcedResizableInfoActivity.EXTRA_FORCED_RESIZEABLE_REASON;
+import static com.android.wm.shell.legacysplitscreen.ForcedResizableInfoActivity.EXTRA_FORCED_RESIZEABLE_REASON;
import android.app.ActivityOptions;
import android.content.Context;
@@ -69,7 +69,7 @@
}
ForcedResizableInfoActivityController(Context context,
- SplitScreenController splitScreenController) {
+ LegacySplitScreenController splitScreenController) {
mContext = context;
splitScreenController.registerInSplitScreenListener(mDockedStackExistsListener);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitDisplayLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitDisplayLayout.java
similarity index 97%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitDisplayLayout.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitDisplayLayout.java
index 7d5e1a8..477ec33 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitDisplayLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitDisplayLayout.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.wm.shell.splitscreen;
+package com.android.wm.shell.legacysplitscreen;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
@@ -40,14 +40,14 @@
* Handles split-screen related internal display layout. In general, this represents the
* WM-facing understanding of the splits.
*/
-public class SplitDisplayLayout {
+public class LegacySplitDisplayLayout {
/** Minimum size of an adjusted stack bounds relative to original stack bounds. Used to
* restrict IME adjustment so that a min portion of top stack remains visible.*/
private static final float ADJUSTED_STACK_FRACTION_MIN = 0.3f;
private static final int DIVIDER_WIDTH_INACTIVE_DP = 4;
- SplitScreenTaskListener mTiles;
+ LegacySplitScreenTaskListener mTiles;
DisplayLayout mDisplayLayout;
Context mContext;
@@ -62,7 +62,8 @@
Rect mAdjustedPrimary = null;
Rect mAdjustedSecondary = null;
- public SplitDisplayLayout(Context ctx, DisplayLayout dl, SplitScreenTaskListener taskTiles) {
+ public LegacySplitDisplayLayout(Context ctx, DisplayLayout dl,
+ LegacySplitScreenTaskListener taskTiles) {
mTiles = taskTiles;
mDisplayLayout = dl;
mContext = ctx;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreen.java
similarity index 96%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreen.java
index 7c70a4efa..499a9c5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreen.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.wm.shell.splitscreen;
+package com.android.wm.shell.legacysplitscreen;
import android.graphics.Rect;
import android.window.WindowContainerToken;
@@ -29,7 +29,7 @@
* Interface to engage split screen feature.
*/
@ExternalThread
-public interface SplitScreen {
+public interface LegacySplitScreen {
/** Called when keyguard showing state changed. */
void onKeyguardVisibilityChanged(boolean isShowing);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java
similarity index 96%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java
index 6d6c761..d88696d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.wm.shell.splitscreen;
+package com.android.wm.shell.legacysplitscreen;
import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
@@ -65,7 +65,7 @@
/**
* Controls split screen feature.
*/
-public class SplitScreenController implements SplitScreen,
+public class LegacySplitScreenController implements LegacySplitScreen,
DisplayController.OnDisplaysChangedListener {
static final boolean DEBUG = false;
@@ -80,7 +80,7 @@
private final DividerState mDividerState = new DividerState();
private final ForcedResizableInfoActivityController mForcedResizableController;
private final Handler mHandler;
- private final SplitScreenTaskListener mSplits;
+ private final LegacySplitScreenTaskListener mSplits;
private final SystemWindows mSystemWindows;
final TransactionPool mTransactionPool;
private final WindowManagerProxy mWindowManagerProxy;
@@ -96,12 +96,12 @@
private DividerView mView;
// Keeps track of real-time split geometry including snap positions and ime adjustments
- private SplitDisplayLayout mSplitLayout;
+ private LegacySplitDisplayLayout mSplitLayout;
// Transient: this contains the layout calculated for a new rotation requested by WM. This is
// kept around so that we can wait for a matching configuration change and then use the exact
// layout that we sent back to WM.
- private SplitDisplayLayout mRotateSplitLayout;
+ private LegacySplitDisplayLayout mRotateSplitLayout;
private boolean mIsKeyguardShowing;
private boolean mVisible = false;
@@ -109,7 +109,7 @@
private boolean mAdjustedForIme = false;
private boolean mHomeStackResizable = false;
- public SplitScreenController(Context context,
+ public LegacySplitScreenController(Context context,
DisplayController displayController, SystemWindows systemWindows,
DisplayImeController imeController, Handler handler, TransactionPool transactionPool,
ShellTaskOrganizer shellTaskOrganizer, SyncTransactionQueue syncQueue,
@@ -123,7 +123,7 @@
mTransactionPool = transactionPool;
mWindowManagerProxy = new WindowManagerProxy(syncQueue, shellTaskOrganizer);
mTaskOrganizer = shellTaskOrganizer;
- mSplits = new SplitScreenTaskListener(this, shellTaskOrganizer, syncQueue);
+ mSplits = new LegacySplitScreenTaskListener(this, shellTaskOrganizer, syncQueue);
mImePositionProcessor = new DividerImeController(mSplits, mTransactionPool, mHandler,
shellTaskOrganizer);
mRotationController =
@@ -134,8 +134,8 @@
WindowContainerTransaction t = new WindowContainerTransaction();
DisplayLayout displayLayout =
new DisplayLayout(mDisplayController.getDisplayLayout(display));
- SplitDisplayLayout sdl =
- new SplitDisplayLayout(mContext, displayLayout, mSplits);
+ LegacySplitDisplayLayout sdl =
+ new LegacySplitDisplayLayout(mContext, displayLayout, mSplits);
sdl.rotateTo(toRotation);
mRotateSplitLayout = sdl;
final int position = isDividerVisible()
@@ -229,7 +229,7 @@
if (displayId != DEFAULT_DISPLAY) {
return;
}
- mSplitLayout = new SplitDisplayLayout(mDisplayController.getDisplayContext(displayId),
+ mSplitLayout = new LegacySplitDisplayLayout(mDisplayController.getDisplayContext(displayId),
mDisplayController.getDisplayLayout(displayId), mSplits);
mImeController.addPositionProcessor(mImePositionProcessor);
mDisplayController.addDisplayChangingController(mRotationController);
@@ -251,7 +251,7 @@
if (displayId != DEFAULT_DISPLAY || !mSplits.isSplitScreenSupported()) {
return;
}
- mSplitLayout = new SplitDisplayLayout(mDisplayController.getDisplayContext(displayId),
+ mSplitLayout = new LegacySplitDisplayLayout(mDisplayController.getDisplayContext(displayId),
mDisplayController.getDisplayLayout(displayId), mSplits);
if (mRotateSplitLayout == null) {
int midPos = mSplitLayout.getSnapAlgorithm().getMiddleTarget().position;
@@ -586,7 +586,7 @@
}
}
- SplitDisplayLayout getSplitLayout() {
+ LegacySplitDisplayLayout getSplitLayout() {
return mSplitLayout;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenTaskListener.java
similarity index 96%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskListener.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenTaskListener.java
index af451ae..02c82de 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenTaskListener.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.wm.shell.splitscreen;
+package com.android.wm.shell.legacysplitscreen;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
@@ -43,9 +43,9 @@
import java.io.PrintWriter;
import java.util.ArrayList;
-class SplitScreenTaskListener implements ShellTaskOrganizer.TaskListener {
- private static final String TAG = "SplitScreenTaskListener";
- private static final boolean DEBUG = SplitScreenController.DEBUG;
+class LegacySplitScreenTaskListener implements ShellTaskOrganizer.TaskListener {
+ private static final String TAG = LegacySplitScreenTaskListener.class.getSimpleName();
+ private static final boolean DEBUG = LegacySplitScreenController.DEBUG;
private final ShellTaskOrganizer mTaskOrganizer;
private final SyncTransactionQueue mSyncQueue;
@@ -58,12 +58,12 @@
SurfaceControl mPrimaryDim;
SurfaceControl mSecondaryDim;
Rect mHomeBounds = new Rect();
- final SplitScreenController mSplitScreenController;
+ final LegacySplitScreenController mSplitScreenController;
private boolean mSplitScreenSupported = false;
final SurfaceSession mSurfaceSession = new SurfaceSession();
- SplitScreenTaskListener(SplitScreenController splitScreenController,
+ LegacySplitScreenTaskListener(LegacySplitScreenController splitScreenController,
ShellTaskOrganizer shellTaskOrganizer,
SyncTransactionQueue syncQueue) {
mSplitScreenController = splitScreenController;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MinimizedDockShadow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/MinimizedDockShadow.java
similarity index 98%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MinimizedDockShadow.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/MinimizedDockShadow.java
index 06f4ef1..1e9223c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MinimizedDockShadow.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/MinimizedDockShadow.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.wm.shell.splitscreen;
+package com.android.wm.shell.legacysplitscreen;
import android.annotation.Nullable;
import android.content.Context;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/WindowManagerProxy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/WindowManagerProxy.java
similarity index 96%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/WindowManagerProxy.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/WindowManagerProxy.java
index 0307206..68da35d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/WindowManagerProxy.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/WindowManagerProxy.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.wm.shell.splitscreen;
+package com.android.wm.shell.legacysplitscreen;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
@@ -88,8 +88,8 @@
mTaskOrganizer = taskOrganizer;
}
- void dismissOrMaximizeDocked(final SplitScreenTaskListener tiles, SplitDisplayLayout layout,
- final boolean dismissOrMaximize) {
+ void dismissOrMaximizeDocked(final LegacySplitScreenTaskListener tiles,
+ LegacySplitDisplayLayout layout, final boolean dismissOrMaximize) {
mExecutor.execute(() -> applyDismissSplit(tiles, layout, dismissOrMaximize));
}
@@ -114,7 +114,7 @@
mExecutor.execute(mSetTouchableRegionRunnable);
}
- void applyResizeSplits(int position, SplitDisplayLayout splitLayout) {
+ void applyResizeSplits(int position, LegacySplitDisplayLayout splitLayout) {
WindowContainerTransaction t = new WindowContainerTransaction();
splitLayout.resizeSplits(position, t);
new WindowOrganizer().applyTransaction(t);
@@ -141,7 +141,7 @@
* split is minimized. This actually "sticks out" of the secondary split area, but when in
* minimized mode, the secondary split gets a 'negative' crop to expose it.
*/
- boolean applyHomeTasksMinimized(SplitDisplayLayout layout, WindowContainerToken parent,
+ boolean applyHomeTasksMinimized(LegacySplitDisplayLayout layout, WindowContainerToken parent,
@NonNull WindowContainerTransaction wct) {
// Resize the home/recents stacks to the larger minimized-state size
final Rect homeBounds;
@@ -189,7 +189,7 @@
*
* @return whether the home stack is resizable
*/
- boolean applyEnterSplit(SplitScreenTaskListener tiles, SplitDisplayLayout layout) {
+ boolean applyEnterSplit(LegacySplitScreenTaskListener tiles, LegacySplitDisplayLayout layout) {
// Set launchtile first so that any stack created after
// getAllRootTaskInfos and before reparent (even if unlikely) are placed
// correctly.
@@ -241,7 +241,7 @@
* split (thus resulting in the top of the secondary split becoming
* fullscreen. {@code false} resolves the other way.
*/
- void applyDismissSplit(SplitScreenTaskListener tiles, SplitDisplayLayout layout,
+ void applyDismissSplit(LegacySplitScreenTaskListener tiles, LegacySplitDisplayLayout layout,
boolean dismissOrMaximize) {
// Set launch root first so that any task created after getChildContainers and
// before reparent (pretty unlikely) are put into fullscreen.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
index e8c6cb7..d5db0cc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
@@ -45,6 +45,7 @@
import com.android.wm.shell.onehanded.OneHandedGestureHandler.OneHandedGestureEventCallback;
import java.io.PrintWriter;
+import java.util.concurrent.Executor;
/**
* Manages and manipulates the one handed states, transitions, and gesture for phones.
@@ -169,7 +170,7 @@
@Nullable
public static OneHandedController create(
Context context, DisplayController displayController,
- TaskStackListenerImpl taskStackListener) {
+ TaskStackListenerImpl taskStackListener, Executor executor) {
if (!SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false)) {
Slog.w(TAG, "Device doesn't support OneHanded feature");
return null;
@@ -182,7 +183,7 @@
OneHandedGestureHandler gestureHandler = new OneHandedGestureHandler(
context, displayController);
OneHandedDisplayAreaOrganizer organizer = new OneHandedDisplayAreaOrganizer(
- context, displayController, animationController, tutorialHandler);
+ context, displayController, animationController, tutorialHandler, executor);
IOverlayManager overlayManager = IOverlayManager.Stub.asInterface(
ServiceManager.getService(Context.OVERLAY_SERVICE));
return new OneHandedController(context, displayController, organizer, touchHandler,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
index 0311030..7fb1faa 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizer.java
@@ -47,6 +47,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
+import java.util.concurrent.Executor;
/**
* Manages OneHanded display areas such as offset.
@@ -151,7 +152,8 @@
public OneHandedDisplayAreaOrganizer(Context context,
DisplayController displayController,
OneHandedAnimationController animationController,
- OneHandedTutorialHandler tutorialHandler) {
+ OneHandedTutorialHandler tutorialHandler, Executor executor) {
+ super(executor);
mUpdateHandler = new Handler(OneHandedThread.get().getLooper(), mUpdateCallback);
mAnimationController = animationController;
mDisplayController = displayController;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index 9081783..4b283e4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -66,7 +66,7 @@
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.pip.phone.PipMotionHelper;
import com.android.wm.shell.pip.phone.PipUpdateThread;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -142,7 +142,7 @@
private final int mEnterExitAnimationDuration;
private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;
private final Map<IBinder, Configuration> mInitialState = new HashMap<>();
- private final Optional<SplitScreen> mSplitScreenOptional;
+ private final Optional<LegacySplitScreen> mSplitScreenOptional;
protected final ShellTaskOrganizer mTaskOrganizer;
// These callbacks are called on the update thread
@@ -265,7 +265,7 @@
@NonNull PipBoundsAlgorithm boundsHandler,
@NonNull PipMenuController pipMenuController,
@NonNull PipSurfaceTransactionHelper surfaceTransactionHelper,
- Optional<SplitScreen> splitScreenOptional,
+ Optional<LegacySplitScreen> splitScreenOptional,
@NonNull DisplayController displayController,
@NonNull PipUiEventLogger pipUiEventLogger,
@NonNull ShellTaskOrganizer shellTaskOrganizer) {
@@ -1118,7 +1118,7 @@
}
/**
- * Sync with {@link SplitScreen} on destination bounds if PiP is going to split screen.
+ * Sync with {@link LegacySplitScreen} on destination bounds if PiP is going to split screen.
*
* @param destinationBoundsOut contain the updated destination bounds if applicable
* @return {@code true} if destinationBounds is altered for split screen
@@ -1128,15 +1128,15 @@
return false;
}
- SplitScreen splitScreen = mSplitScreenOptional.get();
- if (!splitScreen.isDividerVisible()) {
+ LegacySplitScreen legacySplitScreen = mSplitScreenOptional.get();
+ if (!legacySplitScreen.isDividerVisible()) {
// fail early if system is not in split screen mode
return false;
}
// PiP window will go to split-secondary mode instead of fullscreen, populates the
// split screen bounds here.
- destinationBoundsOut.set(splitScreen.getDividerView()
+ destinationBoundsOut.set(legacySplitScreen.getDividerView()
.getNonMinimizedSplitScreenSecondaryBounds());
return true;
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
index 1638d72..c5b54bc 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
@@ -16,8 +16,10 @@
package com.android.wm.shell.flicker
+import android.graphics.Region
import com.android.server.wm.flicker.dsl.EventLogAssertion
import com.android.server.wm.flicker.dsl.LayersAssertion
+import com.android.server.wm.flicker.helpers.WindowUtils
@JvmOverloads
fun LayersAssertion.appPairsDividerIsVisible(
@@ -59,6 +61,50 @@
}
}
+@JvmOverloads
+fun LayersAssertion.dockedStackPrimaryBoundsIsVisible(
+ rotation: Int,
+ primaryLayerName: String,
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ end("PrimaryAppBounds", bugId, enabled) {
+ val entry = this.trace.entries.firstOrNull()
+ ?: throw IllegalStateException("Trace is empty")
+ val dividerRegion = entry.getVisibleBounds(FlickerTestBase.DOCKED_STACK_DIVIDER)
+ this.hasVisibleRegion(primaryLayerName, getPrimaryRegion(dividerRegion, rotation))
+ }
+}
+
+@JvmOverloads
+fun LayersAssertion.dockedStackSecondaryBoundsIsVisible(
+ rotation: Int,
+ secondaryLayerName: String,
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ end("SecondaryAppBounds", bugId, enabled) {
+ val entry = this.trace.entries.firstOrNull()
+ ?: throw IllegalStateException("Trace is empty")
+ val dividerRegion = entry.getVisibleBounds(FlickerTestBase.DOCKED_STACK_DIVIDER)
+ this.hasVisibleRegion(secondaryLayerName, getSecondaryRegion(dividerRegion, rotation))
+ }
+}
+
+fun getPrimaryRegion(dividerRegion: Region, rotation: Int): Region {
+ val displayBounds = WindowUtils.getDisplayBounds(rotation)
+ return Region(0, 0, displayBounds.getBounds().right,
+ dividerRegion.getBounds().bottom - WindowUtils.dockedStackDividerInset)
+}
+
+fun getSecondaryRegion(dividerRegion: Region, rotation: Int): Region {
+ val displayBounds = WindowUtils.getDisplayBounds(rotation)
+ return Region(0,
+ dividerRegion.getBounds().bottom - WindowUtils.dockedStackDividerInset,
+ displayBounds.getBounds().right,
+ displayBounds.getBounds().bottom - WindowUtils.navigationBarHeight)
+}
+
fun EventLogAssertion.focusChanges(
vararg windows: String,
bugId: Int = 0,
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 e67fc97..fb795c7 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,9 +17,7 @@
package com.android.wm.shell.flicker.helpers
import android.app.Instrumentation
-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(
@@ -43,20 +41,6 @@
SystemClock.sleep(TIMEOUT_MS)
}
- fun getPrimaryBounds(dividerBounds: Region): android.graphics.Region {
- val primaryAppBounds = Region(0, 0, dividerBounds.bounds.right,
- dividerBounds.bounds.bottom + WindowUtils.dockedStackDividerInset)
- return primaryAppBounds
- }
-
- fun getSecondaryBounds(dividerBounds: Region): android.graphics.Region {
- val displayBounds = WindowUtils.displayBounds
- val secondaryAppBounds = Region(0,
- dividerBounds.bounds.bottom - WindowUtils.dockedStackDividerInset,
- displayBounds.right, displayBounds.bottom - WindowUtils.navigationBarHeight)
- return secondaryAppBounds
- }
-
companion object {
const val TEST_REPETITIONS = 1
const val TIMEOUT_MS = 3_000L
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterLegacySplitScreenTest.kt
similarity index 86%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenTest.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterLegacySplitScreenTest.kt
index d36ad93..02f6f8c 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterLegacySplitScreenTest.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.wm.shell.flicker.splitscreen
+package com.android.wm.shell.flicker.legacysplitscreen
import android.platform.test.annotations.Presubmit
import android.view.Surface
@@ -35,6 +35,8 @@
import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisible
+import com.android.wm.shell.flicker.dockedStackSecondaryBoundsIsVisible
import org.junit.Assert
import org.junit.FixMethodOrder
import org.junit.Test
@@ -50,7 +52,7 @@
@RequiresDevice
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class EnterSplitScreenTest(
+class EnterLegacySplitScreenTest(
rotationName: String,
rotation: Int
) : SplitScreenTestBase(rotationName, rotation) {
@@ -102,13 +104,8 @@
assertions {
layersTrace {
dockedStackDividerIsVisible()
- end("appsEndingBounds", enabled = false) {
- val entry = this.trace.entries.firstOrNull()
- ?: throw IllegalStateException("Trace is empty")
- this.hasVisibleRegion(splitScreenApp.defaultWindowName,
- splitScreenApp.getPrimaryBounds(
- entry.getVisibleBounds(DOCKED_STACK_DIVIDER)))
- }
+ dockedStackPrimaryBoundsIsVisible(
+ rotation, splitScreenApp.defaultWindowName, 169271943)
}
windowManagerTrace {
end {
@@ -136,17 +133,10 @@
assertions {
layersTrace {
dockedStackDividerIsVisible()
- end("appsEndingBounds", enabled = false) {
- val entry = this.trace.entries.firstOrNull()
- ?: throw IllegalStateException("Trace is empty")
- this.hasVisibleRegion(splitScreenApp.defaultWindowName,
- splitScreenApp.getPrimaryBounds(
- entry.getVisibleBounds(DOCKED_STACK_DIVIDER)))
- .and()
- .hasVisibleRegion(secondaryApp.defaultWindowName,
- splitScreenApp.getSecondaryBounds(
- entry.getVisibleBounds(DOCKED_STACK_DIVIDER)))
- }
+ dockedStackPrimaryBoundsIsVisible(
+ rotation, splitScreenApp.defaultWindowName, 169271943)
+ dockedStackSecondaryBoundsIsVisible(
+ rotation, secondaryApp.defaultWindowName, 169271943)
}
windowManagerTrace {
end {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/ExitSplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenTest.kt
similarity index 97%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/ExitSplitScreenTest.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenTest.kt
index 7c47d1f..33306bf 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/ExitSplitScreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenTest.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.wm.shell.flicker.splitscreen
+package com.android.wm.shell.flicker.legacysplitscreen
import android.platform.test.annotations.Presubmit
import android.util.Rational
@@ -45,7 +45,7 @@
@RequiresDevice
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class ExitSplitScreenTest(
+class ExitLegacySplitScreenTest(
rotationName: String,
rotation: Int
) : SplitScreenTestBase(rotationName, rotation) {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenToLauncherTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncherTest.kt
similarity index 98%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenToLauncherTest.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncherTest.kt
index 00979fa..cc02aa3 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenToLauncherTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncherTest.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.wm.shell.flicker.splitscreen
+package com.android.wm.shell.flicker.legacysplitscreen
import android.platform.test.annotations.Presubmit
import android.view.Surface
@@ -54,7 +54,7 @@
@RequiresDevice
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class SplitScreenToLauncherTest(
+class LegacySplitScreenToLauncherTest(
testName: String,
flickerSpec: Flicker
) : FlickerTestRunner(testName, flickerSpec) {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/OpenAppToSplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OpenAppToLegacySplitScreenTest.kt
similarity index 97%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/OpenAppToSplitScreenTest.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OpenAppToLegacySplitScreenTest.kt
index c85561d..bb80726 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/OpenAppToSplitScreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OpenAppToLegacySplitScreenTest.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.wm.shell.flicker.splitscreen
+package com.android.wm.shell.flicker.legacysplitscreen
import android.platform.test.annotations.Presubmit
import android.view.Surface
@@ -54,7 +54,7 @@
@RequiresDevice
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class OpenAppToSplitScreenTest(
+class OpenAppToLegacySplitScreenTest(
testName: String,
flickerSpec: Flicker
) : FlickerTestRunner(testName, flickerSpec) {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/ResizeSplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreenTest.kt
similarity index 98%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/ResizeSplitScreenTest.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreenTest.kt
index 7c83846..e3beb41 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/ResizeSplitScreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreenTest.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.wm.shell.flicker.splitscreen
+package com.android.wm.shell.flicker.legacysplitscreen
import android.graphics.Region
import android.util.Rational
@@ -63,7 +63,7 @@
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@FlakyTest(bugId = 159096424)
-class ResizeSplitScreenTest(
+class ResizeLegacySplitScreenTest(
testName: String,
flickerSpec: Flicker
) : FlickerTestRunner(testName, flickerSpec) {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppTest.kt
new file mode 100644
index 0000000..ae2200c
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppTest.kt
@@ -0,0 +1,146 @@
+/*
+ * 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.legacysplitscreen
+
+import android.view.Surface
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.dsl.runWithFlicker
+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.server.wm.flicker.navBarLayerRotatesAndScales
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import com.android.wm.shell.flicker.dockedStackDividerIsVisible
+import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisible
+import com.android.wm.shell.flicker.helpers.SplitScreenHelper
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test open app to split screen.
+ * To run this test: `atest WMShellFlickerTests:RotateOneLaunchedAppTest`
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class RotateOneLaunchedAppTest(
+ rotationName: String,
+ rotation: Int
+) : SplitScreenTestBase(rotationName, rotation) {
+ private val splitScreenRotationSetup: FlickerBuilder
+ get() = FlickerBuilder(instrumentation).apply {
+ val testSetupRotation = "testSetupRotation"
+ withTestName {
+ testSetupRotation
+ }
+ setup {
+ test {
+ device.wakeUpAndGoToHomeScreen()
+ }
+ }
+ teardown {
+ eachRun {
+ if (uiDevice.isInSplitScreen()) {
+ uiDevice.exitSplitScreen()
+ }
+ setRotation(Surface.ROTATION_0)
+ splitScreenApp.exit()
+ secondaryApp.exit()
+ }
+ }
+ }
+
+ @Test
+ fun testRotateInSplitScreenMode() {
+ val testTag = "testEnterSplitScreen_launchToSide"
+ runWithFlicker(splitScreenRotationSetup) {
+ withTestName { testTag }
+ repeat {
+ SplitScreenHelper.TEST_REPETITIONS
+ }
+ transitions {
+ splitScreenApp.launchViaIntent()
+ device.launchSplitScreen()
+ setRotation(rotation)
+ }
+ assertions {
+ layersTrace {
+ navBarLayerRotatesAndScales(Surface.ROTATION_0, rotation, 169271943)
+ statusBarLayerRotatesScales(Surface.ROTATION_0, rotation, 169271943)
+ dockedStackDividerIsVisible()
+ dockedStackPrimaryBoundsIsVisible(
+ rotation, splitScreenApp.defaultWindowName, 169271943)
+ }
+ windowManagerTrace {
+ navBarWindowIsAlwaysVisible()
+ statusBarWindowIsAlwaysVisible()
+ end {
+ showsAppWindow(splitScreenApp.defaultWindowName)
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun testRotateAndEnterSplitScreenMode() {
+ val testTag = "testRotateAndEnterSplitScreenMode"
+ runWithFlicker(splitScreenRotationSetup) {
+ withTestName { testTag }
+ repeat {
+ SplitScreenHelper.TEST_REPETITIONS
+ }
+ transitions {
+ splitScreenApp.launchViaIntent()
+ setRotation(rotation)
+ device.launchSplitScreen()
+ }
+ assertions {
+ layersTrace {
+ navBarLayerRotatesAndScales(Surface.ROTATION_0, rotation, 169271943)
+ statusBarLayerRotatesScales(Surface.ROTATION_0, rotation, 169271943)
+ dockedStackDividerIsVisible()
+ dockedStackPrimaryBoundsIsVisible(
+ rotation, splitScreenApp.defaultWindowName, 169271943)
+ }
+ windowManagerTrace {
+ navBarWindowIsAlwaysVisible()
+ statusBarWindowIsAlwaysVisible()
+ end {
+ showsAppWindow(splitScreenApp.defaultWindowName)
+ }
+ }
+ }
+ }
+ }
+
+ companion object {
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): Collection<Array<Any>> {
+ val supportedRotations = intArrayOf(Surface.ROTATION_90, Surface.ROTATION_270)
+ 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/legacysplitscreen/RotateTwoLaunchedAppTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppTest.kt
new file mode 100644
index 0000000..a1b44f0
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppTest.kt
@@ -0,0 +1,157 @@
+/*
+ * 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.legacysplitscreen
+
+import android.view.Surface
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.dsl.runWithFlicker
+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.server.wm.flicker.navBarLayerRotatesAndScales
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import com.android.wm.shell.flicker.dockedStackDividerIsVisible
+import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisible
+import com.android.wm.shell.flicker.dockedStackSecondaryBoundsIsVisible
+import com.android.wm.shell.flicker.helpers.SplitScreenHelper
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test open app to split screen.
+ * To run this test: `atest WMShellFlickerTests:RotateTwoLaunchedAppTest`
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class RotateTwoLaunchedAppTest(
+ rotationName: String,
+ rotation: Int
+) : SplitScreenTestBase(rotationName, rotation) {
+ private val splitScreenRotationSetup: FlickerBuilder
+ get() = FlickerBuilder(instrumentation).apply {
+ val testSetupRotation = "testSetupRotation"
+ withTestName {
+ testSetupRotation
+ }
+ setup {
+ test {
+ device.wakeUpAndGoToHomeScreen()
+ }
+ }
+ teardown {
+ eachRun {
+ if (uiDevice.isInSplitScreen()) {
+ uiDevice.exitSplitScreen()
+ }
+ setRotation(Surface.ROTATION_0)
+ splitScreenApp.exit()
+ secondaryApp.exit()
+ }
+ }
+ }
+
+ @Test
+ fun testRotateInSplitScreenMode() {
+ val testTag = "testRotateInSplitScreenMode"
+ runWithFlicker(splitScreenRotationSetup) {
+ withTestName { testTag }
+ repeat {
+ SplitScreenHelper.TEST_REPETITIONS
+ }
+ transitions {
+ secondaryApp.launchViaIntent()
+ splitScreenApp.launchViaIntent()
+ device.launchSplitScreen()
+ splitScreenApp.reopenAppFromOverview()
+ setRotation(rotation)
+ }
+ assertions {
+ layersTrace {
+ navBarLayerRotatesAndScales(Surface.ROTATION_0, rotation, 169271943)
+ statusBarLayerRotatesScales(Surface.ROTATION_0, rotation, 169271943)
+ dockedStackDividerIsVisible()
+ dockedStackPrimaryBoundsIsVisible(
+ rotation, splitScreenApp.defaultWindowName, 169271943)
+ dockedStackSecondaryBoundsIsVisible(
+ rotation, secondaryApp.defaultWindowName, 169271943)
+ }
+ windowManagerTrace {
+ navBarWindowIsAlwaysVisible()
+ statusBarWindowIsAlwaysVisible()
+ end {
+ showsAppWindow(splitScreenApp.defaultWindowName)
+ .and().showsAppWindow(secondaryApp.defaultWindowName)
+ }
+ }
+ }
+ }
+ }
+
+ @Test
+ fun testRotateAndEnterSplitScreenMode() {
+ val testTag = "testRotateAndEnterSplitScreenMode"
+ runWithFlicker(splitScreenRotationSetup) {
+ withTestName { testTag }
+ repeat {
+ SplitScreenHelper.TEST_REPETITIONS
+ }
+ transitions {
+ secondaryApp.launchViaIntent()
+ splitScreenApp.launchViaIntent()
+ setRotation(rotation)
+ device.launchSplitScreen()
+ splitScreenApp.reopenAppFromOverview()
+ }
+ assertions {
+ layersTrace {
+ navBarLayerRotatesAndScales(Surface.ROTATION_0, rotation, 169271943)
+ statusBarLayerRotatesScales(Surface.ROTATION_0, rotation, 169271943)
+ dockedStackDividerIsVisible()
+ dockedStackPrimaryBoundsIsVisible(
+ rotation, splitScreenApp.defaultWindowName, 169271943)
+ dockedStackSecondaryBoundsIsVisible(
+ rotation, secondaryApp.defaultWindowName, 169271943)
+ }
+ windowManagerTrace {
+ navBarWindowIsAlwaysVisible()
+ statusBarWindowIsAlwaysVisible()
+ end {
+ showsAppWindow(splitScreenApp.defaultWindowName)
+ .and().showsAppWindow(secondaryApp.defaultWindowName)
+ }
+ }
+ }
+ }
+ }
+
+ companion object {
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): Collection<Array<Any>> {
+ val supportedRotations = intArrayOf(Surface.ROTATION_90, Surface.ROTATION_270)
+ 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/splitscreen/SplitScreenTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/SplitScreenTestBase.kt
similarity index 96%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenTestBase.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/SplitScreenTestBase.kt
index 42c509d..a2e325e 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/legacysplitscreen/SplitScreenTestBase.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.wm.shell.flicker.splitscreen
+package com.android.wm.shell.flicker.legacysplitscreen
import com.android.wm.shell.flicker.NonRotationTestBase
import com.android.wm.shell.flicker.TEST_APP_NONRESIZEABLE_LABEL
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/PipLegacySplitScreenTest.kt
similarity index 99%
rename from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipSplitScreenTest.kt
rename to libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
index f79b21f..81cdbf0 100644
--- 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/PipLegacySplitScreenTest.kt
@@ -47,7 +47,7 @@
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@FlakyTest(bugId = 161435597)
-class PipSplitScreenTest(
+class PipLegacySplitScreenTest(
rotationName: String,
rotation: Int
) : AppTestBase(rotationName, rotation) {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenRotateOneLaunchedAppTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenRotateOneLaunchedAppTest.kt
deleted file mode 100644
index d2371bd..0000000
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenRotateOneLaunchedAppTest.kt
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.flicker.splitscreen
-
-import androidx.test.filters.FlakyTest
-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.helpers.StandardAppHelper
-import com.android.server.wm.flicker.startRotation
-import com.android.server.wm.flicker.endRotation
-import com.android.server.wm.flicker.helpers.buildTestTag
-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.setRotation
-import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
-import com.android.server.wm.flicker.repetitions
-import org.junit.FixMethodOrder
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test open app to split screen.
- * To run this test: `atest WMShellFlickerTests:SplitScreenRotateOneLaunchedAppTest`
- */
-@RequiresDevice
-@RunWith(Parameterized::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-@FlakyTest
-class SplitScreenRotateOneLaunchedAppTest(
- 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 = StandardAppHelper(instrumentation,
- "com.android.wm.shell.flicker.testapp", "SimpleApp")
-
- return FlickerTestRunnerFactory(instrumentation, repetitions = 3)
- .buildTest { configuration ->
- withTestName {
- buildTestTag("splitScreenRotateOneApp", testApp, configuration)
- }
- repeat { configuration.repetitions }
- setup {
- test {
- device.wakeUpAndGoToHomeScreen()
- testApp.open()
- device.launchSplitScreen()
- device.waitForIdle()
- }
- eachRun {
- this.setRotation(configuration.startRotation)
- }
- }
- teardown {
- eachRun {
- setRotation(Surface.ROTATION_0)
- }
- test {
- testApp.exit()
- if (device.isInSplitScreen()) {
- device.exitSplitScreen()
- }
- }
- }
- transitions {
- this.setRotation(configuration.endRotation)
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenRotateTwoLaunchedAppTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenRotateTwoLaunchedAppTest.kt
deleted file mode 100644
index 6734642..0000000
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenRotateTwoLaunchedAppTest.kt
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.flicker.splitscreen
-
-import androidx.test.filters.FlakyTest
-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.helpers.StandardAppHelper
-import com.android.server.wm.flicker.startRotation
-import com.android.server.wm.flicker.endRotation
-import com.android.server.wm.flicker.helpers.buildTestTag
-import com.android.server.wm.flicker.helpers.exitSplitScreen
-import com.android.server.wm.flicker.helpers.reopenAppFromOverview
-import com.android.server.wm.flicker.helpers.isInSplitScreen
-import com.android.server.wm.flicker.helpers.launchSplitScreen
-import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
-import com.android.server.wm.flicker.repetitions
-import org.junit.FixMethodOrder
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test open app to split screen.
- * To run this test: `atest WMShellFlickerTests:SplitScreenRotateTwoLaunchedAppTest`
- */
-@RequiresDevice
-@RunWith(Parameterized::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-@FlakyTest
-class SplitScreenRotateTwoLaunchedAppTest(
- 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 = StandardAppHelper(instrumentation,
- "com.android.wm.shell.flicker.testapp", "SimpleApp")
- val secondaryApp = StandardAppHelper(instrumentation,
- "com.android.wm.shell.flicker.testapp",
- "SplitScreenSecondaryApp")
-
- return FlickerTestRunnerFactory(instrumentation, repetitions = 3)
- .buildTest { configuration ->
- withTestName {
- buildTestTag("splitScreenRotateTwoApps", testApp, configuration)
- }
- repeat { configuration.repetitions }
- setup {
- test {
- device.wakeUpAndGoToHomeScreen()
- testApp.open()
- device.pressHome()
- secondaryApp.open()
- device.pressHome()
- device.launchSplitScreen()
- device.reopenAppFromOverview()
- device.waitForIdle()
- }
- eachRun {
- this.setRotation(configuration.startRotation)
- }
- }
- teardown {
- eachRun {
- setRotation(Surface.ROTATION_0)
- }
- test {
- testApp.exit()
- secondaryApp.exit()
- if (device.isInSplitScreen()) {
- device.exitSplitScreen()
- }
- }
- }
- transitions {
- this.setRotation(configuration.endRotation)
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
index 9fdd59b..708a6c5 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
@@ -58,7 +58,7 @@
mContext,
getConfiguration(false),
mLayoutChangeListener,
- mRootLeash);
+ b -> b.setParent(mRootLeash));
}
@Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java
index aa0eb2f..c170563 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitWindowManagerTests.java
@@ -49,7 +49,8 @@
MockitoAnnotations.initMocks(this);
final Configuration configuration = new Configuration();
configuration.setToDefaults();
- mSplitWindowManager = new SplitWindowManager(mContext, configuration, mSurfaceControl);
+ mSplitWindowManager = new SplitWindowManager(mContext, configuration,
+ b -> b.setParent(mSurfaceControl));
when(mSplitLayout.getDividerBounds()).thenReturn(
new Rect(0, 0, configuration.windowConfiguration.getBounds().width(),
configuration.windowConfiguration.getBounds().height()));
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java
index 92d4bee..912418d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java
@@ -61,8 +61,8 @@
import com.android.wm.shell.common.DisplayLayout;
import com.android.wm.shell.draganddrop.DragAndDropPolicy.Target;
-import com.android.wm.shell.splitscreen.DividerView;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.DividerView;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import org.junit.Before;
import org.junit.Test;
@@ -90,7 +90,7 @@
private ActivityTaskManager mActivityTaskManager;
@Mock
- private SplitScreen mSplitScreen;
+ private LegacySplitScreen mLegacySplitScreen;
@Mock
private DragAndDropPolicy.Starter mStarter;
@@ -123,7 +123,7 @@
mInsets = Insets.of(0, 0, 0, 0);
DividerView divider = mock(DividerView.class);
- doReturn(divider).when(mSplitScreen).getDividerView();
+ doReturn(divider).when(mLegacySplitScreen).getDividerView();
doReturn(new Rect(50, 0, 100, 100)).when(divider)
.getNonMinimizedSplitScreenSecondaryBounds();
@@ -131,9 +131,10 @@
Consumer<Boolean> callback = invocation.getArgument(0);
callback.accept(true);
return null;
- }).when(mSplitScreen).registerInSplitScreenListener(any());
+ }).when(mLegacySplitScreen).registerInSplitScreenListener(any());
- mPolicy = new DragAndDropPolicy(mContext, mActivityTaskManager, mSplitScreen, mStarter);
+ mPolicy = new DragAndDropPolicy(
+ mContext, mActivityTaskManager, mLegacySplitScreen, mStarter);
mActivityClipData = createClipData(MIMETYPE_APPLICATION_ACTIVITY);
mNonResizeableActivityClipData = createClipData(MIMETYPE_APPLICATION_ACTIVITY);
setClipDataResizeable(mNonResizeableActivityClipData, false);
@@ -207,7 +208,7 @@
}
private void setInSplitScreen(boolean inSplitscreen) {
- doReturn(inSplitscreen).when(mSplitScreen).isDividerVisible();
+ doReturn(inSplitscreen).when(mLegacySplitScreen).isDividerVisible();
}
@Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizerTest.java
index 2e4fd6a..e0c835b 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizerTest.java
@@ -93,7 +93,7 @@
when(mMockDisplayController.getDisplay(anyInt())).thenReturn(mDisplay);
HideDisplayCutoutOrganizer organizer = new HideDisplayCutoutOrganizer(
- mContext, mMockDisplayController);
+ mContext, mMockDisplayController, Runnable::run);
mOrganizer = Mockito.spy(organizer);
doNothing().when(mOrganizer).unregisterOrganizer();
doNothing().when(mOrganizer).applyBoundsAndOffsets(any(), any(), any(), any());
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java
index 8ef077e..e37e154 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java
@@ -93,7 +93,8 @@
final OneHandedAnimationController animationController = new OneHandedAnimationController(
mContext);
OneHandedDisplayAreaOrganizer displayAreaOrganizer = new OneHandedDisplayAreaOrganizer(
- mContext, mMockDisplayController, animationController, mMockTutorialHandler);
+ mContext, mMockDisplayController, animationController, mMockTutorialHandler,
+ Runnable::run);
assertThat(displayAreaOrganizer.isInOneHanded()).isFalse();
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java
index 6d1a3c4..5d742b3 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedDisplayAreaOrganizerTest.java
@@ -111,7 +111,8 @@
mDisplayAreaOrganizer = new OneHandedDisplayAreaOrganizer(mContext,
mMockDisplayController,
mMockAnimationController,
- mTutorialHandler);
+ mTutorialHandler,
+ Runnable::run);
mSpyUpdateHandler = spy(new Handler(OneHandedThread.get().getLooper(), mUpdateCallback));
mDisplayAreaOrganizer.setUpdateHandler(mSpyUpdateHandler);
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
index 45e4241..b5d10d7 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
@@ -45,7 +45,7 @@
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.pip.phone.PhonePipMenuController;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import org.junit.Before;
import org.junit.Test;
@@ -69,7 +69,7 @@
@Mock private PhonePipMenuController mMockPhonePipMenuController;
@Mock private PipSurfaceTransactionHelper mMockPipSurfaceTransactionHelper;
@Mock private PipUiEventLogger mMockPipUiEventLogger;
- @Mock private Optional<SplitScreen> mMockOptionalSplitScreen;
+ @Mock private Optional<LegacySplitScreen> mMockOptionalSplitScreen;
@Mock private ShellTaskOrganizer mMockShellTaskOrganizer;
private PipBoundsState mPipBoundsState;
diff --git a/lowpan/java/android/net/lowpan/LowpanManager.java b/lowpan/java/android/net/lowpan/LowpanManager.java
index 76876ce..33b35e6 100644
--- a/lowpan/java/android/net/lowpan/LowpanManager.java
+++ b/lowpan/java/android/net/lowpan/LowpanManager.java
@@ -24,6 +24,10 @@
import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BackgroundThread;
+
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;
@@ -97,10 +101,14 @@
*
* @param context the application context
* @param service the Binder interface
- * @param looper the default Looper to run callbacks on
* @hide - hide this because it takes in a parameter of type ILowpanManager, which is a system
* private class.
*/
+ public LowpanManager(Context context, ILowpanManager service) {
+ this(context, service, BackgroundThread.get().getLooper());
+ }
+
+ @VisibleForTesting
public LowpanManager(Context context, ILowpanManager service, Looper looper) {
mContext = context;
mService = service;
diff --git a/media/java/android/media/IMediaRouterService.aidl b/media/java/android/media/IMediaRouterService.aidl
index 068f968..4b8a8ad 100644
--- a/media/java/android/media/IMediaRouterService.aidl
+++ b/media/java/android/media/IMediaRouterService.aidl
@@ -73,6 +73,8 @@
void unregisterManager(IMediaRouter2Manager manager);
void setRouteVolumeWithManager(IMediaRouter2Manager manager, int requestId,
in MediaRoute2Info route, int volume);
+ void startScan(IMediaRouter2Manager manager);
+ void stopScan(IMediaRouter2Manager manager);
void requestCreateSessionWithManager(IMediaRouter2Manager manager, int requestId,
in RoutingSessionInfo oldSession, in @nullable MediaRoute2Info route);
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index c2168f1..e7e83eb 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -25,6 +25,7 @@
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
+import android.os.Process;
import android.os.SystemProperties;
import android.util.Log;
import android.util.Pair;
@@ -188,13 +189,14 @@
// COMMON CONSTANTS
private static final Range<Integer> POSITIVE_INTEGERS =
- Range.create(1, Integer.MAX_VALUE);
+ Range.create(1, Integer.MAX_VALUE);
private static final Range<Long> POSITIVE_LONGS =
- Range.create(1l, Long.MAX_VALUE);
+ Range.create(1L, Long.MAX_VALUE);
private static final Range<Rational> POSITIVE_RATIONALS =
- Range.create(new Rational(1, Integer.MAX_VALUE),
- new Rational(Integer.MAX_VALUE, 1));
- private static final Range<Integer> SIZE_RANGE = Range.create(1, 32768);
+ Range.create(new Rational(1, Integer.MAX_VALUE),
+ new Rational(Integer.MAX_VALUE, 1));
+ private static final Range<Integer> SIZE_RANGE =
+ Process.is64Bit() ? Range.create(1, 32768) : Range.create(1, 4096);
private static final Range<Integer> FRAME_RATE_RANGE = Range.create(0, 960);
private static final Range<Integer> BITRATE_RANGE = Range.create(0, 500000000);
private static final int DEFAULT_MAX_SUPPORTED_INSTANCES = 32;
@@ -1399,6 +1401,9 @@
/**
* Returns the range of supported video widths.
+ * <p class=note>
+ * 32-bit processes will not support resolutions larger than 4096x4096 due to
+ * the limited address space.
*/
public Range<Integer> getSupportedWidths() {
return mWidthRange;
@@ -1406,6 +1411,9 @@
/**
* Returns the range of supported video heights.
+ * <p class=note>
+ * 32-bit processes will not support resolutions larger than 4096x4096 due to
+ * the limited address space.
*/
public Range<Integer> getSupportedHeights() {
return mHeightRange;
@@ -1857,6 +1865,10 @@
&& aligned.mMaxMacroBlockRate >= otherAligned.mMaxMacroBlockRate);
}
+ /* package private */ boolean isEqualDimension(@NonNull PerformancePoint other) {
+ return mWidth == other.mWidth && mHeight == other.mHeight;
+ }
+
private @NonNull Size getCommonBlockSize(@NonNull PerformancePoint other) {
return new Size(
Math.max(mBlockSize.getWidth(), other.mBlockSize.getWidth()) * 16,
@@ -1997,6 +2009,9 @@
* Performance points assume a single active codec. For use cases where multiple
* codecs are active, should use that highest pixel count, and add the frame rates of
* each individual codec.
+ * <p class=note>
+ * Supported resolution could be further restricted for 32-bit processes due to
+ * the limited virtual memory space.
*/
@Nullable
public List<PerformancePoint> getSupportedPerformancePoints() {
@@ -2164,6 +2179,12 @@
if (size == null || size.getWidth() * size.getHeight() <= 0) {
continue;
}
+ if (size.getWidth() > SIZE_RANGE.getUpper()
+ || size.getHeight() > SIZE_RANGE.getUpper()) {
+ size = new Size(
+ Math.min(size.getWidth(), SIZE_RANGE.getUpper()),
+ Math.min(size.getHeight(), SIZE_RANGE.getUpper()));
+ }
Range<Long> range = Utils.parseLongRange(map.get(key), null);
if (range == null || range.getLower() < 0 || range.getUpper() < 0) {
continue;
@@ -2193,6 +2214,29 @@
(a.getMaxMacroBlockRate() < b.getMaxMacroBlockRate() ? -1 : 1) :
(a.getMaxFrameRate() != b.getMaxFrameRate()) ?
(a.getMaxFrameRate() < b.getMaxFrameRate() ? -1 : 1) : 0));
+
+ // remove redundant points
+ for (int i = 1; i < ret.size(); ++i) {
+ PerformancePoint a = ret.get(i);
+ for (int j = 0; j < i; ++j) {
+ PerformancePoint b = ret.get(j);
+ if (b.isEqualDimension(a) && b.covers(a)) {
+ ret.set(i, null);
+ break;
+ }
+ }
+ }
+ int newSize = 0;
+ for (int i = 0; i < ret.size(); ++i) {
+ PerformancePoint a = ret.get(i);
+ if (a == null) {
+ continue;
+ }
+ ret.set(newSize, a);
+ ++newSize;
+ }
+ ret.setSize(newSize);
+
return Collections.unmodifiableList(ret);
}
diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java
index 4b09a5f..68237de 100644
--- a/media/java/android/media/MediaRouter2Manager.java
+++ b/media/java/android/media/MediaRouter2Manager.java
@@ -147,6 +147,36 @@
}
/**
+ * Starts scanning remote routes.
+ * @see #stopScan(String)
+ */
+ public void startScan() {
+ Client client = getOrCreateClient();
+ if (client != null) {
+ try {
+ mMediaRouterService.startScan(client);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Unable to get sessions. Service probably died.", ex);
+ }
+ }
+ }
+
+ /**
+ * Stops scanning remote routes to reduce resource consumption.
+ * @see #startScan(String)
+ */
+ public void stopScan() {
+ Client client = getOrCreateClient();
+ if (client != null) {
+ try {
+ mMediaRouterService.stopScan(client);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Unable to get sessions. Service probably died.", ex);
+ }
+ }
+ }
+
+ /**
* Gets a {@link android.media.session.MediaController} associated with the
* given routing session.
* If there is no matching media session, {@code null} is returned.
diff --git a/media/java/android/media/RouteDiscoveryPreference.java b/media/java/android/media/RouteDiscoveryPreference.java
index 68f2964..2f95247 100644
--- a/media/java/android/media/RouteDiscoveryPreference.java
+++ b/media/java/android/media/RouteDiscoveryPreference.java
@@ -153,6 +153,7 @@
return false;
}
RouteDiscoveryPreference other = (RouteDiscoveryPreference) o;
+ //TODO: Make this order-free
return Objects.equals(mPreferredFeatures, other.mPreferredFeatures)
&& mShouldPerformActiveScan == other.mShouldPerformActiveScan;
}
diff --git a/packages/CarrierDefaultApp/AndroidManifest.xml b/packages/CarrierDefaultApp/AndroidManifest.xml
index 4473610..3e65df2 100644
--- a/packages/CarrierDefaultApp/AndroidManifest.xml
+++ b/packages/CarrierDefaultApp/AndroidManifest.xml
@@ -48,6 +48,7 @@
android:name="com.android.carrierdefaultapp.CaptivePortalLoginActivity"
android:label="@string/action_bar_label"
android:exported="true"
+ android:permission="android.permission.MODIFY_PHONE_STATE"
android:theme="@style/AppTheme"
android:configChanges="keyboardHidden|orientation|screenSize">
<intent-filter>
diff --git a/packages/Connectivity/OWNERS b/packages/Connectivity/OWNERS
new file mode 100644
index 0000000..48e54da
--- /dev/null
+++ b/packages/Connectivity/OWNERS
@@ -0,0 +1,3 @@
+set noparent
+
+include platform/frameworks/base:/services/core/java/com/android/server/net/OWNERS
diff --git a/packages/SystemUI/res/drawable/ic_1x_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_1x_mobiledata.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_1x_mobiledata.xml
rename to packages/SettingsLib/res/drawable/ic_1x_mobiledata.xml
diff --git a/packages/SystemUI/res/drawable/ic_3g_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_3g_mobiledata.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_3g_mobiledata.xml
rename to packages/SettingsLib/res/drawable/ic_3g_mobiledata.xml
diff --git a/packages/SystemUI/res/drawable/ic_4g_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_4g_mobiledata.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_4g_mobiledata.xml
rename to packages/SettingsLib/res/drawable/ic_4g_mobiledata.xml
diff --git a/packages/SystemUI/res/drawable/ic_4g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_4g_plus_mobiledata.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_4g_plus_mobiledata.xml
rename to packages/SettingsLib/res/drawable/ic_4g_plus_mobiledata.xml
diff --git a/packages/SystemUI/res/drawable/ic_5g_e_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_5g_e_mobiledata.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_5g_e_mobiledata.xml
rename to packages/SettingsLib/res/drawable/ic_5g_e_mobiledata.xml
diff --git a/packages/SystemUI/res/drawable/ic_5g_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_5g_mobiledata.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_5g_mobiledata.xml
rename to packages/SettingsLib/res/drawable/ic_5g_mobiledata.xml
diff --git a/packages/SystemUI/res/drawable/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_5g_plus_mobiledata.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_5g_plus_mobiledata.xml
rename to packages/SettingsLib/res/drawable/ic_5g_plus_mobiledata.xml
diff --git a/packages/SystemUI/res/drawable/ic_e_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_e_mobiledata.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_e_mobiledata.xml
rename to packages/SettingsLib/res/drawable/ic_e_mobiledata.xml
diff --git a/packages/SystemUI/res/drawable/ic_g_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_g_mobiledata.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_g_mobiledata.xml
rename to packages/SettingsLib/res/drawable/ic_g_mobiledata.xml
diff --git a/packages/SystemUI/res/drawable/ic_h_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_h_mobiledata.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_h_mobiledata.xml
rename to packages/SettingsLib/res/drawable/ic_h_mobiledata.xml
diff --git a/packages/SystemUI/res/drawable/ic_h_plus_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_h_plus_mobiledata.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_h_plus_mobiledata.xml
rename to packages/SettingsLib/res/drawable/ic_h_plus_mobiledata.xml
diff --git a/packages/SystemUI/res/drawable/ic_lte_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_lte_mobiledata.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_lte_mobiledata.xml
rename to packages/SettingsLib/res/drawable/ic_lte_mobiledata.xml
diff --git a/packages/SystemUI/res/drawable/ic_lte_plus_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_lte_plus_mobiledata.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_lte_plus_mobiledata.xml
rename to packages/SettingsLib/res/drawable/ic_lte_plus_mobiledata.xml
diff --git a/packages/SystemUI/res/drawable/stat_sys_airplane_mode.xml b/packages/SettingsLib/res/drawable/stat_sys_airplane_mode.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/stat_sys_airplane_mode.xml
rename to packages/SettingsLib/res/drawable/stat_sys_airplane_mode.xml
diff --git a/packages/SystemUI/res/values-mcc310-mnc004/strings.xml b/packages/SettingsLib/res/values-mcc310-mnc004/strings.xml
similarity index 100%
rename from packages/SystemUI/res/values-mcc310-mnc004/strings.xml
rename to packages/SettingsLib/res/values-mcc310-mnc004/strings.xml
diff --git a/packages/SystemUI/res/values-mcc311-mnc480/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc480/strings.xml
similarity index 100%
rename from packages/SystemUI/res/values-mcc311-mnc480/strings.xml
rename to packages/SettingsLib/res/values-mcc311-mnc480/strings.xml
diff --git a/packages/SettingsLib/res/values/config.xml b/packages/SettingsLib/res/values/config.xml
index 332d6c7..45253bb 100644
--- a/packages/SettingsLib/res/values/config.xml
+++ b/packages/SettingsLib/res/values/config.xml
@@ -21,4 +21,11 @@
<!-- Threshold in micro watts above which a charger is rated as "fast"; 1.5A @ 5V -->
<integer name="config_chargingFastThreshold">7500000</integer>
+
+ <!-- When true, show 1/2G networks as 3G. -->
+ <bool name="config_showMin3G">false</bool>
+
+ <!-- Control whether status bar should distinguish HSPA data icon form UMTS
+ data icon on devices -->
+ <bool name="config_hspa_data_distinguishable">false</bool>
</resources>
\ No newline at end of file
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 4e97212..f518b74 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1112,7 +1112,7 @@
<string name="power_remaining_charging_duration_only"><xliff:g id="time">%1$s</xliff:g> left until charged</string>
<!-- [CHAR_LIMIT=40] Label for battery level chart when charging with duration -->
<string name="power_charging_duration"><xliff:g id="level">%1$s</xliff:g> - <xliff:g id="time">%2$s</xliff:g> until charged</string>
- <!-- [CHAR_LIMIT=40] Label for battery level chart when charge been limited -->
+ <!-- [CHAR_LIMIT=80] Label for battery level chart when charge been limited -->
<string name="power_charging_limited"><xliff:g id="level">%1$s</xliff:g> - Optimizing for battery health</string>
<!-- Battery Info screen. Value for a status item. Used for diagnostic info screens, precise translation isn't needed -->
@@ -1404,4 +1404,79 @@
<string name="wifi_hotspot_switch_on_text">On</string>
<!-- Label for Wifi hotspot switch off. Toggles hotspot off [CHAR LIMIT=30] -->
<string name="wifi_hotspot_switch_off_text">Off</string>
+
+ <!-- Content description of the carrier network changing icon. [CHAR LIMIT=NONE] -->
+ <string name="carrier_network_change_mode">Carrier network changing</string>
+
+ <!-- Content description of the data connection type 3G. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_3g">3G</string>
+
+ <!-- Content description of the data connection type Edge. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_edge">EDGE</string>
+
+ <!-- Content description of the data connection type CDMA. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_cdma">1X</string>
+
+ <!-- Content description of the data connection type GPRS. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_gprs">GPRS</string>
+
+ <!-- Content description of the data connection type 3.5G. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_3_5g">H</string>
+
+ <!-- Content description of the data connection type 3.5G+. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_3_5g_plus">H+</string>
+
+ <!-- Content description of the data connection type 4G . [CHAR LIMIT=NONE] -->
+ <string name="data_connection_4g">4G</string>
+
+ <!-- Content description of the data connection type 4G+. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_4g_plus">4G+</string>
+
+ <!-- Content description of the data connection type LTE. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_lte">LTE</string>
+
+ <!-- Content description of the data connection type LTE+. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_lte_plus">LTE+</string>
+
+ <!-- Content description of the data connection type 5Ge with HTML styling. DO NOT TRANSLATE [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5ge_html" translate="false"> <i>5G <small>E</small></i> </string>
+
+ <!-- Content description of the data connection type 5G. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g" translatable="false">5G</string>
+
+ <!-- Content description of the data connection type 5G+. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G+</string>
+
+ <!-- Content description of the cell data being disabled. [CHAR LIMIT=NONE] -->
+ <string name="cell_data_off_content_description">Mobile data off</string>
+
+ <!-- Content description of the cell data for not default subscription. [CHAR LIMIT=NONE] -->
+ <string name="not_default_data_content_description">Not set to use data</string>
+
+ <!-- Content description of the phone signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_no_phone">No phone.</string>
+ <!-- Content description of the phone signal when it is one bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_phone_one_bar">Phone one bar.</string>
+ <!-- Content description of the phone signal when it is two bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_phone_two_bars">Phone two bars.</string>
+ <!-- Content description of the phone signal when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_phone_three_bars">Phone three bars.</string>
+ <!-- Content description of the phone signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_phone_signal_full">Phone signal full.</string>
+
+ <!-- Content description of the data signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_no_data">No data.</string>
+ <!-- Content description of the data signal when it is one bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_data_one_bar">Data one bar.</string>
+ <!-- Content description of the data signal when it is two bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_data_two_bars">Data two bars.</string>
+ <!-- Content description of the data signal when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_data_three_bars">Data three bars.</string>
+ <!-- Content description of the data signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_data_signal_full">Data signal full.</string>
+
+ <!-- Content description of the Ethernet connection when disconnected for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_ethernet_disconnected">Ethernet disconnected.</string>
+ <!-- Content description of the Ethernet connection when connected for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_ethernet_connected">Ethernet connected.</string>
</resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/AccessibilityContentDescriptions.java b/packages/SettingsLib/src/com/android/settingslib/AccessibilityContentDescriptions.java
new file mode 100644
index 0000000..45028ff
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/AccessibilityContentDescriptions.java
@@ -0,0 +1,55 @@
+/*
+ * 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.settingslib;
+
+/**
+ * Content descriptions for accessibility support.
+ */
+public class AccessibilityContentDescriptions {
+
+ private AccessibilityContentDescriptions() {}
+ public static final int[] PHONE_SIGNAL_STRENGTH = {
+ R.string.accessibility_no_phone,
+ R.string.accessibility_phone_one_bar,
+ R.string.accessibility_phone_two_bars,
+ R.string.accessibility_phone_three_bars,
+ R.string.accessibility_phone_signal_full
+ };
+
+ public static final int[] DATA_CONNECTION_STRENGTH = {
+ R.string.accessibility_no_data,
+ R.string.accessibility_data_one_bar,
+ R.string.accessibility_data_two_bars,
+ R.string.accessibility_data_three_bars,
+ R.string.accessibility_data_signal_full
+ };
+
+ public static final int[] WIFI_CONNECTION_STRENGTH = {
+ R.string.accessibility_no_wifi,
+ R.string.accessibility_wifi_one_bar,
+ R.string.accessibility_wifi_two_bars,
+ R.string.accessibility_wifi_three_bars,
+ R.string.accessibility_wifi_signal_full
+ };
+
+ public static final int WIFI_NO_CONNECTION = R.string.accessibility_no_wifi;
+
+ public static final int[] ETHERNET_CONNECTION_VALUES = {
+ R.string.accessibility_ethernet_disconnected,
+ R.string.accessibility_ethernet_connected,
+ };
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/SignalIcon.java b/packages/SettingsLib/src/com/android/settingslib/SignalIcon.java
new file mode 100644
index 0000000..bc0c6f3
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/SignalIcon.java
@@ -0,0 +1,224 @@
+/*
+ * 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.settingslib;
+
+import java.text.SimpleDateFormat;
+import java.util.Objects;
+
+/**
+ * Icons and states for SysUI and Settings.
+ */
+public class SignalIcon {
+
+ /**
+ * Holds icons for a given state. Arrays are generally indexed as inet
+ * state (full connectivity or not) first, and second dimension as
+ * signal strength.
+ */
+ public static class IconGroup {
+ public final int[][] sbIcons;
+ public final int[][] qsIcons;
+ public final int[] contentDesc;
+ public final int sbNullState;
+ public final int qsNullState;
+ public final int sbDiscState;
+ public final int qsDiscState;
+ public final int discContentDesc;
+ // For logging.
+ public final String name;
+
+ public IconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc,
+ int sbNullState, int qsNullState, int sbDiscState, int qsDiscState,
+ int discContentDesc) {
+ this.name = name;
+ this.sbIcons = sbIcons;
+ this.qsIcons = qsIcons;
+ this.contentDesc = contentDesc;
+ this.sbNullState = sbNullState;
+ this.qsNullState = qsNullState;
+ this.sbDiscState = sbDiscState;
+ this.qsDiscState = qsDiscState;
+ this.discContentDesc = discContentDesc;
+ }
+
+ @Override
+ public String toString() {
+ return "IconGroup(" + name + ")";
+ }
+ }
+
+ /**
+ * Holds states for SysUI.
+ */
+ public static class State {
+ // No locale as it's only used for logging purposes
+ private static SimpleDateFormat sSDF = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
+ public boolean connected;
+ public boolean enabled;
+ public boolean activityIn;
+ public boolean activityOut;
+ public int level;
+ public IconGroup iconGroup;
+ public int inetCondition;
+ public int rssi; // Only for logging.
+
+ // Not used for comparison, just used for logging.
+ public long time;
+
+ /**
+ * Generates a copy of the source state.
+ */
+ public void copyFrom(State state) {
+ connected = state.connected;
+ enabled = state.enabled;
+ level = state.level;
+ iconGroup = state.iconGroup;
+ inetCondition = state.inetCondition;
+ activityIn = state.activityIn;
+ activityOut = state.activityOut;
+ rssi = state.rssi;
+ time = state.time;
+ }
+
+ @Override
+ public String toString() {
+ if (time != 0) {
+ StringBuilder builder = new StringBuilder();
+ toString(builder);
+ return builder.toString();
+ } else {
+ return "Empty " + getClass().getSimpleName();
+ }
+ }
+
+ protected void toString(StringBuilder builder) {
+ builder.append("connected=").append(connected).append(',')
+ .append("enabled=").append(enabled).append(',')
+ .append("level=").append(level).append(',')
+ .append("inetCondition=").append(inetCondition).append(',')
+ .append("iconGroup=").append(iconGroup).append(',')
+ .append("activityIn=").append(activityIn).append(',')
+ .append("activityOut=").append(activityOut).append(',')
+ .append("rssi=").append(rssi).append(',')
+ .append("lastModified=").append(sSDF.format(time));
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!o.getClass().equals(getClass())) {
+ return false;
+ }
+ State other = (State) o;
+ return other.connected == connected
+ && other.enabled == enabled
+ && other.level == level
+ && other.inetCondition == inetCondition
+ && other.iconGroup == iconGroup
+ && other.activityIn == activityIn
+ && other.activityOut == activityOut
+ && other.rssi == rssi;
+ }
+ }
+
+ /**
+ * Holds icons for a given MobileState.
+ */
+ public static class MobileIconGroup extends IconGroup {
+ public final int dataContentDescription; // mContentDescriptionDataType
+ public final int dataType;
+ public final boolean isWide;
+ public final int qsDataType;
+
+ public MobileIconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc,
+ int sbNullState, int qsNullState, int sbDiscState, int qsDiscState,
+ int discContentDesc, int dataContentDesc, int dataType, boolean isWide) {
+ super(name, sbIcons, qsIcons, contentDesc, sbNullState, qsNullState, sbDiscState,
+ qsDiscState, discContentDesc);
+ this.dataContentDescription = dataContentDesc;
+ this.dataType = dataType;
+ this.isWide = isWide;
+ this.qsDataType = dataType; // TODO: remove this field
+ }
+ }
+
+ /**
+ * Holds mobile states for SysUI.
+ */
+ public static class MobileState extends State {
+ public String networkName;
+ public String networkNameData;
+ public boolean dataSim;
+ public boolean dataConnected;
+ public boolean isEmergency;
+ public boolean airplaneMode;
+ public boolean carrierNetworkChangeMode;
+ public boolean isDefault;
+ public boolean userSetup;
+ public boolean roaming;
+ public boolean defaultDataOff; // Tracks the on/off state of the defaultDataSubscription
+
+ @Override
+ public void copyFrom(State s) {
+ super.copyFrom(s);
+ MobileState state = (MobileState) s;
+ dataSim = state.dataSim;
+ networkName = state.networkName;
+ networkNameData = state.networkNameData;
+ dataConnected = state.dataConnected;
+ isDefault = state.isDefault;
+ isEmergency = state.isEmergency;
+ airplaneMode = state.airplaneMode;
+ carrierNetworkChangeMode = state.carrierNetworkChangeMode;
+ userSetup = state.userSetup;
+ roaming = state.roaming;
+ defaultDataOff = state.defaultDataOff;
+ }
+
+ @Override
+ protected void toString(StringBuilder builder) {
+ super.toString(builder);
+ builder.append(',');
+ builder.append("dataSim=").append(dataSim).append(',');
+ builder.append("networkName=").append(networkName).append(',');
+ builder.append("networkNameData=").append(networkNameData).append(',');
+ builder.append("dataConnected=").append(dataConnected).append(',');
+ builder.append("roaming=").append(roaming).append(',');
+ builder.append("isDefault=").append(isDefault).append(',');
+ builder.append("isEmergency=").append(isEmergency).append(',');
+ builder.append("airplaneMode=").append(airplaneMode).append(',');
+ builder.append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode)
+ .append(',');
+ builder.append("userSetup=").append(userSetup).append(',');
+ builder.append("defaultDataOff=").append(defaultDataOff);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return super.equals(o)
+ && Objects.equals(((MobileState) o).networkName, networkName)
+ && Objects.equals(((MobileState) o).networkNameData, networkNameData)
+ && ((MobileState) o).dataSim == dataSim
+ && ((MobileState) o).dataConnected == dataConnected
+ && ((MobileState) o).isEmergency == isEmergency
+ && ((MobileState) o).airplaneMode == airplaneMode
+ && ((MobileState) o).carrierNetworkChangeMode == carrierNetworkChangeMode
+ && ((MobileState) o).userSetup == userSetup
+ && ((MobileState) o).isDefault == isDefault
+ && ((MobileState) o).roaming == roaming
+ && ((MobileState) o).defaultDataOff == defaultDataOff;
+ }
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/mobile/MobileMappings.java b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileMappings.java
index 5689860..09f285b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/mobile/MobileMappings.java
+++ b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileMappings.java
@@ -15,10 +15,21 @@
*/
package com.android.settingslib.mobile;
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.PersistableBundle;
import android.telephony.Annotation;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyDisplayInfo;
import android.telephony.TelephonyManager;
+import com.android.settingslib.R;
+import com.android.settingslib.SignalIcon.MobileIconGroup;
+
+import java.util.HashMap;
+import java.util.Map;
+
/**
* Holds the utility functions to create the RAT to MobileIconGroup mappings.
*/
@@ -60,4 +71,165 @@
return "unsupported";
}
}
+
+ /**
+ * Produce the default MobileIconGroup.
+ */
+ public static MobileIconGroup getDefaultIcons(Config config) {
+ if (!config.showAtLeast3G) {
+ return TelephonyIcons.G;
+ } else {
+ return TelephonyIcons.THREE_G;
+ }
+ }
+
+ /**
+ * Produce a mapping of data network types to icon groups for simple and quick use in
+ * updateTelephony.
+ */
+ public static Map<String, MobileIconGroup> mapIconSets(Config config) {
+ final Map<String, MobileIconGroup> networkToIconLookup = new HashMap<>();
+
+ networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EVDO_0),
+ TelephonyIcons.THREE_G);
+ networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EVDO_A),
+ TelephonyIcons.THREE_G);
+ networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EVDO_B),
+ TelephonyIcons.THREE_G);
+ networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EHRPD),
+ TelephonyIcons.THREE_G);
+ if (config.show4gFor3g) {
+ networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_UMTS),
+ TelephonyIcons.FOUR_G);
+ } else {
+ networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_UMTS),
+ TelephonyIcons.THREE_G);
+ }
+ networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_TD_SCDMA),
+ TelephonyIcons.THREE_G);
+
+ if (!config.showAtLeast3G) {
+ networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_UNKNOWN),
+ TelephonyIcons.UNKNOWN);
+ networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EDGE),
+ TelephonyIcons.E);
+ networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_CDMA),
+ TelephonyIcons.ONE_X);
+ networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_1xRTT),
+ TelephonyIcons.ONE_X);
+ } else {
+ networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_UNKNOWN),
+ TelephonyIcons.THREE_G);
+ networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EDGE),
+ TelephonyIcons.THREE_G);
+ networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_CDMA),
+ TelephonyIcons.THREE_G);
+ networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_1xRTT),
+ TelephonyIcons.THREE_G);
+ }
+
+ MobileIconGroup hGroup = TelephonyIcons.THREE_G;
+ MobileIconGroup hPlusGroup = TelephonyIcons.THREE_G;
+ if (config.show4gFor3g) {
+ hGroup = TelephonyIcons.FOUR_G;
+ hPlusGroup = TelephonyIcons.FOUR_G;
+ } else if (config.hspaDataDistinguishable) {
+ hGroup = TelephonyIcons.H;
+ hPlusGroup = TelephonyIcons.H_PLUS;
+ }
+
+ networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_HSDPA), hGroup);
+ networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_HSUPA), hGroup);
+ networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_HSPA), hGroup);
+ networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_HSPAP), hPlusGroup);
+
+ if (config.show4gForLte) {
+ networkToIconLookup.put(toIconKey(
+ TelephonyManager.NETWORK_TYPE_LTE),
+ TelephonyIcons.FOUR_G);
+ if (config.hideLtePlus) {
+ networkToIconLookup.put(toDisplayIconKey(
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA),
+ TelephonyIcons.FOUR_G);
+ } else {
+ networkToIconLookup.put(toDisplayIconKey(
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA),
+ TelephonyIcons.FOUR_G_PLUS);
+ }
+ } else {
+ networkToIconLookup.put(toIconKey(
+ TelephonyManager.NETWORK_TYPE_LTE),
+ TelephonyIcons.LTE);
+ if (config.hideLtePlus) {
+ networkToIconLookup.put(toDisplayIconKey(
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA),
+ TelephonyIcons.LTE);
+ } else {
+ networkToIconLookup.put(toDisplayIconKey(
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA),
+ TelephonyIcons.LTE_PLUS);
+ }
+ }
+ networkToIconLookup.put(toIconKey(
+ TelephonyManager.NETWORK_TYPE_IWLAN),
+ TelephonyIcons.WFC);
+ networkToIconLookup.put(toDisplayIconKey(
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO),
+ TelephonyIcons.LTE_CA_5G_E);
+ networkToIconLookup.put(toDisplayIconKey(
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA),
+ TelephonyIcons.NR_5G);
+ networkToIconLookup.put(toDisplayIconKey(
+ TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE),
+ TelephonyIcons.NR_5G_PLUS);
+ networkToIconLookup.put(toIconKey(
+ TelephonyManager.NETWORK_TYPE_NR),
+ TelephonyIcons.NR_5G);
+ return networkToIconLookup;
+ }
+
+ /**
+ * Wrapper class of system configs and Carrier configs.
+ */
+ public static class Config {
+ public boolean showAtLeast3G = false;
+ public boolean show4gFor3g = false;
+ public boolean alwaysShowCdmaRssi = false;
+ public boolean show4gForLte = false;
+ public boolean hideLtePlus = false;
+ public boolean hspaDataDistinguishable;
+ public boolean alwaysShowDataRatIcon = false;
+
+ /**
+ * Reads the latest configs.
+ */
+ public static Config readConfig(Context context) {
+ Config config = new Config();
+ Resources res = context.getResources();
+
+ config.showAtLeast3G = res.getBoolean(R.bool.config_showMin3G);
+ config.alwaysShowCdmaRssi =
+ res.getBoolean(com.android.internal.R.bool.config_alwaysUseCdmaRssi);
+ config.hspaDataDistinguishable =
+ res.getBoolean(R.bool.config_hspa_data_distinguishable);
+
+ CarrierConfigManager configMgr = (CarrierConfigManager)
+ context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
+ // Handle specific carrier config values for the default data SIM
+ int defaultDataSubId = SubscriptionManager.from(context)
+ .getDefaultDataSubscriptionId();
+ PersistableBundle b = configMgr.getConfigForSubId(defaultDataSubId);
+ if (b != null) {
+ config.alwaysShowDataRatIcon = b.getBoolean(
+ CarrierConfigManager.KEY_ALWAYS_SHOW_DATA_RAT_ICON_BOOL);
+ config.show4gForLte = b.getBoolean(
+ CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL);
+ config.show4gFor3g = b.getBoolean(
+ CarrierConfigManager.KEY_SHOW_4G_FOR_3G_DATA_ICON_BOOL);
+ config.hideLtePlus = b.getBoolean(
+ CarrierConfigManager.KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL);
+ }
+ return config;
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SettingsLib/src/com/android/settingslib/mobile/TelephonyIcons.java
similarity index 74%
rename from packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
rename to packages/SettingsLib/src/com/android/settingslib/mobile/TelephonyIcons.java
index d9591cf..c2613a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
+++ b/packages/SettingsLib/src/com/android/settingslib/mobile/TelephonyIcons.java
@@ -14,33 +14,37 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.policy;
+package com.android.settingslib.mobile;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.policy.MobileSignalController.MobileIconGroup;
+import com.android.settingslib.AccessibilityContentDescriptions;
+import com.android.settingslib.R;
+import com.android.settingslib.SignalIcon.MobileIconGroup;
import java.util.HashMap;
import java.util.Map;
-class TelephonyIcons {
+/**
+ * Telephony related icons and strings for SysUI and Settings.
+ */
+public class TelephonyIcons {
//***** Data connection icons
- static final int FLIGHT_MODE_ICON = R.drawable.stat_sys_airplane_mode;
+ public static final int FLIGHT_MODE_ICON = R.drawable.stat_sys_airplane_mode;
- static final int ICON_LTE = R.drawable.ic_lte_mobiledata;
- static final int ICON_LTE_PLUS = R.drawable.ic_lte_plus_mobiledata;
- static final int ICON_G = R.drawable.ic_g_mobiledata;
- static final int ICON_E = R.drawable.ic_e_mobiledata;
- static final int ICON_H = R.drawable.ic_h_mobiledata;
- static final int ICON_H_PLUS = R.drawable.ic_h_plus_mobiledata;
- static final int ICON_3G = R.drawable.ic_3g_mobiledata;
- static final int ICON_4G = R.drawable.ic_4g_mobiledata;
- static final int ICON_4G_PLUS = R.drawable.ic_4g_plus_mobiledata;
- static final int ICON_5G_E = R.drawable.ic_5g_e_mobiledata;
- static final int ICON_1X = R.drawable.ic_1x_mobiledata;
- static final int ICON_5G = R.drawable.ic_5g_mobiledata;
- static final int ICON_5G_PLUS = R.drawable.ic_5g_plus_mobiledata;
+ public static final int ICON_LTE = R.drawable.ic_lte_mobiledata;
+ public static final int ICON_LTE_PLUS = R.drawable.ic_lte_plus_mobiledata;
+ public static final int ICON_G = R.drawable.ic_g_mobiledata;
+ public static final int ICON_E = R.drawable.ic_e_mobiledata;
+ public static final int ICON_H = R.drawable.ic_h_mobiledata;
+ public static final int ICON_H_PLUS = R.drawable.ic_h_plus_mobiledata;
+ public static final int ICON_3G = R.drawable.ic_3g_mobiledata;
+ public static final int ICON_4G = R.drawable.ic_4g_mobiledata;
+ public static final int ICON_4G_PLUS = R.drawable.ic_4g_plus_mobiledata;
+ public static final int ICON_5G_E = R.drawable.ic_5g_e_mobiledata;
+ public static final int ICON_1X = R.drawable.ic_1x_mobiledata;
+ public static final int ICON_5G = R.drawable.ic_5g_mobiledata;
+ public static final int ICON_5G_PLUS = R.drawable.ic_5g_plus_mobiledata;
- static final MobileIconGroup CARRIER_NETWORK_CHANGE = new MobileIconGroup(
+ public static final MobileIconGroup CARRIER_NETWORK_CHANGE = new MobileIconGroup(
"CARRIER_NETWORK_CHANGE",
null,
null,
@@ -53,7 +57,7 @@
0,
false);
- static final MobileIconGroup THREE_G = new MobileIconGroup(
+ public static final MobileIconGroup THREE_G = new MobileIconGroup(
"3G",
null,
null,
@@ -66,7 +70,7 @@
TelephonyIcons.ICON_3G,
true);
- static final MobileIconGroup WFC = new MobileIconGroup(
+ public static final MobileIconGroup WFC = new MobileIconGroup(
"WFC",
null,
null,
@@ -77,7 +81,7 @@
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
0, 0, false);
- static final MobileIconGroup UNKNOWN = new MobileIconGroup(
+ public static final MobileIconGroup UNKNOWN = new MobileIconGroup(
"Unknown",
null,
null,
@@ -88,7 +92,7 @@
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
0, 0, false);
- static final MobileIconGroup E = new MobileIconGroup(
+ public static final MobileIconGroup E = new MobileIconGroup(
"E",
null,
null,
@@ -101,7 +105,7 @@
TelephonyIcons.ICON_E,
false);
- static final MobileIconGroup ONE_X = new MobileIconGroup(
+ public static final MobileIconGroup ONE_X = new MobileIconGroup(
"1X",
null,
null,
@@ -114,7 +118,7 @@
TelephonyIcons.ICON_1X,
true);
- static final MobileIconGroup G = new MobileIconGroup(
+ public static final MobileIconGroup G = new MobileIconGroup(
"G",
null,
null,
@@ -127,7 +131,7 @@
TelephonyIcons.ICON_G,
false);
- static final MobileIconGroup H = new MobileIconGroup(
+ public static final MobileIconGroup H = new MobileIconGroup(
"H",
null,
null,
@@ -140,7 +144,7 @@
TelephonyIcons.ICON_H,
false);
- static final MobileIconGroup H_PLUS = new MobileIconGroup(
+ public static final MobileIconGroup H_PLUS = new MobileIconGroup(
"H+",
null,
null,
@@ -153,7 +157,7 @@
TelephonyIcons.ICON_H_PLUS,
false);
- static final MobileIconGroup FOUR_G = new MobileIconGroup(
+ public static final MobileIconGroup FOUR_G = new MobileIconGroup(
"4G",
null,
null,
@@ -166,12 +170,12 @@
TelephonyIcons.ICON_4G,
true);
- static final MobileIconGroup FOUR_G_PLUS = new MobileIconGroup(
+ public static final MobileIconGroup FOUR_G_PLUS = new MobileIconGroup(
"4G+",
null,
null,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
- 0,0,
+ 0, 0,
0,
0,
AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
@@ -179,7 +183,7 @@
TelephonyIcons.ICON_4G_PLUS,
true);
- static final MobileIconGroup LTE = new MobileIconGroup(
+ public static final MobileIconGroup LTE = new MobileIconGroup(
"LTE",
null,
null,
@@ -192,7 +196,7 @@
TelephonyIcons.ICON_LTE,
true);
- static final MobileIconGroup LTE_PLUS = new MobileIconGroup(
+ public static final MobileIconGroup LTE_PLUS = new MobileIconGroup(
"LTE+",
null,
null,
@@ -205,7 +209,7 @@
TelephonyIcons.ICON_LTE_PLUS,
true);
- static final MobileIconGroup LTE_CA_5G_E = new MobileIconGroup(
+ public static final MobileIconGroup LTE_CA_5G_E = new MobileIconGroup(
"5Ge",
null,
null,
@@ -218,7 +222,7 @@
TelephonyIcons.ICON_5G_E,
true);
- static final MobileIconGroup NR_5G = new MobileIconGroup(
+ public static final MobileIconGroup NR_5G = new MobileIconGroup(
"5G",
null,
null,
@@ -232,7 +236,7 @@
TelephonyIcons.ICON_5G,
true);
- static final MobileIconGroup NR_5G_PLUS = new MobileIconGroup(
+ public static final MobileIconGroup NR_5G_PLUS = new MobileIconGroup(
"5G_PLUS",
null,
null,
@@ -246,7 +250,7 @@
TelephonyIcons.ICON_5G_PLUS,
true);
- static final MobileIconGroup DATA_DISABLED = new MobileIconGroup(
+ public static final MobileIconGroup DATA_DISABLED = new MobileIconGroup(
"DataDisabled",
null,
null,
@@ -259,7 +263,7 @@
0,
false);
- static final MobileIconGroup NOT_DEFAULT_DATA = new MobileIconGroup(
+ public static final MobileIconGroup NOT_DEFAULT_DATA = new MobileIconGroup(
"NotDefaultData",
null,
null,
@@ -276,7 +280,7 @@
// in QSCarrier#hasValidTypeContentDescription
/** Mapping icon name(lower case) to the icon object. */
- static final Map<String, MobileIconGroup> ICON_NAME_TO_ICON;
+ public static final Map<String, MobileIconGroup> ICON_NAME_TO_ICON;
static {
ICON_NAME_TO_ICON = new HashMap<>();
ICON_NAME_TO_ICON.put("carrier_network_change", CARRIER_NETWORK_CHANGE);
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 5ad43e3..846efa7 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -180,7 +180,7 @@
<!-- Default state of tap to wake -->
<bool name="def_double_tap_to_wake">true</bool>
- <!-- Default for Settings.Secure.NFC_PAYMENT_COMPONENT -->
+ <!-- Default for Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT -->
<string name="def_nfc_payment_component"></string>
<!-- Default setting for ability to add users from the lock screen -->
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index af775cc6..411a78a 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -155,6 +155,7 @@
<uses-permission android:name="android.permission.MANAGE_CONTENT_CAPTURE" />
<uses-permission android:name="android.permission.MANAGE_CONTENT_SUGGESTIONS" />
<uses-permission android:name="android.permission.MANAGE_APP_PREDICTIONS" />
+ <uses-permission android:name="android.permission.MANAGE_SEARCH_UI" />
<uses-permission android:name="android.permission.NETWORK_SETTINGS" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.SET_TIME" />
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 285c4a1..3fb5a9c 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -103,6 +103,7 @@
<uses-permission android:name="android.permission.START_ACTIVITY_AS_CALLER" />
<uses-permission android:name="android.permission.START_TASKS_FROM_RECENTS" />
<uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT" />
+ <uses-permission android:name="android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS" />
<!-- WindowManager -->
<uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" />
@@ -390,7 +391,7 @@
</activity-alias>
<activity
- android:name="com.android.wm.shell.splitscreen.ForcedResizableInfoActivity"
+ android:name="com.android.wm.shell.legacysplitscreen.ForcedResizableInfoActivity"
android:theme="@style/ForcedResizableTheme"
android:excludeFromRecents="true"
android:stateNotNeeded="true"
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTileView.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTileView.java
index 53f7e44..bcd28a6 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTileView.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSTileView.java
@@ -50,4 +50,6 @@
public abstract void onStateChanged(State state);
public abstract int getDetailY();
+
+ public void setShowLabels(boolean show) {}
}
diff --git a/packages/SystemUI/res/layout/feedback_info.xml b/packages/SystemUI/res/layout/feedback_info.xml
index 753f56a..e013a4e 100644
--- a/packages/SystemUI/res/layout/feedback_info.xml
+++ b/packages/SystemUI/res/layout/feedback_info.xml
@@ -24,18 +24,18 @@
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="vertical"
- android:paddingStart="@*android:dimen/notification_content_margin_start"
- android:paddingEnd="@*android:dimen/notification_content_margin_end"
- android:background="?android:attr/colorBackground"
- android:theme="@*android:style/Theme.DeviceDefault.Light">
+ android:paddingStart="@dimen/notification_shade_content_margin_horizontal"
+ android:paddingEnd="@dimen/notification_shade_content_margin_horizontal"
+ android:background="?android:attr/colorBackground">
<!-- Package Info -->
<LinearLayout
android:id="@+id/header"
android:layout_width="match_parent"
- android:layout_height="@dimen/notification_guts_conversation_header_height"
+ android:layout_height="wrap_content"
android:gravity="center_vertical"
android:clipChildren="false"
+ android:paddingTop="@dimen/notification_guts_header_top_padding"
android:clipToPadding="false">
<ImageView
android:id="@+id/pkg_icon"
@@ -49,7 +49,6 @@
android:layout_weight="1"
android:layout_width="0dp"
android:orientation="vertical"
-
android:layout_height="wrap_content"
android:minHeight="@dimen/notification_guts_conversation_icon_size"
android:layout_centerVertical="true"
@@ -63,10 +62,11 @@
android:orientation="horizontal">
<TextView
android:id="@+id/pkg_name"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- style="@style/TextAppearance.NotificationImportanceChannelGroup"
+ style="@style/TextAppearance.NotificationImportanceApp"
android:ellipsize="end"
+ android:textDirection="locale"
android:maxLines="1"/>
</LinearLayout>
</LinearLayout>
@@ -76,8 +76,7 @@
android:id="@+id/prompt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginTop="@*android:dimen/notification_header_padding_top"
- style="@style/TextAppearance.NotificationInfo.Secondary" />
+ android:layout_marginTop="@*android:dimen/notification_header_padding_top" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 2bf513c..101124e 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -24,10 +24,6 @@
certain GPU's and thus can be turned off with only minimal visual impact. -->
<bool name="config_notifications_round_rect_clipping">true</bool>
- <!-- Control whether status bar should distinguish HSPA data icon form UMTS
- data icon on devices -->
- <bool name="config_hspa_data_distinguishable">false</bool>
-
<!-- Component to be used as the status bar service. Must implement the IStatusBar
interface. This name is in the ComponentName flattened format (package/class) -->
<string name="config_statusBarComponent" translatable="false">com.android.systemui.statusbar.phone.StatusBar</string>
@@ -56,9 +52,6 @@
<!-- Show phone (voice) signal strength instead of data in mobile RSSI. -->
<bool name="config_showPhoneRSSIForData">false</bool>
- <!-- When true, show 1/2G networks as 3G. -->
- <bool name="config_showMin3G">false</bool>
-
<!-- Show rotation lock toggle in System UI-->
<bool name="config_showRotationLock">true</bool>
@@ -358,7 +351,7 @@
<bool name="config_showNotificationGear">true</bool>
<!-- Whether or not a background should be drawn behind a notification. -->
- <bool name="config_drawNotificationBackground">true</bool>
+ <bool name="config_drawNotificationBackground">false</bool>
<!-- Whether or the notifications can be shown and dismissed with a drag. -->
<bool name="config_enableNotificationShadeDrag">true</bool>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 7989b7a..6fa4aa1 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -450,28 +450,6 @@
<!-- Content description of the battery when battery state is unknown for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_battery_unknown">Battery percentage unknown.</string>
- <!-- Content description of the phone signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_no_phone">No phone.</string>
- <!-- Content description of the phone signal when it is one bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_phone_one_bar">Phone one bar.</string>
- <!-- Content description of the phone signal when it is two bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_phone_two_bars">Phone two bars.</string>
- <!-- Content description of the phone signal when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_phone_three_bars">Phone three bars.</string>
- <!-- Content description of the phone signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_phone_signal_full">Phone signal full.</string>
-
- <!-- Content description of the data signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_no_data">No data.</string>
- <!-- Content description of the data signal when it is one bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_data_one_bar">Data one bar.</string>
- <!-- Content description of the data signal when it is two bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_data_two_bars">Data two bars.</string>
- <!-- Content description of the data signal when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_data_three_bars">Data three bars.</string>
- <!-- Content description of the data signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_data_signal_full">Data signal full.</string>
-
<!-- Content description of the wifi label showing what we are connected to. [CHAR LIMIT=NONE] -->
<string name="accessibility_wifi_name">Connected to <xliff:g id="wifi" example="Home Network">%s</xliff:g>.</string>
@@ -493,11 +471,6 @@
<!-- Content description of the WiMAX signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_wimax_signal_full">WiMAX signal full.</string>
- <!-- Content description of the Ethernet connection when disconnected for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_ethernet_disconnected">Ethernet disconnected.</string>
- <!-- Content description of the Ethernet connection when connected for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_ethernet_connected">Ethernet connected.</string>
-
<!-- Content description of an item with no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_no_signal">No signal.</string>
<!-- Content description of an item with no signal and no connection for accessibility (not shown on the screen) [CHAR LIMIT=NONE] -->
@@ -522,54 +495,16 @@
<!-- Content description of an item that is connecting for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_desc_connecting">Connecting.</string>
- <!-- Content description of the data connection type GPRS. [CHAR LIMIT=NONE] -->
- <string name="data_connection_gprs">GPRS</string>
-
<!-- Content description of the data connection type HSPA and its variants. [CHAR LIMIT=NONE] -->
<string name="data_connection_hspa">HSPA</string>
- <!-- Content description of the data connection type 3G. [CHAR LIMIT=NONE] -->
- <string name="data_connection_3g">3G</string>
-
- <!-- Content description of the data connection type 3.5G. [CHAR LIMIT=NONE] -->
- <string name="data_connection_3_5g">H</string>
-
- <!-- Content description of the data connection type 3.5G+. [CHAR LIMIT=NONE] -->
- <string name="data_connection_3_5g_plus">H+</string>
-
- <!-- Content description of the data connection type 4G . [CHAR LIMIT=NONE] -->
- <string name="data_connection_4g">4G</string>
-
- <!-- Content description of the data connection type 4G+. [CHAR LIMIT=NONE] -->
- <string name="data_connection_4g_plus">4G+</string>
-
- <!-- Content description of the data connection type LTE. [CHAR LIMIT=NONE] -->
- <string name="data_connection_lte">LTE</string>
-
- <!-- Content description of the data connection type LTE+. [CHAR LIMIT=NONE] -->
- <string name="data_connection_lte_plus">LTE+</string>
-
<!-- Content description of the data connection type 5Ge. [CHAR LIMIT=NONE] -->
<string name="data_connection_5ge" translatable="false">5Ge</string>
- <!-- Content description of the data connection type 5Ge with HTML styling. DO NOT TRANSLATE [CHAR LIMIT=NONE] -->
- <string name="data_connection_5ge_html" translate="false"> <i>5G <small>E</small></i> </string>
-
- <!-- Content description of the data connection type 5G. [CHAR LIMIT=NONE] -->
- <string name="data_connection_5g" translatable="false">5G</string>
-
- <!-- Content description of the data connection type 5G+. [CHAR LIMIT=NONE] -->
- <string name="data_connection_5g_plus" translatable="false">5G+</string>
-
- <!-- Content description of the data connection type CDMA. [CHAR LIMIT=NONE] -->
- <string name="data_connection_cdma">1X</string>
<!-- Content description of the roaming data connection type. [CHAR LIMIT=NONE] -->
<string name="data_connection_roaming">Roaming</string>
- <!-- Content description of the data connection type Edge. [CHAR LIMIT=NONE] -->
- <string name="data_connection_edge">EDGE</string>
-
<!-- Content description of the data connection type WiFi for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_data_connection_wifi">Wi-Fi</string>
@@ -582,12 +517,6 @@
<!-- Content description of the cell data being enabled. [CHAR LIMIT=NONE] -->
<string name="accessibility_cell_data_on">Mobile Data On</string>
- <!-- Content description of the cell data being disabled. [CHAR LIMIT=NONE] -->
- <string name="cell_data_off_content_description">Mobile data off</string>
-
- <!-- Content description of the cell data for not default subscription. [CHAR LIMIT=NONE] -->
- <string name="not_default_data_content_description">Not set to use data</string>
-
<!-- Content description of the cell data being disabled but shortened. [CHAR LIMIT=20] -->
<string name="cell_data_off">Off</string>
@@ -603,9 +532,6 @@
<!-- Content description of the no sim icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_no_sims">No SIM card.</string>
- <!-- Content description of the carrier network changing icon. [CHAR LIMIT=NONE] -->
- <string name="carrier_network_change_mode">Carrier network changing</string>
-
<!-- Content description of button to open battery details icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_battery_details">Open battery details</string>
@@ -1876,6 +1802,18 @@
<!-- [CHAR LIMIT=150] Notification Importance title: automatic importance level summary -->
<string name="notification_channel_summary_automatic">Have the system determine if this notification should make sound or vibration</string>
+ <!-- [CHAR LIMIT=150] Notification Importance title: automatic importance level summary (alerted) -->
+ <string name="notification_channel_summary_automatic_alerted"><b>Status:</b> Promoted to Default</string>
+
+ <!-- [CHAR LIMIT=150] Notification Importance title: automatic importance level summary (silenced) -->
+ <string name="notification_channel_summary_automatic_silenced"><b>Status:</b> Demoted to Silent</string>
+
+ <!-- [CHAR LIMIT=150] Notification Importance title: automatic importance level summary (promoted) -->
+ <string name="notification_channel_summary_automatic_promoted"><b>Status:</b> Ranked Higher</string>
+
+ <!-- [CHAR LIMIT=150] Notification Importance title: automatic importance level summary (demoted) -->
+ <string name="notification_channel_summary_automatic_demoted"><b>Status:</b> Ranked Lower</string>
+
<!-- [CHAR LIMIT=150] Notification Importance title: important conversation level summary -->
<string name="notification_channel_summary_priority">Shows at top of conversation section, appears as floating bubble, displays profile picture on lock screen</string>
@@ -1922,11 +1860,13 @@
<string name="notification_appops_ok">OK</string>
<!-- Notification Inline controls: describes how the notification was adjusted [CHAR_LIMIT=NONE] -->
- <string name="feedback_silenced">This notification was silenced by the system.</string>
+ <string name="feedback_alerted">This notification was automatically <b>promoted to Default</b> by the system.</string>
<!-- Notification Inline controls: describes how the notification was adjusted [CHAR_LIMIT=NONE] -->
- <string name="feedback_promoted">This notification was promoted by the system.</string>
+ <string name="feedback_silenced">This notification was automatically <b>demoted to Silent</b> by the system.</string>
<!-- Notification Inline controls: describes how the notification was adjusted [CHAR_LIMIT=NONE] -->
- <string name="feedback_demoted">This notification was demoted by the system.</string>
+ <string name="feedback_promoted">This notification was automatically <b>ranked higher</b> in your shade.</string>
+ <!-- Notification Inline controls: describes how the notification was adjusted [CHAR_LIMIT=NONE] -->
+ <string name="feedback_demoted">This notification was automatically <b>ranked lower</b> in your shade.</string>
<!-- Notification Inline controls: prompts the user for feedback [CHAR_LIMIT=NONE] -->
<string name="feedback_prompt">Was this correct?</string>
<!-- Notification Inline controls: responds to user provided feedback [CHAR_LIMIT=NONE] -->
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java
deleted file mode 100644
index c0f8cae..0000000
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java
+++ /dev/null
@@ -1,109 +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.
- */
-
-package com.android.systemui;
-
-import android.annotation.NonNull;
-import android.app.Notification;
-import android.os.Handler;
-import android.os.Looper;
-import android.util.ArraySet;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.statusbar.NotificationInteractionTracker;
-import com.android.systemui.statusbar.NotificationLifetimeExtender;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.util.time.SystemClock;
-
-import javax.inject.Inject;
-
-/**
- * Extends the lifetime of foreground notification services such that they show for at least
- * five seconds
- */
-public class ForegroundServiceLifetimeExtender implements NotificationLifetimeExtender {
-
- private static final String TAG = "FGSLifetimeExtender";
- @VisibleForTesting
- static final int MIN_FGS_TIME_MS = 5000;
-
- private NotificationSafeToRemoveCallback mNotificationSafeToRemoveCallback;
- private ArraySet<NotificationEntry> mManagedEntries = new ArraySet<>();
- private Handler mHandler = new Handler(Looper.getMainLooper());
- private final SystemClock mSystemClock;
- private final NotificationInteractionTracker mInteractionTracker;
-
- @Inject
- public ForegroundServiceLifetimeExtender(
- NotificationInteractionTracker interactionTracker,
- SystemClock systemClock) {
- mSystemClock = systemClock;
- mInteractionTracker = interactionTracker;
- }
-
- @Override
- public void setCallback(@NonNull NotificationSafeToRemoveCallback callback) {
- mNotificationSafeToRemoveCallback = callback;
- }
-
- @Override
- public boolean shouldExtendLifetime(@NonNull NotificationEntry entry) {
- if ((entry.getSbn().getNotification().flags
- & Notification.FLAG_FOREGROUND_SERVICE) == 0) {
- return false;
- }
-
- // Entry has triggered a HUN or some other interruption, therefore it has been seen and the
- // interrupter might be retaining it anyway.
- if (entry.hasInterrupted()) {
- return false;
- }
-
- boolean hasInteracted = mInteractionTracker.hasUserInteractedWith(entry.getKey());
- long aliveTime = mSystemClock.uptimeMillis() - entry.getCreationTime();
- return aliveTime < MIN_FGS_TIME_MS && !hasInteracted;
- }
-
- @Override
- public boolean shouldExtendLifetimeForPendingNotification(
- @NonNull NotificationEntry entry) {
- return shouldExtendLifetime(entry);
- }
-
- @Override
- public void setShouldManageLifetime(
- @NonNull NotificationEntry entry, boolean shouldManage) {
- if (!shouldManage) {
- mManagedEntries.remove(entry);
- return;
- }
-
- mManagedEntries.add(entry);
-
- Runnable r = () -> {
- if (mManagedEntries.contains(entry)) {
- mManagedEntries.remove(entry);
- if (mNotificationSafeToRemoveCallback != null) {
- mNotificationSafeToRemoveCallback.onSafeToRemove(entry.getKey());
- }
- }
- };
- long delayAmt = MIN_FGS_TIME_MS
- - (mSystemClock.uptimeMillis() - entry.getCreationTime());
- mHandler.postDelayed(r, delayAmt);
- }
-}
-
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
index d6cb114..04e26d3 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
@@ -50,7 +50,6 @@
ForegroundServiceController foregroundServiceController,
NotificationEntryManager notificationEntryManager,
NotifPipeline notifPipeline,
- ForegroundServiceLifetimeExtender fgsLifetimeExtender,
SystemClock systemClock) {
mContext = context;
mForegroundServiceController = foregroundServiceController;
@@ -78,7 +77,6 @@
removeNotification(entry.getSbn());
}
});
- mEntryManager.addNotificationLifetimeExtender(fgsLifetimeExtender);
notifPipeline.addCollectionListener(new NotifCollectionListener() {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 6b4e8bd..08262de 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -106,7 +106,7 @@
// components that shouldn't be run in the test environment
builder = prepareSysUIComponentBuilder(builder, mWMComponent)
.setPip(mWMComponent.getPip())
- .setSplitScreen(mWMComponent.getSplitScreen())
+ .setLegacySplitScreen(mWMComponent.getLegacySplitScreen())
.setOneHanded(mWMComponent.getOneHanded())
.setBubbles(mWMComponent.getBubbles())
.setHideDisplayCutout(mWMComponent.getHideDisplayCutout())
@@ -117,7 +117,7 @@
// is separating this logic into newly creating SystemUITestsFactory.
builder = prepareSysUIComponentBuilder(builder, mWMComponent)
.setPip(Optional.ofNullable(null))
- .setSplitScreen(Optional.ofNullable(null))
+ .setLegacySplitScreen(Optional.ofNullable(null))
.setOneHanded(Optional.ofNullable(null))
.setBubbles(Optional.ofNullable(null))
.setHideDisplayCutout(Optional.ofNullable(null))
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
index 275bfaa..f22fa32 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
@@ -82,7 +82,7 @@
import com.android.systemui.theme.ThemeOverlayApplier;
import com.android.systemui.util.leak.LeakDetector;
import com.android.wm.shell.pip.Pip;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import java.util.Optional;
import java.util.concurrent.Executor;
@@ -213,7 +213,7 @@
BroadcastDispatcher broadcastDispatcher,
CommandQueue commandQueue,
Optional<Pip> pipOptional,
- Optional<SplitScreen> splitScreenOptional,
+ Optional<LegacySplitScreen> splitScreenOptional,
Optional<Recents> recentsOptional,
Lazy<StatusBar> statusBarLazy,
ShadeController shadeController,
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
index f9f68e2..926062b 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
@@ -30,7 +30,7 @@
import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout;
import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.pip.Pip;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import java.util.Optional;
@@ -59,7 +59,7 @@
Builder setPip(Optional<Pip> p);
@BindsInstance
- Builder setSplitScreen(Optional<SplitScreen> s);
+ Builder setLegacySplitScreen(Optional<LegacySplitScreen> s);
@BindsInstance
Builder setAppPairs(Optional<AppPairs> s);
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
index ec8c7da..a1bde58 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
@@ -24,7 +24,7 @@
import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout;
import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.pip.Pip;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import java.util.Optional;
@@ -69,7 +69,7 @@
Optional<Pip> getPip();
@WMSingleton
- Optional<SplitScreen> getSplitScreen();
+ Optional<LegacySplitScreen> getLegacySplitScreen();
@WMSingleton
Optional<AppPairs> getAppPairs();
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
index eb86128..9e25389 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
@@ -24,6 +24,7 @@
import android.graphics.drawable.Icon;
import android.media.MediaMetadata;
import android.media.MediaRoute2Info;
+import android.media.MediaRouter2Manager;
import android.media.RoutingSessionInfo;
import android.media.session.MediaController;
import android.media.session.MediaSessionManager;
@@ -76,6 +77,7 @@
private final List<MediaDevice> mGroupMediaDevices = new CopyOnWriteArrayList<>();
private final boolean mAboveStatusbar;
private final NotificationEntryManager mNotificationEntryManager;
+ private final MediaRouter2Manager mRouterManager;
@VisibleForTesting
final List<MediaDevice> mMediaDevices = new CopyOnWriteArrayList<>();
@@ -104,6 +106,7 @@
mLocalMediaManager = new LocalMediaManager(mContext, lbm, imm, packageName);
mMetricLogger = new MediaOutputMetricLogger(mContext, mPackageName);
mUiEventLogger = uiEventLogger;
+ mRouterManager = MediaRouter2Manager.getInstance(mContext);
}
void start(@NonNull Callback cb) {
@@ -134,6 +137,7 @@
mLocalMediaManager.stopScan();
mLocalMediaManager.registerCallback(this);
mLocalMediaManager.startScan();
+ mRouterManager.startScan();
}
void stop() {
@@ -144,6 +148,9 @@
mLocalMediaManager.unregisterCallback(this);
mLocalMediaManager.stopScan();
}
+ if (mRouterManager != null) {
+ mRouterManager.stopScan();
+ }
mMediaDevices.clear();
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index b6ca77b..f7a4aca 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -137,7 +137,7 @@
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.wm.shell.pip.Pip;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import java.io.PrintWriter;
import java.util.List;
@@ -181,7 +181,7 @@
private final BroadcastDispatcher mBroadcastDispatcher;
private final CommandQueue mCommandQueue;
private final Optional<Pip> mPipOptional;
- private final Optional<SplitScreen> mSplitScreenOptional;
+ private final Optional<LegacySplitScreen> mSplitScreenOptional;
private final Optional<Recents> mRecentsOptional;
private final SystemActions mSystemActions;
private final Handler mHandler;
@@ -409,7 +409,7 @@
BroadcastDispatcher broadcastDispatcher,
CommandQueue commandQueue,
Optional<Pip> pipOptional,
- Optional<SplitScreen> splitScreenOptional,
+ Optional<LegacySplitScreen> splitScreenOptional,
Optional<Recents> recentsOptional, Lazy<StatusBar> statusBarLazy,
ShadeController shadeController,
NotificationRemoteInputManager notificationRemoteInputManager,
@@ -697,7 +697,7 @@
}
if (mStartingQuickSwitchRotation == -1 || mSplitScreenOptional
- .map(SplitScreen::isDividerVisible).orElse(false)) {
+ .map(LegacySplitScreen::isDividerVisible).orElse(false)) {
// Hide the secondary home handle if we are in multiwindow since apps in multiwindow
// aren't allowed to set the display orientation
resetSecondaryHandle();
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
index f7f3400..461ab3a 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
@@ -65,7 +65,7 @@
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.wm.shell.pip.Pip;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -98,7 +98,7 @@
private final BroadcastDispatcher mBroadcastDispatcher;
private final CommandQueue mCommandQueue;
private final Optional<Pip> mPipOptional;
- private final Optional<SplitScreen> mSplitScreenOptional;
+ private final Optional<LegacySplitScreen> mSplitScreenOptional;
private final Optional<Recents> mRecentsOptional;
private final Lazy<StatusBar> mStatusBarLazy;
private final ShadeController mShadeController;
@@ -133,7 +133,7 @@
BroadcastDispatcher broadcastDispatcher,
CommandQueue commandQueue,
Optional<Pip> pipOptional,
- Optional<SplitScreen> splitScreenOptional,
+ Optional<LegacySplitScreen> splitScreenOptional,
Optional<Recents> recentsOptional,
Lazy<StatusBar> statusBarLazy,
ShadeController shadeController,
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
index 4c3ac40..d6f0799 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
@@ -93,7 +93,7 @@
import com.android.systemui.statusbar.phone.NotificationPanelViewController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.wm.shell.pip.Pip;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import java.io.PrintWriter;
import java.util.function.Consumer;
@@ -1289,8 +1289,8 @@
return super.onApplyWindowInsets(insets);
}
- void registerDockedListener(SplitScreen splitScreen) {
- splitScreen.registerInSplitScreenListener(mDockedListener);
+ void registerDockedListener(LegacySplitScreen legacySplitScreen) {
+ legacySplitScreen.registerInSplitScreenListener(mDockedListener);
}
void registerPipExclusionBoundsChangeListener(Pip pip) {
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
index dddd39b..bc9500a 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
@@ -21,7 +21,6 @@
import android.app.people.ConversationChannel;
import android.app.people.IPeopleManager;
import android.app.people.PeopleSpaceTile;
-import android.appwidget.AppWidgetHost;
import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.content.Intent;
@@ -120,8 +119,7 @@
e -> e.getValue().getId().equals(shortcutId)).findFirst();
if (!entry.isPresent() || shortcutId == null) {
if (DEBUG) Log.d(TAG, "Matching conversation not found for shortcut ID");
- AppWidgetHost host = new AppWidgetHost(context, 0);
- host.deleteAppWidgetId(appWidgetId);
+ //TODO: Delete app widget id when crash is fixed (b/175486868)
continue;
}
PeopleSpaceTile tile = entry.get().getValue();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index addbd5f..321f732 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -70,6 +70,8 @@
private int mMinRows = 1;
private int mMaxColumns = TileLayout.NO_MAX_COLUMNS;
+ private boolean mShowLabels = true;
+
public PagedTileLayout(Context context, AttributeSet attrs) {
super(context, attrs);
mScroller = new Scroller(context, SCROLL_CUBIC);
@@ -82,6 +84,16 @@
}
private int mLastMaxHeight = -1;
+ @Override
+ public void setShowLabels(boolean show) {
+ mShowLabels = show;
+ for (TilePage p : mPages) {
+ p.setShowLabels(show);
+ }
+ mDistributeTiles = true;
+ requestLayout();
+ }
+
public void saveInstanceState(Bundle outState) {
outState.putInt(CURRENT_PAGE, getCurrentItem());
}
@@ -219,6 +231,7 @@
.inflate(R.layout.qs_paged_page, this, false);
page.setMinRows(mMinRows);
page.setMaxColumns(mMaxColumns);
+ page.setShowLabels(mShowLabels);
return page;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 87a8da0..65f174c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -829,6 +829,8 @@
default void setExpansion(float expansion) {}
int getNumVisibleTiles();
+
+ default void setShowLabels(boolean show) {}
}
interface OnConfigurationChangedListener {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
index 8ee284b..d58895e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
@@ -52,6 +52,8 @@
*/
@QSScope
public class QSPanelController extends QSPanelControllerBase<QSPanel> {
+ public static final String QS_REMOVE_LABELS = "sysui_remove_labels";
+
private final QSSecurityFooter mQsSecurityFooter;
private final TunerService mTunerService;
private final QSCustomizerController mQsCustomizerController;
@@ -120,6 +122,7 @@
updateMediaDisappearParameters();
mTunerService.addTunable(mView, QS_SHOW_BRIGHTNESS);
+ mTunerService.addTunable(mTunable, QS_REMOVE_LABELS);
mView.updateResources();
if (mView.isListening()) {
refreshAllTiles();
@@ -133,6 +136,13 @@
}
@Override
+ boolean switchTileLayout(boolean force) {
+ boolean result = super.switchTileLayout(force);
+ getTileLayout().setShowLabels(mShowLabels);
+ return result;
+ }
+
+ @Override
protected QSTileRevealController createTileRevealController() {
return mQsTileRevealControllerFactory.create(
this, (PagedTileLayout) mView.createRegularTileLayout());
@@ -140,6 +150,7 @@
@Override
protected void onViewDetached() {
+ mTunerService.removeTunable(mTunable);
mTunerService.removeTunable(mView);
mView.removeOnConfigurationChangedListener(mOnConfigurationChangedListener);
if (mBrightnessMirrorController != null) {
@@ -305,5 +316,21 @@
public boolean isExpanded() {
return mView.isExpanded();
}
+
+ private TunerService.Tunable mTunable = new TunerService.Tunable() {
+ @Override
+ public void onTuningChanged(String key, String newValue) {
+ if (QS_REMOVE_LABELS.equals(key)) {
+ boolean newShowLabels = "0".equals(newValue);
+ if (mShowLabels == newShowLabels) return;
+ mShowLabels = newShowLabels;
+ for (TileRecord t : mRecords) {
+ t.tileView.setShowLabels(mShowLabels);
+ }
+ getTileLayout().setShowLabels(mShowLabels);
+ mView.requestLayout();
+ }
+ }
+ };
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
index 4418a74..5282f08 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
@@ -71,6 +71,7 @@
private float mRevealExpansion;
private final QSHost.Callback mQSHostCallback = this::setTiles;
+ protected boolean mShowLabels = true;
private final QSPanel.OnConfigurationChangedListener mOnConfigurationChangedListener =
new QSPanel.OnConfigurationChangedListener() {
@@ -183,6 +184,7 @@
final TileRecord r = new TileRecord();
r.tile = tile;
r.tileView = mHost.createTileView(tile, collapsedView);
+ r.tileView.setShowLabels(mShowLabels);
mView.addTile(r);
mRecords.add(r);
mCachedSpecs = getTilesSpecs();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
index 348dca5..e38c931 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
@@ -26,6 +26,7 @@
protected int mColumns;
protected int mCellWidth;
protected int mCellHeight;
+ protected int mMaxCellHeight;
protected int mCellMarginHorizontal;
protected int mCellMarginVertical;
protected int mSidePadding;
@@ -35,6 +36,7 @@
private int mCellMarginTop;
protected boolean mListening;
protected int mMaxAllowedRows = 3;
+ private boolean mShowLabels;
// Prototyping with less rows
private final boolean mLessRows;
@@ -49,10 +51,17 @@
public TileLayout(Context context, AttributeSet attrs) {
super(context, attrs);
setFocusableInTouchMode(true);
- mLessRows = (Settings.System.getInt(context.getContentResolver(), "qs_less_rows", 0) != 0)
- || useQsMediaPlayer(context);
+ mShowLabels = Settings.Secure.getInt(context.getContentResolver(),
+ QSPanelController.QS_REMOVE_LABELS, 0) == 0;
+ mLessRows = ((Settings.System.getInt(context.getContentResolver(), "qs_less_rows", 0) != 0)
+ || useQsMediaPlayer(context));
updateResources();
+ }
+ @Override
+ public void setShowLabels(boolean show) {
+ mShowLabels = show;
+ updateResources();
}
@Override
@@ -117,12 +126,15 @@
public boolean updateResources() {
final Resources res = mContext.getResources();
mResourceColumns = Math.max(1, res.getInteger(R.integer.quick_settings_num_columns));
- mCellHeight = mContext.getResources().getDimensionPixelSize(R.dimen.qs_tile_height);
+ mMaxCellHeight = mContext.getResources().getDimensionPixelSize(R.dimen.qs_tile_height);
mCellMarginHorizontal = res.getDimensionPixelSize(R.dimen.qs_tile_margin_horizontal);
mCellMarginVertical= res.getDimensionPixelSize(R.dimen.qs_tile_margin_vertical);
+ if (!mShowLabels && mCellMarginVertical == 0) {
+ mCellMarginVertical = mCellMarginHorizontal;
+ }
mCellMarginTop = res.getDimensionPixelSize(R.dimen.qs_tile_margin_top);
mMaxAllowedRows = Math.max(1, getResources().getInteger(R.integer.quick_settings_max_rows));
- if (mLessRows) mMaxAllowedRows = Math.max(mMinRows, mMaxAllowedRows - 1);
+ if (mLessRows && mShowLabels) mMaxAllowedRows = Math.max(mMinRows, mMaxAllowedRows - 1);
if (updateColumns()) {
requestLayout();
return true;
@@ -153,10 +165,12 @@
// Measure each QS tile.
View previousView = this;
+ int verticalMeasure = exactly(getCellHeight());
for (TileRecord record : mRecords) {
if (record.tileView.getVisibility() == GONE) continue;
- record.tileView.measure(exactly(mCellWidth), exactly(mCellHeight));
+ record.tileView.measure(exactly(mCellWidth), verticalMeasure);
previousView = record.tileView.updateAccessibilityOrder(previousView);
+ mCellHeight = record.tileView.getMeasuredHeight();
}
// Only include the top margin in our measurement if we have more than 1 row to show.
@@ -180,9 +194,10 @@
// Add the cell margin in order to divide easily by the height + the margin below
+ mCellMarginVertical;
final int previousRows = mRows;
- mRows = availableHeight / (mCellHeight + mCellMarginVertical);
- if (mRows < mMinRows) {
- mRows = mMinRows;
+ mRows = availableHeight / (getCellHeight() + mCellMarginVertical);
+ final int minRows = mShowLabels ? mMinRows : mMinRows + 1;
+ if (mRows < minRows) {
+ mRows = minRows;
} else if (mRows >= mMaxAllowedRows) {
mRows = mMaxAllowedRows;
}
@@ -201,6 +216,9 @@
return MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
}
+ private int getCellHeight() {
+ return mShowLabels ? mMaxCellHeight : mMaxCellHeight / 2;
+ }
protected void layoutTileRecords(int numRecords) {
final boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java
index ad275f1..39b92dc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java
@@ -116,9 +116,11 @@
return TextUtils.equals(typeContentDescription,
mContext.getString(R.string.data_connection_no_internet))
|| TextUtils.equals(typeContentDescription,
- mContext.getString(R.string.cell_data_off_content_description))
+ mContext.getString(
+ com.android.settingslib.R.string.cell_data_off_content_description))
|| TextUtils.equals(typeContentDescription,
- mContext.getString(R.string.not_default_data_content_description));
+ mContext.getString(
+ com.android.settingslib.R.string.not_default_data_content_description));
}
public void setCarrierText(CharSequence text) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index dce081f..d7933d3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -20,6 +20,7 @@
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.content.res.Configuration;
+import android.os.Build;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.ContextThemeWrapper;
@@ -47,6 +48,7 @@
public class QSCustomizer extends LinearLayout {
static final int MENU_RESET = Menu.FIRST;
+ static final int MENU_REMOVE_LABELS = Menu.FIRST + 1;
static final String EXTRA_QS_CUSTOMIZING = "qs_customizing";
private final QSDetailClipper mClipper;
@@ -75,6 +77,11 @@
toolbar.getMenu().add(Menu.NONE, MENU_RESET, 0,
mContext.getString(com.android.internal.R.string.reset));
+ if (Build.IS_ENG || Build.IS_USERDEBUG) {
+ // Prototype menu item
+ toolbar.getMenu().add(Menu.NONE, MENU_REMOVE_LABELS, Menu.NONE, "Remove labels")
+ .setCheckable(true);
+ }
toolbar.setTitle(R.string.qs_edit);
mRecyclerView = findViewById(android.R.id.list);
mTransparentView = findViewById(R.id.customizer_transparent_view);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
index 7ba51e5..9bf3b8c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
@@ -17,6 +17,7 @@
package com.android.systemui.qs.customize;
import static com.android.systemui.qs.customize.QSCustomizer.EXTRA_QS_CUSTOMIZING;
+import static com.android.systemui.qs.customize.QSCustomizer.MENU_REMOVE_LABELS;
import static com.android.systemui.qs.customize.QSCustomizer.MENU_RESET;
import android.content.res.Configuration;
@@ -36,6 +37,7 @@
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.qs.QSEditEvent;
import com.android.systemui.qs.QSFragment;
+import com.android.systemui.qs.QSPanelController;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.qs.dagger.QSScope;
import com.android.systemui.statusbar.phone.LightBarController;
@@ -43,6 +45,7 @@
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.ViewController;
import java.util.ArrayList;
@@ -62,6 +65,7 @@
private final ConfigurationController mConfigurationController;
private final UiEventLogger mUiEventLogger;
private final Toolbar mToolbar;
+ private final TunerService mTunerService;
private final OnMenuItemClickListener mOnMenuItemClickListener = new OnMenuItemClickListener() {
@Override
@@ -69,6 +73,11 @@
if (item.getItemId() == MENU_RESET) {
mUiEventLogger.log(QSEditEvent.QS_EDIT_RESET);
reset();
+ } else if (item.getItemId() == MENU_REMOVE_LABELS) {
+ item.setChecked(!item.isChecked());
+ mTunerService.setValue(
+ QSPanelController.QS_REMOVE_LABELS, item.isChecked() ? "1" : "0");
+ return false;
}
return false;
}
@@ -93,11 +102,19 @@
}
};
+ private final TunerService.Tunable mTunable = new TunerService.Tunable() {
+ @Override
+ public void onTuningChanged(String key, String newValue) {
+ mToolbar.getMenu().findItem(MENU_REMOVE_LABELS).setChecked(!("0".equals(newValue)));
+ }
+ };
+
@Inject
protected QSCustomizerController(QSCustomizer view, TileQueryHelper tileQueryHelper,
QSTileHost qsTileHost, TileAdapter tileAdapter, ScreenLifecycle screenLifecycle,
KeyguardStateController keyguardStateController, LightBarController lightBarController,
- ConfigurationController configurationController, UiEventLogger uiEventLogger) {
+ ConfigurationController configurationController, UiEventLogger uiEventLogger,
+ TunerService tunerService) {
super(view);
mTileQueryHelper = tileQueryHelper;
mQsTileHost = qsTileHost;
@@ -109,11 +126,14 @@
mUiEventLogger = uiEventLogger;
mToolbar = mView.findViewById(com.android.internal.R.id.action_bar);
+
+ mTunerService = tunerService;
}
@Override
protected void onViewAttached() {
mView.updateNavBackDrop(getResources().getConfiguration(), mLightBarController);
+ mTunerService.addTunable(mTunable, QSPanelController.QS_REMOVE_LABELS);
mConfigurationController.addCallback(mConfigurationListener);
@@ -143,6 +163,7 @@
@Override
protected void onViewDetached() {
+ mTunerService.removeTunable(mTunable);
mTileQueryHelper.setListener(null);
mToolbar.setOnMenuItemClickListener(null);
mConfigurationController.removeCallback(mConfigurationListener);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
index ef501c8..655e4e2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java
@@ -56,7 +56,7 @@
private static final String TAG = "QSTileBaseView";
private static final int ICON_MASK_ID = com.android.internal.R.string.config_icon_mask;
- private final H mHandler = new H();
+ protected final Handler mHandler = new H();
private final int[] mLocInScreen = new int[2];
private final FrameLayout mIconFrame;
protected QSIconView mIcon;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
index 8a360ee..6502066 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileView.java
@@ -43,7 +43,7 @@
protected TextView mSecondLine;
private ImageView mPadLock;
private int mState;
- private ViewGroup mLabelContainer;
+ protected ViewGroup mLabelContainer;
private View mExpandIndicator;
private View mExpandSpace;
private ColorStateList mColorLabelDefault;
@@ -151,4 +151,9 @@
mLabelContainer.setClickable(false);
mLabelContainer.setLongClickable(false);
}
+
+ @Override
+ public void setShowLabels(boolean show) {
+ mHandler.post(() -> mLabelContainer.setVisibility(show ? VISIBLE : GONE));
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index c27b047..6d9d587 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -95,7 +95,7 @@
import com.android.wm.shell.onehanded.OneHandedEvents;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.pip.PipAnimationController;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -130,7 +130,7 @@
private final Context mContext;
private final Optional<Pip> mPipOptional;
private final Optional<Lazy<StatusBar>> mStatusBarOptionalLazy;
- private final Optional<SplitScreen> mSplitScreenOptional;
+ private final Optional<LegacySplitScreen> mSplitScreenOptional;
private SysUiState mSysUiState;
private final Handler mHandler;
private final Lazy<NavigationBarController> mNavBarControllerLazy;
@@ -636,7 +636,7 @@
NavigationModeController navModeController,
NotificationShadeWindowController statusBarWinController, SysUiState sysUiState,
Optional<Pip> pipOptional,
- Optional<SplitScreen> splitScreenOptional,
+ Optional<LegacySplitScreen> splitScreenOptional,
Optional<Lazy<StatusBar>> statusBarOptionalLazy,
Optional<OneHanded> oneHandedOptional,
BroadcastDispatcher broadcastDispatcher) {
diff --git a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
index 6202057..9933438 100644
--- a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
@@ -26,8 +26,8 @@
import com.android.internal.policy.DividerSnapAlgorithm;
import com.android.systemui.SystemUI;
import com.android.systemui.dagger.SysUISingleton;
-import com.android.wm.shell.splitscreen.DividerView;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.DividerView;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import java.util.Optional;
@@ -41,7 +41,7 @@
implements ShortcutKeyServiceProxy.Callbacks {
private static final String TAG = "ShortcutKeyDispatcher";
- private final Optional<SplitScreen> mSplitScreenOptional;
+ private final Optional<LegacySplitScreen> mSplitScreenOptional;
private ShortcutKeyServiceProxy mShortcutKeyServiceProxy = new ShortcutKeyServiceProxy(this);
private IWindowManager mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
@@ -55,7 +55,7 @@
protected final long SC_DOCK_RIGHT = META_MASK | KeyEvent.KEYCODE_RIGHT_BRACKET;
@Inject
- public ShortcutKeyDispatcher(Context context, Optional<SplitScreen> splitScreenOptional) {
+ public ShortcutKeyDispatcher(Context context, Optional<LegacySplitScreen> splitScreenOptional) {
super(context);
mSplitScreenOptional = splitScreenOptional;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index 9bd34ad..4b6d66e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -484,8 +484,8 @@
stack.push(notificationChildren.get(i));
}
}
-
- row.showFeedbackIcon(mAssistantFeedbackController.showFeedbackIndicator(entry));
+ row.showFeedbackIcon(mAssistantFeedbackController.showFeedbackIndicator(entry),
+ mAssistantFeedbackController.getFeedbackImageResource(entry));
row.setLastAudiblyAlertedMs(entry.getLastAudiblyAlertedMs());
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java
index 87a3f07..a350c5d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java
@@ -18,6 +18,7 @@
import static android.service.notification.NotificationListenerService.Ranking;
+import android.app.NotificationManager;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
@@ -29,6 +30,7 @@
import androidx.annotation.Nullable;
+import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -47,6 +49,12 @@
= Settings.Global.getUriFor(Settings.Global.NOTIFICATION_FEEDBACK_ENABLED);
private ContentResolver mResolver;
+ public static final int STATUS_UNCHANGED = 0;
+ public static final int STATUS_ALERTED = 1;
+ public static final int STATUS_SILENCED = 2;
+ public static final int STATUS_PROMOTED = 3;
+ public static final int STATUS_DEMOTED = 4;
+
private boolean mFeedbackEnabled;
/** Injected constructor */
@@ -81,16 +89,88 @@
}
/**
- * Determines whether to show feedback indicator. The feedback indicator will be shown if
- * {@link #isFeedbackEnabled()} is enabled and assistant has changed this notification's rank or
- * importance.
+ * Get the feedback status according to assistant's adjustments
+ *
+ * @param entry Notification Entry to show feedback for
+ */
+ public int getFeedbackStatus(NotificationEntry entry) {
+ if (!isFeedbackEnabled()) {
+ return STATUS_UNCHANGED;
+ }
+ Ranking ranking = entry.getRanking();
+ int oldImportance = ranking.getChannel().getImportance();
+ int newImportance = ranking.getImportance();
+ if (oldImportance < NotificationManager.IMPORTANCE_DEFAULT
+ && newImportance >= NotificationManager.IMPORTANCE_DEFAULT) {
+ return STATUS_ALERTED;
+ } else if (oldImportance >= NotificationManager.IMPORTANCE_DEFAULT
+ && newImportance < NotificationManager.IMPORTANCE_DEFAULT) {
+ return STATUS_SILENCED;
+ } else if (oldImportance < newImportance
+ || ranking.getRankingAdjustment() == ranking.RANKING_PROMOTED) {
+ return STATUS_PROMOTED;
+ } else if (oldImportance > newImportance
+ || ranking.getRankingAdjustment() == ranking.RANKING_DEMOTED) {
+ return STATUS_DEMOTED;
+ } else {
+ return STATUS_UNCHANGED;
+ }
+ }
+
+ /**
+ * Determines whether to show feedback indicator. The feedback indicator will be shown
+ * if {@link #isFeedbackEnabled()} is enabled and assistant has changed this notification's rank
+ * or importance.
*
* @param entry Notification Entry to show feedback for
*/
public boolean showFeedbackIndicator(NotificationEntry entry) {
- Ranking ranking = entry.getRanking();
- return isFeedbackEnabled()
- && (ranking.getImportance() != ranking.getChannel().getImportance()
- || ranking.getRankingAdjustment() != Ranking.RANKING_UNCHANGED);
+ return getFeedbackStatus(entry) != STATUS_UNCHANGED;
+ }
+
+ /**
+ * Get the feedback indicator image resource according to assistant's changes on this
+ * notification's rank or importance.
+ *
+ * @param entry Notification Entry to show feedback for
+ */
+ public int getFeedbackImageResource(NotificationEntry entry) {
+ int feedbackStatus = getFeedbackStatus(entry);
+ switch (feedbackStatus) {
+ case STATUS_ALERTED:
+ return R.drawable.ic_feedback_alerted;
+ case STATUS_SILENCED:
+ return R.drawable.ic_feedback_silenced;
+ case STATUS_PROMOTED:
+ return R.drawable.ic_feedback_uprank;
+ case STATUS_DEMOTED:
+ return R.drawable.ic_feedback_downrank;
+ default:
+ return 0;
+ }
+ }
+
+ /**
+ * Get the inline settings description resource according to assistant's changes on this
+ * notification's rank or importance.
+ *
+ * @param entry Notification Entry to show feedback for
+ */
+ public int getInlineDescriptionResource(NotificationEntry entry) {
+ int feedbackStatus = getFeedbackStatus(entry);
+ switch (feedbackStatus) {
+ case STATUS_ALERTED:
+ return com.android.systemui.R.string.notification_channel_summary_automatic_alerted;
+ case STATUS_SILENCED:
+ return com.android.systemui.R.string
+ .notification_channel_summary_automatic_silenced;
+ case STATUS_PROMOTED:
+ return com.android.systemui.R.string
+ .notification_channel_summary_automatic_promoted;
+ case STATUS_DEMOTED:
+ return com.android.systemui.R.string.notification_channel_summary_automatic_demoted;
+ default:
+ return com.android.systemui.R.string.notification_channel_summary_automatic;
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
index 1f9bc77..e58ea7b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
@@ -59,7 +59,7 @@
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.NotificationChannels;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import java.util.List;
import java.util.Optional;
@@ -82,11 +82,11 @@
private final CommandQueue mCommandQueue;
private boolean mDockedStackExists;
private KeyguardStateController mKeyguardStateController;
- private final Optional<SplitScreen> mSplitScreenOptional;
+ private final Optional<LegacySplitScreen> mSplitScreenOptional;
@Inject
public InstantAppNotifier(Context context, CommandQueue commandQueue,
- @UiBackground Executor uiBgExecutor, Optional<SplitScreen> splitScreenOptional) {
+ @UiBackground Executor uiBgExecutor, Optional<LegacySplitScreen> splitScreenOptional) {
super(context);
mSplitScreenOptional = splitScreenOptional;
mCommandQueue = commandQueue;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java
index c7ac403..998ae9e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java
@@ -30,12 +30,8 @@
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner;
-import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
import com.android.systemui.util.concurrency.DelayableExecutor;
-import java.util.HashMap;
-import java.util.Map;
-
import javax.inject.Inject;
/**
@@ -75,9 +71,6 @@
public void attach(NotifPipeline pipeline) {
mNotifPipeline = pipeline;
- // extend the lifetime of foreground notification services to show for at least 5 seconds
- mNotifPipeline.addNotificationLifetimeExtender(mForegroundLifetimeExtender);
-
// filter out foreground service notifications that aren't necessary anymore
mNotifPipeline.addPreGroupFilter(mNotifFilter);
@@ -119,64 +112,6 @@
};
/**
- * Extends the lifetime of foreground notification services such that they show for at least
- * five seconds
- */
- private final NotifLifetimeExtender mForegroundLifetimeExtender =
- new NotifLifetimeExtender() {
- private static final int MIN_FGS_TIME_MS = 5000;
- private OnEndLifetimeExtensionCallback mEndCallback;
- private Map<NotificationEntry, Runnable> mEndRunnables = new HashMap<>();
-
- @Override
- public String getName() {
- return TAG;
- }
-
- @Override
- public void setCallback(OnEndLifetimeExtensionCallback callback) {
- mEndCallback = callback;
- }
-
- @Override
- public boolean shouldExtendLifetime(NotificationEntry entry, int reason) {
- if ((entry.getSbn().getNotification().flags
- & Notification.FLAG_FOREGROUND_SERVICE) == 0) {
- return false;
- }
-
- final long currTime = System.currentTimeMillis();
- final boolean extendLife = currTime - entry.getSbn().getPostTime() < MIN_FGS_TIME_MS;
-
- if (extendLife) {
- if (!mEndRunnables.containsKey(entry)) {
- final Runnable endExtensionRunnable = () -> {
- mEndRunnables.remove(entry);
- mEndCallback.onEndLifetimeExtension(
- mForegroundLifetimeExtender,
- entry);
- };
-
- final Runnable cancelRunnable = mMainExecutor.executeDelayed(
- endExtensionRunnable,
- MIN_FGS_TIME_MS - (currTime - entry.getSbn().getPostTime()));
- mEndRunnables.put(entry, cancelRunnable);
- }
- }
-
- return extendLife;
- }
-
- @Override
- public void cancelLifetimeExtension(NotificationEntry entry) {
- Runnable cancelRunnable = mEndRunnables.remove(entry);
- if (cancelRunnable != null) {
- cancelRunnable.run();
- }
- }
- };
-
- /**
* Puts foreground service notifications into its own section.
*/
private final NotifSectioner mNotifSectioner = new NotifSectioner("ForegroundService") {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 10118e4..11b829c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -1672,12 +1672,12 @@
requestLayout();
}
- public void showFeedbackIcon(boolean show) {
+ public void showFeedbackIcon(boolean show, int resId) {
if (mIsSummaryWithChildren) {
- mChildrenContainer.showFeedbackIcon(show);
+ mChildrenContainer.showFeedbackIcon(show, resId);
}
- mPrivateLayout.showFeedbackIcon(show);
- mPublicLayout.showFeedbackIcon(show);
+ mPrivateLayout.showFeedbackIcon(show, resId);
+ mPublicLayout.showFeedbackIcon(show, resId);
}
/** Sets the last time the notification being displayed audibly alerted the user. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
index 2ff43d0..85f556f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
@@ -54,7 +54,8 @@
R.id.bottom_roundess_animator_end_tag,
R.id.bottom_roundess_animator_start_tag);
private static final AnimationProperties ROUNDNESS_PROPERTIES =
- new AnimationProperties().setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+ new AnimationProperties().setDuration(
+ StackStateAnimator.ANIMATION_DURATION_CORNER_RADIUS);
private static final Path EMPTY_PATH = new Path();
private final Rect mOutlineRect = new Rect();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
index 73e0804..ba03d01 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
@@ -69,6 +69,7 @@
private float mContentTranslation;
protected boolean mLastInSection;
protected boolean mFirstInSection;
+ boolean mIsBeingSwiped;
public ExpandableView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -173,6 +174,14 @@
return false;
}
+ public void setIsBeingSwiped(boolean swiped) {
+ mIsBeingSwiped = swiped;
+ }
+
+ public boolean isBeingSwiped() {
+ return mIsBeingSwiped;
+ }
+
public boolean isHeadsUpAnimatingAway() {
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FeedbackInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FeedbackInfo.java
index 149ee8c..35f3561 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FeedbackInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FeedbackInfo.java
@@ -16,10 +16,6 @@
package com.android.systemui.statusbar.notification.row;
-import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
-import static android.service.notification.NotificationListenerService.Ranking.RANKING_DEMOTED;
-import static android.service.notification.NotificationListenerService.Ranking.RANKING_PROMOTED;
-
import android.annotation.SuppressLint;
import android.app.Notification;
import android.content.Context;
@@ -30,6 +26,7 @@
import android.os.RemoteException;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
+import android.text.Html;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
@@ -138,30 +135,30 @@
no.setVisibility(View.VISIBLE);
yes.setOnClickListener(this::positiveFeedback);
no.setOnClickListener(this::negativeFeedback);
- prompt.setText(getPrompt());
+ prompt.setText(Html.fromHtml(getPrompt()));
}
@SuppressLint("DefaultLocale")
private String getPrompt() {
StringBuilder sb = new StringBuilder();
- int oldImportance = mRanking.getChannel().getImportance();
- int newImportance = mRanking.getImportance();
- int ranking = mRanking.getRankingAdjustment();
+ int status = mFeedbackController.getFeedbackStatus(mEntry);
if (DEBUG) {
sb.append(String.format(
"[DEBUG]: oldImportance=%d, newImportance=%d, ranking=%d\n\n",
mRanking.getChannel().getImportance(), mRanking.getImportance(),
mRanking.getRankingAdjustment()));
}
- if (oldImportance >= IMPORTANCE_DEFAULT && newImportance < IMPORTANCE_DEFAULT) {
- sb.append(mContext.getString(R.string.feedback_silenced));
- } else if (newImportance > oldImportance || ranking == RANKING_PROMOTED) {
- sb.append(mContext.getString(R.string.feedback_promoted));
- } else if (newImportance < oldImportance || ranking == RANKING_DEMOTED) {
- sb.append(mContext.getString(R.string.feedback_demoted));
+ if (status == mFeedbackController.STATUS_ALERTED) {
+ sb.append(mContext.getText(R.string.feedback_alerted));
+ } else if (status == mFeedbackController.STATUS_SILENCED) {
+ sb.append(mContext.getText(R.string.feedback_silenced));
+ } else if (status == mFeedbackController.STATUS_PROMOTED) {
+ sb.append(mContext.getText(R.string.feedback_promoted));
+ } else if (status == mFeedbackController.STATUS_DEMOTED) {
+ sb.append(mContext.getText(R.string.feedback_demoted));
}
sb.append(" ");
- sb.append(mContext.getString(R.string.feedback_prompt));
+ sb.append(mContext.getText(R.string.feedback_prompt));
return sb.toString();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index 74e6c00..475f627 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -1586,15 +1586,15 @@
return null;
}
- public void showFeedbackIcon(boolean show) {
+ public void showFeedbackIcon(boolean show, int resId) {
if (mContractedChild != null) {
- mContractedWrapper.showFeedbackIcon(show);
+ mContractedWrapper.showFeedbackIcon(show, resId);
}
if (mExpandedChild != null) {
- mExpandedWrapper.showFeedbackIcon(show);
+ mExpandedWrapper.showFeedbackIcon(show, resId);
}
if (mHeadsUpChild != null) {
- mHeadsUpWrapper.showFeedbackIcon(show);
+ mHeadsUpWrapper.showFeedbackIcon(show, resId);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index c4f0098..2fd17a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -378,7 +378,7 @@
mDeviceProvisionedController.isDeviceProvisioned(),
row.getIsNonblockable(),
mHighPriorityProvider.isHighPriority(row.getEntry()),
- mAssistantFeedbackController.isFeedbackEnabled());
+ mAssistantFeedbackController);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
index 6ff5ed1..d12d98e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
@@ -41,6 +41,7 @@
import android.os.Handler;
import android.os.RemoteException;
import android.service.notification.StatusBarNotification;
+import android.text.Html;
import android.text.TextUtils;
import android.transition.ChangeBounds;
import android.transition.Fade;
@@ -60,6 +61,7 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.AssistantFeedbackController;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import java.lang.annotation.Retention;
@@ -96,6 +98,7 @@
private PackageManager mPm;
private MetricsLogger mMetricsLogger;
private ChannelEditorDialogController mChannelEditorDialogController;
+ private AssistantFeedbackController mAssistantFeedbackController;
private String mPackageName;
private String mAppName;
@@ -200,12 +203,13 @@
boolean isDeviceProvisioned,
boolean isNonblockable,
boolean wasShownHighPriority,
- boolean showAutomaticSetting)
+ AssistantFeedbackController assistantFeedbackController)
throws RemoteException {
mINotificationManager = iNotificationManager;
mMetricsLogger = Dependency.get(MetricsLogger.class);
mOnUserInteractionCallback = onUserInteractionCallback;
mChannelEditorDialogController = channelEditorDialogController;
+ mAssistantFeedbackController = assistantFeedbackController;
mPackageName = pkg;
mUniqueChannelsInRow = uniqueChannelsInRow;
mNumUniqueChannelsInRow = uniqueChannelsInRow.size();
@@ -222,7 +226,7 @@
mAppUid = mSbn.getUid();
mDelegatePkg = mSbn.getOpPkg();
mIsDeviceProvisioned = isDeviceProvisioned;
- mShowAutomaticSetting = showAutomaticSetting;
+ mShowAutomaticSetting = mAssistantFeedbackController.isFeedbackEnabled();
mUiEventLogger = uiEventLogger;
int numTotalChannels = mINotificationManager.getNumNotificationChannelsForPackage(
@@ -280,6 +284,8 @@
View automatic = findViewById(R.id.automatic);
if (mShowAutomaticSetting) {
+ mAutomaticDescriptionView.setText(Html.fromHtml(mContext.getText(
+ mAssistantFeedbackController.getInlineDescriptionResource(mEntry)).toString()));
automatic.setVisibility(VISIBLE);
automatic.setOnClickListener(mOnAutomatic);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
index 7c5d4a3..152527f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
@@ -29,6 +29,7 @@
import android.view.ViewGroup.MarginLayoutParams;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
+import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
@@ -131,8 +132,11 @@
/** Shows or hides feedback indicator */
@Override
- public void showFeedbackIcon(boolean show) {
+ public void showFeedbackIcon(boolean show, int resId) {
mFeedbackIcon.setVisibility(show ? View.VISIBLE : View.GONE);
+ if (show && mFeedbackIcon instanceof ImageButton) {
+ ((ImageButton) mFeedbackIcon).setImageResource(resId);
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
index 2d706a4..04cbe87c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
@@ -103,7 +103,7 @@
/**
* Shows or hides feedback icon.
*/
- public void showFeedbackIcon(boolean show) {
+ public void showFeedbackIcon(boolean show, int resId) {
}
public void onReinflated() {
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 885048d..c5dd3c7 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
@@ -42,8 +42,6 @@
private final SectionProvider mSectionProvider;
private int mScrollY;
- private int mAnchorViewIndex;
- private int mAnchorViewY;
private boolean mDimmed;
private ActivatableNotificationView mActivatedChild;
private float mOverScrollTopAmount;
@@ -140,27 +138,6 @@
}
/**
- * Index of the child view whose Y position on screen is returned by {@link #getAnchorViewY()}.
- * Other views are laid out outwards from this view in both directions.
- */
- public int getAnchorViewIndex() {
- return mAnchorViewIndex;
- }
-
- public void setAnchorViewIndex(int anchorViewIndex) {
- mAnchorViewIndex = anchorViewIndex;
- }
-
- /** Current Y position of the view at {@link #getAnchorViewIndex()}. */
- public int getAnchorViewY() {
- return mAnchorViewY;
- }
-
- public void setAnchorViewY(int anchorViewY) {
- mAnchorViewY = anchorViewY;
- }
-
- /**
* @param dimmed Whether we are in a dimmed state (on the lockscreen), where the backgrounds are
* translucent and everything is scaled back a bit.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
index 601fc19..a56ae7d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
@@ -1300,12 +1300,12 @@
/**
* Shows or hides feedback icon.
*/
- public void showFeedbackIcon(boolean show) {
+ public void showFeedbackIcon(boolean show, int resId) {
if (mNotificationHeaderWrapper != null) {
- mNotificationHeaderWrapper.showFeedbackIcon(show);
+ mNotificationHeaderWrapper.showFeedbackIcon(show, resId);
}
if (mNotificationHeaderWrapperLowPriority != null) {
- mNotificationHeaderWrapperLowPriority.showFeedbackIcon(show);
+ mNotificationHeaderWrapperLowPriority.showFeedbackIcon(show, resId);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
index f9d7c1f..3160071 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
@@ -67,7 +67,7 @@
}
}
- private boolean updateViewWithoutCallback(ExpandableView view,
+ boolean updateViewWithoutCallback(ExpandableView view,
boolean animate) {
float topRoundness = getRoundness(view, true /* top */);
float bottomRoundness = getRoundness(view, false /* top */);
@@ -107,7 +107,9 @@
}
private float getRoundness(ExpandableView view, boolean top) {
- if ((view.isPinned() || view.isHeadsUpAnimatingAway()) && !mExpanded) {
+ if ((view.isPinned()
+ || view.isBeingSwiped()
+ || (view.isHeadsUpAnimatingAway()) && !mExpanded)) {
return 1.0f;
}
if (isFirstInSection(view, true /* include first section */) && top) {
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 4f7e14b..6c8cdf6 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
@@ -73,7 +73,6 @@
private lateinit var parent: NotificationStackScrollLayout
private var initialized = false
- private var onClearSilentNotifsClickListener: View.OnClickListener? = null
@VisibleForTesting
val silentHeaderView: SectionHeaderView?
@@ -441,11 +440,6 @@
}
}
- /** Listener for when the "clear all" button is clicked on the gentle notification header. */
- fun setOnClearSilentNotifsClickListener(listener: View.OnClickListener) {
- onClearSilentNotifsClickListener = listener
- }
-
fun setHeaderForegroundColor(@ColorInt color: Int) {
peopleHeaderView?.setForegroundColor(color)
silentHeaderView?.setForegroundColor(color)
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 4487142..0dc824f 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
@@ -19,7 +19,6 @@
import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_SCROLL_FLING;
import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_SILENT;
-import static com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.ANCHOR_SCROLLING;
import static com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_SWIPE;
import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
@@ -164,9 +163,6 @@
private float mExpandedHeight;
private int mOwnScrollY;
-
- private View mScrollAnchorView;
- private int mScrollAnchorViewY;
private int mMaxLayoutHeight;
private VelocityTracker mVelocityTracker;
@@ -387,7 +383,6 @@
}
}
};
- private PorterDuffXfermode mSrcMode = new PorterDuffXfermode(PorterDuff.Mode.SRC);
private boolean mPulsing;
private boolean mScrollable;
private View mForcedScroll;
@@ -423,9 +418,6 @@
private int mCachedBackgroundColor;
private boolean mHeadsUpGoingAwayAnimationsAllowed = true;
private Runnable mReflingAndAnimateScroll = () -> {
- if (ANCHOR_SCROLLING) {
- maybeReflingScroller();
- }
animateScroll();
};
private int mCornerRadius;
@@ -480,23 +472,12 @@
private final ScrollAdapter mScrollAdapter = new ScrollAdapter() {
@Override
public boolean isScrolledToTop() {
- if (ANCHOR_SCROLLING) {
- updateScrollAnchor();
- // TODO: once we're recycling this will need to check the adapter position of the
- // child
- return mScrollAnchorView == getFirstChildNotGone() && mScrollAnchorViewY >= 0;
- } else {
- return mOwnScrollY == 0;
- }
+ return mOwnScrollY == 0;
}
@Override
public boolean isScrolledToBottom() {
- if (ANCHOR_SCROLLING) {
- return getMaxPositiveScrollAmount() <= 0;
- } else {
- return mOwnScrollY >= getScrollRange();
- }
+ return mOwnScrollY >= getScrollRange();
}
@Override
@@ -519,12 +500,6 @@
mSectionsManager = notificationSectionsManager;
mSectionsManager.initialize(this, LayoutInflater.from(context));
- mSectionsManager.setOnClearSilentNotifsClickListener(v -> {
- // Leave the shade open if there will be other notifs left over to clear
- final boolean closeShade =
- !mController.hasActiveClearableNotifications(ROWS_HIGH_PRIORITY);
- clearNotifications(ROWS_GENTLE, closeShade);
- });
mSections = mSectionsManager.createSectionsForBuckets();
mAmbientState = new AmbientState(context, mSectionsManager);
@@ -665,30 +640,6 @@
}
}
- @Override
- public void draw(Canvas canvas) {
- super.draw(canvas);
-
- if (DEBUG && ANCHOR_SCROLLING) {
- if (mScrollAnchorView instanceof ExpandableNotificationRow) {
- canvas.drawRect(0,
- mScrollAnchorView.getTranslationY(),
- getWidth(),
- mScrollAnchorView.getTranslationY()
- + ((ExpandableNotificationRow) mScrollAnchorView).getActualHeight(),
- mDebugPaint);
- canvas.drawText(Integer.toString(mScrollAnchorViewY), getWidth() - 200,
- mScrollAnchorView.getTranslationY() + 30, mDebugPaint);
- int y = (int) mShelf.getTranslationY();
- canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
- }
- canvas.drawText(Integer.toString(getMaxNegativeScrollAmount()), getWidth() - 100,
- getTopPadding() + 30, mDebugPaint);
- canvas.drawText(Integer.toString(getMaxPositiveScrollAmount()), getWidth() - 100,
- getHeight() - 30, mDebugPaint);
- }
- }
-
@ShadeViewRefactor(RefactorComponent.DECORATOR)
private void drawBackground(Canvas canvas) {
int lockScreenLeft = mSidePaddings;
@@ -823,13 +774,6 @@
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 */,
@@ -996,10 +940,6 @@
mListener = listener;
}
- public void setScrollAnchorView(View scrollAnchorView) {
- mScrollAnchorView = scrollAnchorView;
- }
-
@ShadeViewRefactor(RefactorComponent.LAYOUT_ALGORITHM)
private void setMaxLayoutHeight(int maxLayoutHeight) {
mMaxLayoutHeight = maxLayoutHeight;
@@ -1030,12 +970,7 @@
mAmbientState.setCurrentScrollVelocity(mScroller.isFinished()
? 0
: mScroller.getCurrVelocity());
- if (ANCHOR_SCROLLING) {
- mAmbientState.setAnchorViewIndex(indexOfChild(mScrollAnchorView));
- mAmbientState.setAnchorViewY(mScrollAnchorViewY);
- } else {
- mAmbientState.setScrollY(mOwnScrollY);
- }
+ mAmbientState.setScrollY(mOwnScrollY);
mStackScrollAlgorithm.resetViewStates(mAmbientState, getSpeedBumpIndex());
if (!isCurrentlyAnimating() && !mNeedsAnimation) {
applyCurrentState();
@@ -1081,18 +1016,16 @@
if (mChildrenToAddAnimated.isEmpty()) {
return;
}
- if (!ANCHOR_SCROLLING) {
- for (int i = 0; i < getChildCount(); i++) {
- ExpandableView child = (ExpandableView) getChildAt(i);
- if (mChildrenToAddAnimated.contains(child)) {
- final int startingPosition = getPositionInLinearLayout(child);
- final int childHeight = getIntrinsicHeight(child) + mPaddingBetweenElements;
- if (startingPosition < mOwnScrollY) {
- // This child starts off screen, so let's keep it offscreen to keep the
- // others visible
+ for (int i = 0; i < getChildCount(); i++) {
+ ExpandableView child = (ExpandableView) getChildAt(i);
+ if (mChildrenToAddAnimated.contains(child)) {
+ final int startingPosition = getPositionInLinearLayout(child);
+ final int childHeight = getIntrinsicHeight(child) + mPaddingBetweenElements;
+ if (startingPosition < mOwnScrollY) {
+ // This child starts off screen, so let's keep it offscreen to keep the
+ // others visible
- setOwnScrollY(mOwnScrollY + childHeight);
- }
+ setOwnScrollY(mOwnScrollY + childHeight);
}
}
}
@@ -1110,17 +1043,11 @@
int positionInLinearLayout = getPositionInLinearLayout(expandableView);
int targetScroll = targetScrollForView(expandableView, positionInLinearLayout);
int outOfViewScroll = positionInLinearLayout + expandableView.getIntrinsicHeight();
-
- if (ANCHOR_SCROLLING) {
- // TODO
- } else {
- targetScroll = Math.max(0, Math.min(targetScroll, getScrollRange()));
-
- // Only apply the scroll if we're scrolling the view upwards, or the view is so
- // far up that it is not visible anymore.
- if (mOwnScrollY < targetScroll || outOfViewScroll < mOwnScrollY) {
- setOwnScrollY(targetScroll);
- }
+ targetScroll = Math.max(0, Math.min(targetScroll, getScrollRange()));
+ // Only apply the scroll if we're scrolling the view upwards, or the view is so
+ // far up that it is not visible anymore.
+ if (mOwnScrollY < targetScroll || outOfViewScroll < mOwnScrollY) {
+ setOwnScrollY(targetScroll);
}
}
}
@@ -1155,13 +1082,9 @@
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
private void clampScrollPosition() {
- if (ANCHOR_SCROLLING) {
- // TODO
- } else {
- int scrollRange = getScrollRange();
- if (scrollRange < mOwnScrollY) {
- setOwnScrollY(scrollRange);
- }
+ int scrollRange = getScrollRange();
+ if (scrollRange < mOwnScrollY) {
+ setOwnScrollY(scrollRange);
}
}
@@ -1425,12 +1348,6 @@
}
@ShadeViewRefactor(RefactorComponent.ADAPTER)
- public int getFirstItemMinHeight() {
- final ExpandableView firstChild = getFirstChildNotGone();
- return firstChild != null ? firstChild.getMinHeight() : mCollapsedSize;
- }
-
- @ShadeViewRefactor(RefactorComponent.ADAPTER)
public void setQsContainer(ViewGroup qsContainer) {
mQsContainer = qsContainer;
}
@@ -1454,36 +1371,6 @@
}
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
- public ExpandableView getClosestChildAtRawPosition(float touchX, float touchY) {
- getLocationOnScreen(mTempInt2);
- float localTouchY = touchY - mTempInt2[1];
-
- ExpandableView closestChild = null;
- float minDist = Float.MAX_VALUE;
-
- // find the view closest to the location, accounting for GONE views
- final int count = getChildCount();
- for (int childIdx = 0; childIdx < count; childIdx++) {
- ExpandableView slidingChild = (ExpandableView) getChildAt(childIdx);
- if (slidingChild.getVisibility() == GONE
- || slidingChild instanceof StackScrollerDecorView) {
- continue;
- }
- float childTop = slidingChild.getTranslationY();
- float top = childTop + slidingChild.getClipTopAmount();
- float bottom = childTop + slidingChild.getActualHeight()
- - slidingChild.getClipBottomAmount();
-
- float dist = Math.min(Math.abs(top - localTouchY), Math.abs(bottom - localTouchY));
- if (dist < minDist) {
- closestChild = slidingChild;
- minDist = dist;
- }
- }
- return closestChild;
- }
-
- @ShadeViewRefactor(RefactorComponent.COORDINATOR)
private ExpandableView getChildAtPosition(float touchX, float touchY) {
return getChildAtPosition(
touchX, touchY, true /* requireMinHeight */, true /* ignoreDecors */);
@@ -1559,21 +1446,17 @@
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public boolean scrollTo(View v) {
ExpandableView expandableView = (ExpandableView) v;
- if (ANCHOR_SCROLLING) {
- // TODO
- } else {
- int positionInLinearLayout = getPositionInLinearLayout(v);
- int targetScroll = targetScrollForView(expandableView, positionInLinearLayout);
- int outOfViewScroll = positionInLinearLayout + expandableView.getIntrinsicHeight();
+ int positionInLinearLayout = getPositionInLinearLayout(v);
+ int targetScroll = targetScrollForView(expandableView, positionInLinearLayout);
+ int outOfViewScroll = positionInLinearLayout + expandableView.getIntrinsicHeight();
- // Only apply the scroll if we're scrolling the view upwards, or the view is so far up
- // that it is not visible anymore.
- if (mOwnScrollY < targetScroll || outOfViewScroll < mOwnScrollY) {
- mScroller.startScroll(mScrollX, mOwnScrollY, 0, targetScroll - mOwnScrollY);
- mDontReportNextOverScroll = true;
- animateScroll();
- return true;
- }
+ // Only apply the scroll if we're scrolling the view upwards, or the view is so far up
+ // that it is not visible anymore.
+ if (mOwnScrollY < targetScroll || outOfViewScroll < mOwnScrollY) {
+ mScroller.startScroll(mScrollX, mOwnScrollY, 0, targetScroll - mOwnScrollY);
+ mDontReportNextOverScroll = true;
+ animateScroll();
+ return true;
}
return false;
}
@@ -1600,20 +1483,16 @@
mWaterfallTopInset = cutout.getWaterfallInsets().top;
}
- if (ANCHOR_SCROLLING) {
- // TODO
- } else {
- int range = getScrollRange();
- if (mOwnScrollY > range) {
- // HACK: We're repeatedly getting staggered insets here while the IME is
- // animating away. To work around that we'll wait until things have settled.
- removeCallbacks(mReclamp);
- postDelayed(mReclamp, 50);
- } else if (mForcedScroll != null) {
- // The scroll was requested before we got the actual inset - in case we need
- // to scroll up some more do so now.
- scrollTo(mForcedScroll);
- }
+ int range = getScrollRange();
+ if (mOwnScrollY > range) {
+ // HACK: We're repeatedly getting staggered insets here while the IME is
+ // animating away. To work around that we'll wait until things have settled.
+ removeCallbacks(mReclamp);
+ postDelayed(mReclamp, 50);
+ } else if (mForcedScroll != null) {
+ // The scroll was requested before we got the actual inset - in case we need
+ // to scroll up some more do so now.
+ scrollTo(mForcedScroll);
}
return insets;
}
@@ -1622,12 +1501,8 @@
private Runnable mReclamp = new Runnable() {
@Override
public void run() {
- if (ANCHOR_SCROLLING) {
- // TODO
- } else {
- int range = getScrollRange();
- mScroller.startScroll(mScrollX, mOwnScrollY, 0, range - mOwnScrollY);
- }
+ int range = getScrollRange();
+ mScroller.startScroll(mScrollX, mOwnScrollY, 0, range - mOwnScrollY);
mDontReportNextOverScroll = true;
mDontClampNextScroll = true;
animateScroll();
@@ -1701,39 +1576,20 @@
}
// Top overScroll might not grab all scrolling motion,
// we have to scroll as well.
- if (ANCHOR_SCROLLING) {
- float scrollAmount = newTopAmount < 0 ? -newTopAmount : 0.0f;
- // TODO: once we're recycling this will need to check the adapter position of the child
- ExpandableView lastRow = getLastRowNotGone();
- if (lastRow != null && !lastRow.isInShelf()) {
- float distanceToMax = Math.max(0, getMaxPositiveScrollAmount());
- if (scrollAmount > distanceToMax) {
- float currentBottomPixels = getCurrentOverScrolledPixels(false);
- // We overScroll on the bottom
- setOverScrolledPixels(currentBottomPixels + (scrollAmount - distanceToMax),
- false /* onTop */,
- false /* animate */);
- mScrollAnchorViewY -= distanceToMax;
- scrollAmount = 0f;
- }
+ float scrollAmount = newTopAmount < 0 ? -newTopAmount : 0.0f;
+ float newScrollY = mOwnScrollY + scrollAmount;
+ if (newScrollY > range) {
+ if (!mExpandedInThisMotion) {
+ float currentBottomPixels = getCurrentOverScrolledPixels(false);
+ // We overScroll on the bottom
+ setOverScrolledPixels(currentBottomPixels + newScrollY - range,
+ false /* onTop */,
+ false /* animate */);
}
- return scrollAmount;
- } else {
- float scrollAmount = newTopAmount < 0 ? -newTopAmount : 0.0f;
- float newScrollY = mOwnScrollY + scrollAmount;
- if (newScrollY > range) {
- if (!mExpandedInThisMotion) {
- float currentBottomPixels = getCurrentOverScrolledPixels(false);
- // We overScroll on the bottom
- setOverScrolledPixels(currentBottomPixels + newScrollY - range,
- false /* onTop */,
- false /* animate */);
- }
- setOwnScrollY(range);
- scrollAmount = 0.0f;
- }
- return scrollAmount;
+ setOwnScrollY(range);
+ scrollAmount = 0.0f;
}
+ return scrollAmount;
}
/**
@@ -1754,37 +1610,18 @@
}
// Bottom overScroll might not grab all scrolling motion,
// we have to scroll as well.
- if (ANCHOR_SCROLLING) {
- float scrollAmount = newBottomAmount < 0 ? newBottomAmount : 0.0f;
- // TODO: once we're recycling this will need to check the adapter position of the child
- ExpandableView firstChild = getFirstChildNotGone();
- float top = firstChild.getTranslationY();
- float distanceToTop = mScrollAnchorView.getTranslationY() - top - mScrollAnchorViewY;
- if (distanceToTop < -scrollAmount) {
- float currentTopPixels = getCurrentOverScrolledPixels(true);
- // We overScroll on the top
- setOverScrolledPixels(currentTopPixels + (-scrollAmount - distanceToTop),
- true /* onTop */,
- false /* animate */);
- mScrollAnchorView = firstChild;
- mScrollAnchorViewY = 0;
- scrollAmount = 0f;
- }
- return scrollAmount;
- } else {
- float scrollAmount = newBottomAmount < 0 ? newBottomAmount : 0.0f;
- float newScrollY = mOwnScrollY + scrollAmount;
- if (newScrollY < 0) {
- float currentTopPixels = getCurrentOverScrolledPixels(true);
- // We overScroll on the top
- setOverScrolledPixels(currentTopPixels - newScrollY,
- true /* onTop */,
- false /* animate */);
- setOwnScrollY(0);
- scrollAmount = 0.0f;
- }
- return scrollAmount;
+ float scrollAmount = newBottomAmount < 0 ? newBottomAmount : 0.0f;
+ float newScrollY = mOwnScrollY + scrollAmount;
+ if (newScrollY < 0) {
+ float currentTopPixels = getCurrentOverScrolledPixels(true);
+ // We overScroll on the top
+ setOverScrolledPixels(currentTopPixels - newScrollY,
+ true /* onTop */,
+ false /* animate */);
+ setOwnScrollY(0);
+ scrollAmount = 0.0f;
}
+ return scrollAmount;
}
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
@@ -1819,42 +1656,23 @@
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
private void animateScroll() {
if (mScroller.computeScrollOffset()) {
- if (ANCHOR_SCROLLING) {
- int oldY = mLastScrollerY;
- int y = mScroller.getCurrY();
- int deltaY = y - oldY;
- if (deltaY != 0) {
- int maxNegativeScrollAmount = getMaxNegativeScrollAmount();
- int maxPositiveScrollAmount = getMaxPositiveScrollAmount();
- if ((maxNegativeScrollAmount < 0 && deltaY < maxNegativeScrollAmount)
- || (maxPositiveScrollAmount > 0 && deltaY > maxPositiveScrollAmount)) {
- // This frame takes us into overscroll, so set the max overscroll based on
- // the current velocity
- setMaxOverScrollFromCurrentVelocity();
- }
- customOverScrollBy(deltaY, oldY, 0, (int) mMaxOverScroll);
- mLastScrollerY = y;
- }
- } else {
- int oldY = mOwnScrollY;
- int y = mScroller.getCurrY();
+ int oldY = mOwnScrollY;
+ int y = mScroller.getCurrY();
- if (oldY != y) {
- int range = getScrollRange();
- if (y < 0 && oldY >= 0 || y > range && oldY <= range) {
- // This frame takes us into overscroll, so set the max overscroll based on
- // the current velocity
- setMaxOverScrollFromCurrentVelocity();
- }
-
- if (mDontClampNextScroll) {
- range = Math.max(range, oldY);
- }
- customOverScrollBy(y - oldY, oldY, range,
- (int) (mMaxOverScroll));
+ if (oldY != y) {
+ int range = getScrollRange();
+ if (y < 0 && oldY >= 0 || y > range && oldY <= range) {
+ // This frame takes us into overscroll, so set the max overscroll based on
+ // the current velocity
+ setMaxOverScrollFromCurrentVelocity();
}
+
+ if (mDontClampNextScroll) {
+ range = Math.max(range, oldY);
+ }
+ customOverScrollBy(y - oldY, oldY, range,
+ (int) (mMaxOverScroll));
}
-
postOnAnimation(mReflingAndAnimateScroll);
} else {
mDontClampNextScroll = false;
@@ -1877,9 +1695,7 @@
*
* This method performs the determination of whether we're exceeding the overscroll and clamps
* the scroll amount if so. The actual scrolling/overscrolling happens in
- * {@link #onCustomOverScrolled(int, boolean)} (absolute scrolling) or
- * {@link #onCustomOverScrolledBy(int, boolean)} (anchor scrolling).
- *
+ * {@link #onCustomOverScrolled(int, boolean)}
* @param deltaY The (signed) number of pixels to scroll.
* @param scrollY The current scroll position (absolute scrolling only).
* @param scrollRangeY The maximum allowable scroll position (absolute scrolling only).
@@ -1887,44 +1703,20 @@
*/
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
private void customOverScrollBy(int deltaY, int scrollY, int scrollRangeY, int maxOverScrollY) {
- if (ANCHOR_SCROLLING) {
- boolean clampedY = false;
- if (deltaY < 0) {
- int maxScrollAmount = getMaxNegativeScrollAmount();
- if (maxScrollAmount > Integer.MIN_VALUE) {
- maxScrollAmount -= maxOverScrollY;
- if (deltaY < maxScrollAmount) {
- deltaY = maxScrollAmount;
- clampedY = true;
- }
- }
- } else {
- int maxScrollAmount = getMaxPositiveScrollAmount();
- if (maxScrollAmount < Integer.MAX_VALUE) {
- maxScrollAmount += maxOverScrollY;
- if (deltaY > maxScrollAmount) {
- deltaY = maxScrollAmount;
- clampedY = true;
- }
- }
- }
- onCustomOverScrolledBy(deltaY, clampedY);
- } else {
- int newScrollY = scrollY + deltaY;
- final int top = -maxOverScrollY;
- final int bottom = maxOverScrollY + scrollRangeY;
+ int newScrollY = scrollY + deltaY;
+ final int top = -maxOverScrollY;
+ final int bottom = maxOverScrollY + scrollRangeY;
- boolean clampedY = false;
- if (newScrollY > bottom) {
- newScrollY = bottom;
- clampedY = true;
- } else if (newScrollY < top) {
- newScrollY = top;
- clampedY = true;
- }
-
- onCustomOverScrolled(newScrollY, clampedY);
+ boolean clampedY = false;
+ if (newScrollY > bottom) {
+ newScrollY = bottom;
+ clampedY = true;
+ } else if (newScrollY < top) {
+ newScrollY = top;
+ clampedY = true;
}
+
+ onCustomOverScrolled(newScrollY, clampedY);
}
/**
@@ -2043,35 +1835,6 @@
}
/**
- * Scrolls by the given delta, overscrolling if needed. If called during a fling and the delta
- * would cause us to exceed the provided maximum overscroll, springs back instead.
- *
- * @param deltaY The (signed) number of pixels to scroll.
- * @param clampedY Whether this value was clamped by the calling method, meaning we've reached
- * the overscroll limit.
- */
- private void onCustomOverScrolledBy(int deltaY, boolean clampedY) {
- assert ANCHOR_SCROLLING;
- mScrollAnchorViewY -= deltaY;
- // Treat animating scrolls differently; see #computeScroll() for why.
- if (!mScroller.isFinished()) {
- if (clampedY) {
- springBack();
- } else {
- float overScrollTop = getCurrentOverScrollAmount(true /* top */);
- if (mScrollAdapter.isScrolledToTop() && mScrollAnchorViewY > 0) {
- notifyOverscrollTopListener(mScrollAnchorViewY,
- isRubberbanded(true /* onTop */));
- } else {
- notifyOverscrollTopListener(overScrollTop, isRubberbanded(true /* onTop */));
- }
- }
- }
- updateScrollAnchor();
- updateOnScrollChange();
- }
-
- /**
* Scrolls to the given position, overscrolling if needed. If called during a fling and the
* position exceeds the provided maximum overscroll, springs back instead.
*
@@ -2081,7 +1844,6 @@
*/
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
private void onCustomOverScrolled(int scrollY, boolean clampedY) {
- assert !ANCHOR_SCROLLING;
// Treat animating scrolls differently; see #computeScroll() for why.
if (!mScroller.isFinished()) {
setOwnScrollY(scrollY);
@@ -2106,45 +1868,25 @@
*/
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
private void springBack() {
- if (ANCHOR_SCROLLING) {
- boolean overScrolledTop = mScrollAdapter.isScrolledToTop() && mScrollAnchorViewY > 0;
- int maxPositiveScrollAmount = getMaxPositiveScrollAmount();
- boolean overscrolledBottom = maxPositiveScrollAmount < 0;
- if (overScrolledTop || overscrolledBottom) {
- float newAmount;
- if (overScrolledTop) {
- newAmount = mScrollAnchorViewY;
- mScrollAnchorViewY = 0;
- mDontReportNextOverScroll = true;
- } else {
- newAmount = -maxPositiveScrollAmount;
- mScrollAnchorViewY -= maxPositiveScrollAmount;
- }
- setOverScrollAmount(newAmount, overScrolledTop, false);
- setOverScrollAmount(0.0f, overScrolledTop, true);
- mScroller.forceFinished(true);
+ int scrollRange = getScrollRange();
+ boolean overScrolledTop = mOwnScrollY <= 0;
+ boolean overScrolledBottom = mOwnScrollY >= scrollRange;
+ if (overScrolledTop || overScrolledBottom) {
+ boolean onTop;
+ float newAmount;
+ if (overScrolledTop) {
+ onTop = true;
+ newAmount = -mOwnScrollY;
+ setOwnScrollY(0);
+ mDontReportNextOverScroll = true;
+ } else {
+ onTop = false;
+ newAmount = mOwnScrollY - scrollRange;
+ setOwnScrollY(scrollRange);
}
- } else {
- int scrollRange = getScrollRange();
- boolean overScrolledTop = mOwnScrollY <= 0;
- boolean overScrolledBottom = mOwnScrollY >= scrollRange;
- if (overScrolledTop || overScrolledBottom) {
- boolean onTop;
- float newAmount;
- if (overScrolledTop) {
- onTop = true;
- newAmount = -mOwnScrollY;
- setOwnScrollY(0);
- mDontReportNextOverScroll = true;
- } else {
- onTop = false;
- newAmount = mOwnScrollY - scrollRange;
- setOwnScrollY(scrollRange);
- }
- setOverScrollAmount(newAmount, onTop, false);
- setOverScrollAmount(0.0f, onTop, true);
- mScroller.forceFinished(true);
- }
+ setOverScrollAmount(newAmount, onTop, false);
+ setOverScrollAmount(0.0f, onTop, true);
+ mScroller.forceFinished(true);
}
}
@@ -2183,25 +1925,6 @@
}
/**
- * @return the child before the given view which has visibility unequal to GONE
- */
- @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- public ExpandableView getViewBeforeView(ExpandableView view) {
- ExpandableView previousView = null;
- int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- View child = getChildAt(i);
- if (child == view) {
- return previousView;
- }
- if (child.getVisibility() != View.GONE) {
- previousView = (ExpandableView) child;
- }
- }
- return null;
- }
-
- /**
* @return The first child which has visibility unequal to GONE which is currently below the
* given translationY or equal to it.
*/
@@ -2334,8 +2057,7 @@
ExpandableView current,
int visibleIndex
) {
- return mStackScrollAlgorithm.getGapHeightForChild(mSectionsManager,
- mAmbientState.getAnchorViewIndex(), visibleIndex, current,
+ return mStackScrollAlgorithm.getGapHeightForChild(mSectionsManager, visibleIndex, current,
previous);
}
@@ -2566,21 +2288,13 @@
float topAmount = getCurrentOverScrollAmount(true);
float bottomAmount = getCurrentOverScrollAmount(false);
if (velocityY < 0 && topAmount > 0) {
- if (ANCHOR_SCROLLING) {
- mScrollAnchorViewY += topAmount;
- } else {
- setOwnScrollY(mOwnScrollY - (int) topAmount);
- }
+ setOwnScrollY(mOwnScrollY - (int) topAmount);
mDontReportNextOverScroll = true;
setOverScrollAmount(0, true, false);
mMaxOverScroll = Math.abs(velocityY) / 1000f * getRubberBandFactor(true /* onTop */)
* mOverflingDistance + topAmount;
} else if (velocityY > 0 && bottomAmount > 0) {
- if (ANCHOR_SCROLLING) {
- mScrollAnchorViewY -= bottomAmount;
- } else {
- setOwnScrollY((int) (mOwnScrollY + bottomAmount));
- }
+ setOwnScrollY((int) (mOwnScrollY + bottomAmount));
setOverScrollAmount(0, false, false);
mMaxOverScroll = Math.abs(velocityY) / 1000f
* getRubberBandFactor(false /* onTop */) * mOverflingDistance
@@ -2589,139 +2303,19 @@
// it will be set once we reach the boundary
mMaxOverScroll = 0.0f;
}
- if (ANCHOR_SCROLLING) {
- flingScroller(velocityY);
- } else {
- int scrollRange = getScrollRange();
- int minScrollY = Math.max(0, scrollRange);
- if (mExpandedInThisMotion) {
- minScrollY = Math.min(minScrollY, mMaxScrollAfterExpand);
- }
- mScroller.fling(mScrollX, mOwnScrollY, 1, velocityY, 0, 0, 0, minScrollY, 0,
- mExpandedInThisMotion && mOwnScrollY >= 0 ? 0 : Integer.MAX_VALUE / 2);
+ int scrollRange = getScrollRange();
+ int minScrollY = Math.max(0, scrollRange);
+ if (mExpandedInThisMotion) {
+ minScrollY = Math.min(minScrollY, mMaxScrollAfterExpand);
}
+ mScroller.fling(mScrollX, mOwnScrollY, 1, velocityY, 0, 0, 0, minScrollY, 0,
+ mExpandedInThisMotion && mOwnScrollY >= 0 ? 0 : Integer.MAX_VALUE / 2);
animateScroll();
}
}
/**
- * Flings the overscroller with the given velocity (anchor-based scrolling).
- *
- * Because anchor-based scrolling can't track the current scroll position, the overscroller is
- * always started at startY = 0, and we interpret the positions it computes as relative to the
- * start of the scroll.
- */
- private void flingScroller(int velocityY) {
- assert ANCHOR_SCROLLING;
- mIsScrollerBoundSet = false;
- maybeFlingScroller(velocityY, true /* always fling */);
- }
-
- private void maybeFlingScroller(int velocityY, boolean alwaysFling) {
- assert ANCHOR_SCROLLING;
- // Attempt to determine the maximum amount to scroll before we reach the end.
- // If the first view is not materialized (for an upwards scroll) or the last view is either
- // not materialized or is pinned to the shade (for a downwards scroll), we don't know this
- // amount, so we do an unbounded fling and rely on {@link #maybeReflingScroller()} to update
- // the scroller once we approach the start/end of the list.
- int minY = Integer.MIN_VALUE;
- int maxY = Integer.MAX_VALUE;
- if (velocityY < 0) {
- minY = getMaxNegativeScrollAmount();
- if (minY > Integer.MIN_VALUE) {
- mIsScrollerBoundSet = true;
- }
- } else {
- maxY = getMaxPositiveScrollAmount();
- if (maxY < Integer.MAX_VALUE) {
- mIsScrollerBoundSet = true;
- }
- }
- if (mIsScrollerBoundSet || alwaysFling) {
- mLastScrollerY = 0;
- // x velocity is set to 1 to avoid overscroller bug
- mScroller.fling(0, 0, 1, velocityY, 0, 0, minY, maxY, 0,
- mExpandedInThisMotion
- && !mScrollAdapter.isScrolledToTop() ? 0 : Integer.MAX_VALUE / 2);
- }
- }
-
- /**
- * Returns the maximum number of pixels we can scroll in the positive direction (downwards)
- * before reaching the bottom of the list (discounting overscroll).
- *
- * If the return value is negative then we have overscrolled; this is a transient state which
- * should immediately be handled by adjusting the anchor position and adding the extra space to
- * the bottom overscroll amount.
- *
- * If we don't know how many pixels we have left to scroll (because the last row has not been
- * materialized, or it's in the shelf so it doesn't have its "natural" position), we return
- * {@link Integer#MAX_VALUE}.
- */
- private int getMaxPositiveScrollAmount() {
- assert ANCHOR_SCROLLING;
- // TODO: once we're recycling we need to check the adapter position of the last child.
- ExpandableNotificationRow lastRow = getLastRowNotGone();
- if (mScrollAnchorView != null && lastRow != null && !lastRow.isInShelf()) {
- // distance from bottom of last child to bottom of notifications area is:
- // distance from bottom of last child
- return (int) (lastRow.getTranslationY() + lastRow.getActualHeight()
- // to top of anchor view
- - mScrollAnchorView.getTranslationY()
- // plus distance from anchor view to top of notifications area
- + mScrollAnchorViewY
- // minus height of notifications area.
- - (mMaxLayoutHeight - getIntrinsicPadding() - mFooterView.getActualHeight()));
- } else {
- return Integer.MAX_VALUE;
- }
- }
-
- /**
- * Returns the maximum number of pixels (as a negative number) we can scroll in the negative
- * direction (upwards) before reaching the top of the list (discounting overscroll).
- *
- * If the return value is positive then we have overscrolled; this is a transient state which
- * should immediately be handled by adjusting the anchor position and adding the extra space to
- * the top overscroll amount.
- *
- * If we don't know how many pixels we have left to scroll (because the first row has not been
- * materialized), we return {@link Integer#MIN_VALUE}.
- */
- private int getMaxNegativeScrollAmount() {
- assert ANCHOR_SCROLLING;
- // TODO: once we're recycling we need to check the adapter position of the first child.
- ExpandableView firstChild = getFirstChildNotGone();
- if (mScrollAnchorView != null && firstChild != null) {
- // distance from top of first child to top of notifications area is:
- // distance from top of anchor view
- return (int) -(mScrollAnchorView.getTranslationY()
- // to top of first child
- - firstChild.getTranslationY()
- // minus distance from top of anchor view to top of notifications area.
- - mScrollAnchorViewY);
- } else {
- return Integer.MIN_VALUE;
- }
- }
-
- /**
- * During a fling, if we were unable to set the bounds of the fling due to the top/bottom view
- * not being materialized or being pinned to the shelf, we need to check on every frame if we're
- * able to set the bounds. If we are, we fling the scroller again with the newly computed
- * bounds.
- */
- private void maybeReflingScroller() {
- if (!mIsScrollerBoundSet) {
- // Because mScroller is a flywheel scroller, we fling with the minimum possible
- // velocity to establish direction, so as not to perceptibly affect the velocity.
- maybeFlingScroller((int) Math.signum(mScroller.getCurrVelocity()),
- false /* alwaysFling */);
- }
- }
-
- /**
* @return Whether a fling performed on the top overscroll edge lead to the expanded
* overScroll view (i.e QS).
*/
@@ -2990,38 +2584,17 @@
*/
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
private void updateScrollStateForRemovedChild(ExpandableView removedChild) {
- if (ANCHOR_SCROLLING) {
- if (removedChild == mScrollAnchorView) {
- ExpandableView firstChild = getFirstChildNotGone();
- if (firstChild != null) {
- mScrollAnchorView = firstChild;
- } else {
- mScrollAnchorView = mShelf;
- }
- // Adjust anchor view Y by the distance between the old and new anchors
- // so that there's no visible change.
- mScrollAnchorViewY +=
- mScrollAnchorView.getTranslationY() - removedChild.getTranslationY();
- }
- updateScrollAnchor();
- // TODO: once we're recycling this will need to check the adapter position of the child
- if (mScrollAnchorView == getFirstChildNotGone() && mScrollAnchorViewY > 0) {
- mScrollAnchorViewY = 0;
- }
- updateOnScrollChange();
- } else {
- final int startingPosition = getPositionInLinearLayout(removedChild);
- final int childHeight = getIntrinsicHeight(removedChild) + mPaddingBetweenElements;
- final int endPosition = startingPosition + childHeight;
- if (endPosition <= mOwnScrollY) {
- // This child is fully scrolled of the top, so we have to deduct its height from the
- // scrollPosition
- setOwnScrollY(mOwnScrollY - childHeight);
- } else if (startingPosition < mOwnScrollY) {
- // This child is currently being scrolled into, set the scroll position to the
- // start of this child
- setOwnScrollY(startingPosition);
- }
+ final int startingPosition = getPositionInLinearLayout(removedChild);
+ final int childHeight = getIntrinsicHeight(removedChild) + mPaddingBetweenElements;
+ final int endPosition = startingPosition + childHeight;
+ if (endPosition <= mOwnScrollY) {
+ // This child is fully scrolled of the top, so we have to deduct its height from the
+ // scrollPosition
+ setOwnScrollY(mOwnScrollY - childHeight);
+ } else if (startingPosition < mOwnScrollY) {
+ // This child is currently being scrolled into, set the scroll position to the
+ // start of this child
+ setOwnScrollY(startingPosition);
}
}
@@ -3115,15 +2688,6 @@
if (child instanceof ExpandableNotificationRow) {
((ExpandableNotificationRow) child).setDismissRtl(mDismissRtl);
}
- if (ANCHOR_SCROLLING) {
- // TODO: once we're recycling this will need to check the adapter position of the child
- if (child == getFirstChildNotGone()
- && (mScrollAdapter.isScrolledToTop() || !mIsExpanded)) {
- // New child was added at the top while we're scrolled to the top;
- // make it the new anchor view so that we stay at the top.
- mScrollAnchorView = child;
- }
- }
}
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
@@ -3581,24 +3145,17 @@
final float vscroll = event.getAxisValue(MotionEvent.AXIS_VSCROLL);
if (vscroll != 0) {
final int delta = (int) (vscroll * getVerticalScrollFactor());
- if (ANCHOR_SCROLLING) {
- mScrollAnchorViewY -= delta;
- updateScrollAnchor();
- clampScrollPosition();
- updateOnScrollChange();
- } else {
- final int range = getScrollRange();
- int oldScrollY = mOwnScrollY;
- int newScrollY = oldScrollY - delta;
- if (newScrollY < 0) {
- newScrollY = 0;
- } else if (newScrollY > range) {
- newScrollY = range;
- }
- if (newScrollY != oldScrollY) {
- setOwnScrollY(newScrollY);
- return true;
- }
+ final int range = getScrollRange();
+ int oldScrollY = mOwnScrollY;
+ int newScrollY = oldScrollY - delta;
+ if (newScrollY < 0) {
+ newScrollY = 0;
+ } else if (newScrollY > range) {
+ newScrollY = range;
+ }
+ if (newScrollY != oldScrollY) {
+ setOwnScrollY(newScrollY);
+ return true;
}
}
}
@@ -3676,13 +3233,9 @@
mLastMotionY = y;
float scrollAmount;
int range;
- if (ANCHOR_SCROLLING) {
- range = 0; // unused in the methods it's being passed to
- } else {
- range = getScrollRange();
- if (mExpandedInThisMotion) {
- range = Math.min(range, mMaxScrollAfterExpand);
- }
+ range = getScrollRange();
+ if (mExpandedInThisMotion) {
+ range = Math.min(range, mMaxScrollAfterExpand);
}
if (deltaY < 0) {
scrollAmount = overScrollDown(deltaY);
@@ -3727,13 +3280,9 @@
onOverScrollFling(false, initialVelocity);
}
} else {
- if (ANCHOR_SCROLLING) {
- // TODO
- } else {
- if (mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0,
- getScrollRange())) {
- animateScroll();
- }
+ if (mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0,
+ getScrollRange())) {
+ animateScroll();
}
}
}
@@ -3745,13 +3294,9 @@
break;
case MotionEvent.ACTION_CANCEL:
if (mIsBeingDragged && getChildCount() > 0) {
- if (ANCHOR_SCROLLING) {
- // TODO
- } else {
- if (mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0,
- getScrollRange())) {
- animateScroll();
- }
+ if (mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0,
+ getScrollRange())) {
+ animateScroll();
}
mActivePointerId = INVALID_POINTER;
endDrag();
@@ -3970,12 +3515,8 @@
setIsBeingDragged(false);
mActivePointerId = INVALID_POINTER;
recycleVelocityTracker();
- if (ANCHOR_SCROLLING) {
- // TODO
- } else {
- if (mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0, getScrollRange())) {
- animateScroll();
- }
+ if (mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0, getScrollRange())) {
+ animateScroll();
}
break;
case MotionEvent.ACTION_POINTER_UP:
@@ -4050,20 +3591,16 @@
case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD:
// fall through
case android.R.id.accessibilityActionScrollUp:
- if (ANCHOR_SCROLLING) {
- // TODO
- } else {
- final int viewportHeight =
- getHeight() - mPaddingBottom - mTopPadding - mPaddingTop
- - mShelf.getIntrinsicHeight();
- final int targetScrollY = Math.max(0,
- Math.min(mOwnScrollY + direction * viewportHeight, getScrollRange()));
- if (targetScrollY != mOwnScrollY) {
- mScroller.startScroll(mScrollX, mOwnScrollY, 0,
- targetScrollY - mOwnScrollY);
- animateScroll();
- return true;
- }
+ final int viewportHeight =
+ getHeight() - mPaddingBottom - mTopPadding - mPaddingTop
+ - mShelf.getIntrinsicHeight();
+ final int targetScrollY = Math.max(0,
+ Math.min(mOwnScrollY + direction * viewportHeight, getScrollRange()));
+ if (targetScrollY != mOwnScrollY) {
+ mScroller.startScroll(mScrollX, mOwnScrollY, 0,
+ targetScrollY - mOwnScrollY);
+ animateScroll();
+ return true;
}
break;
}
@@ -4166,14 +3703,7 @@
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
void resetScrollPosition() {
mScroller.abortAnimation();
- if (ANCHOR_SCROLLING) {
- // TODO: once we're recycling this will need to modify the adapter position instead
- mScrollAnchorView = getFirstChildNotGone();
- mScrollAnchorViewY = 0;
- updateOnScrollChange();
- } else {
- setOwnScrollY(0);
- }
+ setOwnScrollY(0);
}
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
@@ -4262,13 +3792,7 @@
layoutEnd -= mShelf.getIntrinsicHeight() + mPaddingBetweenElements;
}
if (endPosition > layoutEnd) {
- if (ANCHOR_SCROLLING) {
- mScrollAnchorViewY -= (endPosition - layoutEnd);
- updateScrollAnchor();
- updateOnScrollChange();
- } else {
- setOwnScrollY((int) (mOwnScrollY + endPosition - layoutEnd));
- }
+ setOwnScrollY((int) (mOwnScrollY + endPosition - layoutEnd));
mDisallowScrollingInThisMotion = true;
}
}
@@ -4765,12 +4289,8 @@
super.onInitializeAccessibilityEventInternal(event);
event.setScrollable(mScrollable);
event.setMaxScrollX(mScrollX);
- if (ANCHOR_SCROLLING) {
- // TODO
- } else {
- event.setScrollY(mOwnScrollY);
- event.setMaxScrollY(getScrollRange());
- }
+ event.setScrollY(mOwnScrollY);
+ event.setMaxScrollY(getScrollRange());
}
@Override
@@ -4955,7 +4475,6 @@
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
private void setOwnScrollY(int ownScrollY) {
- assert !ANCHOR_SCROLLING;
if (ownScrollY != mOwnScrollY) {
// We still want to call the normal scrolled changed for accessibility reasons
onScrollChanged(mScrollX, ownScrollY, mScrollX, mOwnScrollY);
@@ -4969,51 +4488,6 @@
requestChildrenUpdate();
}
- private void updateScrollAnchor() {
- int anchorIndex = indexOfChild(mScrollAnchorView);
- // If the anchor view has been scrolled off the top, move to the next view.
- while (mScrollAnchorViewY < 0) {
- View nextAnchor = null;
- for (int i = anchorIndex + 1; i < getChildCount(); i++) {
- View child = getChildAt(i);
- if (child.getVisibility() != View.GONE
- && child instanceof ExpandableNotificationRow) {
- anchorIndex = i;
- nextAnchor = child;
- break;
- }
- }
- if (nextAnchor == null) {
- break;
- }
- mScrollAnchorViewY +=
- (int) (nextAnchor.getTranslationY() - mScrollAnchorView.getTranslationY());
- mScrollAnchorView = nextAnchor;
- }
- // If the view above the anchor view is fully visible, make it the anchor view.
- while (anchorIndex > 0 && mScrollAnchorViewY > 0) {
- View prevAnchor = null;
- for (int i = anchorIndex - 1; i >= 0; i--) {
- View child = getChildAt(i);
- if (child.getVisibility() != View.GONE
- && child instanceof ExpandableNotificationRow) {
- anchorIndex = i;
- prevAnchor = child;
- break;
- }
- }
- if (prevAnchor == null) {
- break;
- }
- float distanceToPreviousAnchor =
- mScrollAnchorView.getTranslationY() - prevAnchor.getTranslationY();
- if (distanceToPreviousAnchor < mScrollAnchorViewY) {
- mScrollAnchorViewY -= (int) distanceToPreviousAnchor;
- mScrollAnchorView = prevAnchor;
- }
- }
- }
-
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void setShelfController(NotificationShelfController notificationShelfController) {
int index = -1;
@@ -5026,9 +4500,6 @@
mAmbientState.setShelf(mShelf);
mStateAnimator.setShelf(mShelf);
notificationShelfController.bind(mAmbientState, mController);
- if (ANCHOR_SCROLLING) {
- mScrollAnchorView = mShelf;
- }
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
@@ -5496,7 +4967,13 @@
mSwipedOutViews.add(v);
}
- void onSwipeBegin() {
+ void onSwipeBegin(View v) {
+ if (v instanceof ExpandableView) {
+ ExpandableView ev = (ExpandableView) v;
+ ev.setIsBeingSwiped(true);
+ mController.getNoticationRoundessManager()
+ .updateViewWithoutCallback(ev, true /* animate */);
+ }
requestDisallowInterceptTouchEvent(true);
updateFirstAndLastBackgroundViews();
updateContinuousShadowDrawing();
@@ -5504,7 +4981,13 @@
requestChildrenUpdate();
}
- void onSwipeEnd() {
+ void onSwipeEnd(View v) {
+ if (v instanceof ExpandableView) {
+ ExpandableView ev = (ExpandableView) v;
+ ev.setIsBeingSwiped(false);
+ mController.getNoticationRoundessManager()
+ .updateViewWithoutCallback(ev, true /* animate */);
+ }
updateFirstAndLastBackgroundViews();
}
@@ -5631,15 +5114,7 @@
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) {
@@ -6166,11 +5641,7 @@
public void expansionStateChanged(boolean isExpanding) {
mExpandingNotification = isExpanding;
if (!mExpandedInThisMotion) {
- if (ANCHOR_SCROLLING) {
- // TODO
- } else {
- mMaxScrollAfterExpand = mOwnScrollY;
- }
+ mMaxScrollAfterExpand = mOwnScrollY;
mExpandedInThisMotion = true;
}
}
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 c2d030b..e332f18 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
@@ -395,7 +395,7 @@
if (mView.getDismissAllInProgress()) {
return;
}
- mView.onSwipeEnd();
+ mView.onSwipeEnd(view);
if (view instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) view;
if (row.isHeadsUp()) {
@@ -450,12 +450,12 @@
@Override
public void onBeginDrag(View v) {
mFalsingCollector.onNotificationStartDismissing();
- mView.onSwipeBegin();
+ mView.onSwipeBegin(v);
}
@Override
public void onChildSnappedBack(View animView, float targetLeft) {
- mView.onSwipeEnd();
+ mView.onSwipeEnd(animView);
if (animView instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) animView;
if (row.isPinned() && !canChildBeDismissed(row)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index d85baa9..2c206b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -45,8 +45,6 @@
*/
public class StackScrollAlgorithm {
- static final boolean ANCHOR_SCROLLING = false;
-
private static final String LOG_TAG = "StackScrollAlgorithm";
private final ViewGroup mHostView;
@@ -229,10 +227,6 @@
scrollY = Math.max(0, scrollY);
state.scrollY = (int) (scrollY + bottomOverScroll);
- if (ANCHOR_SCROLLING) {
- state.anchorViewY = (int) (ambientState.getAnchorViewY() - bottomOverScroll);
- }
-
//now init the visible children and update paddings
int childCount = hostView.getChildCount();
state.visibleChildren.clear();
@@ -240,11 +234,6 @@
int notGoneIndex = 0;
ExpandableView lastView = null;
for (int i = 0; i < childCount; i++) {
- if (ANCHOR_SCROLLING) {
- if (i == ambientState.getAnchorViewIndex()) {
- state.anchorViewIndex = state.visibleChildren.size();
- }
- }
ExpandableView v = (ExpandableView) hostView.getChildAt(i);
if (v.getVisibility() != View.GONE) {
if (v == ambientState.getShelf()) {
@@ -293,26 +282,12 @@
*/
private void updatePositionsForState(StackScrollAlgorithmState algorithmState,
AmbientState ambientState) {
- if (ANCHOR_SCROLLING) {
- float currentYPosition = algorithmState.anchorViewY;
- int childCount = algorithmState.visibleChildren.size();
- for (int i = algorithmState.anchorViewIndex; i < childCount; i++) {
- currentYPosition = updateChild(i, algorithmState, ambientState, currentYPosition,
- false /* reverse */);
- }
- currentYPosition = algorithmState.anchorViewY;
- for (int i = algorithmState.anchorViewIndex - 1; i >= 0; i--) {
- currentYPosition = updateChild(i, algorithmState, ambientState, currentYPosition,
- true /* reverse */);
- }
- } else {
- // The y coordinate of the current child.
- float currentYPosition = -algorithmState.scrollY;
- int childCount = algorithmState.visibleChildren.size();
- for (int i = 0; i < childCount; i++) {
- currentYPosition = updateChild(i, algorithmState, ambientState, currentYPosition,
- false /* reverse */);
- }
+ // The y coordinate of the current child.
+ float currentYPosition = -algorithmState.scrollY;
+ int childCount = algorithmState.visibleChildren.size();
+ for (int i = 0; i < childCount; i++) {
+ currentYPosition = updateChild(i, algorithmState, ambientState, currentYPosition,
+ false /* reverse */);
}
}
@@ -343,7 +318,7 @@
ExpandableView previousChild = i > 0 ? algorithmState.visibleChildren.get(i - 1) : null;
final boolean applyGapHeight =
childNeedsGapHeight(
- ambientState.getSectionProvider(), algorithmState.anchorViewIndex, i,
+ ambientState.getSectionProvider(), i,
child, previousChild);
ExpandableViewState childViewState = child.getViewState();
childViewState.location = ExpandableViewState.LOCATION_UNKNOWN;
@@ -409,7 +384,6 @@
* Get the gap height needed for before a view
*
* @param sectionProvider the sectionProvider used to understand the sections
- * @param anchorViewIndex the anchorView index when anchor scrolling, can be 0 if not
* @param visibleIndex the visible index of this view in the list
* @param child the child asked about
* @param previousChild the child right before it or null if none
@@ -417,12 +391,11 @@
*/
public float getGapHeightForChild(
SectionProvider sectionProvider,
- int anchorViewIndex,
int visibleIndex,
View child,
View previousChild) {
- if (childNeedsGapHeight(sectionProvider, anchorViewIndex, visibleIndex, child,
+ if (childNeedsGapHeight(sectionProvider, visibleIndex, child,
previousChild)) {
return mGapHeight;
} else {
@@ -434,7 +407,6 @@
* Does a given child need a gap, i.e spacing before a view?
*
* @param sectionProvider the sectionProvider used to understand the sections
- * @param anchorViewIndex the anchorView index when anchor scrolling, can be 0 if not
* @param visibleIndex the visible index of this view in the list
* @param child the child asked about
* @param previousChild the child right before it or null if none
@@ -442,16 +414,12 @@
*/
private boolean childNeedsGapHeight(
SectionProvider sectionProvider,
- int anchorViewIndex,
int visibleIndex,
View child,
View previousChild) {
boolean needsGapHeight = sectionProvider.beginsSection(child, previousChild)
&& visibleIndex > 0;
- if (ANCHOR_SCROLLING) {
- needsGapHeight &= visibleIndex != anchorViewIndex;
- }
return needsGapHeight;
}
@@ -537,7 +505,6 @@
// To check if the row need to do translation according to scroll Y
// heads up show full of row's content and any scroll y indicate that the
// translationY need to move up the HUN.
- // TODO: fix this check for anchor scrolling.
if (!mIsExpanded && isTopEntry && ambientState.getScrollY() > 0) {
childState.yTranslation -= ambientState.getScrollY();
}
@@ -701,14 +668,6 @@
*/
public int scrollY;
- /** The index of the anchor view (anchor scrolling). */
- public int anchorViewIndex;
-
- /**
- * The Y position, relative to the top of the screen, of the anchor view (anchor scrolling).
- */
- public int anchorViewY;
-
/**
* The children from the host view which are not gone.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
index d4add95..66a48f1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
@@ -42,6 +42,7 @@
public class StackStateAnimator {
public static final int ANIMATION_DURATION_STANDARD = 360;
+ public static final int ANIMATION_DURATION_CORNER_RADIUS = 200;
public static final int ANIMATION_DURATION_WAKEUP = 500;
public static final int ANIMATION_DURATION_GO_TO_FULL_SHADE = 448;
public static final int ANIMATION_DURATION_APPEAR_DISAPPEAR = 464;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index 01a7292..8d3b128 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -1140,6 +1140,7 @@
if (isFullyCollapsed()) {
expand(true /* animate */);
} else {
+ traceQsJank(true /* startTracing */, false /* wasCancelled */);
flingSettings(0 /* velocity */, FLING_EXPAND);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java
index 9ea402d..d074e64 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java
@@ -652,7 +652,7 @@
pw.println(TAG + ":");
pw.println(" mKeyguardDisplayMode=" + mKeyguardDisplayMode);
pw.println(mCurrentState);
- mNotificationShadeView.getViewRootImpl().dump(" ", fd, pw, args);
+ mNotificationShadeView.getViewRootImpl().dump(" ", pw);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
index 5a01f47..8ed9710 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
@@ -862,6 +862,8 @@
mView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
if (mAnimateAfterExpanding) {
notifyExpandingStarted();
+ InteractionJankMonitor.getInstance().begin(
+ CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE);
fling(0, true /* expand */);
} else {
setExpandedFraction(1f);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 9ebde53..a18d87c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -234,7 +234,7 @@
import com.android.systemui.volume.VolumeComponent;
import com.android.systemui.wmshell.BubblesManager;
import com.android.wm.shell.bubbles.Bubbles;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -394,7 +394,7 @@
private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
private final Provider<StatusBarComponent.Builder> mStatusBarComponentBuilder;
private final PluginManager mPluginManager;
- private final Optional<SplitScreen> mSplitScreenOptional;
+ private final Optional<LegacySplitScreen> mSplitScreenOptional;
private final StatusBarNotificationActivityStarter.Builder
mStatusBarNotificationActivityStarterBuilder;
private final ShadeController mShadeController;
@@ -738,7 +738,7 @@
CommandQueue commandQueue,
Provider<StatusBarComponent.Builder> statusBarComponentBuilder,
PluginManager pluginManager,
- Optional<SplitScreen> splitScreenOptional,
+ Optional<LegacySplitScreen> splitScreenOptional,
LightsOutNotifController lightsOutNotifController,
StatusBarNotificationActivityStarter.Builder
statusBarNotificationActivityStarterBuilder,
@@ -1568,14 +1568,14 @@
return false;
}
- final SplitScreen splitScreen = mSplitScreenOptional.get();
- if (splitScreen.isDividerVisible()) {
- if (splitScreen.isMinimized() && !splitScreen.isHomeStackResizable()) {
+ final LegacySplitScreen legacySplitScreen = mSplitScreenOptional.get();
+ if (legacySplitScreen.isDividerVisible()) {
+ if (legacySplitScreen.isMinimized() && !legacySplitScreen.isHomeStackResizable()) {
// Undocking from the minimized state is not supported
return false;
}
- splitScreen.onUndockingTask();
+ legacySplitScreen.onUndockingTask();
if (metricsUndockAction != -1) {
mMetricsLogger.action(metricsUndockAction);
}
@@ -1587,7 +1587,7 @@
return false;
}
- if (splitScreen.splitPrimaryTask()) {
+ if (legacySplitScreen.splitPrimaryTask()) {
if (metricsDockAction != -1) {
mMetricsLogger.action(metricsDockAction);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
index 2aa3f37..26e1959 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
@@ -100,7 +100,7 @@
import com.android.systemui.volume.VolumeComponent;
import com.android.systemui.wmshell.BubblesManager;
import com.android.wm.shell.bubbles.Bubbles;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import java.util.Optional;
import java.util.concurrent.Executor;
@@ -181,7 +181,7 @@
CommandQueue commandQueue,
Provider<StatusBarComponent.Builder> statusBarComponentBuilder,
PluginManager pluginManager,
- Optional<SplitScreen> splitScreenOptional,
+ Optional<LegacySplitScreen> splitScreenOptional,
LightsOutNotifController lightsOutNotifController,
StatusBarNotificationActivityStarter.Builder
statusBarNotificationActivityStarterBuilder,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java
deleted file mode 100644
index 8f86e2d..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2011 Google Inc. All Rights Reserved.
-
-package com.android.systemui.statusbar.policy;
-
-import com.android.systemui.R;
-
-/**
- * Content descriptions for accessibility support.
- */
-public class AccessibilityContentDescriptions {
-
- private AccessibilityContentDescriptions() {}
- static final int[] PHONE_SIGNAL_STRENGTH = {
- R.string.accessibility_no_phone,
- R.string.accessibility_phone_one_bar,
- R.string.accessibility_phone_two_bars,
- R.string.accessibility_phone_three_bars,
- R.string.accessibility_phone_signal_full
- };
-
- static final int[] DATA_CONNECTION_STRENGTH = {
- R.string.accessibility_no_data,
- R.string.accessibility_data_one_bar,
- R.string.accessibility_data_two_bars,
- R.string.accessibility_data_three_bars,
- R.string.accessibility_data_signal_full
- };
-
- static final int[] WIFI_CONNECTION_STRENGTH = {
- R.string.accessibility_no_wifi,
- R.string.accessibility_wifi_one_bar,
- R.string.accessibility_wifi_two_bars,
- R.string.accessibility_wifi_three_bars,
- R.string.accessibility_wifi_signal_full
- };
-
- static final int WIFI_NO_CONNECTION = R.string.accessibility_no_wifi;
-
- static final int[] ETHERNET_CONNECTION_VALUES = {
- R.string.accessibility_ethernet_disconnected,
- R.string.accessibility_ethernet_connected,
- };
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java
index 4fbf5ff..2eff04e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java
@@ -18,6 +18,9 @@
import android.content.Context;
import android.net.NetworkCapabilities;
+import com.android.settingslib.AccessibilityContentDescriptions;
+import com.android.settingslib.SignalIcon.IconGroup;
+import com.android.settingslib.SignalIcon.State;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
@@ -25,7 +28,7 @@
public class EthernetSignalController extends
- SignalController<SignalController.State, SignalController.IconGroup> {
+ SignalController<State, IconGroup> {
public EthernetSignalController(Context context,
CallbackHandler callbackHandler, NetworkControllerImpl networkController) {
@@ -57,7 +60,7 @@
}
@Override
- public SignalController.State cleanState() {
- return new SignalController.State();
+ public State cleanState() {
+ return new State();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index dd9165d..947b9182 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -15,9 +15,9 @@
*/
package com.android.systemui.statusbar.policy;
+import static com.android.settingslib.mobile.MobileMappings.getDefaultIcons;
import static com.android.settingslib.mobile.MobileMappings.getIconKey;
-import static com.android.settingslib.mobile.MobileMappings.toDisplayIconKey;
-import static com.android.settingslib.mobile.MobileMappings.toIconKey;
+import static com.android.settingslib.mobile.MobileMappings.mapIconSets;
import android.content.Context;
import android.content.Intent;
@@ -39,25 +39,28 @@
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.settingslib.SignalIcon.MobileIconGroup;
+import com.android.settingslib.SignalIcon.MobileState;
import com.android.settingslib.Utils;
import com.android.settingslib.graph.SignalDrawable;
+import com.android.settingslib.mobile.MobileMappings.Config;
import com.android.settingslib.mobile.MobileStatusTracker;
import com.android.settingslib.mobile.MobileStatusTracker.SubscriptionDefaults;
+import com.android.settingslib.mobile.TelephonyIcons;
import com.android.settingslib.net.SignalStrengthUtil;
import com.android.systemui.R;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
-import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
import java.io.PrintWriter;
import java.util.BitSet;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.Objects;
-public class MobileSignalController extends SignalController<
- MobileSignalController.MobileState, MobileSignalController.MobileIconGroup> {
+/**
+ * Monitors the mobile signal changes and update the SysUI icons.
+ */
+public class MobileSignalController extends SignalController<MobileState, MobileIconGroup> {
private final TelephonyManager mPhone;
private final SubscriptionDefaults mDefaults;
private final String mNetworkNameDefault;
@@ -66,7 +69,8 @@
// Save entire info for logging, we only use the id.
final SubscriptionInfo mSubscriptionInfo;
// @VisibleForDemoMode
- final Map<String, MobileIconGroup> mNetworkToIconLookup;
+ Map<String, MobileIconGroup> mNetworkToIconLookup;
+
// Since some pieces of the phone state are interdependent we store it locally,
// this could potentially become part of MobileState for simplification/complication
// of code.
@@ -93,7 +97,6 @@
super("MobileSignalController(" + info.getSubscriptionId() + ")", context,
NetworkCapabilities.TRANSPORT_CELLULAR, callbackHandler,
networkController);
- mNetworkToIconLookup = new HashMap<>();
mConfig = config;
mPhone = phone;
mDefaults = defaults;
@@ -102,7 +105,10 @@
.toString();
mNetworkNameDefault = getTextIfExists(
com.android.internal.R.string.lockscreen_carrier_default).toString();
- mapIconSets();
+
+ mNetworkToIconLookup = mapIconSets(mConfig);
+ mDefaultIcons = getDefaultIcons(mConfig);
+
String networkName = info.getCarrierName() != null ? info.getCarrierName().toString()
: mNetworkNameDefault;
mLastState.networkName = mCurrentState.networkName = networkName;
@@ -139,7 +145,8 @@
public void setConfiguration(Config config) {
mConfig = config;
updateInflateSignalStrength();
- mapIconSets();
+ mNetworkToIconLookup = mapIconSets(mConfig);
+ mDefaultIcons = getDefaultIcons(mConfig);
updateTelephony();
}
@@ -187,113 +194,6 @@
mContext.getContentResolver().unregisterContentObserver(mObserver);
}
- /**
- * Produce a mapping of data network types to icon groups for simple and quick use in
- * updateTelephony.
- */
- private void mapIconSets() {
- mNetworkToIconLookup.clear();
-
- mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EVDO_0),
- TelephonyIcons.THREE_G);
- mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EVDO_A),
- TelephonyIcons.THREE_G);
- mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EVDO_B),
- TelephonyIcons.THREE_G);
- mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EHRPD),
- TelephonyIcons.THREE_G);
- if (mConfig.show4gFor3g) {
- mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_UMTS),
- TelephonyIcons.FOUR_G);
- } else {
- mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_UMTS),
- TelephonyIcons.THREE_G);
- }
- mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_TD_SCDMA),
- TelephonyIcons.THREE_G);
-
- if (!mConfig.showAtLeast3G) {
- mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_UNKNOWN),
- TelephonyIcons.UNKNOWN);
- mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EDGE),
- TelephonyIcons.E);
- mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_CDMA),
- TelephonyIcons.ONE_X);
- mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_1xRTT),
- TelephonyIcons.ONE_X);
-
- mDefaultIcons = TelephonyIcons.G;
- } else {
- mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_UNKNOWN),
- TelephonyIcons.THREE_G);
- mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EDGE),
- TelephonyIcons.THREE_G);
- mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_CDMA),
- TelephonyIcons.THREE_G);
- mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_1xRTT),
- TelephonyIcons.THREE_G);
- mDefaultIcons = TelephonyIcons.THREE_G;
- }
-
- MobileIconGroup hGroup = TelephonyIcons.THREE_G;
- MobileIconGroup hPlusGroup = TelephonyIcons.THREE_G;
- if (mConfig.show4gFor3g) {
- hGroup = TelephonyIcons.FOUR_G;
- hPlusGroup = TelephonyIcons.FOUR_G;
- } else if (mConfig.hspaDataDistinguishable) {
- hGroup = TelephonyIcons.H;
- hPlusGroup = TelephonyIcons.H_PLUS;
- }
-
- mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_HSDPA), hGroup);
- mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_HSUPA), hGroup);
- mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_HSPA), hGroup);
- mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_HSPAP), hPlusGroup);
-
- if (mConfig.show4gForLte) {
- mNetworkToIconLookup.put(toIconKey(
- TelephonyManager.NETWORK_TYPE_LTE),
- TelephonyIcons.FOUR_G);
- if (mConfig.hideLtePlus) {
- mNetworkToIconLookup.put(toDisplayIconKey(
- TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA),
- TelephonyIcons.FOUR_G);
- } else {
- mNetworkToIconLookup.put(toDisplayIconKey(
- TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA),
- TelephonyIcons.FOUR_G_PLUS);
- }
- } else {
- mNetworkToIconLookup.put(toIconKey(
- TelephonyManager.NETWORK_TYPE_LTE),
- TelephonyIcons.LTE);
- if (mConfig.hideLtePlus) {
- mNetworkToIconLookup.put(toDisplayIconKey(
- TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA),
- TelephonyIcons.LTE);
- } else {
- mNetworkToIconLookup.put(toDisplayIconKey(
- TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA),
- TelephonyIcons.LTE_PLUS);
- }
- }
- mNetworkToIconLookup.put(toIconKey(
- TelephonyManager.NETWORK_TYPE_IWLAN),
- TelephonyIcons.WFC);
- mNetworkToIconLookup.put(toDisplayIconKey(
- TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO),
- TelephonyIcons.LTE_CA_5G_E);
- mNetworkToIconLookup.put(toDisplayIconKey(
- TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA),
- TelephonyIcons.NR_5G);
- mNetworkToIconLookup.put(toDisplayIconKey(
- TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE),
- TelephonyIcons.NR_5G_PLUS);
- mNetworkToIconLookup.put(toIconKey(
- TelephonyManager.NETWORK_TYPE_NR),
- TelephonyIcons.NR_5G);
- }
-
private void updateInflateSignalStrength() {
mInflateSignalStrengths = SignalStrengthUtil.shouldInflateSignalStrength(mContext,
mSubscriptionInfo.getSubscriptionId());
@@ -339,7 +239,7 @@
MobileIconGroup icons = getIcons();
String contentDescription = getTextIfExists(getContentDescription()).toString();
- CharSequence dataContentDescriptionHtml = getTextIfExists(icons.mDataContentDescription);
+ CharSequence dataContentDescriptionHtml = getTextIfExists(icons.dataContentDescription);
//TODO: Hacky
// The data content description can sometimes be shown in a text view and might come to us
@@ -363,7 +263,7 @@
CharSequence description = null;
// Only send data sim callbacks to QS.
if (mCurrentState.dataSim) {
- qsTypeIcon = (showDataIcon || mConfig.alwaysShowDataRatIcon) ? icons.mQsDataType : 0;
+ qsTypeIcon = (showDataIcon || mConfig.alwaysShowDataRatIcon) ? icons.qsDataType : 0;
qsIcon = new IconState(mCurrentState.enabled
&& !mCurrentState.isEmergency, getQsCurrentIconId(), contentDescription);
description = mCurrentState.isEmergency ? null : mCurrentState.networkName;
@@ -375,10 +275,10 @@
&& !mCurrentState.carrierNetworkChangeMode
&& mCurrentState.activityOut;
showDataIcon &= mCurrentState.isDefault || dataDisabled;
- int typeIcon = (showDataIcon || mConfig.alwaysShowDataRatIcon) ? icons.mDataType : 0;
+ int typeIcon = (showDataIcon || mConfig.alwaysShowDataRatIcon) ? icons.dataType : 0;
callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
activityIn, activityOut, dataContentDescription, dataContentDescriptionHtml,
- description, icons.mIsWide, mSubscriptionInfo.getSubscriptionId(),
+ description, icons.isWide, mSubscriptionInfo.getSubscriptionId(),
mCurrentState.roaming);
}
@@ -610,87 +510,4 @@
pw.println(" mInflateSignalStrengths=" + mInflateSignalStrengths + ",");
pw.println(" isDataDisabled=" + isDataDisabled() + ",");
}
-
- static class MobileIconGroup extends SignalController.IconGroup {
- final int mDataContentDescription; // mContentDescriptionDataType
- final int mDataType;
- final boolean mIsWide;
- final int mQsDataType;
-
- public MobileIconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc,
- int sbNullState, int qsNullState, int sbDiscState, int qsDiscState,
- int discContentDesc, int dataContentDesc, int dataType, boolean isWide) {
- super(name, sbIcons, qsIcons, contentDesc, sbNullState, qsNullState, sbDiscState,
- qsDiscState, discContentDesc);
- mDataContentDescription = dataContentDesc;
- mDataType = dataType;
- mIsWide = isWide;
- mQsDataType = dataType; // TODO: remove this field
- }
- }
-
- static class MobileState extends SignalController.State {
- String networkName;
- String networkNameData;
- boolean dataSim;
- boolean dataConnected;
- boolean isEmergency;
- boolean airplaneMode;
- boolean carrierNetworkChangeMode;
- boolean isDefault;
- boolean userSetup;
- boolean roaming;
- boolean defaultDataOff; // Tracks the on/off state of the defaultDataSubscription
-
- @Override
- public void copyFrom(State s) {
- super.copyFrom(s);
- MobileState state = (MobileState) s;
- dataSim = state.dataSim;
- networkName = state.networkName;
- networkNameData = state.networkNameData;
- dataConnected = state.dataConnected;
- isDefault = state.isDefault;
- isEmergency = state.isEmergency;
- airplaneMode = state.airplaneMode;
- carrierNetworkChangeMode = state.carrierNetworkChangeMode;
- userSetup = state.userSetup;
- roaming = state.roaming;
- defaultDataOff = state.defaultDataOff;
- }
-
- @Override
- protected void toString(StringBuilder builder) {
- super.toString(builder);
- builder.append(',');
- builder.append("dataSim=").append(dataSim).append(',');
- builder.append("networkName=").append(networkName).append(',');
- builder.append("networkNameData=").append(networkNameData).append(',');
- builder.append("dataConnected=").append(dataConnected).append(',');
- builder.append("roaming=").append(roaming).append(',');
- builder.append("isDefault=").append(isDefault).append(',');
- builder.append("isEmergency=").append(isEmergency).append(',');
- builder.append("airplaneMode=").append(airplaneMode).append(',');
- builder.append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode)
- .append(',');
- builder.append("userSetup=").append(userSetup).append(',');
- builder.append("defaultDataOff=").append(defaultDataOff);
- }
-
- @Override
- public boolean equals(Object o) {
- return super.equals(o)
- && Objects.equals(((MobileState) o).networkName, networkName)
- && Objects.equals(((MobileState) o).networkNameData, networkNameData)
- && ((MobileState) o).dataSim == dataSim
- && ((MobileState) o).dataConnected == dataConnected
- && ((MobileState) o).isEmergency == isEmergency
- && ((MobileState) o).airplaneMode == airplaneMode
- && ((MobileState) o).carrierNetworkChangeMode == carrierNetworkChangeMode
- && ((MobileState) o).userSetup == userSetup
- && ((MobileState) o).isDefault == isDefault
- && ((MobileState) o).roaming == roaming
- && ((MobileState) o).defaultDataOff == defaultDataOff;
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index a3abb31..0ca2b4a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -30,7 +30,6 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
-import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
@@ -40,7 +39,6 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
-import android.os.PersistableBundle;
import android.provider.Settings;
import android.telephony.CarrierConfigManager;
import android.telephony.CellSignalStrength;
@@ -59,7 +57,9 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.settingslib.mobile.MobileMappings.Config;
import com.android.settingslib.mobile.MobileStatusTracker.SubscriptionDefaults;
+import com.android.settingslib.mobile.TelephonyIcons;
import com.android.settingslib.net.DataUsageController;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
@@ -1201,45 +1201,4 @@
registerListeners();
}
};
-
- @VisibleForTesting
- static class Config {
- boolean showAtLeast3G = false;
- boolean show4gFor3g = false;
- boolean alwaysShowCdmaRssi = false;
- boolean show4gForLte = false;
- boolean hideLtePlus = false;
- boolean hspaDataDistinguishable;
- boolean alwaysShowDataRatIcon = false;
-
- static Config readConfig(Context context) {
- Config config = new Config();
- Resources res = context.getResources();
-
- config.showAtLeast3G = res.getBoolean(R.bool.config_showMin3G);
- config.alwaysShowCdmaRssi =
- res.getBoolean(com.android.internal.R.bool.config_alwaysUseCdmaRssi);
- config.hspaDataDistinguishable =
- res.getBoolean(R.bool.config_hspa_data_distinguishable);
-
- CarrierConfigManager configMgr = (CarrierConfigManager)
- context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
- // Handle specific carrier config values for the default data SIM
- int defaultDataSubId = SubscriptionManager.from(context)
- .getDefaultDataSubscriptionId();
- PersistableBundle b = configMgr.getConfigForSubId(defaultDataSubId);
- if (b != null) {
- config.alwaysShowDataRatIcon = b.getBoolean(
- CarrierConfigManager.KEY_ALWAYS_SHOW_DATA_RAT_ICON_BOOL);
- config.show4gForLte = b.getBoolean(
- CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL);
- config.show4gFor3g = b.getBoolean(
- CarrierConfigManager.KEY_SHOW_4G_FOR_3G_DATA_ICON_BOOL);
- config.hideLtePlus = b.getBoolean(
- CarrierConfigManager.KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL);
- }
-
- return config;
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
index 3a45691..a05fe1f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
@@ -21,18 +21,21 @@
import android.content.Context;
import android.util.Log;
+import com.android.settingslib.SignalIcon.IconGroup;
+import com.android.settingslib.SignalIcon.State;
import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
import java.io.PrintWriter;
-import java.text.SimpleDateFormat;
import java.util.BitSet;
/**
* Common base class for handling signal for both wifi and mobile data.
+ *
+ * @param <T> State of the SysUI controller.
+ * @param <I> Icon groups of the SysUI controller for a given State.
*/
-public abstract class SignalController<T extends SignalController.State,
- I extends SignalController.IconGroup> {
+public abstract class SignalController<T extends State, I extends IconGroup> {
// Save the previous SignalController.States of all SignalControllers for dumps.
static final boolean RECORD_HISTORY = true;
// If RECORD_HISTORY how many to save, must be a power of 2.
@@ -124,11 +127,11 @@
*/
public int getQsCurrentIconId() {
if (mCurrentState.connected) {
- return getIcons().mQsIcons[mCurrentState.inetCondition][mCurrentState.level];
+ return getIcons().qsIcons[mCurrentState.inetCondition][mCurrentState.level];
} else if (mCurrentState.enabled) {
- return getIcons().mQsDiscState;
+ return getIcons().qsDiscState;
} else {
- return getIcons().mQsNullState;
+ return getIcons().qsNullState;
}
}
@@ -137,11 +140,11 @@
*/
public int getCurrentIconId() {
if (mCurrentState.connected) {
- return getIcons().mSbIcons[mCurrentState.inetCondition][mCurrentState.level];
+ return getIcons().sbIcons[mCurrentState.inetCondition][mCurrentState.level];
} else if (mCurrentState.enabled) {
- return getIcons().mSbDiscState;
+ return getIcons().sbDiscState;
} else {
- return getIcons().mSbNullState;
+ return getIcons().sbNullState;
}
}
@@ -151,9 +154,9 @@
*/
public int getContentDescription() {
if (mCurrentState.connected) {
- return getIcons().mContentDesc[mCurrentState.level];
+ return getIcons().contentDesc[mCurrentState.level];
} else {
- return getIcons().mDiscContentDesc;
+ return getIcons().discContentDesc;
}
}
@@ -216,108 +219,4 @@
* Generate a blank T.
*/
protected abstract T cleanState();
-
- /*
- * Holds icons for a given state. Arrays are generally indexed as inet
- * state (full connectivity or not) first, and second dimension as
- * signal strength.
- */
- static class IconGroup {
- final int[][] mSbIcons;
- final int[][] mQsIcons;
- final int[] mContentDesc;
- final int mSbNullState;
- final int mQsNullState;
- final int mSbDiscState;
- final int mQsDiscState;
- final int mDiscContentDesc;
- // For logging.
- final String mName;
-
- public IconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc,
- int sbNullState, int qsNullState, int sbDiscState, int qsDiscState,
- int discContentDesc) {
- mName = name;
- mSbIcons = sbIcons;
- mQsIcons = qsIcons;
- mContentDesc = contentDesc;
- mSbNullState = sbNullState;
- mQsNullState = qsNullState;
- mSbDiscState = sbDiscState;
- mQsDiscState = qsDiscState;
- mDiscContentDesc = discContentDesc;
- }
-
- @Override
- public String toString() {
- return "IconGroup(" + mName + ")";
- }
- }
-
- static class State {
- // No locale as it's only used for logging purposes
- private static SimpleDateFormat sSDF = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
- boolean connected;
- boolean enabled;
- boolean activityIn;
- boolean activityOut;
- int level;
- IconGroup iconGroup;
- int inetCondition;
- int rssi; // Only for logging.
-
- // Not used for comparison, just used for logging.
- long time;
-
- public void copyFrom(State state) {
- connected = state.connected;
- enabled = state.enabled;
- level = state.level;
- iconGroup = state.iconGroup;
- inetCondition = state.inetCondition;
- activityIn = state.activityIn;
- activityOut = state.activityOut;
- rssi = state.rssi;
- time = state.time;
- }
-
- @Override
- public String toString() {
- if (time != 0) {
- StringBuilder builder = new StringBuilder();
- toString(builder);
- return builder.toString();
- } else {
- return "Empty " + getClass().getSimpleName();
- }
- }
-
- protected void toString(StringBuilder builder) {
- builder.append("connected=").append(connected).append(',')
- .append("enabled=").append(enabled).append(',')
- .append("level=").append(level).append(',')
- .append("inetCondition=").append(inetCondition).append(',')
- .append("iconGroup=").append(iconGroup).append(',')
- .append("activityIn=").append(activityIn).append(',')
- .append("activityOut=").append(activityOut).append(',')
- .append("rssi=").append(rssi).append(',')
- .append("lastModified=").append(sSDF.format(time));
- }
-
- @Override
- public boolean equals(Object o) {
- if (!o.getClass().equals(getClass())) {
- return false;
- }
- State other = (State) o;
- return other.connected == connected
- && other.enabled == enabled
- && other.level == level
- && other.inetCondition == inetCondition
- && other.iconGroup == iconGroup
- && other.activityIn == activityIn
- && other.activityOut == activityOut
- && other.rssi == rssi;
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
index 4ae9665..82ce4c8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
@@ -28,6 +28,9 @@
import android.text.TextUtils;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.settingslib.AccessibilityContentDescriptions;
+import com.android.settingslib.SignalIcon.IconGroup;
+import com.android.settingslib.SignalIcon.State;
import com.android.settingslib.wifi.WifiStatusTracker;
import com.android.systemui.R;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
@@ -36,7 +39,7 @@
import java.util.Objects;
public class WifiSignalController extends
- SignalController<WifiSignalController.WifiState, SignalController.IconGroup> {
+ SignalController<WifiSignalController.WifiState, IconGroup> {
private final boolean mHasMobileDataFeature;
private final WifiStatusTracker mWifiTracker;
@@ -156,7 +159,7 @@
}
}
- static class WifiState extends SignalController.State {
+ static class WifiState extends State {
String ssid;
boolean isTransient;
boolean isDefault;
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java
index 8dea5b5..125b5d4c 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java
@@ -36,7 +36,7 @@
import com.android.wm.shell.pip.tv.PipControlsViewController;
import com.android.wm.shell.pip.tv.PipNotification;
import com.android.wm.shell.pip.tv.TvPipMenuController;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import java.util.Optional;
@@ -120,7 +120,7 @@
PipBoundsState pipBoundsState,
PipBoundsAlgorithm pipBoundsAlgorithm,
PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
- Optional<SplitScreen> splitScreenOptional, DisplayController displayController,
+ Optional<LegacySplitScreen> splitScreenOptional, DisplayController displayController,
PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer) {
return new PipTaskOrganizer(context, pipBoundsState, pipBoundsAlgorithm,
tvMenuController, pipSurfaceTransactionHelper, splitScreenOptional,
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java
index 06f1522..765fd32 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java
@@ -29,8 +29,8 @@
import com.android.wm.shell.common.SystemWindows;
import com.android.wm.shell.common.TaskStackListenerImpl;
import com.android.wm.shell.common.TransactionPool;
-import com.android.wm.shell.splitscreen.SplitScreen;
-import com.android.wm.shell.splitscreen.SplitScreenController;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController;
import java.util.concurrent.Executor;
@@ -54,12 +54,12 @@
@WMSingleton
@Provides
- static SplitScreen provideSplitScreen(Context context,
+ static LegacySplitScreen provideSplitScreen(Context context,
DisplayController displayController, SystemWindows systemWindows,
DisplayImeController displayImeController, @Main Handler handler,
TransactionPool transactionPool, ShellTaskOrganizer shellTaskOrganizer,
SyncTransactionQueue syncQueue, TaskStackListenerImpl taskStackListener) {
- return new SplitScreenController(context, displayController, systemWindows,
+ return new LegacySplitScreenController(context, displayController, systemWindows,
displayImeController, handler, transactionPool, shellTaskOrganizer, syncQueue,
taskStackListener);
}
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
index 2a18f3c5..0819429 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
@@ -61,7 +61,7 @@
import com.android.wm.shell.onehanded.OneHandedTransitionCallback;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.protolog.ShellProtoLogImpl;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -93,7 +93,7 @@
private final ScreenLifecycle mScreenLifecycle;
private final SysUiState mSysUiState;
private final Optional<Pip> mPipOptional;
- private final Optional<SplitScreen> mSplitScreenOptional;
+ private final Optional<LegacySplitScreen> mSplitScreenOptional;
private final Optional<OneHanded> mOneHandedOptional;
private final Optional<HideDisplayCutout> mHideDisplayCutoutOptional;
private final ProtoTracer mProtoTracer;
@@ -112,7 +112,7 @@
ScreenLifecycle screenLifecycle,
SysUiState sysUiState,
Optional<Pip> pipOptional,
- Optional<SplitScreen> splitScreenOptional,
+ Optional<LegacySplitScreen> splitScreenOptional,
Optional<OneHanded> oneHandedOptional,
Optional<HideDisplayCutout> hideDisplayCutoutOptional,
ProtoTracer protoTracer,
@@ -190,7 +190,7 @@
}
@VisibleForTesting
- void initSplitScreen(SplitScreen splitScreen) {
+ void initSplitScreen(LegacySplitScreen legacySplitScreen) {
mSplitScreenKeyguardCallback = new KeyguardUpdateMonitorCallback() {
@Override
public void onKeyguardVisibilityChanged(boolean showing) {
@@ -198,7 +198,7 @@
// above everything, it is actually transparent except for notifications, so
// we still need to hide any surfaces that are below it.
// TODO(b/148906453): Figure out keyguard dismiss animation for divider view.
- splitScreen.onKeyguardVisibilityChanged(showing);
+ legacySplitScreen.onKeyguardVisibilityChanged(showing);
}
};
mKeyguardUpdateMonitor.registerCallback(mSplitScreenKeyguardCallback);
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
index ee58947..bcb2a8c 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
@@ -34,6 +34,7 @@
import com.android.systemui.dagger.WMSingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.wm.shell.FullscreenTaskListener;
+import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
import com.android.wm.shell.ShellCommandHandler;
import com.android.wm.shell.ShellInit;
import com.android.wm.shell.ShellTaskOrganizer;
@@ -65,7 +66,7 @@
import com.android.wm.shell.pip.PipUiEventLogger;
import com.android.wm.shell.pip.phone.PipAppOpsListener;
import com.android.wm.shell.pip.phone.PipTouchHandler;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
@@ -169,14 +170,14 @@
static ShellInit provideShellInit(DisplayImeController displayImeController,
DragAndDropController dragAndDropController,
ShellTaskOrganizer shellTaskOrganizer,
- Optional<SplitScreen> splitScreenOptional,
+ Optional<LegacySplitScreen> legacySplitScreenOptional,
Optional<AppPairs> appPairsOptional,
FullscreenTaskListener fullscreenTaskListener,
Transitions transitions) {
return new ShellInit(displayImeController,
dragAndDropController,
shellTaskOrganizer,
- splitScreenOptional,
+ legacySplitScreenOptional,
appPairsOptional,
fullscreenTaskListener,
transitions);
@@ -190,12 +191,12 @@
@Provides
static Optional<ShellCommandHandler> provideShellCommandHandler(
ShellTaskOrganizer shellTaskOrganizer,
- Optional<SplitScreen> splitScreenOptional,
+ Optional<LegacySplitScreen> legacySplitScreenOptional,
Optional<Pip> pipOptional,
Optional<OneHanded> oneHandedOptional,
Optional<HideDisplayCutout> hideDisplayCutout,
Optional<AppPairs> appPairsOptional) {
- return Optional.of(new ShellCommandHandler(shellTaskOrganizer, splitScreenOptional,
+ return Optional.of(new ShellCommandHandler(shellTaskOrganizer, legacySplitScreenOptional,
pipOptional, oneHandedOptional, hideDisplayCutout, appPairsOptional));
}
@@ -282,12 +283,19 @@
@WMSingleton
@Provides
+ static RootTaskDisplayAreaOrganizer provideRootTaskDisplayAreaOrganizer(
+ @ShellMainThread ShellExecutor mainExecutor, Context context) {
+ return new RootTaskDisplayAreaOrganizer(mainExecutor);
+ }
+
+ @WMSingleton
+ @Provides
static TaskStackListenerImpl providerTaskStackListenerImpl(@Main Handler handler) {
return new TaskStackListenerImpl(handler);
}
@BindsOptionalOf
- abstract SplitScreen optionalSplitScreen();
+ abstract LegacySplitScreen optionalLegacySplitScreen();
@BindsOptionalOf
abstract AppPairs optionalAppPairs();
@@ -311,16 +319,18 @@
@WMSingleton
@Provides
static Optional<OneHanded> provideOneHandedController(Context context,
- DisplayController displayController, TaskStackListenerImpl taskStackListener) {
+ DisplayController displayController, TaskStackListenerImpl taskStackListener,
+ @ShellMainThread ShellExecutor mainExecutor) {
return Optional.ofNullable(OneHandedController.create(context, displayController,
- taskStackListener));
+ taskStackListener, mainExecutor));
}
@WMSingleton
@Provides
static Optional<HideDisplayCutout> provideHideDisplayCutoutController(Context context,
- DisplayController displayController) {
- return Optional.ofNullable(HideDisplayCutoutController.create(context, displayController));
+ DisplayController displayController, @ShellMainThread ShellExecutor mainExecutor) {
+ return Optional.ofNullable(
+ HideDisplayCutoutController.create(context, displayController, mainExecutor));
}
@WMSingleton
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
index 281b1aa..3399a0b 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
@@ -46,8 +46,8 @@
import com.android.wm.shell.pip.phone.PipAppOpsListener;
import com.android.wm.shell.pip.phone.PipController;
import com.android.wm.shell.pip.phone.PipTouchHandler;
-import com.android.wm.shell.splitscreen.SplitScreen;
-import com.android.wm.shell.splitscreen.SplitScreenController;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController;
import java.util.Optional;
import java.util.concurrent.Executor;
@@ -72,12 +72,12 @@
@WMSingleton
@Provides
- static SplitScreen provideSplitScreen(Context context,
+ static LegacySplitScreen provideLegacySplitScreen(Context context,
DisplayController displayController, SystemWindows systemWindows,
DisplayImeController displayImeController, @Main Handler handler,
TransactionPool transactionPool, ShellTaskOrganizer shellTaskOrganizer,
SyncTransactionQueue syncQueue, TaskStackListenerImpl taskStackListener) {
- return new SplitScreenController(context, displayController, systemWindows,
+ return new LegacySplitScreenController(context, displayController, systemWindows,
displayImeController, handler, transactionPool, shellTaskOrganizer, syncQueue,
taskStackListener);
}
@@ -145,7 +145,7 @@
PipBoundsAlgorithm pipBoundsAlgorithm,
PhonePipMenuController menuPhoneController,
PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
- Optional<SplitScreen> splitScreenOptional, DisplayController displayController,
+ Optional<LegacySplitScreen> splitScreenOptional, DisplayController displayController,
PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer) {
return new PipTaskOrganizer(context, pipBoundsState, pipBoundsAlgorithm,
menuPhoneController, pipSurfaceTransactionHelper, splitScreenOptional,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
index e967a5d..6c3b37e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
@@ -24,10 +24,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -54,8 +51,6 @@
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.util.time.FakeSystemClock;
-import junit.framework.Assert;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -84,8 +79,7 @@
MockitoAnnotations.initMocks(this);
mFsc = new ForegroundServiceController(mAppOpsController, mMainHandler);
mListener = new ForegroundServiceNotificationListener(
- mContext, mFsc, mEntryManager, mNotifPipeline,
- mock(ForegroundServiceLifetimeExtender.class), mClock);
+ mContext, mFsc, mEntryManager, mNotifPipeline, mClock);
ArgumentCaptor<NotificationEntryListener> entryListenerCaptor =
ArgumentCaptor.forClass(NotificationEntryListener.class);
verify(mEntryManager).addNotificationEntryListener(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceNotificationListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceNotificationListenerTest.java
deleted file mode 100644
index 9a40421..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceNotificationListenerTest.java
+++ /dev/null
@@ -1,110 +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.
- */
-
-package com.android.systemui;
-
-import static com.android.systemui.ForegroundServiceLifetimeExtender.MIN_FGS_TIME_MS;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import android.app.Notification;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.systemui.statusbar.NotificationInteractionTracker;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
-import com.android.systemui.util.time.FakeSystemClock;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class ForegroundServiceNotificationListenerTest extends SysuiTestCase {
- private ForegroundServiceLifetimeExtender mExtender;
- private NotificationEntry mEntry;
- private Notification mNotif;
- private final FakeSystemClock mClock = new FakeSystemClock();
-
- @Mock
- private NotificationInteractionTracker mInteractionTracker;
-
- @Before
- public void setup() {
- MockitoAnnotations.initMocks(this);
- mExtender = new ForegroundServiceLifetimeExtender(mInteractionTracker, mClock);
-
- mNotif = new Notification.Builder(mContext, "")
- .setSmallIcon(R.drawable.ic_person)
- .setContentTitle("Title")
- .setContentText("Text")
- .build();
-
- mEntry = new NotificationEntryBuilder()
- .setCreationTime(mClock.uptimeMillis())
- .setNotification(mNotif)
- .build();
- }
-
- /**
- * ForegroundServiceLifetimeExtenderTest
- */
- @Test
- public void testShouldExtendLifetime_should_foreground() {
- // Extend the lifetime of a FGS notification iff it has not been visible
- // for the minimum time
- mNotif.flags |= Notification.FLAG_FOREGROUND_SERVICE;
-
- // No time has elapsed, keep showing
- assertTrue(mExtender.shouldExtendLifetime(mEntry));
- }
-
- @Test
- public void testShouldExtendLifetime_shouldNot_foreground() {
- mNotif.flags |= Notification.FLAG_FOREGROUND_SERVICE;
-
- // Entry was created at mClock.uptimeMillis(), advance it MIN_FGS_TIME_MS + 1
- mClock.advanceTime(MIN_FGS_TIME_MS + 1);
- assertFalse(mExtender.shouldExtendLifetime(mEntry));
- }
-
- @Test
- public void testShouldExtendLifetime_shouldNot_notForeground() {
- mNotif.flags = 0;
-
- // Entry was created at mClock.uptimeMillis(), advance it MIN_FGS_TIME_MS + 1
- mClock.advanceTime(MIN_FGS_TIME_MS + 1);
- assertFalse(mExtender.shouldExtendLifetime(mEntry));
- }
-
- @Test
- public void testShouldExtendLifetime_shouldNot_interruped() {
- // GIVEN a notification that would trigger lifetime extension
- mNotif.flags |= Notification.FLAG_FOREGROUND_SERVICE;
-
- // GIVEN the notification has alerted
- mEntry.setInterruption();
-
- // THEN the notification does not need to have its lifetime extended by this extender
- assertFalse(mExtender.shouldExtendLifetime(mEntry));
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
index 32c360f..96f46eaa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
@@ -60,7 +60,7 @@
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.wm.shell.pip.Pip;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import org.junit.After;
import org.junit.Before;
@@ -98,7 +98,7 @@
mock(BroadcastDispatcher.class),
mock(CommandQueue.class),
Optional.of(mock(Pip.class)),
- Optional.of(mock(SplitScreen.class)),
+ Optional.of(mock(LegacySplitScreen.class)),
Optional.of(mock(Recents.class)),
() -> mock(StatusBar.class),
mock(ShadeController.class),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
index 57eac74..851d486 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
@@ -77,7 +77,7 @@
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.utils.leaks.LeakCheckedTest;
import com.android.wm.shell.pip.Pip;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import org.junit.Before;
import org.junit.Rule;
@@ -225,7 +225,7 @@
mBroadcastDispatcher,
mCommandQueue,
Optional.of(mock(Pip.class)),
- Optional.of(mock(SplitScreen.class)),
+ Optional.of(mock(LegacySplitScreen.class)),
Optional.of(mock(Recents.class)),
() -> mock(StatusBar.class),
mock(ShadeController.class),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java
index a6c2d08..14de7aa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java
@@ -103,6 +103,7 @@
when(mQSPanel.isAttachedToWindow()).thenReturn(true);
when(mQSPanel.getDumpableTag()).thenReturn("QSPanel");
when(mQSPanel.createRegularTileLayout()).thenReturn(mPagedTileLayout);
+ when(mQSPanel.getTileLayout()).thenReturn(mPagedTileLayout);
when(mQSTileHost.getTiles()).thenReturn(Collections.singleton(mQSTile));
when(mQSTileHost.createTileView(eq(mQSTile), anyBoolean())).thenReturn(mQSTileView);
when(mToggleSliderViewControllerFactory.create(any(), any()))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
index 3f2b4da..c490c4c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
@@ -24,12 +24,14 @@
import com.android.systemui.dump.DumpManager
import com.android.systemui.media.MediaHost
import com.android.systemui.plugins.qs.QSTile
+import com.android.systemui.plugins.qs.QSTileView
import com.android.systemui.qs.customize.QSCustomizerController
import com.android.systemui.qs.logging.QSLogger
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.Mock
import org.mockito.Mockito.`when`
import org.mockito.Mockito.any
@@ -59,6 +61,8 @@
private lateinit var tile: QSTile
@Mock
private lateinit var tileLayout: TileLayout
+ @Mock
+ private lateinit var tileView: QSTileView
private lateinit var controller: QuickQSPanelController
@@ -68,6 +72,7 @@
`when`(quickQSPanel.tileLayout).thenReturn(tileLayout)
`when`(quickQSPanel.dumpableTag).thenReturn("")
+ `when`(qsTileHost.createTileView(any(), anyBoolean())).thenReturn(tileView)
controller = QuickQSPanelController(
quickQSPanel,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.java
index 0c3db57..b3176dd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.java
@@ -41,7 +41,7 @@
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.wm.shell.pip.Pip;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import org.junit.Before;
import org.junit.Test;
@@ -70,7 +70,7 @@
@Mock private NavigationModeController mMockNavModeController;
@Mock private NotificationShadeWindowController mMockStatusBarWinController;
@Mock private Optional<Pip> mMockPipOptional;
- @Mock private Optional<SplitScreen> mMockSplitScreenOptional;
+ @Mock private Optional<LegacySplitScreen> mMockSplitScreenOptional;
@Mock private Optional<Lazy<StatusBar>> mMockStatusBarOptionalLazy;
@Mock private Optional<com.android.wm.shell.onehanded.OneHanded> mMockOneHandedOptional;
@Mock private PackageManager mPackageManager;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AssistantFeedbackControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AssistantFeedbackControllerTest.java
index fb8c3d9..3f1cf83 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AssistantFeedbackControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AssistantFeedbackControllerTest.java
@@ -25,6 +25,12 @@
import static android.service.notification.NotificationListenerService.Ranking.RANKING_PROMOTED;
import static android.service.notification.NotificationListenerService.Ranking.RANKING_UNCHANGED;
+import static com.android.systemui.statusbar.notification.AssistantFeedbackController.STATUS_DEMOTED;
+import static com.android.systemui.statusbar.notification.AssistantFeedbackController.STATUS_PROMOTED;
+import static com.android.systemui.statusbar.notification.AssistantFeedbackController.STATUS_SILENCED;
+import static com.android.systemui.statusbar.notification.AssistantFeedbackController.STATUS_UNCHANGED;
+
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -40,6 +46,8 @@
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
+import junit.framework.Assert;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -76,28 +84,46 @@
}
@Test
- public void testShowFeedbackIndicator_settingDisabled() {
+ public void testFeedback_settingDisabled() {
switchSetting(OFF);
+ assertEquals(STATUS_UNCHANGED, mAssistantFeedbackController.getFeedbackStatus(
+ getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_DEFAULT, RANKING_UNCHANGED)));
assertFalse(mAssistantFeedbackController.showFeedbackIndicator(
getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_DEFAULT, RANKING_UNCHANGED)));
}
@Test
- public void testShowFeedbackIndicator_changedImportance() {
- assertTrue(mAssistantFeedbackController.showFeedbackIndicator(
- getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_HIGH, RANKING_UNCHANGED)));
- assertTrue(mAssistantFeedbackController.showFeedbackIndicator(
- getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_LOW, RANKING_UNCHANGED)));
- assertTrue(mAssistantFeedbackController.showFeedbackIndicator(
- getEntry(IMPORTANCE_LOW, IMPORTANCE_MIN, RANKING_UNCHANGED)));
+ public void testFeedback_changedImportance() {
+ NotificationEntry entry = getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_HIGH, RANKING_UNCHANGED);
+ assertEquals(STATUS_PROMOTED, mAssistantFeedbackController.getFeedbackStatus(entry));
+ assertTrue(mAssistantFeedbackController.showFeedbackIndicator(entry));
+
+ entry = getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_LOW, RANKING_UNCHANGED);
+ assertEquals(STATUS_SILENCED, mAssistantFeedbackController.getFeedbackStatus(entry));
+ assertTrue(mAssistantFeedbackController.showFeedbackIndicator(entry));
+
+ entry = getEntry(IMPORTANCE_LOW, IMPORTANCE_MIN, RANKING_UNCHANGED);
+ assertEquals(STATUS_DEMOTED, mAssistantFeedbackController.getFeedbackStatus(entry));
+ assertTrue(mAssistantFeedbackController.showFeedbackIndicator(entry));
}
@Test
- public void testShowFeedbackIndicator_changedRanking() {
- assertTrue(mAssistantFeedbackController.showFeedbackIndicator(
- getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_DEFAULT, RANKING_PROMOTED)));
- assertTrue(mAssistantFeedbackController.showFeedbackIndicator(
- getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_DEFAULT, RANKING_DEMOTED)));
+ public void testFeedback_changedRanking() {
+ NotificationEntry entry =
+ getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_DEFAULT, RANKING_PROMOTED);
+ assertEquals(STATUS_PROMOTED, mAssistantFeedbackController.getFeedbackStatus(entry));
+ assertTrue(mAssistantFeedbackController.showFeedbackIndicator(entry));
+
+ entry = getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_DEFAULT, RANKING_DEMOTED);
+ assertEquals(STATUS_DEMOTED, mAssistantFeedbackController.getFeedbackStatus(entry));
+ assertTrue(mAssistantFeedbackController.showFeedbackIndicator(entry));
+ }
+
+ @Test
+ public void testGetFeedbackImageResource_settingDisabled() {
+ switchSetting(OFF);
+ Assert.assertEquals(0, mAssistantFeedbackController.getFeedbackImageResource(
+ getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_DEFAULT, RANKING_UNCHANGED)));
}
private NotificationEntry getEntry(int oldImportance, int newImportance,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java
index 639e791..0954621 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java
@@ -31,7 +31,6 @@
import android.app.Notification;
import android.os.Bundle;
import android.os.UserHandle;
-import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -46,7 +45,6 @@
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner;
-import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;
@@ -71,7 +69,6 @@
private NotificationEntryBuilder mEntryBuilder;
private AppOpsCoordinator mAppOpsCoordinator;
private NotifFilter mForegroundFilter;
- private NotifLifetimeExtender mForegroundNotifLifetimeExtender;
private NotifSectioner mFgsSection;
private FakeSystemClock mClock = new FakeSystemClock();
@@ -98,13 +95,6 @@
verify(mNotifPipeline, times(1)).addPreGroupFilter(filterCaptor.capture());
mForegroundFilter = filterCaptor.getValue();
- // capture lifetime extender
- ArgumentCaptor<NotifLifetimeExtender> lifetimeExtenderCaptor =
- ArgumentCaptor.forClass(NotifLifetimeExtender.class);
- verify(mNotifPipeline, times(1)).addNotificationLifetimeExtender(
- lifetimeExtenderCaptor.capture());
- mForegroundNotifLifetimeExtender = lifetimeExtenderCaptor.getValue();
-
mFgsSection = mAppOpsCoordinator.getSectioner();
}
@@ -160,55 +150,6 @@
}
@Test
- public void extendLifetimeText_notForeground() {
- // GIVEN the notification doesn't represent a foreground service
- mEntryBuilder.modifyNotification(mContext)
- .setFlag(FLAG_FOREGROUND_SERVICE, false);
-
- // THEN don't extend the lifetime
- assertFalse(mForegroundNotifLifetimeExtender
- .shouldExtendLifetime(mEntryBuilder.build(),
- NotificationListenerService.REASON_CLICK));
- }
-
- @Test
- public void extendLifetimeText_foregroundNotifRecentlyPosted() {
- // GIVEN the notification represents a foreground service that was just posted
- Notification notification = new Notification.Builder(mContext, "test_channel")
- .setFlag(FLAG_FOREGROUND_SERVICE, true)
- .build();
- NotificationEntry entry = mEntryBuilder
- .setSbn(new StatusBarNotification(TEST_PKG, TEST_PKG, NOTIF_USER_ID, "",
- NOTIF_USER_ID, NOTIF_USER_ID, notification,
- new UserHandle(NOTIF_USER_ID), "", System.currentTimeMillis()))
- .setNotification(notification)
- .build();
-
- // THEN extend the lifetime
- assertTrue(mForegroundNotifLifetimeExtender
- .shouldExtendLifetime(entry, NotificationListenerService.REASON_CLICK));
- }
-
- @Test
- public void extendLifetimeText_foregroundNotifOld() {
- // GIVEN the notification represents a foreground service that was posted 10 seconds ago
- Notification notification = new Notification.Builder(mContext, "test_channel")
- .setFlag(FLAG_FOREGROUND_SERVICE, true)
- .build();
- NotificationEntry entry = mEntryBuilder
- .setSbn(new StatusBarNotification(TEST_PKG, TEST_PKG, NOTIF_USER_ID, "",
- NOTIF_USER_ID, NOTIF_USER_ID, notification,
- new UserHandle(NOTIF_USER_ID), "",
- System.currentTimeMillis() - 10000))
- .setNotification(notification)
- .build();
-
- // THEN don't extend the lifetime because the extended time exceeds MIN_FGS_TIME_MS
- assertFalse(mForegroundNotifLifetimeExtender
- .shouldExtendLifetime(entry, NotificationListenerService.REASON_CLICK));
- }
-
- @Test
public void testIncludeFGSInSection_importanceDefault() {
// GIVEN the notification represents a colorized foreground service with > min importance
mEntryBuilder
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
index 891179c..ca982a6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
@@ -210,7 +210,7 @@
// public notification is custom layout - no header
mGroupRow.setSensitive(true, true);
mGroupRow.setOnFeedbackClickListener(null);
- mGroupRow.showFeedbackIcon(false);
+ mGroupRow.showFeedbackIcon(false, 0);
}
@Test
@@ -224,11 +224,12 @@
mGroupRow.setChildrenContainer(mockContainer);
final boolean show = true;
- mGroupRow.showFeedbackIcon(show);
+ final int resId = 1;
+ mGroupRow.showFeedbackIcon(show, resId);
- verify(mockContainer, times(1)).showFeedbackIcon(show);
- verify(privateLayout, times(1)).showFeedbackIcon(show);
- verify(publicLayout, times(1)).showFeedbackIcon(show);
+ verify(mockContainer, times(1)).showFeedbackIcon(show, resId);
+ verify(privateLayout, times(1)).showFeedbackIcon(show, resId);
+ verify(publicLayout, times(1)).showFeedbackIcon(show, resId);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java
index 9d87579..53ff957 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java
@@ -17,13 +17,13 @@
package com.android.systemui.statusbar.notification.row;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
-import static android.app.NotificationManager.IMPORTANCE_HIGH;
-import static android.app.NotificationManager.IMPORTANCE_LOW;
-import static android.app.NotificationManager.IMPORTANCE_MIN;
-import static android.service.notification.NotificationListenerService.Ranking.RANKING_DEMOTED;
-import static android.service.notification.NotificationListenerService.Ranking.RANKING_PROMOTED;
import static android.service.notification.NotificationListenerService.Ranking.RANKING_UNCHANGED;
+import static com.android.systemui.statusbar.notification.AssistantFeedbackController.STATUS_ALERTED;
+import static com.android.systemui.statusbar.notification.AssistantFeedbackController.STATUS_DEMOTED;
+import static com.android.systemui.statusbar.notification.AssistantFeedbackController.STATUS_PROMOTED;
+import static com.android.systemui.statusbar.notification.AssistantFeedbackController.STATUS_SILENCED;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
@@ -79,6 +79,8 @@
private final NotificationGuts mGutsParent = mock(NotificationGuts.class);
private final ExpandableNotificationRow mMockNotificationRow =
mock(ExpandableNotificationRow.class);
+ private final AssistantFeedbackController mAssistantFeedbackController =
+ mock(AssistantFeedbackController.class);
private StatusBarNotification mSbn;
@Mock
@@ -120,7 +122,7 @@
public void testBindNotification_SetsTextApplicationName() {
when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(),
- mMockNotificationRow, mock(AssistantFeedbackController.class));
+ mMockNotificationRow, mAssistantFeedbackController);
final TextView textView = mFeedbackInfo.findViewById(R.id.pkg_name);
assertTrue(textView.getText().toString().contains("App Name"));
}
@@ -131,65 +133,60 @@
when(mMockPackageManager.getApplicationIcon(any(ApplicationInfo.class)))
.thenReturn(iconDrawable);
mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(),
- mMockNotificationRow, mock(AssistantFeedbackController.class));
+ mMockNotificationRow, mAssistantFeedbackController);
final ImageView iconView = mFeedbackInfo.findViewById(R.id.pkg_icon);
assertEquals(iconDrawable, iconView.getDrawable());
}
@Test
public void testPrompt_silenced() {
- mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(IMPORTANCE_DEFAULT,
- IMPORTANCE_LOW, RANKING_UNCHANGED), mMockNotificationRow,
- mock(AssistantFeedbackController.class));
+ when(mAssistantFeedbackController.getFeedbackStatus(any(NotificationEntry.class)))
+ .thenReturn(STATUS_SILENCED);
+ mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), mMockNotificationRow,
+ mAssistantFeedbackController);
TextView prompt = mFeedbackInfo.findViewById(R.id.prompt);
- assertEquals("This notification was silenced by the system. Was this correct?",
- prompt.getText());
+ assertEquals("This notification was automatically demoted to Silent by the system. "
+ + "Was this correct?", prompt.getText().toString());
}
@Test
- public void testPrompt_promoted_importance() {
- mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(IMPORTANCE_DEFAULT,
- IMPORTANCE_HIGH, RANKING_UNCHANGED), mMockNotificationRow,
- mock(AssistantFeedbackController.class));
+ public void testPrompt_promoted() {
+ when(mAssistantFeedbackController.getFeedbackStatus(any(NotificationEntry.class)))
+ .thenReturn(STATUS_PROMOTED);
+ mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), mMockNotificationRow,
+ mAssistantFeedbackController);
TextView prompt = mFeedbackInfo.findViewById(R.id.prompt);
- assertEquals("This notification was promoted by the system. Was this correct?",
- prompt.getText());
+ assertEquals("This notification was automatically ranked higher in your shade. "
+ + "Was this correct?", prompt.getText().toString());
}
@Test
- public void testPrompt_promoted_ranking() {
- mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(IMPORTANCE_DEFAULT,
- IMPORTANCE_DEFAULT, RANKING_PROMOTED), mMockNotificationRow,
- mock(AssistantFeedbackController.class));
+ public void testPrompt_alerted() {
+ when(mAssistantFeedbackController.getFeedbackStatus(any(NotificationEntry.class)))
+ .thenReturn(STATUS_ALERTED);
+ mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), mMockNotificationRow,
+ mAssistantFeedbackController);
TextView prompt = mFeedbackInfo.findViewById(R.id.prompt);
- assertEquals("This notification was promoted by the system. Was this correct?",
- prompt.getText());
+ assertEquals("This notification was automatically promoted to Default by the system. "
+ + "Was this correct?",
+ prompt.getText().toString());
}
@Test
- public void testPrompt_demoted_importance() {
- mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(IMPORTANCE_LOW,
- IMPORTANCE_MIN, RANKING_UNCHANGED), mMockNotificationRow,
- mock(AssistantFeedbackController.class));
+ public void testPrompt_demoted() {
+ when(mAssistantFeedbackController.getFeedbackStatus(any(NotificationEntry.class)))
+ .thenReturn(STATUS_DEMOTED);
+ mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), mMockNotificationRow,
+ mAssistantFeedbackController);
TextView prompt = mFeedbackInfo.findViewById(R.id.prompt);
- assertEquals("This notification was demoted by the system. Was this correct?",
- prompt.getText());
- }
-
- @Test
- public void testPrompt_demoted_ranking() {
- mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(IMPORTANCE_DEFAULT,
- IMPORTANCE_DEFAULT, RANKING_DEMOTED), mMockNotificationRow,
- mock(AssistantFeedbackController.class));
- TextView prompt = mFeedbackInfo.findViewById(R.id.prompt);
- assertEquals("This notification was demoted by the system. Was this correct?",
- prompt.getText());
+ assertEquals("This notification was automatically ranked lower in your shade. "
+ + "Was this correct?", prompt.getText().toString());
}
@Test
public void testPositiveFeedback() {
mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), mMockNotificationRow,
- mock(AssistantFeedbackController.class));
+ mAssistantFeedbackController);
final View yes = mFeedbackInfo.findViewById(R.id.yes);
yes.performClick();
@@ -206,7 +203,7 @@
.thenReturn(true);
mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), mMockNotificationRow,
- mock(AssistantFeedbackController.class));
+ mAssistantFeedbackController);
final View no = mFeedbackInfo.findViewById(R.id.no);
no.performClick();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java
index 2101ea1..377a69d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java
@@ -95,7 +95,7 @@
mView.setExpandedChild(mockExpanded);
mView.setHeadsUpChild(mockHeadsUp);
- mView.showFeedbackIcon(true);
+ mView.showFeedbackIcon(true, 1);
verify(mockContracted, times(1)).setVisibility(View.VISIBLE);
verify(mockExpanded, times(1)).setVisibility(View.VISIBLE);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
index 3000b8b..458a058 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -374,7 +374,7 @@
eq(false),
eq(false),
eq(true), /* wasShownHighPriority */
- eq(false) /* showAutomaticSetting */);
+ eq(mAssistantFeedbackController));
}
@Test
@@ -408,7 +408,7 @@
eq(true),
eq(false),
eq(false), /* wasShownHighPriority */
- eq(false) /* showAutomaticSetting */);
+ eq(mAssistantFeedbackController));
}
@Test
@@ -440,7 +440,7 @@
eq(false),
eq(false),
eq(false), /* wasShownHighPriority */
- eq(false) /* showAutomaticSetting */);
+ eq(mAssistantFeedbackController));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
index 4a2cbcc..324f0ac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
@@ -64,6 +64,7 @@
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.notification.AssistantFeedbackController;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
@@ -113,6 +114,8 @@
private OnUserInteractionCallback mOnUserInteractionCallback;
@Mock
private ChannelEditorDialogController mChannelEditorDialogController;
+ @Mock
+ private AssistantFeedbackController mAssistantFeedbackController;
@Before
public void setUp() throws Exception {
@@ -160,6 +163,9 @@
mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0,
new Notification(), UserHandle.CURRENT, null, 0);
mEntry = new NotificationEntryBuilder().setSbn(mSbn).build();
+ when(mAssistantFeedbackController.isFeedbackEnabled()).thenReturn(false);
+ when(mAssistantFeedbackController.getInlineDescriptionResource(any()))
+ .thenReturn(R.string.notification_channel_summary_automatic);
}
@Test
@@ -180,7 +186,7 @@
true,
false,
true,
- false);
+ mAssistantFeedbackController);
final TextView textView = mNotificationInfo.findViewById(R.id.pkg_name);
assertTrue(textView.getText().toString().contains("App Name"));
assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.header).getVisibility());
@@ -206,7 +212,7 @@
true,
false,
true,
- false);
+ mAssistantFeedbackController);
final ImageView iconView = mNotificationInfo.findViewById(R.id.pkg_icon);
assertEquals(iconDrawable, iconView.getDrawable());
}
@@ -228,7 +234,7 @@
true,
false,
true,
- false);
+ mAssistantFeedbackController);
final TextView nameView = mNotificationInfo.findViewById(R.id.delegate_name);
assertEquals(GONE, nameView.getVisibility());
}
@@ -259,7 +265,7 @@
true,
false,
true,
- false);
+ mAssistantFeedbackController);
final TextView nameView = mNotificationInfo.findViewById(R.id.delegate_name);
assertEquals(VISIBLE, nameView.getVisibility());
assertTrue(nameView.getText().toString().contains("Proxied"));
@@ -282,7 +288,7 @@
true,
false,
true,
- false);
+ mAssistantFeedbackController);
final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name);
assertEquals(GONE, groupNameView.getVisibility());
}
@@ -310,7 +316,7 @@
true,
false,
true,
- false);
+ mAssistantFeedbackController);
final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name);
assertEquals(View.VISIBLE, groupNameView.getVisibility());
assertEquals("Test Group Name", groupNameView.getText());
@@ -333,7 +339,7 @@
true,
false,
true,
- false);
+ mAssistantFeedbackController);
final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(TEST_CHANNEL_NAME, textView.getText());
}
@@ -355,7 +361,7 @@
true,
false,
true,
- false);
+ mAssistantFeedbackController);
final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(GONE, textView.getVisibility());
}
@@ -381,7 +387,7 @@
true,
false,
true,
- false);
+ mAssistantFeedbackController);
final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(VISIBLE, textView.getVisibility());
}
@@ -403,7 +409,7 @@
true,
true,
true,
- false);
+ mAssistantFeedbackController);
final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(VISIBLE, textView.getVisibility());
}
@@ -429,7 +435,7 @@
true,
false,
true,
- false);
+ mAssistantFeedbackController);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
settingsButton.performClick();
@@ -454,7 +460,7 @@
true,
false,
true,
- false);
+ mAssistantFeedbackController);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
assertTrue(settingsButton.getVisibility() != View.VISIBLE);
}
@@ -479,7 +485,7 @@
false,
false,
true,
- false);
+ mAssistantFeedbackController);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
assertTrue(settingsButton.getVisibility() != View.VISIBLE);
}
@@ -501,7 +507,7 @@
true,
false,
true,
- false);
+ mAssistantFeedbackController);
mNotificationInfo.bindNotification(
mMockPackageManager,
mMockINotificationManager,
@@ -517,7 +523,7 @@
true,
false,
true,
- false);
+ mAssistantFeedbackController);
final View settingsButton = mNotificationInfo.findViewById(R.id.info);
assertEquals(View.VISIBLE, settingsButton.getVisibility());
}
@@ -542,7 +548,7 @@
true,
true,
true,
- false);
+ mAssistantFeedbackController);
mNotificationInfo.findViewById(R.id.info).performClick();
// Verify that listener was triggered.
@@ -568,7 +574,7 @@
true,
false,
true,
- false);
+ mAssistantFeedbackController);
final TextView channelNameView =
mNotificationInfo.findViewById(R.id.channel_name);
assertEquals(GONE, channelNameView.getVisibility());
@@ -592,7 +598,7 @@
true,
false,
true,
- false);
+ mAssistantFeedbackController);
assertEquals(GONE, mNotificationInfo.findViewById(
R.id.interruptiveness_settings).getVisibility());
assertEquals(VISIBLE, mNotificationInfo.findViewById(
@@ -616,7 +622,7 @@
true,
true,
true,
- false);
+ mAssistantFeedbackController);
final TextView view = mNotificationInfo.findViewById(R.id.non_configurable_text);
assertEquals(View.VISIBLE, view.getVisibility());
assertEquals(mContext.getString(R.string.notification_unblockable_desc),
@@ -627,6 +633,7 @@
@Test
public void testBindNotification_automaticIsVisible() throws Exception {
+ when(mAssistantFeedbackController.isFeedbackEnabled()).thenReturn(true);
mNotificationInfo.bindNotification(
mMockPackageManager,
mMockINotificationManager,
@@ -642,7 +649,7 @@
true,
false,
true,
- true);
+ mAssistantFeedbackController);
assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.automatic).getVisibility());
assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.automatic_summary).getVisibility());
}
@@ -664,13 +671,14 @@
true,
false,
true,
- false);
+ mAssistantFeedbackController);
assertEquals(GONE, mNotificationInfo.findViewById(R.id.automatic).getVisibility());
assertEquals(GONE, mNotificationInfo.findViewById(R.id.automatic_summary).getVisibility());
}
@Test
public void testBindNotification_automaticIsSelected() throws Exception {
+ when(mAssistantFeedbackController.isFeedbackEnabled()).thenReturn(true);
mNotificationChannel.unlockFields(USER_LOCKED_IMPORTANCE);
mNotificationInfo.bindNotification(
mMockPackageManager,
@@ -687,7 +695,7 @@
true,
false,
true,
- true);
+ mAssistantFeedbackController);
assertTrue(mNotificationInfo.findViewById(R.id.automatic).isSelected());
}
@@ -708,7 +716,7 @@
true,
false,
true,
- false);
+ mAssistantFeedbackController);
assertTrue(mNotificationInfo.findViewById(R.id.alert).isSelected());
}
@@ -729,7 +737,7 @@
true,
false,
false,
- false);
+ mAssistantFeedbackController);
assertTrue(mNotificationInfo.findViewById(R.id.silence).isSelected());
}
@@ -750,7 +758,7 @@
true,
false,
true,
- false);
+ mAssistantFeedbackController);
mTestableLooper.processAllMessages();
verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
anyString(), eq(TEST_UID), any());
@@ -773,7 +781,7 @@
true,
false,
true,
- false);
+ mAssistantFeedbackController);
assertEquals(1, mUiEventLogger.numLogs());
assertEquals(NotificationControlsEvent.NOTIFICATION_CONTROLS_OPEN.getId(),
mUiEventLogger.eventId(0));
@@ -797,7 +805,7 @@
true,
false,
false,
- false);
+ mAssistantFeedbackController);
mNotificationInfo.findViewById(R.id.alert).performClick();
mTestableLooper.processAllMessages();
@@ -824,7 +832,7 @@
true,
false,
true,
- false);
+ mAssistantFeedbackController);
mNotificationInfo.findViewById(R.id.silence).performClick();
mTestableLooper.processAllMessages();
@@ -851,7 +859,7 @@
true,
false,
true,
- false);
+ mAssistantFeedbackController);
mNotificationInfo.findViewById(R.id.automatic).performClick();
mTestableLooper.processAllMessages();
@@ -862,6 +870,7 @@
@Test
public void testHandleCloseControls_persistAutomatic()
throws Exception {
+ when(mAssistantFeedbackController.isFeedbackEnabled()).thenReturn(true);
mNotificationChannel.unlockFields(USER_LOCKED_IMPORTANCE);
mNotificationInfo.bindNotification(
mMockPackageManager,
@@ -878,7 +887,7 @@
true,
false,
true,
- true);
+ mAssistantFeedbackController);
mNotificationInfo.handleCloseControls(true, false);
mTestableLooper.processAllMessages();
@@ -905,7 +914,7 @@
true,
false,
true,
- false);
+ mAssistantFeedbackController);
mNotificationInfo.handleCloseControls(true, false);
mTestableLooper.processAllMessages();
@@ -940,7 +949,7 @@
true,
false,
true,
- false);
+ mAssistantFeedbackController);
mNotificationInfo.handleCloseControls(true, false);
@@ -968,7 +977,7 @@
true,
false,
true,
- false);
+ mAssistantFeedbackController);
mNotificationInfo.findViewById(R.id.silence).performClick();
mNotificationInfo.findViewById(R.id.done).performClick();
@@ -1008,7 +1017,7 @@
true,
false,
false,
- false);
+ mAssistantFeedbackController);
mNotificationInfo.findViewById(R.id.alert).performClick();
mNotificationInfo.findViewById(R.id.done).performClick();
@@ -1026,6 +1035,7 @@
@Test
public void testAutomaticUnlocksUserImportance() throws Exception {
+ when(mAssistantFeedbackController.isFeedbackEnabled()).thenReturn(true);
mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
mNotificationChannel.lockFields(USER_LOCKED_IMPORTANCE);
mNotificationInfo.bindNotification(
@@ -1043,7 +1053,7 @@
true,
false,
true,
- true);
+ mAssistantFeedbackController);
mNotificationInfo.findViewById(R.id.automatic).performClick();
mNotificationInfo.findViewById(R.id.done).performClick();
@@ -1074,7 +1084,7 @@
true,
false,
true,
- false);
+ mAssistantFeedbackController);
mNotificationInfo.findViewById(R.id.silence).performClick();
mNotificationInfo.findViewById(R.id.done).performClick();
@@ -1109,7 +1119,7 @@
true,
false,
false,
- false);
+ mAssistantFeedbackController);
assertEquals(mContext.getString(R.string.inline_done_button),
((TextView) mNotificationInfo.findViewById(R.id.done)).getText());
@@ -1147,7 +1157,7 @@
true,
false,
false,
- false);
+ mAssistantFeedbackController);
assertEquals(mContext.getString(R.string.inline_done_button),
((TextView) mNotificationInfo.findViewById(R.id.done)).getText());
@@ -1184,7 +1194,7 @@
true,
false,
true,
- false);
+ mAssistantFeedbackController);
mNotificationInfo.findViewById(R.id.silence).performClick();
mNotificationInfo.findViewById(R.id.done).performClick();
@@ -1212,7 +1222,7 @@
true,
false,
false,
- false);
+ mAssistantFeedbackController);
assertEquals(mContext.getString(R.string.inline_done_button),
((TextView) mNotificationInfo.findViewById(R.id.done)).getText());
@@ -1243,7 +1253,7 @@
true,
false,
false,
- false);
+ mAssistantFeedbackController);
mNotificationInfo.findViewById(R.id.alert).performClick();
mNotificationInfo.findViewById(R.id.done).performClick();
@@ -1277,7 +1287,7 @@
true,
false,
false,
- false);
+ mAssistantFeedbackController);
mNotificationInfo.findViewById(R.id.alert).performClick();
mNotificationInfo.findViewById(R.id.done).performClick();
@@ -1310,7 +1320,7 @@
true,
false,
false,
- false);
+ mAssistantFeedbackController);
mNotificationInfo.findViewById(R.id.alert).performClick();
mNotificationInfo.findViewById(R.id.done).performClick();
@@ -1343,7 +1353,7 @@
true,
false,
false,
- false);
+ mAssistantFeedbackController);
mNotificationInfo.findViewById(R.id.alert).performClick();
@@ -1369,7 +1379,7 @@
true,
false,
false,
- false);
+ mAssistantFeedbackController);
assertFalse(mNotificationInfo.willBeRemoved());
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 6fb4eba..8e84f1a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -148,7 +148,7 @@
import com.android.systemui.volume.VolumeComponent;
import com.android.systemui.wmshell.BubblesManager;
import com.android.wm.shell.bubbles.Bubbles;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import org.junit.Before;
import org.junit.Ignore;
@@ -245,7 +245,7 @@
@Mock private StatusBarComponent.Builder mStatusBarComponentBuilder;
@Mock private StatusBarComponent mStatusBarComponent;
@Mock private PluginManager mPluginManager;
- @Mock private SplitScreen mSplitScreen;
+ @Mock private LegacySplitScreen mLegacySplitScreen;
@Mock private SuperStatusBarViewFactory mSuperStatusBarViewFactory;
@Mock private LightsOutNotifController mLightsOutNotifController;
@Mock private ViewMediatorCallback mViewMediatorCallback;
@@ -405,7 +405,7 @@
mCommandQueue,
mStatusBarComponentBuilderProvider,
mPluginManager,
- Optional.of(mSplitScreen),
+ Optional.of(mLegacySplitScreen),
mLightsOutNotifController,
mStatusBarNotificationActivityStarterBuilder,
mShadeController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
index 18e7840..ebc45f4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
@@ -26,7 +26,8 @@
import androidx.test.runner.AndroidJUnit4;
-import com.android.systemui.R;
+import com.android.settingslib.R;
+import com.android.settingslib.mobile.TelephonyIcons;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.policy.NetworkController.EmergencyListener;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index ce9ca9d..6adf94e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -60,17 +60,18 @@
import androidx.test.InstrumentationRegistry;
+import com.android.settingslib.R;
import com.android.settingslib.graph.SignalDrawable;
+import com.android.settingslib.mobile.MobileMappings.Config;
import com.android.settingslib.mobile.MobileStatusTracker.SubscriptionDefaults;
+import com.android.settingslib.mobile.TelephonyIcons;
import com.android.settingslib.net.DataUsageController;
-import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.demomode.DemoModeController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
-import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
import org.junit.Before;
import org.junit.Rule;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
index 6899217..d11aee8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
@@ -19,6 +19,7 @@
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
+import com.android.settingslib.mobile.TelephonyIcons;
import com.android.settingslib.net.DataUsageController;
import org.junit.Test;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
index 61f71b7..da35de9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
@@ -38,6 +38,7 @@
import android.testing.TestableLooper.RunWithLooper;
import com.android.settingslib.graph.SignalDrawable;
+import com.android.settingslib.mobile.TelephonyIcons;
import com.android.settingslib.net.DataUsageController;
import com.android.systemui.R;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
index ef25b73..73d87b0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
@@ -40,7 +40,7 @@
import com.android.wm.shell.onehanded.OneHandedTransitionCallback;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.pip.phone.PipTouchHandler;
-import com.android.wm.shell.splitscreen.SplitScreen;
+import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import org.junit.Before;
import org.junit.Test;
@@ -63,7 +63,8 @@
@Mock SysUiState mSysUiState;
@Mock Pip mPip;
@Mock PipTouchHandler mPipTouchHandler;
- @Mock SplitScreen mSplitScreen;
+ @Mock
+ LegacySplitScreen mLegacySplitScreen;
@Mock OneHanded mOneHanded;
@Mock HideDisplayCutout mHideDisplayCutout;
@Mock ProtoTracer mProtoTracer;
@@ -75,7 +76,7 @@
mWMShell = new WMShell(mContext, mCommandQueue, mConfigurationController,
mKeyguardUpdateMonitor, mNavigationModeController,
- mScreenLifecycle, mSysUiState, Optional.of(mPip), Optional.of(mSplitScreen),
+ mScreenLifecycle, mSysUiState, Optional.of(mPip), Optional.of(mLegacySplitScreen),
Optional.of(mOneHanded), Optional.of(mHideDisplayCutout), mProtoTracer,
Optional.of(mShellCommandHandler));
@@ -91,7 +92,7 @@
@Test
public void initSplitScreen_registersCallbacks() {
- mWMShell.initSplitScreen(mSplitScreen);
+ mWMShell.initSplitScreen(mLegacySplitScreen);
verify(mKeyguardUpdateMonitor).registerCallback(any(KeyguardUpdateMonitorCallback.class));
}
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
index b397782..e1af2c4 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
@@ -349,7 +349,7 @@
AccessibilityService.GESTURE_DOUBLE_TAP_AND_HOLD,
event.getDisplayId(),
mGestureDetector.getMotionEvents());
- mAms.onGesture(gestureEvent);
+ dispatchGesture(gestureEvent);
}
mState.startDelegating();
}
@@ -367,7 +367,7 @@
AccessibilityService.GESTURE_DOUBLE_TAP,
event.getDisplayId(),
mGestureDetector.getMotionEvents());
- mAms.onGesture(gestureEvent);
+ dispatchGesture(gestureEvent);
}
if (mSendTouchExplorationEndDelayed.isPending()) {
mSendTouchExplorationEndDelayed.forceSendAndRemove();
@@ -402,13 +402,9 @@
@Override
public boolean onGestureCompleted(AccessibilityGestureEvent gestureEvent) {
- if (DEBUG) {
- Slog.d(LOG_TAG, "Dispatching gesture event:" + gestureEvent.toString());
- }
endGestureDetection(true);
mSendTouchInteractionEndDelayed.cancel();
- mAms.onGesture(gestureEvent);
-
+ dispatchGesture(gestureEvent);
return true;
}
@@ -444,10 +440,7 @@
AccessibilityService.GESTURE_UNKNOWN,
event.getDisplayId(),
mGestureDetector.getMotionEvents());
- if (DEBUG) {
- Slog.d(LOG_TAG, "Dispatching gesture event:" + gestureEvent.toString());
- }
- mAms.onGesture(gestureEvent);
+ dispatchGesture(gestureEvent);
}
return false;
}
@@ -658,7 +651,7 @@
AccessibilityService.GESTURE_PASSTHROUGH,
event.getDisplayId(),
mGestureDetector.getMotionEvents());
- mAms.onGesture(gestureEvent);
+ dispatchGesture(gestureEvent);
}
computeDraggingPointerIdIfNeeded(event);
pointerIdBits = 1 << mDraggingPointerId;
@@ -682,7 +675,7 @@
AccessibilityService.GESTURE_PASSTHROUGH,
event.getDisplayId(),
mGestureDetector.getMotionEvents());
- mAms.onGesture(gestureEvent);
+ dispatchGesture(gestureEvent);
}
mState.startDelegating();
mDispatcher.sendDownForAllNotInjectedPointers(event, policyFlags);
@@ -704,7 +697,7 @@
AccessibilityService.GESTURE_PASSTHROUGH,
event.getDisplayId(),
mGestureDetector.getMotionEvents());
- mAms.onGesture(gestureEvent);
+ dispatchGesture(gestureEvent);
}
mState.startDelegating();
if (mState.isTouchExploring()) {
@@ -725,7 +718,7 @@
AccessibilityService.GESTURE_PASSTHROUGH,
event.getDisplayId(),
mGestureDetector.getMotionEvents());
- mAms.onGesture(gestureEvent);
+ dispatchGesture(gestureEvent);
}
mState.startDelegating();
event = MotionEvent.obtainNoHistory(event);
@@ -1304,7 +1297,7 @@
AccessibilityService.GESTURE_TOUCH_EXPLORATION,
mState.getLastReceivedEvent().getDisplayId(),
mGestureDetector.getMotionEvents());
- mAms.onGesture(gestureEvent);
+ dispatchGesture(gestureEvent);
}
if (!mEvents.isEmpty() && !mRawEvents.isEmpty()) {
// Deliver a down event.
@@ -1439,6 +1432,13 @@
}
}
+ private void dispatchGesture(AccessibilityGestureEvent gestureEvent) {
+ if (DEBUG) {
+ Slog.d(LOG_TAG, "Dispatching gesture event:" + gestureEvent.toString());
+ }
+ mAms.onGesture(gestureEvent);
+ }
+
@Override
public String toString() {
return "TouchExplorer { "
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 9d8901a..c7fd209 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -422,12 +422,15 @@
@GuardedBy("mLock")
private FillRequest mPendingFillRequest;
- @Nullable Consumer<InlineSuggestionsRequest> newAutofillRequestLocked(ViewState viewState,
- boolean isInlineRequest) {
+ void newAutofillRequestLocked(boolean isInlineRequest) {
mPendingFillRequest = null;
mWaitForInlineRequest = isInlineRequest;
mPendingInlineSuggestionsRequest = null;
- return isInlineRequest ? (inlineSuggestionsRequest) -> {
+ }
+
+ @NonNull Consumer<InlineSuggestionsRequest> newInlineRequestConsumerLocked(
+ ViewState viewState) {
+ return (inlineSuggestionsRequest) -> {
synchronized (mLock) {
if (!mWaitForInlineRequest || mPendingInlineSuggestionsRequest != null) {
return;
@@ -436,7 +439,7 @@
maybeRequestFillLocked();
viewState.resetState(ViewState.STATE_PENDING_CREATE_INLINE_REQUEST);
}
- } : null;
+ };
}
void maybeRequestFillLocked() {
@@ -808,32 +811,12 @@
// structure is taken. This causes only one fill request per burst of focus changes.
cancelCurrentRequestLocked();
- // Only ask IME to create inline suggestions request if Autofill provider supports it and
- // the render service is available except the autofill is triggered manually and the view
- // is also not focused.
- final RemoteInlineSuggestionRenderService remoteRenderService =
- mService.getRemoteInlineSuggestionRenderServiceLocked();
- if (mSessionFlags.mInlineSupportedByService
- && remoteRenderService != null
- && isViewFocusedLocked(flags)) {
- Consumer<InlineSuggestionsRequest> inlineSuggestionsRequestConsumer =
- mAssistReceiver.newAutofillRequestLocked(viewState,
- /* isInlineRequest= */ true);
- if (inlineSuggestionsRequestConsumer != null) {
- final AutofillId focusedId = mCurrentViewId;
- remoteRenderService.getInlineSuggestionsRendererInfo(
- new RemoteCallback((extras) -> {
- synchronized (mLock) {
- mInlineSessionController.onCreateInlineSuggestionsRequestLocked(
- focusedId, inlineSuggestionsRequestConsumer, extras);
- }
- }, mHandler)
- );
- viewState.setState(ViewState.STATE_PENDING_CREATE_INLINE_REQUEST);
- }
- } else {
- mAssistReceiver.newAutofillRequestLocked(viewState, /* isInlineRequest= */ false);
- }
+ final Consumer<InlineSuggestionsRequest> inlineSuggestionsRequestConsumer =
+ mAssistReceiver.newInlineRequestConsumerLocked(viewState);
+ final boolean isInlineRequest = maybeRequestCreateInlineSuggestionsRequestLocked(
+ /* isAugmented= */ false, inlineSuggestionsRequestConsumer, viewState,
+ mCurrentViewId, flags);
+ mAssistReceiver.newAutofillRequestLocked(isInlineRequest);
// Now request the assist structure data.
try {
@@ -853,6 +836,60 @@
}
}
+ @GuardedBy("mLock")
+ private boolean maybeRequestCreateInlineSuggestionsRequestLocked(boolean isAugmented,
+ @NonNull Consumer<InlineSuggestionsRequest> requestConsumer,
+ @NonNull ViewState viewState, @NonNull AutofillId focusedId, int flags) {
+ final RemoteInlineSuggestionRenderService remoteRenderService =
+ mService.getRemoteInlineSuggestionRenderServiceLocked();
+ if (remoteRenderService == null || !isViewFocusedLocked(flags)) {
+ return false;
+ }
+
+ // Standard:
+ // Only ask IME to create inline suggestions request if Autofill provider supports it
+ // and the render service is available except the autofill is triggered manually and the
+ // view is also not focused.
+ //
+ // Augmented:
+ // When the inline suggestion render service is available and the view is focused, there
+ // are 3 cases when augmented autofill should ask IME for inline suggestion request,
+ // because standard autofill flow didn't:
+ // 1. the field is augmented autofill only (when standard autofill provider is None or
+ // when it returns null response)
+ // 2. standard autofill provider doesn't support inline suggestion
+ // 3. we re-entered the autofill session and standard autofill was not re-triggered,
+ // this is recognized by seeing mExpiredResponse == true
+ if ((!isAugmented && mSessionFlags.mInlineSupportedByService)
+ || (isAugmented && (mSessionFlags.mAugmentedAutofillOnly
+ || !mSessionFlags.mInlineSupportedByService
+ || mSessionFlags.mExpiredResponse))) {
+ if (sDebug) {
+ Slog.d(TAG, "Create inline request for "
+ + (isAugmented ? "augmented" : "standard") + " autofill");
+ }
+ requestCreateInlineSuggestionsRequestLocked(remoteRenderService, focusedId,
+ requestConsumer);
+ viewState.setState(ViewState.STATE_PENDING_CREATE_INLINE_REQUEST);
+ return true;
+ }
+
+ return false;
+ }
+
+ private void requestCreateInlineSuggestionsRequestLocked(
+ @NonNull RemoteInlineSuggestionRenderService remoteRenderService,
+ @NonNull AutofillId focusedId,
+ @NonNull Consumer<InlineSuggestionsRequest> requestConsumer) {
+ remoteRenderService.getInlineSuggestionsRendererInfo(
+ new RemoteCallback((extras) -> {
+ synchronized (mLock) {
+ mInlineSessionController.onCreateInlineSuggestionsRequestLocked(
+ focusedId, requestConsumer, extras);
+ }
+ }, mHandler));
+ }
+
Session(@NonNull AutofillManagerServiceImpl service, @NonNull AutoFillUI ui,
@NonNull Context context, @NonNull Handler handler, int userId, @NonNull Object lock,
int sessionId, int taskId, int uid, @NonNull IBinder activityToken,
@@ -2570,23 +2607,27 @@
}
/**
- * Starts (if necessary) a new fill request upon entering a view.
+ * Invokes either regular or augmented autofill process upon entering a view.
*
- * <p>A new request will be started in 2 scenarios:
+ * <p> A new standard autofill request will be started in 2 scenarios:
* <ol>
- * <li>If the user manually requested autofill.
- * <li>If the view is part of a new partition.
+ * <li> If the user manually requested autofill.
+ * <li> If the view is part of a new partition.
* </ol>
+ * </p>
+ *
+ * <p> A new augmented autofill request will be started if the autofill id was marked as
+ * uninterested/unfillable by the standard service.
*
* @param id The id of the view that is entered.
* @param viewState The view that is entered.
* @param flags The flag that was passed by the AutofillManager.
*
- * @return {@code true} if a new fill response is requested.
+ * @return {@code true} if either regular or augmented autofill is invoked.
*/
@GuardedBy("mLock")
- private boolean requestNewFillResponseOnViewEnteredIfNecessaryLocked(@NonNull AutofillId id,
- @NonNull ViewState viewState, int flags) {
+ private boolean maybeRequestFillOnViewEnteredLocked(@NonNull AutofillId id,
+ @NonNull ViewState viewState, boolean isSameViewEntered, int flags) {
if ((flags & FLAG_MANUAL_REQUEST) != 0) {
mSessionFlags.mAugmentedAutofillOnly = false;
if (sDebug) Slog.d(TAG, "Re-starting session on view " + id + " and flags " + flags);
@@ -2594,7 +2635,24 @@
return true;
}
- // If it's not, then check if it it should start a partition.
+ if (mAugmentedAutofillableIds != null && mAugmentedAutofillableIds.contains(id)) {
+ // Regular autofill handled the view and returned null response, but it can trigger
+ // augmented autofill.
+ if (!isSameViewEntered) {
+ if (sDebug) Slog.d(TAG, "trigger augmented autofill.");
+ triggerAugmentedAutofillLocked(flags);
+ } else {
+ if (sDebug) Slog.d(TAG, "skip augmented autofill for same view.");
+ }
+ return true;
+ } else if (mSessionFlags.mAugmentedAutofillOnly && isSameViewEntered) {
+ // Regular autofill is disabled.
+ if (sDebug) Slog.d(TAG, "skip augmented autofill for same view.");
+ return true;
+ }
+
+ // If it's not for augmented, then check if it should start a partition for
+ // regular autofill.
if (shouldStartNewPartitionLocked(id)) {
if (sDebug) {
Slog.d(TAG, "Starting partition or augmented request for view id " + id + ": "
@@ -2789,27 +2847,7 @@
return;
}
- if ((flags & FLAG_MANUAL_REQUEST) == 0) {
- // Not a manual request
- if (mAugmentedAutofillableIds != null && mAugmentedAutofillableIds.contains(
- id)) {
- // Regular autofill handled the view and returned null response, but it
- // triggered augmented autofill
- if (!isSameViewEntered) {
- if (sDebug) Slog.d(TAG, "trigger augmented autofill.");
- triggerAugmentedAutofillLocked(flags);
- } else {
- if (sDebug) Slog.d(TAG, "skip augmented autofill for same view.");
- }
- return;
- } else if (mSessionFlags.mAugmentedAutofillOnly && isSameViewEntered) {
- // Regular autofill is disabled.
- if (sDebug) Slog.d(TAG, "skip augmented autofill for same view.");
- return;
- }
- }
-
- if (requestNewFillResponseOnViewEnteredIfNecessaryLocked(id, viewState, flags)) {
+ if (maybeRequestFillOnViewEnteredLocked(id, viewState, isSameViewEntered, flags)) {
return;
}
@@ -3407,34 +3445,12 @@
}
};
- // When the inline suggestion render service is available and the view is focused, there
- // are 3 cases when augmented autofill should ask IME for inline suggestion request,
- // because standard autofill flow didn't:
- // 1. the field is augmented autofill only (when standard autofill provider is None or
- // when it returns null response)
- // 2. standard autofill provider doesn't support inline suggestion
- // 3. we re-entered the autofill session and standard autofill was not re-triggered, this is
- // recognized by seeing mExpiredResponse == true
- final RemoteInlineSuggestionRenderService remoteRenderService =
- mService.getRemoteInlineSuggestionRenderServiceLocked();
- if (remoteRenderService != null
- && (mSessionFlags.mAugmentedAutofillOnly
- || !mSessionFlags.mInlineSupportedByService
- || mSessionFlags.mExpiredResponse)
- && isViewFocusedLocked(flags)) {
- if (sDebug) Slog.d(TAG, "Create inline request for augmented autofill");
- remoteRenderService.getInlineSuggestionsRendererInfo(new RemoteCallback(
- (extras) -> {
- synchronized (mLock) {
- mInlineSessionController.onCreateInlineSuggestionsRequestLocked(
- focusedId, /*requestConsumer=*/ requestAugmentedAutofill,
- extras);
- }
- }, mHandler));
- } else {
+ if (!maybeRequestCreateInlineSuggestionsRequestLocked(/* isAugmented= */ true,
+ requestAugmentedAutofill, viewState, focusedId, flags)) {
requestAugmentedAutofill.accept(
mInlineSessionController.getInlineSuggestionsRequestLocked().orElse(null));
}
+
if (mAugmentedAutofillDestroyer == null) {
mAugmentedAutofillDestroyer = remoteService::onDestroyAutofillWindowsRequest;
}
diff --git a/services/autofill/java/com/android/server/autofill/TEST_MAPPING b/services/autofill/java/com/android/server/autofill/TEST_MAPPING
index cf058ad..d8a6917 100644
--- a/services/autofill/java/com/android/server/autofill/TEST_MAPPING
+++ b/services/autofill/java/com/android/server/autofill/TEST_MAPPING
@@ -1,5 +1,5 @@
{
- "presubmit": [
+ "presubmit-large": [
{
"name": "CtsAutoFillServiceTestCases",
"options": [
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index d363738..55c1e08 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -113,7 +113,6 @@
import android.net.NetworkMonitorManager;
import android.net.NetworkPolicyManager;
import android.net.NetworkProvider;
-import android.net.NetworkQuotaInfo;
import android.net.NetworkRequest;
import android.net.NetworkSpecifier;
import android.net.NetworkStack;
@@ -1781,14 +1780,6 @@
}
@Override
- @Deprecated
- public NetworkQuotaInfo getActiveNetworkQuotaInfo() {
- Log.w(TAG, "Shame on UID " + Binder.getCallingUid()
- + " for calling the hidden API getNetworkQuotaInfo(). Shame!");
- return new NetworkQuotaInfo();
- }
-
- @Override
public boolean isActiveNetworkMetered() {
enforceAccessPermission();
@@ -2823,6 +2814,7 @@
break;
}
case NetworkAgent.EVENT_UNDERLYING_NETWORKS_CHANGED: {
+ // TODO: prevent loops, e.g., if a network declares itself as underlying.
if (!nai.supportsUnderlyingNetworks()) {
Log.wtf(TAG, "Non-virtual networks cannot have underlying networks");
break;
@@ -3422,6 +3414,7 @@
}
}
nai.clearLingerState();
+ propagateUnderlyingNetworkCapabilities(nai.network);
if (nai.isSatisfyingRequest(mDefaultRequest.requestId)) {
mDefaultNetworkNai = null;
updateDataActivityTracking(null /* newNetwork */, nai);
@@ -3429,9 +3422,6 @@
ensureNetworkTransitionWakelock(nai.toShortString());
}
mLegacyTypeTracker.remove(nai, wasDefault);
- if (!nai.networkCapabilities.hasTransport(TRANSPORT_VPN)) {
- propagateUnderlyingNetworkCapabilities();
- }
rematchAllNetworksAndRequests();
mLingerMonitor.noteDisconnect(nai);
if (nai.created) {
@@ -4820,17 +4810,35 @@
}
}
+ private Network[] underlyingNetworksOrDefault(Network[] underlyingNetworks) {
+ final Network defaultNetwork = getNetwork(getDefaultNetwork());
+ if (underlyingNetworks == null && defaultNetwork != null) {
+ // null underlying networks means to track the default.
+ underlyingNetworks = new Network[] { defaultNetwork };
+ }
+ return underlyingNetworks;
+ }
+
+ // Returns true iff |network| is an underlying network of |nai|.
+ private boolean hasUnderlyingNetwork(NetworkAgentInfo nai, Network network) {
+ // TODO: support more than one level of underlying networks, either via a fixed-depth search
+ // (e.g., 2 levels of underlying networks), or via loop detection, or....
+ if (!nai.supportsUnderlyingNetworks()) return false;
+ final Network[] underlying = underlyingNetworksOrDefault(nai.declaredUnderlyingNetworks);
+ return ArrayUtils.contains(underlying, network);
+ }
+
/**
- * Ask all networks with underlying networks to recompute and update their capabilities.
+ * Recompute the capabilities for any networks that had a specific network as underlying.
*
* 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 propagateUnderlyingNetworkCapabilities() {
+ private void propagateUnderlyingNetworkCapabilities(Network updatedNetwork) {
ensureRunningOnConnectivityServiceThread();
for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
- if (nai.supportsUnderlyingNetworks()) {
+ if (updatedNetwork == null || hasUnderlyingNetwork(nai, updatedNetwork)) {
updateCapabilitiesForNetwork(nai);
}
}
@@ -6369,27 +6377,28 @@
* This method should never alter the agent's NetworkCapabilities, only store data in |nai|.
*/
private void processCapabilitiesFromAgent(NetworkAgentInfo nai, NetworkCapabilities nc) {
- nai.declaredMetered = !nc.hasCapability(NET_CAPABILITY_NOT_METERED);
+ // Note: resetting the owner UID before storing the agent capabilities in NAI means that if
+ // the agent attempts to change the owner UID, then nai.declaredCapabilities will not
+ // actually be the same as the capabilities sent by the agent. Still, it is safer to reset
+ // the owner UID here and behave as if the agent had never tried to change it.
if (nai.networkCapabilities.getOwnerUid() != nc.getOwnerUid()) {
Log.e(TAG, nai.toShortString() + ": ignoring attempt to change owner from "
+ nai.networkCapabilities.getOwnerUid() + " to " + nc.getOwnerUid());
nc.setOwnerUid(nai.networkCapabilities.getOwnerUid());
}
+ nai.declaredCapabilities = new NetworkCapabilities(nc);
}
- /** Modifies |caps| based on the capabilities of the specified underlying networks. */
+ /** Modifies |newNc| based on the capabilities of |underlyingNetworks| and |agentCaps|. */
@VisibleForTesting
void applyUnderlyingCapabilities(@Nullable Network[] underlyingNetworks,
- @NonNull NetworkCapabilities caps, boolean declaredMetered) {
- final Network defaultNetwork = getNetwork(getDefaultNetwork());
- if (underlyingNetworks == null && defaultNetwork != null) {
- // null underlying networks means to track the default.
- underlyingNetworks = new Network[] { defaultNetwork };
- }
- int[] transportTypes = new int[] { NetworkCapabilities.TRANSPORT_VPN };
+ @NonNull NetworkCapabilities agentCaps, @NonNull NetworkCapabilities newNc) {
+ underlyingNetworks = underlyingNetworksOrDefault(underlyingNetworks);
+ int[] transportTypes = agentCaps.getTransportTypes();
int downKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
int upKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
- boolean metered = declaredMetered; // metered if any underlying is metered, or agentMetered
+ // metered if any underlying is metered, or originally declared metered by the agent.
+ boolean metered = !agentCaps.hasCapability(NET_CAPABILITY_NOT_METERED);
boolean roaming = false; // roaming if any underlying is roaming
boolean congested = false; // congested if any underlying is congested
boolean suspended = true; // suspended if all underlying are suspended
@@ -6435,13 +6444,13 @@
suspended = false;
}
- caps.setTransportTypes(transportTypes);
- caps.setLinkDownstreamBandwidthKbps(downKbps);
- caps.setLinkUpstreamBandwidthKbps(upKbps);
- caps.setCapability(NET_CAPABILITY_NOT_METERED, !metered);
- caps.setCapability(NET_CAPABILITY_NOT_ROAMING, !roaming);
- caps.setCapability(NET_CAPABILITY_NOT_CONGESTED, !congested);
- caps.setCapability(NET_CAPABILITY_NOT_SUSPENDED, !suspended);
+ newNc.setTransportTypes(transportTypes);
+ newNc.setLinkDownstreamBandwidthKbps(downKbps);
+ newNc.setLinkUpstreamBandwidthKbps(upKbps);
+ newNc.setCapability(NET_CAPABILITY_NOT_METERED, !metered);
+ newNc.setCapability(NET_CAPABILITY_NOT_ROAMING, !roaming);
+ newNc.setCapability(NET_CAPABILITY_NOT_CONGESTED, !congested);
+ newNc.setCapability(NET_CAPABILITY_NOT_SUSPENDED, !suspended);
}
/**
@@ -6498,7 +6507,8 @@
}
if (nai.supportsUnderlyingNetworks()) {
- applyUnderlyingCapabilities(nai.declaredUnderlyingNetworks, newNc, nai.declaredMetered);
+ applyUnderlyingCapabilities(nai.declaredUnderlyingNetworks, nai.declaredCapabilities,
+ newNc);
}
return newNc;
@@ -6577,11 +6587,8 @@
}
}
- if (!newNc.hasTransport(TRANSPORT_VPN)) {
- // Tell VPNs about updated capabilities, since they may need to
- // bubble those changes through.
- propagateUnderlyingNetworkCapabilities();
- }
+ // This network might have been underlying another network. Propagate its capabilities.
+ propagateUnderlyingNetworkCapabilities(nai.network);
if (!newNc.equalsTransportTypes(prevNc)) {
mDnsManager.updateTransportsForNetwork(
@@ -6911,8 +6918,10 @@
updateTcpBufferSizes(null != newNetwork
? newNetwork.linkProperties.getTcpBufferSizes() : null);
notifyIfacesChangedForNetworkStats();
- // Fix up the NetworkCapabilities of any VPNs that don't specify underlying networks.
- propagateUnderlyingNetworkCapabilities();
+ // Fix up the NetworkCapabilities of any networks that have this network as underlying.
+ if (newNetwork != null) {
+ propagateUnderlyingNetworkCapabilities(newNetwork.network);
+ }
}
private void processListenRequests(@NonNull final NetworkAgentInfo nai) {
@@ -7368,13 +7377,11 @@
networkAgent.networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND);
if (!createNativeNetwork(networkAgent)) return;
- if (networkAgent.isVPN()) {
- // Initialize the VPN capabilities to their starting values according to the
- // underlying networks. This will avoid a spurious callback to
- // 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.
- propagateUnderlyingNetworkCapabilities();
+ if (networkAgent.supportsUnderlyingNetworks()) {
+ // Initialize the network's capabilities to their starting values according to the
+ // underlying networks. This ensures that the capabilities are correct before
+ // anything happens to the network.
+ updateCapabilitiesForNetwork(networkAgent);
}
networkAgent.created = true;
}
@@ -7416,10 +7423,6 @@
// doing.
updateSignalStrengthThresholds(networkAgent, "CONNECT", null);
- if (networkAgent.supportsUnderlyingNetworks()) {
- propagateUnderlyingNetworkCapabilities();
- }
-
// Consider network even though it is not yet validated.
rematchAllNetworksAndRequests();
diff --git a/services/core/java/com/android/server/DropBoxManagerService.java b/services/core/java/com/android/server/DropBoxManagerService.java
index 886bfb8..30fc336 100644
--- a/services/core/java/com/android/server/DropBoxManagerService.java
+++ b/services/core/java/com/android/server/DropBoxManagerService.java
@@ -268,7 +268,7 @@
if (!DropBoxManagerService.this.mBooted) {
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
}
- getContext().sendBroadcastAsUser(intent, UserHandle.SYSTEM,
+ getContext().sendBroadcastAsUser(intent, UserHandle.ALL,
android.Manifest.permission.READ_LOGS);
}
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 086cc1c..636da6f 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -90,7 +90,6 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IBatteryStats;
import com.android.internal.util.DumpUtils;
-import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.HexDump;
import com.android.internal.util.Preconditions;
@@ -419,8 +418,6 @@
getBatteryStats().noteMobileRadioPowerState(powerState, tsNanos, uid);
} catch (RemoteException e) {
}
- FrameworkStatsLog.write_non_chained(
- FrameworkStatsLog.MOBILE_RADIO_POWER_STATE_CHANGED, uid, null, powerState);
}
}
@@ -431,8 +428,6 @@
getBatteryStats().noteWifiRadioPowerState(powerState, tsNanos, uid);
} catch (RemoteException e) {
}
- FrameworkStatsLog.write_non_chained(
- FrameworkStatsLog.WIFI_RADIO_POWER_STATE_CHANGED, uid, null, powerState);
}
}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index c95bfd03..d9ddebd 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -108,6 +108,7 @@
import android.os.storage.StorageVolume;
import android.os.storage.VolumeInfo;
import android.os.storage.VolumeRecord;
+import android.provider.DeviceConfig;
import android.provider.DocumentsContract;
import android.provider.Downloads;
import android.provider.MediaStore;
@@ -879,6 +880,8 @@
com.android.internal.R.bool.config_zramWriteback)) {
ZramWriteback.scheduleZramWriteback(mContext);
}
+
+ updateTranscodeEnabled();
}
/**
@@ -910,6 +913,21 @@
}
}
+ private void updateTranscodeEnabled() {
+ // See MediaProvider TranscodeHelper#getBooleanProperty for more information
+ boolean transcodeEnabled = false;
+ boolean defaultValue = true;
+
+ if (SystemProperties.getBoolean("persist.sys.fuse.transcode_user_control", false)) {
+ transcodeEnabled = SystemProperties.getBoolean("persist.sys.fuse.transcode_enabled",
+ defaultValue);
+ } else {
+ transcodeEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
+ "transcode_enabled", defaultValue);
+ }
+ SystemProperties.set("sys.fuse.transcode_enabled", String.valueOf(transcodeEnabled));
+ }
+
/**
* MediaProvider has a ton of code that makes assumptions about storage
* paths never changing, so we outright kill them to pick up new state.
@@ -4375,14 +4393,7 @@
// Create package obb and data dir if it doesn't exist.
int appUid = UserHandle.getUid(userId, mPmInternal.getPackage(pkg).getUid());
- File file = new File(packageObbDir);
- if (!file.exists()) {
- vold.setupAppDir(packageObbDir, appUid);
- }
- file = new File(packageDataDir);
- if (!file.exists()) {
- vold.setupAppDir(packageDataDir, appUid);
- }
+ vold.ensureAppDirsCreated(new String[] {packageObbDir, packageDataDir}, appUid);
}
} catch (ServiceManager.ServiceNotFoundException | RemoteException e) {
Slog.e(TAG, "Unable to create obb and data directories for " + processName,e);
@@ -4488,10 +4499,13 @@
// When using FUSE, we may need to kill the app if the op changes
switch(code) {
case OP_REQUEST_INSTALL_PACKAGES:
- if (previousMode == MODE_ALLOWED || mode == MODE_ALLOWED) {
- // If we transition to/from MODE_ALLOWED, kill the app to make
- // sure it has the correct view of /storage. Changing between
- // MODE_DEFAULT / MODE_ERRORED is a no-op
+ // In R, we used to kill the app here if it transitioned to/from
+ // MODE_ALLOWED, to make sure the app had the correct (writable) OBB
+ // view. But the majority of apps don't handle OBBs anyway, and for those
+ // that do, they can restart themselves. Therefore, starting from S,
+ // only kill the app when it transitions away from MODE_ALLOWED (eg,
+ // when the permission is taken away).
+ if (previousMode == MODE_ALLOWED && mode != MODE_ALLOWED) {
killAppForOpChange(code, uid);
}
return;
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 422ae68..0ab3c9e 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -1097,6 +1097,8 @@
}
});
}
+ FrameworkStatsLog.write_non_chained(
+ FrameworkStatsLog.MOBILE_RADIO_POWER_STATE_CHANGED, uid, null, powerState);
}
public void notePhoneOn() {
@@ -1402,6 +1404,8 @@
}
});
}
+ FrameworkStatsLog.write_non_chained(
+ FrameworkStatsLog.WIFI_RADIO_POWER_STATE_CHANGED, uid, null, powerState);
}
public void noteWifiRunning(final WorkSource ws) {
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index ccd1f3b..52b9f5c 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -138,9 +138,10 @@
// 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;
+ // The capabilities originally announced by the NetworkAgent, regardless of any capabilities
+ // that were added or removed due to this network's underlying networks.
+ // Only set if #supportsUnderlyingNetworks is true.
+ public @Nullable NetworkCapabilities declaredCapabilities;
// 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.
diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
index 7795ed3..3d71b0a 100644
--- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
@@ -334,7 +334,13 @@
*/
public void setProvNotificationVisible(boolean visible, int id, String action) {
if (visible) {
- Intent intent = new Intent(action);
+ // For legacy purposes, action is sent as the action + the phone ID from DcTracker.
+ // Split the string here and send the phone ID as an extra instead.
+ String[] splitAction = action.split(":");
+ Intent intent = new Intent(splitAction[0]);
+ try {
+ intent.putExtra("provision.phone.id", Integer.parseInt(splitAction[1]));
+ } catch (NumberFormatException ignored) { }
PendingIntent pendingIntent = PendingIntent.getBroadcast(
mContext, 0 /* requestCode */, intent, PendingIntent.FLAG_IMMUTABLE);
showNotification(id, NotificationType.SIGN_IN, null, null, pendingIntent, false);
diff --git a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java b/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java
index 1129899..b5f20d7 100644
--- a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java
+++ b/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java
@@ -36,6 +36,7 @@
import android.net.TcpKeepalivePacketData;
import android.net.TcpKeepalivePacketDataParcelable;
import android.net.TcpRepairWindow;
+import android.net.util.KeepalivePacketDataUtil;
import android.os.Handler;
import android.os.MessageQueue;
import android.os.Messenger;
@@ -112,7 +113,7 @@
throws InvalidPacketException, InvalidSocketException {
try {
final TcpKeepalivePacketDataParcelable tcpDetails = switchToRepairMode(fd);
- return TcpKeepalivePacketData.tcpKeepalivePacket(tcpDetails);
+ return KeepalivePacketDataUtil.fromStableParcelable(tcpDetails);
} catch (InvalidPacketException | InvalidSocketException e) {
switchOutOfRepairMode(fd);
throw e;
@@ -122,7 +123,7 @@
* Switch the tcp socket to repair mode and query detail tcp information.
*
* @param fd the fd of socket on which to use keepalive offload.
- * @return a {@link TcpKeepalivePacketData#TcpKeepalivePacketDataParcelable} object for current
+ * @return a {@link TcpKeepalivePacketDataParcelable} object for current
* tcp/ip information.
*/
private static TcpKeepalivePacketDataParcelable switchToRepairMode(FileDescriptor fd)
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 74ea2d7..155b246 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -177,10 +177,10 @@
private final class LocalDisplayDevice extends DisplayDevice {
private final long mPhysicalDisplayId;
- private final LogicalLight mBacklight;
private final SparseArray<DisplayModeRecord> mSupportedModes = new SparseArray<>();
private final ArrayList<Integer> mSupportedColorModes = new ArrayList<>();
private final boolean mIsDefaultDisplay;
+ private final BacklightAdapter mBacklightAdapter;
private DisplayDeviceInfo mInfo;
private boolean mHavePendingChanges;
@@ -205,7 +205,6 @@
private SurfaceControl.DisplayConfig[] mDisplayConfigs;
private Spline mSystemBrightnessToNits;
private Spline mNitsToHalBrightness;
-
private DisplayDeviceConfig mDisplayDeviceConfig;
private DisplayEventReceiver.FrameRateOverride[] mFrameRateOverrides =
@@ -222,12 +221,7 @@
updateDisplayPropertiesLocked(info, configs, activeConfigId, configSpecs, colorModes,
activeColorMode, hdrCapabilities);
mSidekickInternal = LocalServices.getService(SidekickInternal.class);
- if (mIsDefaultDisplay) {
- LightsManager lights = LocalServices.getService(LightsManager.class);
- mBacklight = lights.getLight(LightsManager.LIGHT_ID_BACKLIGHT);
- } else {
- mBacklight = null;
- }
+ mBacklightAdapter = new BacklightAdapter(displayToken, isDefaultDisplay);
mAllmSupported = SurfaceControl.getAutoLowLatencyModeSupport(displayToken);
mGameContentTypeSupported = SurfaceControl.getGameContentTypeSupport(displayToken);
mDisplayDeviceConfig = null;
@@ -643,8 +637,7 @@
brightnessState, PowerManager.BRIGHTNESS_OFF_FLOAT);
final boolean stateChanged = (mState != state);
final boolean brightnessChanged = (!BrightnessSynchronizer.floatEquals(
- mBrightnessState, brightnessState))
- && mBacklight != null;
+ mBrightnessState, brightnessState));
if (stateChanged || brightnessChanged) {
final long physicalDisplayId = mPhysicalDisplayId;
final IBinder token = getDisplayTokenLocked();
@@ -712,9 +705,7 @@
+ "id=" + physicalDisplayId
+ ", state=" + Display.stateToString(state) + ")");
}
- if (mBacklight != null) {
- mBacklight.setVrMode(isVrEnabled);
- }
+ mBacklightAdapter.setVrMode(isVrEnabled);
}
private void setDisplayState(int state) {
@@ -770,13 +761,8 @@
Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayBrightness("
+ "id=" + physicalDisplayId + ", brightness=" + brightness + ")");
try {
- if (isHalBrightnessRangeSpecified()) {
- brightness = displayBrightnessToHalBrightness(
- BrightnessSynchronizer.brightnessFloatToIntRange(brightness));
- }
- if (mBacklight != null) {
- mBacklight.setBrightness(brightness);
- }
+ brightness = displayBrightnessToHalBrightness(brightness);
+ mBacklightAdapter.setBrightness(brightness);
Trace.traceCounter(Trace.TRACE_TAG_POWER,
"ScreenBrightness",
BrightnessSynchronizer.brightnessFloatToInt(brightness));
@@ -785,26 +771,33 @@
}
}
- private boolean isHalBrightnessRangeSpecified() {
- return !(mSystemBrightnessToNits == null || mNitsToHalBrightness == null);
- }
-
/**
* Converts brightness range from the framework's brightness space to the
* Hal brightness space if the HAL brightness space has been provided via
* a display device configuration file.
*/
private float displayBrightnessToHalBrightness(float brightness) {
- if (!isHalBrightnessRangeSpecified()) {
- return PowerManager.BRIGHTNESS_INVALID_FLOAT;
+ // TODO: b/171380847 - This needs to be deprecated. The nits-to-brightness
+ // relationship should be specified in display-config OR config.xml, but not
+ // both, and no nits-space conversion should be necessary.
+ //
+ // Only do a conversion if there exists a unique system brightness and a
+ // unique HAL brightness-to-nits range defined.
+ if (mSystemBrightnessToNits == null || mNitsToHalBrightness == null) {
+ return brightness;
}
+ // Sys brightness in this conversion is always specified in the old 1-255
+ // range, so convert that here before the translation.
+ final float brightnessInt =
+ BrightnessSynchronizer.brightnessFloatToIntRange(brightness);
+
if (BrightnessSynchronizer.floatEquals(
- brightness, PowerManager.BRIGHTNESS_OFF)) {
+ brightnessInt, PowerManager.BRIGHTNESS_OFF)) {
return PowerManager.BRIGHTNESS_OFF_FLOAT;
}
- final float nits = mSystemBrightnessToNits.interpolate(brightness);
+ final float nits = mSystemBrightnessToNits.interpolate(brightnessInt);
final float halBrightness = mNitsToHalBrightness.interpolate(nits);
return halBrightness;
}
@@ -988,7 +981,7 @@
pw.println("mDefaultModeId=" + mDefaultModeId);
pw.println("mState=" + Display.stateToString(mState));
pw.println("mBrightnessState=" + mBrightnessState);
- pw.println("mBacklight=" + mBacklight);
+ pw.println("mBacklightAdapter=" + mBacklightAdapter);
pw.println("mAllmSupported=" + mAllmSupported);
pw.println("mAllmRequested=" + mAllmRequested);
pw.println("mGameContentTypeSupported=" + mGameContentTypeSupported);
@@ -1209,4 +1202,44 @@
}
}
}
+
+ static class BacklightAdapter {
+ private final IBinder mDisplayToken;
+ private final LogicalLight mBacklight;
+ private final boolean mUseSurfaceControlBrightness;
+
+ BacklightAdapter(IBinder displayToken, boolean isDefaultDisplay) {
+ mDisplayToken = displayToken;
+
+ mUseSurfaceControlBrightness =
+ SurfaceControl.getDisplayBrightnessSupport(mDisplayToken);
+
+ if (!mUseSurfaceControlBrightness && isDefaultDisplay) {
+ LightsManager lights = LocalServices.getService(LightsManager.class);
+ mBacklight = lights.getLight(LightsManager.LIGHT_ID_BACKLIGHT);
+ } else {
+ mBacklight = null;
+ }
+ }
+
+ public void setBrightness(float brightness) {
+ if (mUseSurfaceControlBrightness) {
+ SurfaceControl.setDisplayBrightness(mDisplayToken, brightness);
+ } else if (mBacklight != null) {
+ mBacklight.setBrightness(brightness);
+ }
+ }
+
+ public void setVrMode(boolean isVrModeEnabled) {
+ if (mBacklight != null) {
+ mBacklight.setVrMode(isVrModeEnabled);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "BacklightAdapter [useSurfaceControl=" + mUseSurfaceControlBrightness
+ + ", backlight=" + mBacklight + "]";
+ }
+ }
}
diff --git a/services/core/java/com/android/server/lights/LightsService.java b/services/core/java/com/android/server/lights/LightsService.java
index d624019..43c965d 100644
--- a/services/core/java/com/android/server/lights/LightsService.java
+++ b/services/core/java/com/android/server/lights/LightsService.java
@@ -29,14 +29,12 @@
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
-import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.Trace;
import android.provider.Settings;
import android.util.Slog;
import android.util.SparseArray;
-import android.view.SurfaceControl;
import com.android.internal.BrightnessSynchronizer;
import com.android.internal.annotations.GuardedBy;
@@ -262,25 +260,9 @@
}
private final class LightImpl extends LogicalLight {
- private final IBinder mDisplayToken;
- private final int mSurfaceControlMaximumBrightness;
private LightImpl(Context context, HwLight hwLight) {
mHwLight = hwLight;
- mDisplayToken = SurfaceControl.getInternalDisplayToken();
- final boolean brightnessSupport = SurfaceControl.getDisplayBrightnessSupport(
- mDisplayToken);
- if (DEBUG) {
- Slog.d(TAG, "Display brightness support: " + brightnessSupport);
- }
- int maximumBrightness = 0;
- if (brightnessSupport) {
- PowerManager pm = context.getSystemService(PowerManager.class);
- if (pm != null) {
- maximumBrightness = pm.getMaximumScreenBrightnessSetting();
- }
- }
- mSurfaceControlMaximumBrightness = maximumBrightness;
}
@Override
@@ -301,28 +283,10 @@
+ ": brightness=" + brightness);
return;
}
- // Ideally, we'd like to set the brightness mode through the SF/HWC as well, but
- // right now we just fall back to the old path through Lights brightessMode is
- // anything but USER or the device shouldBeInLowPersistenceMode().
- if (brightnessMode == BRIGHTNESS_MODE_USER && !shouldBeInLowPersistenceMode()
- && mSurfaceControlMaximumBrightness == 255) {
- // New system
- // TODO: the last check should be mSurfaceControlMaximumBrightness != 0; the
- // reason we enforce 255 right now is to stay consistent with the old path. In
- // the future, the framework should be refactored so that brightness is a float
- // between 0.0f and 1.0f, and the actual number of supported brightness levels
- // is determined in the device-specific implementation.
- if (DEBUG) {
- Slog.d(TAG, "Using new setBrightness path!");
- }
- SurfaceControl.setDisplayBrightness(mDisplayToken, brightness);
- } else {
- // Old system
- int brightnessInt = BrightnessSynchronizer.brightnessFloatToInt(brightness);
- int color = brightnessInt & 0x000000ff;
- color = 0xff000000 | (color << 16) | (color << 8) | color;
- setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode);
- }
+ int brightnessInt = BrightnessSynchronizer.brightnessFloatToInt(brightness);
+ int color = brightnessInt & 0x000000ff;
+ color = 0xff000000 | (color << 16) | (color << 8) | color;
+ setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode);
}
}
diff --git a/services/core/java/com/android/server/locksettings/OWNERS b/services/core/java/com/android/server/locksettings/OWNERS
index dad6e39..08b8a8c 100644
--- a/services/core/java/com/android/server/locksettings/OWNERS
+++ b/services/core/java/com/android/server/locksettings/OWNERS
@@ -1,2 +1,3 @@
jaggies@google.com
kchyn@google.com
+rubinxu@google.com
diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java
index 5787f7c4..8d5f553 100644
--- a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java
+++ b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java
@@ -15,20 +15,15 @@
*/
package com.android.server.locksettings;
-
import static android.os.UserHandle.USER_SYSTEM;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.content.Context;
import android.content.pm.UserInfo;
-import android.hardware.rebootescrow.IRebootEscrow;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.ServiceSpecificException;
import android.os.SystemClock;
import android.os.UserManager;
+import android.provider.DeviceConfig;
import android.provider.Settings;
import android.util.Slog;
@@ -44,7 +39,6 @@
import java.util.Date;
import java.util.List;
import java.util.Locale;
-import java.util.NoSuchElementException;
class RebootEscrowManager {
private static final String TAG = "RebootEscrowManager";
@@ -116,8 +110,24 @@
static class Injector {
protected Context mContext;
+ private final RebootEscrowProviderInterface mRebootEscrowProvider;
+
Injector(Context context) {
mContext = context;
+ RebootEscrowProviderInterface rebootEscrowProvider = null;
+ // TODO(xunchang) add implementation for server based ror.
+ if (DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_OTA,
+ "server_based_ror_enabled", false)) {
+ Slog.e(TAG, "Server based ror isn't implemented yet.");
+ } else {
+ rebootEscrowProvider = new RebootEscrowProviderHalImpl();
+ }
+
+ if (rebootEscrowProvider != null && rebootEscrowProvider.hasRebootEscrowSupport()) {
+ mRebootEscrowProvider = rebootEscrowProvider;
+ } else {
+ mRebootEscrowProvider = null;
+ }
}
public Context getContext() {
@@ -128,15 +138,8 @@
return (UserManager) mContext.getSystemService(Context.USER_SERVICE);
}
- @Nullable
- public IRebootEscrow getRebootEscrow() {
- try {
- return IRebootEscrow.Stub.asInterface(ServiceManager.getService(
- "android.hardware.rebootescrow.IRebootEscrow/default"));
- } catch (NoSuchElementException e) {
- Slog.i(TAG, "Device doesn't implement RebootEscrow HAL");
- }
- return null;
+ public RebootEscrowProviderInterface getRebootEscrowProvider() {
+ return mRebootEscrowProvider;
}
public int getBootCount() {
@@ -210,45 +213,18 @@
}
private RebootEscrowKey getAndClearRebootEscrowKey() {
- IRebootEscrow rebootEscrow = mInjector.getRebootEscrow();
- if (rebootEscrow == null) {
- Slog.w(TAG, "Had reboot escrow data for users, but RebootEscrow HAL is unavailable");
+ RebootEscrowProviderInterface rebootEscrowProvider = mInjector.getRebootEscrowProvider();
+ if (rebootEscrowProvider == null) {
+ Slog.w(TAG,
+ "Had reboot escrow data for users, but RebootEscrowProvider is unavailable");
return null;
}
- try {
- byte[] escrowKeyBytes = rebootEscrow.retrieveKey();
- if (escrowKeyBytes == null) {
- Slog.w(TAG, "Had reboot escrow data for users, but could not retrieve key");
- return null;
- } else if (escrowKeyBytes.length != 32) {
- Slog.e(TAG, "IRebootEscrow returned key of incorrect size "
- + escrowKeyBytes.length);
- return null;
- }
-
- // Make sure we didn't get the null key.
- int zero = 0;
- for (int i = 0; i < escrowKeyBytes.length; i++) {
- zero |= escrowKeyBytes[i];
- }
- if (zero == 0) {
- Slog.w(TAG, "IRebootEscrow returned an all-zeroes key");
- return null;
- }
-
- // Overwrite the existing key with the null key
- rebootEscrow.storeKey(new byte[32]);
-
+ RebootEscrowKey key = rebootEscrowProvider.getAndClearRebootEscrowKey(null);
+ if (key != null) {
mEventLog.addEntry(RebootEscrowEvent.RETRIEVED_STORED_KEK);
- return RebootEscrowKey.fromKeyBytes(escrowKeyBytes);
- } catch (RemoteException e) {
- Slog.w(TAG, "Could not retrieve escrow data");
- return null;
- } catch (ServiceSpecificException e) {
- Slog.w(TAG, "Got service-specific exception: " + e.errorCode);
- return null;
}
+ return key;
}
private boolean restoreRebootEscrowForUser(@UserIdInt int userId, RebootEscrowKey key) {
@@ -279,9 +255,9 @@
return;
}
- IRebootEscrow rebootEscrow = mInjector.getRebootEscrow();
- if (rebootEscrow == null) {
- Slog.w(TAG, "Reboot escrow requested, but RebootEscrow HAL is unavailable");
+ if (mInjector.getRebootEscrowProvider() == null) {
+ Slog.w(TAG,
+ "Had reboot escrow data for users, but RebootEscrowProvider is unavailable");
return;
}
@@ -293,6 +269,7 @@
final RebootEscrowData escrowData;
try {
+ // TODO(xunchang) further wrap the escrowData with a key from keystore.
escrowData = RebootEscrowData.fromSyntheticPassword(escrowKey, spVersion,
syntheticPassword);
} catch (IOException e) {
@@ -330,18 +307,16 @@
mRebootEscrowWanted = false;
setRebootEscrowReady(false);
- IRebootEscrow rebootEscrow = mInjector.getRebootEscrow();
- if (rebootEscrow == null) {
+
+ RebootEscrowProviderInterface rebootEscrowProvider = mInjector.getRebootEscrowProvider();
+ if (rebootEscrowProvider == null) {
+ Slog.w(TAG,
+ "Had reboot escrow data for users, but RebootEscrowProvider is unavailable");
return;
}
mStorage.removeKey(REBOOT_ESCROW_ARMED_KEY, USER_SYSTEM);
-
- try {
- rebootEscrow.storeKey(new byte[32]);
- } catch (RemoteException | ServiceSpecificException e) {
- Slog.w(TAG, "Could not call RebootEscrow HAL to shred key");
- }
+ rebootEscrowProvider.clearRebootEscrowKey();
List<UserInfo> users = mUserManager.getUsers();
for (UserInfo user : users) {
@@ -356,9 +331,10 @@
return false;
}
- IRebootEscrow rebootEscrow = mInjector.getRebootEscrow();
- if (rebootEscrow == null) {
- Slog.w(TAG, "Escrow marked as ready, but RebootEscrow HAL is unavailable");
+ RebootEscrowProviderInterface rebootEscrowProvider = mInjector.getRebootEscrowProvider();
+ if (rebootEscrowProvider == null) {
+ Slog.w(TAG,
+ "Had reboot escrow data for users, but RebootEscrowProvider is unavailable");
return false;
}
@@ -372,15 +348,7 @@
return false;
}
- boolean armedRebootEscrow = false;
- try {
- rebootEscrow.storeKey(escrowKey.getKeyBytes());
- armedRebootEscrow = true;
- Slog.i(TAG, "Reboot escrow key stored with RebootEscrow HAL");
- } catch (RemoteException | ServiceSpecificException e) {
- Slog.e(TAG, "Failed escrow secret to RebootEscrow HAL", e);
- }
-
+ boolean armedRebootEscrow = rebootEscrowProvider.storeRebootEscrowKey(escrowKey, null);
if (armedRebootEscrow) {
mStorage.setInt(REBOOT_ESCROW_ARMED_KEY, mInjector.getBootCount(), USER_SYSTEM);
mEventLog.addEntry(RebootEscrowEvent.SET_ARMED_STATUS);
@@ -397,7 +365,7 @@
}
boolean prepareRebootEscrow() {
- if (mInjector.getRebootEscrow() == null) {
+ if (mInjector.getRebootEscrowProvider() == null) {
return false;
}
@@ -408,7 +376,7 @@
}
boolean clearRebootEscrow() {
- if (mInjector.getRebootEscrow() == null) {
+ if (mInjector.getRebootEscrowProvider() == null) {
return false;
}
diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowProviderHalImpl.java b/services/core/java/com/android/server/locksettings/RebootEscrowProviderHalImpl.java
new file mode 100644
index 0000000..6c1040b
--- /dev/null
+++ b/services/core/java/com/android/server/locksettings/RebootEscrowProviderHalImpl.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.locksettings;
+
+import android.annotation.Nullable;
+import android.hardware.rebootescrow.IRebootEscrow;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.ServiceSpecificException;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.NoSuchElementException;
+
+import javax.crypto.SecretKey;
+
+/**
+ * An implementation of the {@link RebootEscrowProviderInterface} by calling the RebootEscrow HAL.
+ */
+class RebootEscrowProviderHalImpl implements RebootEscrowProviderInterface {
+ private static final String TAG = "RebootEscrowProvider";
+
+ private final Injector mInjector;
+
+ static class Injector {
+ @Nullable
+ public IRebootEscrow getRebootEscrow() {
+ try {
+ return IRebootEscrow.Stub.asInterface(ServiceManager.getService(
+ "android.hardware.rebootescrow.IRebootEscrow/default"));
+ } catch (NoSuchElementException e) {
+ Slog.i(TAG, "Device doesn't implement RebootEscrow HAL");
+ }
+ return null;
+ }
+ }
+
+ RebootEscrowProviderHalImpl() {
+ mInjector = new Injector();
+ }
+
+ @VisibleForTesting
+ RebootEscrowProviderHalImpl(Injector injector) {
+ mInjector = injector;
+ }
+
+ @Override
+ public boolean hasRebootEscrowSupport() {
+ return mInjector.getRebootEscrow() != null;
+ }
+
+ @Override
+ public RebootEscrowKey getAndClearRebootEscrowKey(SecretKey decryptionKey) {
+ IRebootEscrow rebootEscrow = mInjector.getRebootEscrow();
+ if (rebootEscrow == null) {
+ Slog.w(TAG, "Had reboot escrow data for users, but RebootEscrow HAL is unavailable");
+ return null;
+ }
+
+ try {
+ byte[] escrowKeyBytes = rebootEscrow.retrieveKey();
+ if (escrowKeyBytes == null) {
+ Slog.w(TAG, "Had reboot escrow data for users, but could not retrieve key");
+ return null;
+ } else if (escrowKeyBytes.length != 32) {
+ Slog.e(TAG, "IRebootEscrow returned key of incorrect size "
+ + escrowKeyBytes.length);
+ return null;
+ }
+
+ // Make sure we didn't get the null key.
+ int zero = 0;
+ for (int i = 0; i < escrowKeyBytes.length; i++) {
+ zero |= escrowKeyBytes[i];
+ }
+ if (zero == 0) {
+ Slog.w(TAG, "IRebootEscrow returned an all-zeroes key");
+ return null;
+ }
+
+ // Overwrite the existing key with the null key
+ rebootEscrow.storeKey(new byte[32]);
+
+ return RebootEscrowKey.fromKeyBytes(escrowKeyBytes);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Could not retrieve escrow data");
+ return null;
+ } catch (ServiceSpecificException e) {
+ Slog.w(TAG, "Got service-specific exception: " + e.errorCode);
+ return null;
+ }
+ }
+
+ @Override
+ public void clearRebootEscrowKey() {
+ IRebootEscrow rebootEscrow = mInjector.getRebootEscrow();
+ if (rebootEscrow == null) {
+ return;
+ }
+
+ try {
+ rebootEscrow.storeKey(new byte[32]);
+ } catch (RemoteException | ServiceSpecificException e) {
+ Slog.w(TAG, "Could not call RebootEscrow HAL to shred key");
+ }
+
+ }
+
+ @Override
+ public boolean storeRebootEscrowKey(RebootEscrowKey escrowKey, SecretKey encryptionKey) {
+ IRebootEscrow rebootEscrow = mInjector.getRebootEscrow();
+ if (rebootEscrow == null) {
+ Slog.w(TAG, "Escrow marked as ready, but RebootEscrow HAL is unavailable");
+ return false;
+ }
+
+ try {
+ // The HAL interface only accept 32 bytes data. And the encrypted bytes for the escrow
+ // key may exceed that limit. So we just store the raw key bytes here.
+ rebootEscrow.storeKey(escrowKey.getKeyBytes());
+ Slog.i(TAG, "Reboot escrow key stored with RebootEscrow HAL");
+ return true;
+ } catch (RemoteException | ServiceSpecificException e) {
+ Slog.e(TAG, "Failed escrow secret to RebootEscrow HAL", e);
+ }
+ return false;
+ }
+}
diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowProviderInterface.java b/services/core/java/com/android/server/locksettings/RebootEscrowProviderInterface.java
new file mode 100644
index 0000000..857ad5f
--- /dev/null
+++ b/services/core/java/com/android/server/locksettings/RebootEscrowProviderInterface.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.locksettings;
+
+import javax.crypto.SecretKey;
+
+/**
+ * Provides APIs for {@link RebootEscrowManager} to access and manage the reboot escrow key.
+ * Implementations need to find a way to persist the key across a reboot, and securely discards the
+ * persisted copy.
+ *
+ * @hide
+ */
+public interface RebootEscrowProviderInterface {
+ /**
+ * Returns true if the secure store/discard of reboot escrow key is supported.
+ */
+ boolean hasRebootEscrowSupport();
+
+ /**
+ * Returns the stored RebootEscrowKey, and clears the storage. If the stored key is encrypted,
+ * use the input key to decrypt the RebootEscrowKey. Returns null on failure.
+ */
+ RebootEscrowKey getAndClearRebootEscrowKey(SecretKey decryptionKey);
+
+ /**
+ * Clears the stored RebootEscrowKey.
+ */
+ void clearRebootEscrowKey();
+
+ /**
+ * Saves the given RebootEscrowKey, optionally encrypt the storage with the encryptionKey.
+ */
+ boolean storeRebootEscrowKey(RebootEscrowKey escrowKey, SecretKey encryptionKey);
+}
diff --git a/services/core/java/com/android/server/media/MediaRoute2Provider.java b/services/core/java/com/android/server/media/MediaRoute2Provider.java
index f882c57..edc9d7c 100644
--- a/services/core/java/com/android/server/media/MediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/MediaRoute2Provider.java
@@ -77,7 +77,7 @@
@NonNull
public List<RoutingSessionInfo> getSessionInfos() {
synchronized (mLock) {
- return mSessionInfos;
+ return new ArrayList<>(mSessionInfos);
}
}
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
index 85af346..ab38dca 100644
--- a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
@@ -108,8 +108,8 @@
mLastDiscoveryPreference = discoveryPreference;
if (mConnectionReady) {
mActiveConnection.updateDiscoveryPreference(discoveryPreference);
- updateBinding();
}
+ updateBinding();
}
@Override
@@ -205,9 +205,11 @@
}
private boolean shouldBind() {
- //TODO: Binding could be delayed until it's necessary.
if (mRunning) {
- return true;
+ // Bind when there is a discovery preference or an active route session.
+ return (mLastDiscoveryPreference != null
+ && !mLastDiscoveryPreference.getPreferredFeatures().isEmpty())
+ || !getSessionInfos().isEmpty();
}
return false;
}
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 1114fe0..31edf43 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -16,6 +16,7 @@
package com.android.server.media;
+import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
import static android.media.MediaRoute2ProviderService.REASON_UNKNOWN_ERROR;
import static android.media.MediaRouter2Utils.getOriginalId;
import static android.media.MediaRouter2Utils.getProviderId;
@@ -73,10 +74,12 @@
// TODO: (In Android S or later) if we add callback methods for generic failures
// in MediaRouter2, remove this constant and replace the usages with the real request IDs.
private static final long DUMMY_REQUEST_ID = -1;
+ private static final int PACKAGE_IMPORTANCE_FOR_DISCOVERY = IMPORTANCE_FOREGROUND;
private final Context mContext;
private final Object mLock = new Object();
final AtomicInteger mNextRouterOrManagerId = new AtomicInteger(1);
+ final ActivityManager mActivityManager;
@GuardedBy("mLock")
private final SparseArray<UserRecord> mUserRecords = new SparseArray<>();
@@ -87,8 +90,21 @@
@GuardedBy("mLock")
private int mCurrentUserId = -1;
+ private final ActivityManager.OnUidImportanceListener mOnUidImportanceListener =
+ (uid, importance) -> {
+ synchronized (mLock) {
+ final int count = mUserRecords.size();
+ for (int i = 0; i < count; i++) {
+ mUserRecords.valueAt(i).mHandler.maybeUpdateDiscoveryPreferenceForUid(uid);
+ }
+ }
+ };
+
MediaRouter2ServiceImpl(Context context) {
mContext = context;
+ mActivityManager = mContext.getSystemService(ActivityManager.class);
+ mActivityManager.addOnUidImportanceListener(mOnUidImportanceListener,
+ PACKAGE_IMPORTANCE_FOR_DISCOVERY);
}
////////////////////////////////////////////////////////////////
@@ -388,6 +404,30 @@
}
}
+ public void startScan(IMediaRouter2Manager manager) {
+ Objects.requireNonNull(manager, "manager must not be null");
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ startScanLocked(manager);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public void stopScan(IMediaRouter2Manager manager) {
+ Objects.requireNonNull(manager, "manager must not be null");
+ final long token = Binder.clearCallingIdentity();
+ try {
+ synchronized (mLock) {
+ stopScanLocked(manager);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
public void setRouteVolumeWithManager(IMediaRouter2Manager manager, int requestId,
MediaRoute2Info route, int volume) {
Objects.requireNonNull(manager, "manager must not be null");
@@ -839,6 +879,24 @@
disposeUserIfNeededLocked(userRecord); // since manager removed from user
}
+ private void startScanLocked(@NonNull IMediaRouter2Manager manager) {
+ final IBinder binder = manager.asBinder();
+ ManagerRecord managerRecord = mAllManagerRecords.get(binder);
+ if (managerRecord == null) {
+ return;
+ }
+ managerRecord.startScan();
+ }
+
+ private void stopScanLocked(@NonNull IMediaRouter2Manager manager) {
+ final IBinder binder = manager.asBinder();
+ ManagerRecord managerRecord = mAllManagerRecords.get(binder);
+ if (managerRecord == null) {
+ return;
+ }
+ managerRecord.stopScan();
+ }
+
private void setRouteVolumeWithManagerLocked(int requestId,
@NonNull IMediaRouter2Manager manager,
@NonNull MediaRoute2Info route, int volume) {
@@ -1122,6 +1180,7 @@
public final String mPackageName;
public final int mManagerId;
public SessionCreationRequest mLastSessionCreationRequest;
+ public boolean mIsScanning;
ManagerRecord(UserRecord userRecord, IMediaRouter2Manager manager,
int uid, int pid, String packageName) {
@@ -1146,6 +1205,24 @@
pw.println(prefix + this);
}
+ public void startScan() {
+ if (mIsScanning) {
+ return;
+ }
+ mIsScanning = true;
+ mUserRecord.mHandler.sendMessage(PooledLambda.obtainMessage(
+ UserHandler::updateDiscoveryPreferenceOnHandler, mUserRecord.mHandler));
+ }
+
+ public void stopScan() {
+ if (!mIsScanning) {
+ return;
+ }
+ mIsScanning = false;
+ mUserRecord.mHandler.sendMessage(PooledLambda.obtainMessage(
+ UserHandler::updateDiscoveryPreferenceOnHandler, mUserRecord.mHandler));
+ }
+
@Override
public String toString() {
return "Manager " + mPackageName + " (pid " + mPid + ")";
@@ -1262,6 +1339,24 @@
return null;
}
+ public void maybeUpdateDiscoveryPreferenceForUid(int uid) {
+ MediaRouter2ServiceImpl service = mServiceRef.get();
+ if (service == null) {
+ return;
+ }
+ boolean isUidRelevant;
+ synchronized (service.mLock) {
+ isUidRelevant = mUserRecord.mRouterRecords.stream().anyMatch(
+ router -> router.mUid == uid)
+ | mUserRecord.mManagerRecords.stream().anyMatch(
+ manager -> manager.mUid == uid);
+ }
+ if (isUidRelevant) {
+ sendMessage(PooledLambda.obtainMessage(
+ UserHandler::updateDiscoveryPreferenceOnHandler, this));
+ }
+ }
+
private void onProviderStateChangedOnHandler(@NonNull MediaRoute2Provider provider) {
int providerInfoIndex = getLastProviderInfoIndex(provider.getUniqueId());
MediaRoute2ProviderInfo currentInfo = provider.getProviderInfo();
@@ -1767,6 +1862,16 @@
return managers;
}
+ private List<RouterRecord> getRouterRecords() {
+ MediaRouter2ServiceImpl service = mServiceRef.get();
+ if (service == null) {
+ return Collections.emptyList();
+ }
+ synchronized (service.mLock) {
+ return new ArrayList<>(mUserRecord.mRouterRecords);
+ }
+ }
+
private List<ManagerRecord> getManagerRecords() {
MediaRouter2ServiceImpl service = mServiceRef.get();
if (service == null) {
@@ -2001,13 +2106,28 @@
return;
}
List<RouteDiscoveryPreference> discoveryPreferences = new ArrayList<>();
- synchronized (service.mLock) {
- for (RouterRecord routerRecord : mUserRecord.mRouterRecords) {
+ List<RouterRecord> routerRecords = getRouterRecords();
+ List<ManagerRecord> managerRecords = getManagerRecords();
+ boolean isAnyManagerScanning =
+ managerRecords.stream().anyMatch(manager -> manager.mIsScanning
+ && service.mActivityManager.getPackageImportance(manager.mPackageName)
+ <= PACKAGE_IMPORTANCE_FOR_DISCOVERY);
+
+ for (RouterRecord routerRecord : routerRecords) {
+ if (isAnyManagerScanning
+ || service.mActivityManager.getPackageImportance(routerRecord.mPackageName)
+ <= PACKAGE_IMPORTANCE_FOR_DISCOVERY) {
discoveryPreferences.add(routerRecord.mDiscoveryPreference);
}
- mUserRecord.mCompositeDiscoveryPreference =
- new RouteDiscoveryPreference.Builder(discoveryPreferences)
- .build();
+ }
+
+ synchronized (service.mLock) {
+ RouteDiscoveryPreference newPreference =
+ new RouteDiscoveryPreference.Builder(discoveryPreferences).build();
+ if (newPreference.equals(mUserRecord.mCompositeDiscoveryPreference)) {
+ return;
+ }
+ mUserRecord.mCompositeDiscoveryPreference = newPreference;
}
for (MediaRoute2Provider provider : mRouteProviders) {
provider.updateDiscoveryPreference(mUserRecord.mCompositeDiscoveryPreference);
diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java
index 0e52a67..b6d6cc4 100644
--- a/services/core/java/com/android/server/media/MediaRouterService.java
+++ b/services/core/java/com/android/server/media/MediaRouterService.java
@@ -544,6 +544,18 @@
// Binder call
@Override
+ public void startScan(IMediaRouter2Manager manager) {
+ mService2.startScan(manager);
+ }
+
+ // Binder call
+ @Override
+ public void stopScan(IMediaRouter2Manager manager) {
+ mService2.stopScan(manager);
+ }
+
+ // Binder call
+ @Override
public void setRouteVolumeWithManager(IMediaRouter2Manager manager, int requestId,
MediaRoute2Info route, int volume) {
mService2.setRouteVolumeWithManager(manager, requestId, route, volume);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 525fca0..d3d998a 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2274,10 +2274,24 @@
if (!DeviceConfig.NAMESPACE_SYSTEMUI.equals(properties.getNamespace())) {
return;
}
- if (properties.getKeyset()
- .contains(SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE)) {
- mAssistants.allowAdjustmentType(Adjustment.KEY_IMPORTANCE);
- mAssistants.resetDefaultAssistantsIfNecessary();
+ for (String name : properties.getKeyset()) {
+ if (SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE.equals(name)) {
+ mAssistants.resetDefaultAssistantsIfNecessary();
+ } else if (SystemUiDeviceConfigFlags.ENABLE_NAS_PRIORITIZER.equals(name)) {
+ String value = properties.getString(name, null);
+ if ("true".equals(value)) {
+ mAssistants.allowAdjustmentType(Adjustment.KEY_IMPORTANCE);
+ } else if ("false".equals(value)) {
+ mAssistants.disallowAdjustmentType(Adjustment.KEY_IMPORTANCE);
+ }
+ } else if (SystemUiDeviceConfigFlags.ENABLE_NAS_RANKING.equals(name)) {
+ String value = properties.getString(name, null);
+ if ("true".equals(value)) {
+ mAssistants.allowAdjustmentType(Adjustment.KEY_RANKING_SCORE);
+ } else if ("false".equals(value)) {
+ mAssistants.disallowAdjustmentType(Adjustment.KEY_RANKING_SCORE);
+ }
+ }
}
};
DeviceConfig.addOnPropertiesChangedListener(
@@ -6349,7 +6363,6 @@
private final int mRank;
private final int mCount;
private final ManagedServiceInfo mListener;
- private final long mWhen;
CancelNotificationRunnable(final int callingUid, final int callingPid,
final String pkg, final String tag, final int id,
@@ -6369,7 +6382,6 @@
this.mRank = rank;
this.mCount = count;
this.mListener = listener;
- this.mWhen = System.currentTimeMillis();
}
@Override
@@ -6381,33 +6393,8 @@
}
synchronized (mNotificationLock) {
- // Check to see if there is a notification in the enqueued list that hasn't had a
- // chance to post yet.
- List<NotificationRecord> enqueued = findEnqueuedNotificationsForCriteria(
- mPkg, mTag, mId, mUserId);
- boolean repost = false;
- if (enqueued.size() > 0) {
- // Found something, let's see what it was
- repost = true;
- // If all enqueues happened before this cancel then wait for them to happen,
- // otherwise we should let this cancel through so the next enqueue happens
- for (NotificationRecord r : enqueued) {
- if (r.mUpdateTimeMs > mWhen) {
- // At least one enqueue was posted after the cancel, so we're invalid
- Slog.i(TAG, "notification cancel ignored due to newer enqueued entry"
- + "key=" + r.getSbn().getKey());
- return;
- }
- }
- }
- if (repost) {
- mHandler.post(this);
- return;
- }
-
- // Look for the notification in the posted list, since we already checked enqueued.
- NotificationRecord r =
- findNotificationByListLocked(mNotificationList, mPkg, mTag, mId, mUserId);
+ // Look for the notification, searching both the posted and enqueued lists.
+ NotificationRecord r = findNotificationLocked(mPkg, mTag, mId, mUserId);
if (r != null) {
// The notification was found, check if it should be removed.
@@ -6430,10 +6417,6 @@
if ((r.getNotification().flags & mMustNotHaveFlags) != 0) {
return;
}
- if (r.getUpdateTimeMs() > mWhen) {
- // In this case, a post must have slipped by when this runnable reposted
- return;
- }
// Bubbled children get to stick around if the summary was manually cancelled
// (user removed) from systemui.
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index dac2e4f..b131aff 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -347,7 +347,7 @@
}
final StateProvider stateProvider = command -> {
synchronized (injector.getLock()) {
- command.currentState(injector.getSettings().mPackages,
+ command.currentState(injector.getSettings().getPackagesLocked(),
injector.getUserManagerInternal().getUserInfos());
}
};
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index 7db2319..d6400f3 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -128,12 +128,12 @@
synchronized (mPackageManagerService.mLock) {
// Important: the packages we need to run with ab-ota compiler-reason.
important = PackageManagerServiceUtils.getPackagesForDexopt(
- mPackageManagerService.mSettings.mPackages.values(), mPackageManagerService,
- DEBUG_DEXOPT);
+ mPackageManagerService.mSettings.getPackagesLocked().values(),
+ mPackageManagerService, DEBUG_DEXOPT);
// Remove Platform Package from A/B OTA b/160735835.
important.removeIf(isPlatformPackage);
// Others: we should optimize this with the (first-)boot compiler-reason.
- others = new ArrayList<>(mPackageManagerService.mSettings.mPackages.values());
+ others = new ArrayList<>(mPackageManagerService.mSettings.getPackagesLocked().values());
others.removeAll(important);
others.removeIf(PackageManagerServiceUtils.REMOVE_IF_NULL_PKG);
others.removeIf(isPlatformPackage);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 9f8f6e44..9e48ddd 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -747,8 +747,8 @@
installerAttributionTag);
session = new PackageInstallerSession(mInternalCallback, mContext, mPm, this,
mInstallThread.getLooper(), mStagingManager, sessionId, userId, callingUid,
- installSource, params, createdMillis, stageDir, stageCid, null, null, false, false,
- false, false, null, SessionInfo.INVALID_ID, false, false, false,
+ installSource, params, createdMillis, 0L, stageDir, stageCid, null, null, false,
+ false, false, false, null, SessionInfo.INVALID_ID, false, false, false,
SessionInfo.STAGED_SESSION_NO_ERROR, "");
synchronized (mSessions) {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 4ab1282..b8daa83 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -35,6 +35,7 @@
import static android.system.OsConstants.O_RDONLY;
import static android.system.OsConstants.O_WRONLY;
+import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
import static com.android.internal.util.XmlUtils.readBitmapAttribute;
import static com.android.internal.util.XmlUtils.readByteArrayAttribute;
import static com.android.internal.util.XmlUtils.readStringAttribute;
@@ -132,6 +133,7 @@
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.NativeLibraryHelper;
import com.android.internal.content.PackageHelper;
import com.android.internal.messages.nano.SystemMessageProto;
@@ -201,6 +203,7 @@
"installOriginatingPackageName";
private static final String ATTR_CREATED_MILLIS = "createdMillis";
private static final String ATTR_UPDATED_MILLIS = "updatedMillis";
+ private static final String ATTR_COMMITTED_MILLIS = "committedMillis";
private static final String ATTR_SESSION_STAGE_DIR = "sessionStageDir";
private static final String ATTR_SESSION_STAGE_CID = "sessionStageCid";
private static final String ATTR_PREPARED = "prepared";
@@ -291,6 +294,10 @@
@GuardedBy("mLock")
private long updatedMillis;
+ /** Timestamp of the time this session is committed */
+ @GuardedBy("mLock")
+ private long committedMillis;
+
/** Uid of the creator of this session. */
private final int mOriginalInstallerUid;
@@ -625,7 +632,7 @@
Context context, PackageManagerService pm,
PackageSessionProvider sessionProvider, Looper looper, StagingManager stagingManager,
int sessionId, int userId, int installerUid, @NonNull InstallSource installSource,
- SessionParams params, long createdMillis,
+ SessionParams params, long createdMillis, long committedMillis,
File stageDir, String stageCid, InstallationFile[] files,
ArrayMap<String, List<CertifiedChecksum>> checksums,
boolean prepared, boolean committed, boolean destroyed, boolean sealed,
@@ -648,6 +655,7 @@
this.params = params;
this.createdMillis = createdMillis;
this.updatedMillis = createdMillis;
+ this.committedMillis = committedMillis;
this.stageDir = stageDir;
this.stageCid = stageCid;
this.mShouldBeSealed = sealed;
@@ -1641,6 +1649,7 @@
mActiveCount.incrementAndGet();
mCommitted = true;
+ committedMillis = System.currentTimeMillis();
}
return true;
} catch (PackageManagerException e) {
@@ -2963,7 +2972,8 @@
/**
* @return the package name of this session
*/
- String getPackageName() {
+ @VisibleForTesting(visibility = PACKAGE)
+ public String getPackageName() {
synchronized (mLock) {
return mPackageName;
}
@@ -2978,6 +2988,12 @@
}
}
+ long getCommittedMillis() {
+ synchronized (mLock) {
+ return committedMillis;
+ }
+ }
+
String getInstallerPackageName() {
return getInstallSource().installerPackageName;
}
@@ -3923,6 +3939,7 @@
pw.printPair("mInstallerUid", mInstallerUid);
pw.printPair("createdMillis", createdMillis);
pw.printPair("updatedMillis", updatedMillis);
+ pw.printPair("committedMillis", committedMillis);
pw.printPair("stageDir", stageDir);
pw.printPair("stageCid", stageCid);
pw.println();
@@ -4099,6 +4116,7 @@
mInstallSource.originatingPackageName);
out.attributeLong(null, ATTR_CREATED_MILLIS, createdMillis);
out.attributeLong(null, ATTR_UPDATED_MILLIS, updatedMillis);
+ out.attributeLong(null, ATTR_COMMITTED_MILLIS, committedMillis);
if (stageDir != null) {
writeStringAttribute(out, ATTR_SESSION_STAGE_DIR,
stageDir.getAbsolutePath());
@@ -4252,6 +4270,7 @@
readStringAttribute(in, ATTR_ORIGINATING_PACKAGE_NAME);
final long createdMillis = in.getAttributeLong(null, ATTR_CREATED_MILLIS);
long updatedMillis = in.getAttributeLong(null, ATTR_UPDATED_MILLIS);
+ final long committedMillis = in.getAttributeLong(null, ATTR_COMMITTED_MILLIS, 0L);
final String stageDirRaw = readStringAttribute(in, ATTR_SESSION_STAGE_DIR);
final File stageDir = (stageDirRaw != null) ? new File(stageDirRaw) : null;
final String stageCid = readStringAttribute(in, ATTR_SESSION_STAGE_CID);
@@ -4395,8 +4414,9 @@
installOriginatingPackageName, installerPackageName, installerAttributionTag);
return new PackageInstallerSession(callback, context, pm, sessionProvider,
installerThread, stagingManager, sessionId, userId, installerUid,
- installSource, params, createdMillis, stageDir, stageCid, fileArray, checksums,
- prepared, committed, destroyed, sealed, childSessionIdsArray, parentSessionId,
- isReady, isFailed, isApplied, stagedSessionErrorCode, stagedSessionErrorMessage);
+ installSource, params, createdMillis, committedMillis, stageDir, stageCid,
+ fileArray, checksums, prepared, committed, destroyed, sealed, childSessionIdsArray,
+ parentSessionId, isReady, isFailed, isApplied, stagedSessionErrorCode,
+ stagedSessionErrorMessage);
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index d14baf5..cd9d11d 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -17692,12 +17692,12 @@
final SparseArray<int[]> newBroadcastAllowList;
final String codePath;
synchronized (mLock) {
- final PackageSetting ps = mSettings.mPackages.get(mPackageName);
+ final PackageSetting ps = mSettings.getPackageLPr(mPackageName);
if (ps == null) {
return;
}
newBroadcastAllowList = mAppsFilter.getVisibilityAllowList(
- ps, mInstalledUserIds, mSettings.mPackages);
+ ps, mInstalledUserIds, mSettings.getPackagesLocked());
codePath = ps.getPathString();
}
Bundle extras = new Bundle();
@@ -17715,12 +17715,12 @@
public void onPackageUnstartable(int reason) {
final SparseArray<int[]> newBroadcastAllowList;
synchronized (mLock) {
- final PackageSetting ps = mSettings.mPackages.get(mPackageName);
+ final PackageSetting ps = mSettings.getPackageLPr(mPackageName);
if (ps == null) {
return;
}
newBroadcastAllowList = mAppsFilter.getVisibilityAllowList(
- ps, mInstalledUserIds, mSettings.mPackages);
+ ps, mInstalledUserIds, mSettings.getPackagesLocked());
}
Bundle extras = new Bundle();
extras.putInt(Intent.EXTRA_UID, mUid);
@@ -17737,12 +17737,12 @@
public void onPackageStartable() {
final SparseArray<int[]> newBroadcastAllowList;
synchronized (mLock) {
- final PackageSetting ps = mSettings.mPackages.get(mPackageName);
+ final PackageSetting ps = mSettings.getPackageLPr(mPackageName);
if (ps == null) {
return;
}
newBroadcastAllowList = mAppsFilter.getVisibilityAllowList(
- ps, mInstalledUserIds, mSettings.mPackages);
+ ps, mInstalledUserIds, mSettings.getPackagesLocked());
}
Bundle extras = new Bundle();
extras.putInt(Intent.EXTRA_UID, mUid);
@@ -17768,7 +17768,7 @@
public void onPackageLoadingProgressChanged(float progress) {
final PackageSetting ps;
synchronized (mLock) {
- ps = mSettings.mPackages.get(mPackageName);
+ ps = mSettings.getPackageLPr(mPackageName);
}
if (ps == null) {
return;
@@ -17791,7 +17791,7 @@
public void onHealthStatus(int storageId, int status) throws RemoteException {
final PackageSetting ps;
synchronized (mLock) {
- ps = mSettings.mPackages.get(mPackageName);
+ ps = mSettings.getPackageLPr(mPackageName);
}
if (ps == null) {
return;
@@ -17804,7 +17804,7 @@
int userId) {
final PackageSetting ps;
synchronized (mLock) {
- ps = mSettings.mPackages.get(packageName);
+ ps = mSettings.getPackageLPr(packageName);
if (ps == null) {
Slog.w(TAG, "Failed to get package setting. Package " + packageName
+ " is not installed");
@@ -24612,7 +24612,7 @@
// which was uninstalled while keeping its data.
AndroidPackage dataOwnerPkg = mPackages.get(packageName);
if (dataOwnerPkg == null) {
- PackageSetting ps = mSettings.mPackages.get(packageName);
+ PackageSetting ps = mSettings.getPackageLPr(packageName);
if (ps != null) {
dataOwnerPkg = ps.pkg;
}
@@ -26059,7 +26059,7 @@
public void notifyPackageCrashOrAnr(@NonNull String packageName) {
final PackageSetting ps;
synchronized (mLock) {
- ps = mSettings.mPackages.get(packageName);
+ ps = mSettings.getPackageLPr(packageName);
if (ps == null) {
Slog.w(TAG, "Failed notifyPackageCrash. Package " + packageName
+ " is not installed");
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 2d5034e..7482ef45 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -295,6 +295,7 @@
private final File mKernelMappingFilename;
/** Map from package name to settings */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
final ArrayMap<String, PackageSetting> mPackages = new ArrayMap<>();
/**
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index c68fe81..56fb5e8 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -537,7 +537,9 @@
synchronized (mLock) {
// Clear the launcher cache for this user. It will be set again next time the default
// launcher is read from RoleManager.
- getUserShortcutsLocked(userId).setCachedLauncher(null);
+ if (isUserLoadedLocked(userId)) {
+ getUserShortcutsLocked(userId).setCachedLauncher(null);
+ }
}
}
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 85c4ab2..222874d 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -59,6 +59,7 @@
import android.util.apk.ApkSignatureVerifier;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.PackageHelper;
import com.android.internal.os.BackgroundThread;
import com.android.server.LocalServices;
@@ -720,7 +721,8 @@
* </ul>
* @throws PackageManagerException if session fails the check
*/
- private void checkNonOverlappingWithStagedSessions(@NonNull PackageInstallerSession session)
+ @VisibleForTesting
+ void checkNonOverlappingWithStagedSessions(@NonNull PackageInstallerSession session)
throws PackageManagerException {
if (session.isMultiPackage()) {
// We cannot say a parent session overlaps until we process its children
@@ -747,6 +749,13 @@
continue;
}
+ if (stagedSession.getCommittedMillis() > session.getCommittedMillis()) {
+ // Ignore sessions that are committed after the provided session. When there are
+ // overlaps between sessions, we will fail the one committed later instead of
+ // the earlier one.
+ continue;
+ }
+
// From here on, stagedSession is a parent active staged session
// Check if session is one of the active sessions
@@ -793,7 +802,8 @@
}
}
- private void createSession(@NonNull PackageInstallerSession sessionInfo) {
+ @VisibleForTesting
+ void createSession(@NonNull PackageInstallerSession sessionInfo) {
synchronized (mStagedSessions) {
mStagedSessions.append(sessionInfo.sessionId, sessionInfo);
}
diff --git a/services/core/java/com/android/server/policy/DisplayFoldController.java b/services/core/java/com/android/server/policy/DisplayFoldController.java
index b007a75..ff51237 100644
--- a/services/core/java/com/android/server/policy/DisplayFoldController.java
+++ b/services/core/java/com/android/server/policy/DisplayFoldController.java
@@ -20,12 +20,10 @@
import android.content.Context;
import android.graphics.Rect;
import android.hardware.ICameraService;
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener;
-import android.hardware.SensorManager;
+import android.hardware.devicestate.DeviceStateManager;
import android.hardware.display.DisplayManagerInternal;
import android.os.Handler;
+import android.os.HandlerExecutor;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.util.Slog;
@@ -63,7 +61,8 @@
private String mFocusedApp;
private final DisplayFoldDurationLogger mDurationLogger = new DisplayFoldDurationLogger();
- DisplayFoldController(WindowManagerInternal windowManagerInternal,
+ DisplayFoldController(
+ Context context, WindowManagerInternal windowManagerInternal,
DisplayManagerInternal displayManagerInternal,
@Nullable CameraServiceProxy cameraServiceProxy, int displayId, Rect foldedArea,
Handler handler) {
@@ -73,6 +72,10 @@
mDisplayId = displayId;
mFoldedArea = new Rect(foldedArea);
mHandler = handler;
+
+ DeviceStateManager deviceStateManager = context.getSystemService(DeviceStateManager.class);
+ deviceStateManager.registerDeviceStateListener(new DeviceStateListener(context),
+ new HandlerExecutor(handler));
}
void finishedGoingToSleep() {
@@ -83,11 +86,7 @@
mDurationLogger.onFinishedWakingUp(mFolded);
}
- void requestDeviceFolded(boolean folded) {
- mHandler.post(() -> setDeviceFolded(folded));
- }
-
- void setDeviceFolded(boolean folded) {
+ private void setDeviceFolded(boolean folded) {
if (mFolded != null && mFolded == folded) {
return;
}
@@ -179,33 +178,6 @@
}
}
- /**
- * Only used for the case that persist.debug.force_foldable is set.
- * This is using proximity sensor to simulate the fold state switch.
- */
- static DisplayFoldController createWithProxSensor(Context context, int displayId) {
- final SensorManager sensorManager = context.getSystemService(SensorManager.class);
- final Sensor proxSensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
- if (proxSensor == null) {
- return null;
- }
-
- final DisplayFoldController result = create(context, displayId);
- sensorManager.registerListener(new SensorEventListener() {
- @Override
- public void onSensorChanged(SensorEvent event) {
- result.requestDeviceFolded(event.values[0] < 1f);
- }
-
- @Override
- public void onAccuracyChanged(Sensor sensor, int accuracy) {
- // Ignore.
- }
- }, proxSensor, SensorManager.SENSOR_DELAY_NORMAL);
-
- return result;
- }
-
void onDefaultDisplayFocusChanged(String pkg) {
mFocusedApp = pkg;
}
@@ -227,7 +199,26 @@
foldedArea = Rect.unflattenFromString(configFoldedArea);
}
- return new DisplayFoldController(windowManagerService, displayService, cameraServiceProxy,
- displayId, foldedArea, DisplayThread.getHandler());
+ return new DisplayFoldController(context, windowManagerService, displayService,
+ cameraServiceProxy, displayId, foldedArea, DisplayThread.getHandler());
+ }
+
+ /**
+ * Listens to changes in device state and reports the state as folded if the device state
+ * matches the value in the {@link com.android.internal.R.integer.config_foldedDeviceState}
+ * resource.
+ */
+ private class DeviceStateListener implements DeviceStateManager.DeviceStateListener {
+ private final int mFoldedDeviceState;
+
+ DeviceStateListener(Context context) {
+ mFoldedDeviceState = context.getResources().getInteger(
+ com.android.internal.R.integer.config_foldedDeviceState);
+ }
+
+ @Override
+ public void onDeviceStateChanged(int deviceState) {
+ setDeviceFolded(deviceState == mFoldedDeviceState);
+ }
}
}
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index a9a94eb..6919cea 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -472,7 +472,6 @@
int mLidKeyboardAccessibility;
int mLidNavigationAccessibility;
- private boolean mLidControlsDisplayFold;
int mShortPressOnPowerBehavior;
int mLongPressOnPowerBehavior;
int mVeryLongPressOnPowerBehavior;
@@ -648,8 +647,8 @@
break;
case MSG_LAUNCH_ASSIST:
final int deviceId = msg.arg1;
- final String hint = (String) msg.obj;
- launchAssistAction(hint, deviceId);
+ final Long eventTime = (Long) msg.obj;
+ launchAssistAction(null /* hint */, deviceId, eventTime);
break;
case MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK:
launchVoiceAssistWithWakeLock();
@@ -659,7 +658,7 @@
finishPowerKeyPress();
break;
case MSG_POWER_LONG_PRESS:
- powerLongPress();
+ powerLongPress((Long) msg.obj /* eventTime */);
break;
case MSG_POWER_VERY_LONG_PRESS:
powerVeryLongPress();
@@ -934,9 +933,10 @@
// Wait for a long press or for the button to be released to decide what to do.
if (hasLongPressOnPowerBehavior()) {
if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
- powerLongPress();
+ powerLongPress(event.getEventTime());
} else {
- Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
+ Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS,
+ event.getEventTime());
msg.setAsynchronous(true);
mHandler.sendMessageDelayed(msg,
ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
@@ -953,9 +953,10 @@
if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) {
if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
- powerLongPress();
+ powerLongPress(event.getEventTime());
} else {
- Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
+ Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS,
+ event.getEventTime());
msg.setAsynchronous(true);
mHandler.sendMessageDelayed(msg,
ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
@@ -1188,7 +1189,7 @@
return 1;
}
- private void powerLongPress() {
+ private void powerLongPress(long eventTime) {
final int behavior = getResolvedLongPressOnPowerBehavior();
switch (behavior) {
case LONG_PRESS_POWER_NOTHING:
@@ -1221,7 +1222,7 @@
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false,
"Power - Long Press - Go To Assistant");
final int powerKeyDeviceId = Integer.MIN_VALUE;
- launchAssistAction(null, powerKeyDeviceId);
+ launchAssistAction(null, powerKeyDeviceId, eventTime);
break;
}
}
@@ -1624,7 +1625,8 @@
} else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
if (!keyguardOn) {
// Post to main thread to avoid blocking input pipeline.
- mHandler.post(() -> handleLongPressOnHome(event.getDeviceId()));
+ mHandler.post(() -> handleLongPressOnHome(event.getDeviceId(),
+ event.getEventTime()));
}
}
return -1;
@@ -1637,7 +1639,7 @@
}
}
- private void handleLongPressOnHome(int deviceId) {
+ private void handleLongPressOnHome(int deviceId, long eventTime) {
if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_NOTHING) {
return;
}
@@ -1649,7 +1651,7 @@
launchAllAppsAction();
break;
case LONG_PRESS_HOME_ASSIST:
- launchAssistAction(null, deviceId);
+ launchAssistAction(null, deviceId, eventTime);
break;
case LONG_PRESS_HOME_NOTIFICATION_PANEL:
toggleNotificationPanel();
@@ -1789,8 +1791,6 @@
com.android.internal.R.integer.config_lidKeyboardAccessibility);
mLidNavigationAccessibility = mContext.getResources().getInteger(
com.android.internal.R.integer.config_lidNavigationAccessibility);
- mLidControlsDisplayFold = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_lidControlsDisplayFold);
mAllowTheaterModeWakeFromKey = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_allowTheaterModeWakeFromKey);
@@ -1847,12 +1847,7 @@
readConfigurationDependentBehaviors();
- if (mLidControlsDisplayFold) {
- mDisplayFoldController = DisplayFoldController.create(context, DEFAULT_DISPLAY);
- } else if (SystemProperties.getBoolean("persist.debug.force_foldable", false)) {
- mDisplayFoldController = DisplayFoldController.createWithProxSensor(context,
- DEFAULT_DISPLAY);
- }
+ mDisplayFoldController = DisplayFoldController.create(context, DEFAULT_DISPLAY);
mAccessibilityManager = (AccessibilityManager) context.getSystemService(
Context.ACCESSIBILITY_SERVICE);
@@ -2791,7 +2786,8 @@
if (down) {
mPendingMetaAction = true;
} else if (mPendingMetaAction) {
- launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD, event.getDeviceId());
+ launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD, event.getDeviceId(),
+ event.getEventTime());
}
return -1;
}
@@ -3161,22 +3157,24 @@
// various parts of the UI.
/** Asks the status bar to startAssist(), usually a full "assistant" interface */
- private void launchAssistAction(String hint, int deviceId) {
+ private void launchAssistAction(String hint, int deviceId, long eventTime) {
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
if (!isUserSetupComplete()) {
// Disable opening assist window during setup
return;
}
+
+ // Add Intent Extra data.
Bundle args = null;
- if (deviceId > Integer.MIN_VALUE || hint != null) {
- args = new Bundle();
- if (deviceId > Integer.MIN_VALUE) {
- args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, deviceId);
- }
- if (hint != null) {
- args.putBoolean(hint, true);
- }
+ args = new Bundle();
+ if (deviceId > Integer.MIN_VALUE) {
+ args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, deviceId);
}
+ if (hint != null) {
+ args.putBoolean(hint, true);
+ }
+ args.putLong(Intent.EXTRA_TIME, eventTime);
+
((SearchManager) mContext.createContextAsUser(UserHandle.of(mCurrentUserId), 0)
.getSystemService(Context.SEARCH_SERVICE)).launchAssist(args);
}
@@ -3798,7 +3796,7 @@
final boolean longPressed = event.getRepeatCount() > 0;
if (down && !longPressed) {
Message msg = mHandler.obtainMessage(MSG_LAUNCH_ASSIST, event.getDeviceId(),
- 0 /* unused */, null /* hint */);
+ 0 /* unused */, event.getEventTime() /* eventTime */);
msg.setAsynchronous(true);
msg.sendToTarget();
}
@@ -4019,9 +4017,12 @@
return true;
}
- // Watches handle BACK specially
+ // Watches handle BACK and hardware buttons specially
if (mHasFeatureWatch && (keyCode == KeyEvent.KEYCODE_BACK
- || keyCode == KeyEvent.KEYCODE_STEM_PRIMARY)) {
+ || keyCode == KeyEvent.KEYCODE_STEM_PRIMARY
+ || keyCode == KeyEvent.KEYCODE_STEM_1
+ || keyCode == KeyEvent.KEYCODE_STEM_2
+ || keyCode == KeyEvent.KEYCODE_STEM_3)) {
return false;
}
@@ -4860,9 +4861,7 @@
private void applyLidSwitchState() {
final int lidState = mDefaultDisplayPolicy.getLidState();
- if (mLidControlsDisplayFold && mDisplayFoldController != null) {
- mDisplayFoldController.requestDeviceFolded(lidState == LID_CLOSED);
- } else if (lidState == LID_CLOSED) {
+ if (lidState == LID_CLOSED) {
int lidBehavior = getLidBehavior();
switch (lidBehavior) {
case LID_BEHAVIOR_LOCK:
diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java
index 8eb66cd..eea79f6 100644
--- a/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java
+++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java
@@ -1138,6 +1138,7 @@
ipw.println(mLastDeviceConfigProperties.getString(key, null));
}
}
+ ipw.decreaseIndent();
ipw.println("mAccessibilityEnabled=" + mAccessibilityEnabled.get());
ipw.println("mAutomotiveProjectionActive=" + mAutomotiveProjectionActive.get());
@@ -1191,7 +1192,7 @@
}
private void dumpMap(PrintWriter pw, ArrayMap<String, String> map) {
- if (map == null) {
+ if (map == null || map.size() == 0) {
pw.println("N/A");
return;
}
diff --git a/services/core/java/com/android/server/recoverysystem/OWNERS b/services/core/java/com/android/server/recoverysystem/OWNERS
new file mode 100644
index 0000000..79ded0d
--- /dev/null
+++ b/services/core/java/com/android/server/recoverysystem/OWNERS
@@ -0,0 +1,2 @@
+rvrolyk@google.com
+zhaojiac@google.com
diff --git a/services/core/java/com/android/server/rollback/Rollback.java b/services/core/java/com/android/server/rollback/Rollback.java
index d9b6702..e12991a 100644
--- a/services/core/java/com/android/server/rollback/Rollback.java
+++ b/services/core/java/com/android/server/rollback/Rollback.java
@@ -51,6 +51,7 @@
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.server.LocalServices;
+import com.android.server.RescueParty;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import java.io.File;
@@ -540,7 +541,10 @@
PackageInstaller.Session parentSession = packageInstaller.openSession(
parentSessionId);
+ List<String> packageNames = new ArrayList<>(info.getPackages().size());
for (PackageRollbackInfo pkgRollbackInfo : info.getPackages()) {
+ packageNames.add(pkgRollbackInfo.getPackageName());
+
if (pkgRollbackInfo.isApkInApex()) {
// No need to issue a downgrade install request for apk-in-apex. It will
// be rolled back when its parent apex is downgraded.
@@ -601,6 +605,9 @@
parentSession.addChildSessionId(sessionId);
}
+ // Clear flags.
+ RescueParty.resetDeviceConfigForPackages(packageNames);
+
Consumer<Intent> onResult = result -> {
mHandler.post(() -> {
assertInWorkerThread();
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 192a003..bd66aa3 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -1316,7 +1316,7 @@
private SparseIntArray getExtensionVersions() {
// This list must be updated whenever the current API level is increased, or should be
// replaced when we have another way of determining the relevant SDK versions.
- final int[] relevantSdkVersions = { Build.VERSION_CODES.R };
+ final int[] relevantSdkVersions = { Build.VERSION_CODES.R, Build.VERSION_CODES.S };
SparseIntArray result = new SparseIntArray(relevantSdkVersions.length);
for (int i = 0; i < relevantSdkVersions.length; i++) {
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index 8438652..8071672 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -1532,8 +1532,8 @@
// All shared app gids are accounted together.
uid = LAST_SHARED_APPLICATION_GID;
mutateInPlace = true;
- } else if (UserHandle.isApp(uid)) {
- // Apps are accounted under their app id.
+ } else {
+ // Everything else is accounted under their base uid.
uid = UserHandle.getAppId(uid);
}
@@ -3164,9 +3164,7 @@
mAttributionTag = attributionTag;
mUid = uid;
mOp = op;
- mHash = ((op.getOpCode() * 961
- + (attributionTag == null ? 0 : attributionTag.hashCode()) * 31
- + packageName.hashCode() + RANDOM_SEED) & 0x7fffffff) % 100;
+ mHash = ((packageName.hashCode() + RANDOM_SEED) & 0x7fffffff) % 100;
}
}
diff --git a/services/core/java/com/android/server/timedetector/OWNERS b/services/core/java/com/android/server/timedetector/OWNERS
index 09447a9..8f80897 100644
--- a/services/core/java/com/android/server/timedetector/OWNERS
+++ b/services/core/java/com/android/server/timedetector/OWNERS
@@ -1 +1,3 @@
-include /core/java/android/app/timezone/OWNERS
+# Bug component: 847766
+mingaleev@google.com
+include /core/java/android/app/timedetector/OWNERS
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorService.java b/services/core/java/com/android/server/timedetector/TimeDetectorService.java
index 7de0e87..c7fe204 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorService.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorService.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.timedetector.GnssTimeSuggestion;
import android.app.timedetector.ITimeDetectorService;
import android.app.timedetector.ManualTimeSuggestion;
import android.app.timedetector.NetworkTimeSuggestion;
@@ -129,6 +130,14 @@
mHandler.post(() -> mTimeDetectorStrategy.suggestNetworkTime(timeSignal));
}
+ @Override
+ public void suggestGnssTime(@NonNull GnssTimeSuggestion timeSignal) {
+ enforceSuggestGnssTimePermission();
+ Objects.requireNonNull(timeSignal);
+
+ mHandler.post(() -> mTimeDetectorStrategy.suggestGnssTime(timeSignal));
+ }
+
/** Internal method for handling the auto time setting being changed. */
@VisibleForTesting
public void handleAutoTimeDetectionChanged() {
@@ -162,4 +171,10 @@
android.Manifest.permission.SET_TIME,
"set time");
}
+
+ private void enforceSuggestGnssTimePermission() {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.SET_TIME,
+ "suggest gnss time");
+ }
}
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
index f278ef6..b539f01 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java
@@ -18,6 +18,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.app.timedetector.GnssTimeSuggestion;
import android.app.timedetector.ManualTimeSuggestion;
import android.app.timedetector.NetworkTimeSuggestion;
import android.app.timedetector.TelephonyTimeSuggestion;
@@ -41,7 +42,7 @@
*/
public interface TimeDetectorStrategy extends Dumpable {
- @IntDef({ ORIGIN_TELEPHONY, ORIGIN_MANUAL, ORIGIN_NETWORK })
+ @IntDef({ ORIGIN_TELEPHONY, ORIGIN_MANUAL, ORIGIN_NETWORK, ORIGIN_GNSS })
@Retention(RetentionPolicy.SOURCE)
@interface Origin {}
@@ -57,6 +58,10 @@
@Origin
int ORIGIN_NETWORK = 3;
+ /** Used when a time value originated from a gnss signal. */
+ @Origin
+ int ORIGIN_GNSS = 4;
+
/** Processes the suggested time from telephony sources. */
void suggestTelephonyTime(@NonNull TelephonyTimeSuggestion timeSuggestion);
@@ -71,6 +76,9 @@
/** Processes the suggested time from network sources. */
void suggestNetworkTime(@NonNull NetworkTimeSuggestion timeSuggestion);
+ /** Processes the suggested time from gnss sources. */
+ void suggestGnssTime(@NonNull GnssTimeSuggestion timeSuggestion);
+
/**
* Handles the auto-time configuration changing For example, when the auto-time setting is
* toggled on or off.
@@ -100,6 +108,8 @@
return "network";
case ORIGIN_TELEPHONY:
return "telephony";
+ case ORIGIN_GNSS:
+ return "gnss";
default:
throw new IllegalArgumentException("origin=" + origin);
}
@@ -117,6 +127,8 @@
return ORIGIN_NETWORK;
case "telephony":
return ORIGIN_TELEPHONY;
+ case "gnss":
+ return ORIGIN_GNSS;
default:
throw new IllegalArgumentException("originString=" + originString);
}
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
index b5d49cf..48af81e5 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
@@ -23,6 +23,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AlarmManager;
+import android.app.timedetector.GnssTimeSuggestion;
import android.app.timedetector.ManualTimeSuggestion;
import android.app.timedetector.NetworkTimeSuggestion;
import android.app.timedetector.TelephonyTimeSuggestion;
@@ -108,6 +109,10 @@
private final ReferenceWithHistory<NetworkTimeSuggestion> mLastNetworkSuggestion =
new ReferenceWithHistory<>(KEEP_SUGGESTION_HISTORY_SIZE);
+ @GuardedBy("this")
+ private final ReferenceWithHistory<GnssTimeSuggestion> mLastGnssSuggestion =
+ new ReferenceWithHistory<>(KEEP_SUGGESTION_HISTORY_SIZE);
+
/**
* The interface used by the strategy to interact with the surrounding service.
*
@@ -165,6 +170,20 @@
}
@Override
+ public synchronized void suggestGnssTime(@NonNull GnssTimeSuggestion timeSuggestion) {
+ final TimestampedValue<Long> newUtcTime = timeSuggestion.getUtcTime();
+
+ if (!validateAutoSuggestionTime(newUtcTime, timeSuggestion)) {
+ return;
+ }
+
+ mLastGnssSuggestion.set(timeSuggestion);
+
+ String reason = "GNSS time suggestion received: suggestion=" + timeSuggestion;
+ doAutoTimeDetection(reason);
+ }
+
+ @Override
public synchronized boolean suggestManualTime(@NonNull ManualTimeSuggestion suggestion) {
final TimestampedValue<Long> newUtcTime = suggestion.getUtcTime();
@@ -278,6 +297,11 @@
mLastNetworkSuggestion.dump(ipw);
ipw.decreaseIndent(); // level 2
+ ipw.println("Gnss suggestion history:");
+ ipw.increaseIndent(); // level 2
+ mLastGnssSuggestion.dump(ipw);
+ ipw.decreaseIndent(); // level 2
+
ipw.decreaseIndent(); // level 1
}
@@ -383,6 +407,14 @@
+ ", networkSuggestion=" + networkSuggestion
+ ", detectionReason=" + detectionReason;
}
+ } else if (origin == ORIGIN_GNSS) {
+ GnssTimeSuggestion gnssTimeSuggestion = findLatestValidGnssSuggestion();
+ if (gnssTimeSuggestion != null) {
+ newUtcTime = gnssTimeSuggestion.getUtcTime();
+ cause = "Found good gnss suggestion."
+ + ", gnssTimeSuggestion=" + gnssTimeSuggestion
+ + ", detectionReason=" + detectionReason;
+ }
} else {
Slog.w(LOG_TAG, "Unknown or unsupported origin=" + origin
+ " in " + Arrays.toString(originPriorities)
@@ -524,6 +556,26 @@
return networkSuggestion;
}
+ /** Returns the latest, valid, gnss suggestion. Returns {@code null} if there isn't one. */
+ @GuardedBy("this")
+ @Nullable
+ private GnssTimeSuggestion findLatestValidGnssSuggestion() {
+ GnssTimeSuggestion gnssTimeSuggestion = mLastGnssSuggestion.get();
+ if (gnssTimeSuggestion == null) {
+ // No gnss suggestions received. This is normal if there's no gnss signal.
+ return null;
+ }
+
+ TimestampedValue<Long> utcTime = gnssTimeSuggestion.getUtcTime();
+ long elapsedRealTimeMillis = mCallback.elapsedRealtimeMillis();
+ if (!validateSuggestionUtcTime(elapsedRealTimeMillis, utcTime)) {
+ // The latest suggestion is not valid, usually due to its age.
+ return null;
+ }
+
+ return gnssTimeSuggestion;
+ }
+
@GuardedBy("this")
private boolean setSystemClockIfRequired(
@Origin int origin, @NonNull TimestampedValue<Long> time, @NonNull String cause) {
@@ -652,6 +704,16 @@
}
/**
+ * Returns the latest valid gnss suggestion. Not intended for general use: it is used during
+ * tests to check strategy behavior.
+ */
+ @VisibleForTesting
+ @Nullable
+ public synchronized GnssTimeSuggestion findLatestValidGnssSuggestionForTests() {
+ return findLatestValidGnssSuggestion();
+ }
+
+ /**
* A method used to inspect state during tests. Not intended for general use.
*/
@VisibleForTesting
@@ -669,6 +731,15 @@
return mLastNetworkSuggestion.get();
}
+ /**
+ * A method used to inspect state during tests. Not intended for general use.
+ */
+ @VisibleForTesting
+ @Nullable
+ public synchronized GnssTimeSuggestion getLatestGnssSuggestion() {
+ return mLastGnssSuggestion.get();
+ }
+
private static boolean validateSuggestionUtcTime(
long elapsedRealtimeMillis, TimestampedValue<Long> utcTime) {
long referenceTimeMillis = utcTime.getReferenceTimeMillis();
diff --git a/services/core/java/com/android/server/timezone/OWNERS b/services/core/java/com/android/server/timezone/OWNERS
index 09447a9..8f80897 100644
--- a/services/core/java/com/android/server/timezone/OWNERS
+++ b/services/core/java/com/android/server/timezone/OWNERS
@@ -1 +1,3 @@
-include /core/java/android/app/timezone/OWNERS
+# Bug component: 847766
+mingaleev@google.com
+include /core/java/android/app/timedetector/OWNERS
diff --git a/services/core/java/com/android/server/timezonedetector/OWNERS b/services/core/java/com/android/server/timezonedetector/OWNERS
index 09447a9..8f80897 100644
--- a/services/core/java/com/android/server/timezonedetector/OWNERS
+++ b/services/core/java/com/android/server/timezonedetector/OWNERS
@@ -1 +1,3 @@
-include /core/java/android/app/timezone/OWNERS
+# Bug component: 847766
+mingaleev@google.com
+include /core/java/android/app/timedetector/OWNERS
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 791d74a..a2b0990 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -2538,9 +2538,7 @@
@Override
public int getLockTaskModeState() {
- synchronized (mGlobalLock) {
- return getLockTaskController().getLockTaskModeState();
- }
+ return getLockTaskController().getLockTaskModeState();
}
@Override
diff --git a/services/core/xsd/device-state-config/OWNERS b/services/core/xsd/device-state-config/OWNERS
new file mode 100644
index 0000000..d9b0e2e
--- /dev/null
+++ b/services/core/xsd/device-state-config/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/devicestate/OWNERS
diff --git a/services/core/xsd/device-state-config/device-state-config.xsd b/services/core/xsd/device-state-config/device-state-config.xsd
index 5014503..94a398f 100644
--- a/services/core/xsd/device-state-config/device-state-config.xsd
+++ b/services/core/xsd/device-state-config/device-state-config.xsd
@@ -37,15 +37,21 @@
</xs:restriction>
</xs:simpleType>
</xs:element>
- <xs:element name="name" type="xs:string" minOccurs="0" />
+ <xs:element name="name" type="xs:string" minOccurs="0">
+ <xs:annotation name="nullable" />
+ </xs:element>
<xs:element name="conditions" type="conditions" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="conditions">
<xs:sequence>
- <xs:element name="lid-switch" type="lidSwitchCondition" minOccurs="0" />
- <xs:element name="sensor" type="sensorCondition" minOccurs="0" maxOccurs="unbounded" />
+ <xs:element name="lid-switch" type="lidSwitchCondition" minOccurs="0">
+ <xs:annotation name="nullable" />
+ </xs:element>
+ <xs:element name="sensor" type="sensorCondition" minOccurs="0" maxOccurs="unbounded">
+ <xs:annotation name="nullable" />
+ </xs:element>
</xs:sequence>
</xs:complexType>
@@ -66,12 +72,20 @@
<xs:complexType name="numericRange">
<xs:sequence>
<xs:choice minOccurs="0">
- <xs:element name="min" type="xs:decimal" />
- <xs:element name="min-inclusive" type="xs:decimal" />
+ <xs:element name="min" type="xs:decimal">
+ <xs:annotation name="nullable" />
+ </xs:element>
+ <xs:element name="min-inclusive" type="xs:decimal">
+ <xs:annotation name="nullable" />
+ </xs:element>
</xs:choice>
<xs:choice minOccurs="0">
- <xs:element name="max" type="xs:decimal" />
- <xs:element name="max-inclusive" type="xs:decimal"/>
+ <xs:element name="max" type="xs:decimal">
+ <xs:annotation name="nullable" />
+ </xs:element>
+ <xs:element name="max-inclusive" type="xs:decimal">
+ <xs:annotation name="nullable" />
+ </xs:element>
</xs:choice>
</xs:sequence>
</xs:complexType>
diff --git a/services/core/xsd/device-state-config/schema/current.txt b/services/core/xsd/device-state-config/schema/current.txt
index b396af0..08fccf8 100644
--- a/services/core/xsd/device-state-config/schema/current.txt
+++ b/services/core/xsd/device-state-config/schema/current.txt
@@ -3,19 +3,19 @@
public class Conditions {
ctor public Conditions();
- method public com.android.server.policy.devicestate.config.LidSwitchCondition getLidSwitch();
- method public java.util.List<com.android.server.policy.devicestate.config.SensorCondition> getSensor();
- method public void setLidSwitch(com.android.server.policy.devicestate.config.LidSwitchCondition);
+ method @Nullable public com.android.server.policy.devicestate.config.LidSwitchCondition getLidSwitch();
+ method @Nullable public java.util.List<com.android.server.policy.devicestate.config.SensorCondition> getSensor();
+ method public void setLidSwitch(@Nullable com.android.server.policy.devicestate.config.LidSwitchCondition);
}
public class DeviceState {
ctor public DeviceState();
method public com.android.server.policy.devicestate.config.Conditions getConditions();
method public java.math.BigInteger getIdentifier();
- method public String getName();
+ method @Nullable public String getName();
method public void setConditions(com.android.server.policy.devicestate.config.Conditions);
method public void setIdentifier(java.math.BigInteger);
- method public void setName(String);
+ method public void setName(@Nullable String);
}
public class DeviceStateConfig {
@@ -31,14 +31,14 @@
public class NumericRange {
ctor public NumericRange();
- method public java.math.BigDecimal getMaxInclusive_optional();
- method public java.math.BigDecimal getMax_optional();
- method public java.math.BigDecimal getMinInclusive_optional();
- method public java.math.BigDecimal getMin_optional();
- method public void setMaxInclusive_optional(java.math.BigDecimal);
- method public void setMax_optional(java.math.BigDecimal);
- method public void setMinInclusive_optional(java.math.BigDecimal);
- method public void setMin_optional(java.math.BigDecimal);
+ method @Nullable public java.math.BigDecimal getMaxInclusive_optional();
+ method @Nullable public java.math.BigDecimal getMax_optional();
+ method @Nullable public java.math.BigDecimal getMinInclusive_optional();
+ method @Nullable public java.math.BigDecimal getMin_optional();
+ method public void setMaxInclusive_optional(@Nullable java.math.BigDecimal);
+ method public void setMax_optional(@Nullable java.math.BigDecimal);
+ method public void setMinInclusive_optional(@Nullable java.math.BigDecimal);
+ method public void setMin_optional(@Nullable java.math.BigDecimal);
}
public class SensorCondition {
diff --git a/services/core/xsd/display-device-config/OWNERS b/services/core/xsd/display-device-config/OWNERS
new file mode 100644
index 0000000..20b75be
--- /dev/null
+++ b/services/core/xsd/display-device-config/OWNERS
@@ -0,0 +1,3 @@
+include /services/core/java/com/android/server/display/OWNERS
+
+flc@google.com
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java
index 31ba199..c766ca0 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java
@@ -16,14 +16,15 @@
package com.android.server.devicepolicy;
+import android.annotation.UserIdInt;
import android.app.admin.DeviceAdminInfo;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.os.FileUtils;
import android.os.PersistableBundle;
-import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.IndentingPrintWriter;
import android.util.Slog;
import android.util.TypedXmlPullParser;
import android.util.TypedXmlSerializer;
@@ -77,13 +78,14 @@
private static final String ATTR_DEVICE_PROVISIONING_CONFIG_APPLIED =
"device-provisioning-config-applied";
private static final String ATTR_DEVICE_PAIRED = "device-paired";
+
private static final String TAG = DevicePolicyManagerService.LOG_TAG;
private static final boolean VERBOSE_LOG = false; // DO NOT SUBMIT WITH TRUE
int mFailedPasswordAttempts = 0;
boolean mPasswordValidAtLastCheckpoint = true;
- int mUserHandle;
+ final @UserIdInt int mUserId;
int mPasswordOwner = -1;
long mLastMaximumTimeToLock = -1;
boolean mUserSetupComplete = false;
@@ -144,8 +146,8 @@
// apps were suspended or unsuspended.
boolean mAppsSuspended = false;
- DevicePolicyData(int userHandle) {
- mUserHandle = userHandle;
+ DevicePolicyData(@UserIdInt int userId) {
+ mUserId = userId;
}
/**
@@ -156,7 +158,7 @@
try {
File chooseForWrite = file.chooseForWrite();
if (VERBOSE_LOG) {
- Slog.v(TAG, "Storing data for user " + policyData.mUserHandle + " on "
+ Slog.v(TAG, "Storing data for user " + policyData.mUserId + " on "
+ chooseForWrite);
}
stream = new FileOutputStream(chooseForWrite, false);
@@ -365,7 +367,7 @@
FileInputStream stream = null;
File file = journaledFile.chooseForRead();
if (VERBOSE_LOG) {
- Slog.v(TAG, "Loading data for user " + policy.mUserHandle + " from " + file);
+ Slog.v(TAG, "Loading data for user " + policy.mUserId + " from " + file);
}
boolean needsRewrite = false;
try {
@@ -556,4 +558,37 @@
}
}
}
+
+ void dump(IndentingPrintWriter pw) {
+ pw.println();
+ pw.println("Enabled Device Admins (User " + mUserId + ", provisioningState: "
+ + mUserProvisioningState + "):");
+ final int n = mAdminList.size();
+ for (int i = 0; i < n; i++) {
+ ActiveAdmin ap = mAdminList.get(i);
+ if (ap != null) {
+ pw.increaseIndent();
+ pw.print(ap.info.getComponent().flattenToShortString());
+ pw.println(":");
+ pw.increaseIndent();
+ ap.dump(pw);
+ pw.decreaseIndent();
+ pw.decreaseIndent();
+ }
+ }
+ if (!mRemovingAdmins.isEmpty()) {
+ pw.increaseIndent();
+ pw.println("Removing Device Admins (User " + mUserId + "): " + mRemovingAdmins);
+ pw.decreaseIndent();
+ }
+ pw.println();
+ pw.increaseIndent();
+ pw.print("mPasswordOwner="); pw.println(mPasswordOwner);
+ pw.print("mUserControlDisabledPackages=");
+ pw.println(mUserControlDisabledPackages);
+ pw.print("mAppsSuspended="); pw.println(mAppsSuspended);
+ pw.print("mUserSetupComplete="); pw.println(mUserSetupComplete);
+ pw.print("mAffiliationIds="); pw.println(mAffiliationIds);
+ pw.decreaseIndent();
+ }
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index d35d806..a27e6b2 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -215,7 +215,6 @@
import android.os.PowerManager;
import android.os.PowerManagerInternal;
import android.os.Process;
-import android.os.RecoverySystem;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.ResultReceiver;
@@ -245,7 +244,6 @@
import android.security.keystore.AttestationUtils;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.ParcelableKeyGenParameterSpec;
-import android.service.persistentdata.PersistentDataBlockManager;
import android.stats.devicepolicy.DevicePolicyEnums;
import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
@@ -940,7 +938,7 @@
// Persist updates if the removed package was an admin or delegate.
if (removedAdmin || removedDelegate) {
- saveSettingsLocked(policy.mUserHandle);
+ saveSettingsLocked(policy.mUserId);
}
}
if (removedAdmin) {
@@ -1026,6 +1024,25 @@
mSafetyChecker = new OneTimeSafetyChecker(this, operation, safe);
}
+ // TODO(b/175392542): remove if not needed by ManagedProvisioning app anymore
+ @Override
+ public void factoryReset(String reason) {
+ Preconditions.checkCallAuthorization(
+ hasCallingOrSelfPermission(permission.MASTER_CLEAR));
+ Slog.w(LOG_TAG, "factoryReset(): " + reason);
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ FactoryResetter.factoryReset(mContext, /* shutdown= */ false, reason,
+ /* force= */ false, /* wipeEuicc= */ false, /* wipeAdoptableStorage= */ false,
+ /* wipeFactoryResetProtection= */ false);
+ } catch (IOException e) {
+ // Shouldn't happen.
+ Slog.wtf(LOG_TAG, "Could not factory reset", e);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
/**
* Unit test will subclass it to inject mocks.
*/
@@ -1276,8 +1293,10 @@
}
void recoverySystemRebootWipeUserData(boolean shutdown, String reason, boolean force,
- boolean wipeEuicc) throws IOException {
- RecoverySystem.rebootWipeUserData(mContext, shutdown, reason, force, wipeEuicc);
+ boolean wipeEuicc, boolean wipeExtRequested, boolean wipeResetProtectionData)
+ throws IOException {
+ FactoryResetter.factoryReset(mContext, shutdown, reason, force, wipeEuicc,
+ wipeExtRequested, wipeResetProtectionData);
}
boolean systemPropertiesGetBoolean(String key, boolean def) {
@@ -6073,17 +6092,14 @@
caller.getUserId()));
}
- private void forceWipeDeviceNoLock(boolean wipeExtRequested, String reason, boolean wipeEuicc) {
+ private void forceWipeDeviceNoLock(boolean wipeExtRequested, String reason, boolean wipeEuicc,
+ boolean wipeResetProtectionData) {
wtfIfInLock();
boolean success = false;
try {
- if (wipeExtRequested) {
- StorageManager sm = (StorageManager) mContext.getSystemService(
- Context.STORAGE_SERVICE);
- sm.wipeAdoptableDisks();
- }
mInjector.recoverySystemRebootWipeUserData(
- /*shutdown=*/ false, reason, /*force=*/ true, /*wipeEuicc=*/ wipeEuicc);
+ /* shutdown= */ false, reason, /* force= */ true, /* wipeEuicc= */ wipeEuicc,
+ wipeExtRequested, wipeResetProtectionData);
success = true;
} catch (IOException | SecurityException e) {
Slog.w(LOG_TAG, "Failed requesting data wipe", e);
@@ -6230,22 +6246,12 @@
+ " restriction is set for user " + userId);
}
- if ((flags & WIPE_RESET_PROTECTION_DATA) != 0) {
- PersistentDataBlockManager manager = (PersistentDataBlockManager)
- mContext.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
- if (manager != null) {
- manager.wipe();
- }
- }
-
- // TODO If split user is enabled and the device owner is set in the primary user
- // (rather than system), we should probably trigger factory reset. Current code just
- // removes that user (but still clears FRP...)
if (userId == UserHandle.USER_SYSTEM) {
- forceWipeDeviceNoLock(/*wipeExtRequested=*/ (
- flags & WIPE_EXTERNAL_STORAGE) != 0,
+ forceWipeDeviceNoLock(
+ (flags & WIPE_EXTERNAL_STORAGE) != 0,
internalReason,
- /*wipeEuicc=*/ (flags & WIPE_EUICC) != 0);
+ (flags & WIPE_EUICC) != 0,
+ (flags & WIPE_RESET_PROTECTION_DATA) != 0);
} else {
forceWipeUser(userId, wipeReasonForUser, (flags & WIPE_SILENTLY) != 0);
}
@@ -8746,37 +8752,7 @@
int userCount = mUserData.size();
for (int u = 0; u < userCount; u++) {
DevicePolicyData policy = getUserData(mUserData.keyAt(u));
- pw.println();
- pw.println("Enabled Device Admins (User " + policy.mUserHandle
- + ", provisioningState: " + policy.mUserProvisioningState + "):");
- final int n = policy.mAdminList.size();
- for (int i = 0; i < n; i++) {
- ActiveAdmin ap = policy.mAdminList.get(i);
- if (ap != null) {
- pw.increaseIndent();
- pw.print(ap.info.getComponent().flattenToShortString());
- pw.println(":");
- pw.increaseIndent();
- ap.dump(pw);
- pw.decreaseIndent();
- pw.decreaseIndent();
- }
- }
- if (!policy.mRemovingAdmins.isEmpty()) {
- pw.increaseIndent();
- pw.println("Removing Device Admins (User " + policy.mUserHandle + "): "
- + policy.mRemovingAdmins);
- pw.decreaseIndent();
- }
- pw.println();
- pw.increaseIndent();
- pw.print("mPasswordOwner="); pw.println(policy.mPasswordOwner);
- pw.print("mUserControlDisabledPackages=");
- pw.println(policy.mUserControlDisabledPackages);
- pw.print("mAppsSuspended="); pw.println(policy.mAppsSuspended);
- pw.print("mUserSetupComplete="); pw.println(policy.mUserSetupComplete);
- pw.print("mAffiliationIds="); pw.println(policy.mAffiliationIds);
- pw.decreaseIndent();
+ policy.dump(pw);
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/FactoryResetter.java b/services/devicepolicy/java/com/android/server/devicepolicy/FactoryResetter.java
new file mode 100644
index 0000000..1ee6f8f
--- /dev/null
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/FactoryResetter.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.devicepolicy;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.RecoverySystem;
+import android.os.UserManager;
+import android.os.storage.StorageManager;
+import android.service.persistentdata.PersistentDataBlockManager;
+import android.util.Log;
+
+import com.android.internal.util.Preconditions;
+
+import java.io.IOException;
+
+/**
+ * Entry point for "factory reset" requests.
+ */
+final class FactoryResetter {
+
+ private static final String TAG = FactoryResetter.class.getSimpleName();
+
+ // TODO(b/171603586): use an object that's constructed with a Builder instead (then update
+ // javadoc)
+ /**
+ * Factory reset the device.
+ */
+ public static void factoryReset(Context context, boolean shutdown, String reason,
+ boolean force, boolean wipeEuicc, boolean wipeAdoptableStorage,
+ boolean wipeFactoryResetProtection) throws IOException {
+ Log.i(TAG, "factoryReset(): shutdown=" + shutdown + ", force=" + force
+ + ", wipeEuicc=" + wipeEuicc + ", wipeAdoptableStorage=" + wipeAdoptableStorage
+ + ", wipeFRP=" + wipeFactoryResetProtection);
+
+ Preconditions.checkCallAuthorization(context.checkCallingOrSelfPermission(
+ android.Manifest.permission.MASTER_CLEAR) == PackageManager.PERMISSION_GRANTED);
+
+ UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ if (!force && um.hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET)) {
+ throw new SecurityException("Factory reset is not allowed for this user.");
+ }
+
+ if (wipeFactoryResetProtection) {
+ PersistentDataBlockManager manager = (PersistentDataBlockManager)
+ context.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
+ if (manager != null) {
+ Log.w(TAG, "Wiping factory reset protection");
+ manager.wipe();
+ } else {
+ Log.w(TAG, "No need to wipe factory reset protection");
+ }
+ }
+
+ if (wipeAdoptableStorage) {
+ Log.w(TAG, "Wiping adoptable storage");
+ StorageManager sm = (StorageManager) context.getSystemService(
+ Context.STORAGE_SERVICE);
+ sm.wipeAdoptableDisks();
+ }
+
+ RecoverySystem.rebootWipeUserData(context, shutdown, reason, force, wipeEuicc);
+ }
+
+ private FactoryResetter() {
+ throw new UnsupportedOperationException("Contains only static methods");
+ }
+}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 92c64f8..242cee8 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1281,6 +1281,10 @@
inputManager = new InputManagerService(context);
t.traceEnd();
+ t.traceBegin("DeviceStateManagerService");
+ mSystemServiceManager.startService(DeviceStateManagerService.class);
+ t.traceEnd();
+
if (!disableCameraService) {
t.traceBegin("StartCameraServiceProxy");
mSystemServiceManager.startService(CameraServiceProxy.class);
@@ -1374,10 +1378,6 @@
mSystemServiceManager.startService(AppIntegrityManagerService.class);
t.traceEnd();
- t.traceBegin("DeviceStateManagerService");
- mSystemServiceManager.startService(DeviceStateManagerService.class);
- t.traceEnd();
-
} catch (Throwable e) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting core service");
diff --git a/services/net/Android.bp b/services/net/Android.bp
index a52fe12..daf1c53 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -37,7 +37,6 @@
"java/android/net/util/NetworkConstants.java",
"java/android/net/IpMemoryStore.java",
"java/android/net/NetworkMonitorManager.java",
- "java/android/net/TcpKeepalivePacketData.java",
],
sdk_version: "module_current",
min_sdk_version: "30",
diff --git a/services/net/java/android/net/TcpKeepalivePacketData.java b/services/net/java/android/net/TcpKeepalivePacketData.java
deleted file mode 100644
index 4875c7c..0000000
--- a/services/net/java/android/net/TcpKeepalivePacketData.java
+++ /dev/null
@@ -1,268 +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.
- */
-package android.net;
-
-import static android.net.SocketKeepalive.ERROR_INVALID_IP_ADDRESS;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.system.OsConstants;
-
-import com.android.net.module.util.IpUtils;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.Objects;
-
-/**
- * Represents the actual tcp keep alive packets which will be used for hardware offload.
- * @hide
- */
-public class TcpKeepalivePacketData extends KeepalivePacketData implements Parcelable {
- private static final String TAG = "TcpKeepalivePacketData";
-
- /** TCP sequence number. */
- public final int tcpSeq;
-
- /** TCP ACK number. */
- public final int tcpAck;
-
- /** TCP RCV window. */
- public final int tcpWnd;
-
- /** TCP RCV window scale. */
- public final int tcpWndScale;
-
- /** IP TOS. */
- public final int ipTos;
-
- /** IP TTL. */
- public final int ipTtl;
-
- private static final int IPV4_HEADER_LENGTH = 20;
- private static final int IPV6_HEADER_LENGTH = 40;
- private static final int TCP_HEADER_LENGTH = 20;
-
- // This should only be constructed via static factory methods, such as
- // tcpKeepalivePacket.
- private TcpKeepalivePacketData(final TcpKeepalivePacketDataParcelable tcpDetails,
- final byte[] data) throws InvalidPacketException, UnknownHostException {
- super(InetAddress.getByAddress(tcpDetails.srcAddress), tcpDetails.srcPort,
- InetAddress.getByAddress(tcpDetails.dstAddress), tcpDetails.dstPort, data);
- tcpSeq = tcpDetails.seq;
- tcpAck = tcpDetails.ack;
- // In the packet, the window is shifted right by the window scale.
- tcpWnd = tcpDetails.rcvWnd;
- tcpWndScale = tcpDetails.rcvWndScale;
- ipTos = tcpDetails.tos;
- ipTtl = tcpDetails.ttl;
- }
-
- private TcpKeepalivePacketData(final InetAddress srcAddress, int srcPort,
- final InetAddress dstAddress, int dstPort, final byte[] data, int tcpSeq,
- int tcpAck, int tcpWnd, int tcpWndScale, int ipTos, int ipTtl)
- throws InvalidPacketException {
- super(srcAddress, srcPort, dstAddress, dstPort, data);
- this.tcpSeq = tcpSeq;
- this.tcpAck = tcpAck;
- this.tcpWnd = tcpWnd;
- this.tcpWndScale = tcpWndScale;
- this.ipTos = ipTos;
- this.ipTtl = ipTtl;
- }
-
- /**
- * Factory method to create tcp keepalive packet structure.
- */
- public static TcpKeepalivePacketData tcpKeepalivePacket(
- TcpKeepalivePacketDataParcelable tcpDetails) throws InvalidPacketException {
- final byte[] packet;
- try {
- if ((tcpDetails.srcAddress != null) && (tcpDetails.dstAddress != null)
- && (tcpDetails.srcAddress.length == 4 /* V4 IP length */)
- && (tcpDetails.dstAddress.length == 4 /* V4 IP length */)) {
- packet = buildV4Packet(tcpDetails);
- } else {
- // TODO: support ipv6
- throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS);
- }
- return new TcpKeepalivePacketData(tcpDetails, packet);
- } catch (UnknownHostException e) {
- throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS);
- }
-
- }
-
- /**
- * Build ipv4 tcp keepalive packet, not including the link-layer header.
- */
- // TODO : if this code is ever moved to the network stack, factorize constants with the ones
- // over there.
- private static byte[] buildV4Packet(TcpKeepalivePacketDataParcelable tcpDetails) {
- final int length = IPV4_HEADER_LENGTH + TCP_HEADER_LENGTH;
- ByteBuffer buf = ByteBuffer.allocate(length);
- buf.order(ByteOrder.BIG_ENDIAN);
- buf.put((byte) 0x45); // IP version and IHL
- buf.put((byte) tcpDetails.tos); // TOS
- buf.putShort((short) length);
- buf.putInt(0x00004000); // ID, flags=DF, offset
- buf.put((byte) tcpDetails.ttl); // TTL
- buf.put((byte) OsConstants.IPPROTO_TCP);
- final int ipChecksumOffset = buf.position();
- buf.putShort((short) 0); // IP checksum
- buf.put(tcpDetails.srcAddress);
- buf.put(tcpDetails.dstAddress);
- buf.putShort((short) tcpDetails.srcPort);
- buf.putShort((short) tcpDetails.dstPort);
- buf.putInt(tcpDetails.seq); // Sequence Number
- buf.putInt(tcpDetails.ack); // ACK
- buf.putShort((short) 0x5010); // TCP length=5, flags=ACK
- buf.putShort((short) (tcpDetails.rcvWnd >> tcpDetails.rcvWndScale)); // Window size
- final int tcpChecksumOffset = buf.position();
- buf.putShort((short) 0); // TCP checksum
- // URG is not set therefore the urgent pointer is zero.
- buf.putShort((short) 0); // Urgent pointer
-
- buf.putShort(ipChecksumOffset, IpUtils.ipChecksum(buf, 0));
- buf.putShort(tcpChecksumOffset, IpUtils.tcpChecksum(
- buf, 0, IPV4_HEADER_LENGTH, TCP_HEADER_LENGTH));
-
- return buf.array();
- }
-
- // TODO: add buildV6Packet.
-
- @Override
- public boolean equals(@Nullable final Object o) {
- if (!(o instanceof TcpKeepalivePacketData)) return false;
- final TcpKeepalivePacketData other = (TcpKeepalivePacketData) o;
- final InetAddress srcAddress = getSrcAddress();
- final InetAddress dstAddress = getDstAddress();
- return srcAddress.equals(other.getSrcAddress())
- && dstAddress.equals(other.getDstAddress())
- && getSrcPort() == other.getSrcPort()
- && getDstPort() == other.getDstPort()
- && this.tcpAck == other.tcpAck
- && this.tcpSeq == other.tcpSeq
- && this.tcpWnd == other.tcpWnd
- && this.tcpWndScale == other.tcpWndScale
- && this.ipTos == other.ipTos
- && this.ipTtl == other.ipTtl;
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(getSrcAddress(), getDstAddress(), getSrcPort(), getDstPort(),
- tcpAck, tcpSeq, tcpWnd, tcpWndScale, ipTos, ipTtl);
- }
-
- /**
- * Parcelable Implementation.
- * Note that this object implements parcelable (and needs to keep doing this as it inherits
- * from a class that does), but should usually be parceled as a stable parcelable using
- * the toStableParcelable() and fromStableParcelable() methods.
- */
- public int describeContents() {
- return 0;
- }
-
- /** Write to parcel. */
- public void writeToParcel(Parcel out, int flags) {
- out.writeString(getSrcAddress().getHostAddress());
- out.writeString(getDstAddress().getHostAddress());
- out.writeInt(getSrcPort());
- out.writeInt(getDstPort());
- out.writeByteArray(getPacket());
- out.writeInt(tcpSeq);
- out.writeInt(tcpAck);
- out.writeInt(tcpWnd);
- out.writeInt(tcpWndScale);
- out.writeInt(ipTos);
- out.writeInt(ipTtl);
- }
-
- private static TcpKeepalivePacketData readFromParcel(Parcel in) throws InvalidPacketException {
- InetAddress srcAddress = InetAddresses.parseNumericAddress(in.readString());
- InetAddress dstAddress = InetAddresses.parseNumericAddress(in.readString());
- int srcPort = in.readInt();
- int dstPort = in.readInt();
- byte[] packet = in.createByteArray();
- int tcpSeq = in.readInt();
- int tcpAck = in.readInt();
- int tcpWnd = in.readInt();
- int tcpWndScale = in.readInt();
- int ipTos = in.readInt();
- int ipTtl = in.readInt();
- return new TcpKeepalivePacketData(srcAddress, srcPort, dstAddress, dstPort, packet, tcpSeq,
- tcpAck, tcpWnd, tcpWndScale, ipTos, ipTtl);
- }
-
- /** Parcelable Creator. */
- public static final @NonNull Parcelable.Creator<TcpKeepalivePacketData> CREATOR =
- new Parcelable.Creator<TcpKeepalivePacketData>() {
- public TcpKeepalivePacketData createFromParcel(Parcel in) {
- try {
- return readFromParcel(in);
- } catch (InvalidPacketException e) {
- throw new IllegalArgumentException(
- "Invalid NAT-T keepalive data: " + e.getError());
- }
- }
-
- public TcpKeepalivePacketData[] newArray(int size) {
- return new TcpKeepalivePacketData[size];
- }
- };
-
- /**
- * Convert this TcpKeepalivePacketData to a TcpKeepalivePacketDataParcelable.
- */
- @NonNull
- public TcpKeepalivePacketDataParcelable toStableParcelable() {
- final TcpKeepalivePacketDataParcelable parcel = new TcpKeepalivePacketDataParcelable();
- final InetAddress srcAddress = getSrcAddress();
- final InetAddress dstAddress = getDstAddress();
- parcel.srcAddress = srcAddress.getAddress();
- parcel.srcPort = getSrcPort();
- parcel.dstAddress = dstAddress.getAddress();
- parcel.dstPort = getDstPort();
- parcel.seq = tcpSeq;
- parcel.ack = tcpAck;
- parcel.rcvWnd = tcpWnd;
- parcel.rcvWndScale = tcpWndScale;
- parcel.tos = ipTos;
- parcel.ttl = ipTtl;
- return parcel;
- }
-
- @Override
- public String toString() {
- return "saddr: " + getSrcAddress()
- + " daddr: " + getDstAddress()
- + " sport: " + getSrcPort()
- + " dport: " + getDstPort()
- + " seq: " + tcpSeq
- + " ack: " + tcpAck
- + " wnd: " + tcpWnd
- + " wndScale: " + tcpWndScale
- + " tos: " + ipTos
- + " ttl: " + ipTtl;
- }
-}
diff --git a/services/net/java/android/net/ip/IpClientManager.java b/services/net/java/android/net/ip/IpClientManager.java
index 94bc1ec..b45405f 100644
--- a/services/net/java/android/net/ip/IpClientManager.java
+++ b/services/net/java/android/net/ip/IpClientManager.java
@@ -21,6 +21,7 @@
import android.net.NattKeepalivePacketData;
import android.net.ProxyInfo;
import android.net.TcpKeepalivePacketData;
+import android.net.TcpKeepalivePacketDataParcelable;
import android.net.shared.Layer2Information;
import android.net.shared.ProvisioningConfiguration;
import android.net.util.KeepalivePacketDataUtil;
@@ -217,9 +218,20 @@
* Add a TCP keepalive packet filter before setting up keepalive offload.
*/
public boolean addKeepalivePacketFilter(int slot, TcpKeepalivePacketData pkt) {
+ return addKeepalivePacketFilter(slot, KeepalivePacketDataUtil.toStableParcelable(pkt));
+ }
+
+ /**
+ * Add a TCP keepalive packet filter before setting up keepalive offload.
+ * @deprecated This method is for use on pre-S platforms where TcpKeepalivePacketData is not
+ * system API. On newer platforms use
+ * addKeepalivePacketFilter(int, TcpKeepalivePacketData) instead.
+ */
+ @Deprecated
+ public boolean addKeepalivePacketFilter(int slot, TcpKeepalivePacketDataParcelable pkt) {
final long token = Binder.clearCallingIdentity();
try {
- mIpClient.addKeepalivePacketFilter(slot, pkt.toStableParcelable());
+ mIpClient.addKeepalivePacketFilter(slot, pkt);
return true;
} catch (RemoteException e) {
log("Error adding Keepalive Packet Filter ", e);
diff --git a/services/net/java/android/net/util/KeepalivePacketDataUtil.java b/services/net/java/android/net/util/KeepalivePacketDataUtil.java
index 4466ea0..6e539bb 100644
--- a/services/net/java/android/net/util/KeepalivePacketDataUtil.java
+++ b/services/net/java/android/net/util/KeepalivePacketDataUtil.java
@@ -16,20 +16,47 @@
package android.net.util;
+import static android.net.SocketKeepalive.ERROR_INVALID_IP_ADDRESS;
+
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.InvalidPacketException;
+import android.net.KeepalivePacketData;
import android.net.NattKeepalivePacketData;
import android.net.NattKeepalivePacketDataParcelable;
+import android.net.TcpKeepalivePacketData;
+import android.net.TcpKeepalivePacketDataParcelable;
+import android.os.Build;
+import android.system.OsConstants;
+import android.util.Log;
+
+import com.android.net.module.util.IpUtils;
import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
-/** @hide */
+/**
+ * Utility class to convert to/from keepalive data parcelables.
+ *
+ * TODO: move to networkstack-client library when it is moved to frameworks/libs/net.
+ * This class cannot go into other shared libraries as it depends on NetworkStack AIDLs.
+ * @hide
+ */
public final class KeepalivePacketDataUtil {
- /**
- * Convert this NattKeepalivePacketData to a NattKeepalivePacketDataParcelable.
+ private static final int IPV4_HEADER_LENGTH = 20;
+ private static final int IPV6_HEADER_LENGTH = 40;
+ private static final int TCP_HEADER_LENGTH = 20;
+
+ private static final String TAG = KeepalivePacketDataUtil.class.getSimpleName();
+
+ /**
+ * Convert a NattKeepalivePacketData to a NattKeepalivePacketDataParcelable.
*/
@NonNull
public static NattKeepalivePacketDataParcelable toStableParcelable(
- NattKeepalivePacketData pkt) {
+ @NonNull NattKeepalivePacketData pkt) {
final NattKeepalivePacketDataParcelable parcel = new NattKeepalivePacketDataParcelable();
final InetAddress srcAddress = pkt.getSrcAddress();
final InetAddress dstAddress = pkt.getDstAddress();
@@ -39,4 +66,158 @@
parcel.dstPort = pkt.getDstPort();
return parcel;
}
+
+ /**
+ * Convert a TcpKeepalivePacketData to a TcpKeepalivePacketDataParcelable.
+ */
+ @NonNull
+ public static TcpKeepalivePacketDataParcelable toStableParcelable(
+ @NonNull TcpKeepalivePacketData pkt) {
+ final TcpKeepalivePacketDataParcelable parcel = new TcpKeepalivePacketDataParcelable();
+ final InetAddress srcAddress = pkt.getSrcAddress();
+ final InetAddress dstAddress = pkt.getDstAddress();
+ parcel.srcAddress = srcAddress.getAddress();
+ parcel.srcPort = pkt.getSrcPort();
+ parcel.dstAddress = dstAddress.getAddress();
+ parcel.dstPort = pkt.getDstPort();
+ parcel.seq = pkt.tcpSeq;
+ parcel.ack = pkt.tcpAck;
+ parcel.rcvWnd = pkt.tcpWindow;
+ parcel.rcvWndScale = pkt.tcpWindowScale;
+ parcel.tos = pkt.ipTos;
+ parcel.ttl = pkt.ipTtl;
+ return parcel;
+ }
+
+ /**
+ * Factory method to create tcp keepalive packet structure.
+ * @hide
+ */
+ public static TcpKeepalivePacketData fromStableParcelable(
+ TcpKeepalivePacketDataParcelable tcpDetails) throws InvalidPacketException {
+ final byte[] packet;
+ try {
+ if ((tcpDetails.srcAddress != null) && (tcpDetails.dstAddress != null)
+ && (tcpDetails.srcAddress.length == 4 /* V4 IP length */)
+ && (tcpDetails.dstAddress.length == 4 /* V4 IP length */)) {
+ packet = buildV4Packet(tcpDetails);
+ } else {
+ // TODO: support ipv6
+ throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS);
+ }
+ return new TcpKeepalivePacketData(
+ InetAddress.getByAddress(tcpDetails.srcAddress),
+ tcpDetails.srcPort,
+ InetAddress.getByAddress(tcpDetails.dstAddress),
+ tcpDetails.dstPort,
+ packet,
+ tcpDetails.seq, tcpDetails.ack, tcpDetails.rcvWnd, tcpDetails.rcvWndScale,
+ tcpDetails.tos, tcpDetails.ttl);
+ } catch (UnknownHostException e) {
+ throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS);
+ }
+
+ }
+
+ /**
+ * Build ipv4 tcp keepalive packet, not including the link-layer header.
+ */
+ // TODO : if this code is ever moved to the network stack, factorize constants with the ones
+ // over there.
+ private static byte[] buildV4Packet(TcpKeepalivePacketDataParcelable tcpDetails) {
+ final int length = IPV4_HEADER_LENGTH + TCP_HEADER_LENGTH;
+ ByteBuffer buf = ByteBuffer.allocate(length);
+ buf.order(ByteOrder.BIG_ENDIAN);
+ buf.put((byte) 0x45); // IP version and IHL
+ buf.put((byte) tcpDetails.tos); // TOS
+ buf.putShort((short) length);
+ buf.putInt(0x00004000); // ID, flags=DF, offset
+ buf.put((byte) tcpDetails.ttl); // TTL
+ buf.put((byte) OsConstants.IPPROTO_TCP);
+ final int ipChecksumOffset = buf.position();
+ buf.putShort((short) 0); // IP checksum
+ buf.put(tcpDetails.srcAddress);
+ buf.put(tcpDetails.dstAddress);
+ buf.putShort((short) tcpDetails.srcPort);
+ buf.putShort((short) tcpDetails.dstPort);
+ buf.putInt(tcpDetails.seq); // Sequence Number
+ buf.putInt(tcpDetails.ack); // ACK
+ buf.putShort((short) 0x5010); // TCP length=5, flags=ACK
+ buf.putShort((short) (tcpDetails.rcvWnd >> tcpDetails.rcvWndScale)); // Window size
+ final int tcpChecksumOffset = buf.position();
+ buf.putShort((short) 0); // TCP checksum
+ // URG is not set therefore the urgent pointer is zero.
+ buf.putShort((short) 0); // Urgent pointer
+
+ buf.putShort(ipChecksumOffset, com.android.net.module.util.IpUtils.ipChecksum(buf, 0));
+ buf.putShort(tcpChecksumOffset, IpUtils.tcpChecksum(
+ buf, 0, IPV4_HEADER_LENGTH, TCP_HEADER_LENGTH));
+
+ return buf.array();
+ }
+
+ // TODO: add buildV6Packet.
+
+ /**
+ * Get a {@link TcpKeepalivePacketDataParcelable} from {@link KeepalivePacketData}, if the
+ * generic class actually contains TCP keepalive data.
+ *
+ * @deprecated This method is used on R platforms where android.net.TcpKeepalivePacketData was
+ * not yet system API. Newer platforms should use android.net.TcpKeepalivePacketData directly.
+ *
+ * @param data A {@link KeepalivePacketData} that may contain TCP keepalive data.
+ * @return A parcelable containing TCP keepalive data, or null if the input data does not
+ * contain TCP keepalive data.
+ */
+ @Deprecated
+ @SuppressWarnings("AndroidFrameworkCompatChange") // API version check used to Log.wtf
+ @Nullable
+ public static TcpKeepalivePacketDataParcelable parseTcpKeepalivePacketData(
+ @Nullable KeepalivePacketData data) {
+ if (data == null) return null;
+
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R) {
+ Log.wtf(TAG, "parseTcpKeepalivePacketData should not be used after R, use "
+ + "TcpKeepalivePacketData instead.");
+ }
+
+ // Reconstruct TcpKeepalivePacketData from the packet contained in KeepalivePacketData
+ final ByteBuffer buffer = ByteBuffer.wrap(data.getPacket());
+ buffer.order(ByteOrder.BIG_ENDIAN);
+
+ // Most of the fields are accessible from the KeepalivePacketData superclass: instead of
+ // using Struct to parse everything, just extract the extra fields necessary for
+ // TcpKeepalivePacketData.
+ final int tcpSeq;
+ final int tcpAck;
+ final int wndSize;
+ final int ipTos;
+ final int ttl;
+ try {
+ // This only support IPv4, because TcpKeepalivePacketData only supports IPv4 for R and
+ // below, and this method should not be used on newer platforms.
+ tcpSeq = buffer.getInt(IPV4_HEADER_LENGTH + 4);
+ tcpAck = buffer.getInt(IPV4_HEADER_LENGTH + 8);
+ wndSize = buffer.getShort(IPV4_HEADER_LENGTH + 14);
+ ipTos = buffer.get(1);
+ ttl = buffer.get(8);
+ } catch (IndexOutOfBoundsException e) {
+ return null;
+ }
+
+ final TcpKeepalivePacketDataParcelable p = new TcpKeepalivePacketDataParcelable();
+ p.srcAddress = data.getSrcAddress().getAddress();
+ p.srcPort = data.getSrcPort();
+ p.dstAddress = data.getDstAddress().getAddress();
+ p.dstPort = data.getDstPort();
+ p.seq = tcpSeq;
+ p.ack = tcpAck;
+ // TcpKeepalivePacketData could actually use non-zero wndScale, but this does not affect
+ // actual functionality as generated packets will be the same (no wndScale option added)
+ p.rcvWnd = wndSize;
+ p.rcvWndScale = 0;
+ p.tos = ipTos;
+ p.ttl = ttl;
+ return p;
+ }
}
diff --git a/services/tests/mockingservicestests/Android.bp b/services/tests/mockingservicestests/Android.bp
index 03083c1..7c935d5 100644
--- a/services/tests/mockingservicestests/Android.bp
+++ b/services/tests/mockingservicestests/Android.bp
@@ -19,6 +19,7 @@
static_libs: [
"services.core",
+ "services.devicepolicy",
"services.net",
"services.usage",
"service-jobscheduler",
diff --git a/services/tests/mockingservicestests/src/com/android/server/devicepolicy/FactoryResetterTest.java b/services/tests/mockingservicestests/src/com/android/server/devicepolicy/FactoryResetterTest.java
new file mode 100644
index 0000000..45160dc
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/devicepolicy/FactoryResetterTest.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.devicepolicy;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertThrows;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.RecoverySystem;
+import android.os.UserManager;
+import android.os.storage.StorageManager;
+import android.platform.test.annotations.Presubmit;
+import android.service.persistentdata.PersistentDataBlockManager;
+import android.util.Log;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+
+/**
+ * Run it as {@code atest FrameworksMockingCoreTests:FactoryResetterTest}
+ */
+@Presubmit
+public final class FactoryResetterTest {
+
+ private static final String TAG = FactoryResetterTest.class.getSimpleName();
+
+ // Fixed parameters
+ private static final String REASON = "self-destruct";
+ private static final boolean SHUTDOWN = true;
+ private static final boolean WIPE_EUICC = true;
+
+ // Parameters under test
+ private static final boolean FORCE = true;
+ private static final boolean NO_FORCE = false;
+ private static final boolean WIPE_ADOPTABLE_STORAGE = true;
+ private static final boolean NO_WIPE_ADOPTABLE_STORAGE = false;
+ private static final boolean WIPE_FACTORY_RESET_PROTECTION = true;
+ private static final boolean NO_WIPE_FACTORY_RESET_PROTECTION = false;
+
+ private MockitoSession mSession;
+
+ private @Mock Context mContext;
+ private @Mock StorageManager mSm;
+ private @Mock PersistentDataBlockManager mPdbm;
+ private @Mock UserManager mUm;
+
+ @Before
+ public void startSession() {
+ mSession = mockitoSession()
+ .initMocks(this)
+ .spyStatic(RecoverySystem.class)
+ .strictness(Strictness.LENIENT)
+ .startMocking();
+
+ when(mContext.getSystemService(any(String.class))).thenAnswer((inv) -> {
+ Log.d(TAG, "Mocking " + inv);
+ String service = (String) inv.getArguments()[0];
+ switch (service) {
+ case Context.PERSISTENT_DATA_BLOCK_SERVICE:
+ return mPdbm;
+ case Context.STORAGE_SERVICE:
+ return mSm;
+ case Context.USER_SERVICE:
+ return mUm;
+ default:
+ throw new IllegalArgumentException("Not expecting call for " + service);
+ }
+ });
+
+ doAnswer((inv) -> {
+ Log.d(TAG, "Mocking " + inv);
+ return null;
+ }).when(() -> RecoverySystem.rebootWipeUserData(any(), anyBoolean(), any(),
+ anyBoolean(), anyBoolean()));
+ }
+
+ @After
+ public void finishSession() {
+ if (mSession == null) {
+ Log.w(TAG, "finishSession(): no session");
+ return;
+ }
+ mSession.finishMocking();
+ }
+
+ @Test
+ public void testFactoryReset_noMasterClearPermission() throws Exception {
+ revokeMasterClearPermission();
+ setFactoryResetRestriction(/* allowed= */ true);
+
+ assertThrows(SecurityException.class,
+ () -> FactoryResetter.factoryReset(mContext, SHUTDOWN, REASON, NO_FORCE,
+ WIPE_EUICC, WIPE_ADOPTABLE_STORAGE, WIPE_FACTORY_RESET_PROTECTION));
+
+ verifyWipeAdoptableStorageNotCalled();
+ verifyWipeFactoryResetProtectionNotCalled();
+ verifyRebootWipeUserDataNotCalled();
+ }
+
+ @Test
+ public void testFactoryReset_noForceDisallowed()
+ throws Exception {
+ setFactoryResetRestriction(/* allowed= */ false);
+
+ assertThrows(SecurityException.class,
+ () -> FactoryResetter.factoryReset(mContext, SHUTDOWN, REASON, NO_FORCE,
+ WIPE_EUICC, WIPE_ADOPTABLE_STORAGE, WIPE_FACTORY_RESET_PROTECTION));
+
+ verifyWipeAdoptableStorageNotCalled();
+ verifyWipeFactoryResetProtectionNotCalled();
+ verifyRebootWipeUserDataNotCalled();
+ }
+
+ @Test
+ public void testFactoryReset_noForceAllowed() throws Exception {
+ setFactoryResetRestriction(/* allowed= */ true);
+
+ FactoryResetter.factoryReset(mContext, SHUTDOWN, REASON, NO_FORCE,
+ WIPE_EUICC, WIPE_ADOPTABLE_STORAGE, WIPE_FACTORY_RESET_PROTECTION);
+
+ verifyWipeAdoptableStorageCalled();
+ verifyWipeFactoryResetProtectionCalled();
+ verifyRebootWipeUserDataCalled(NO_FORCE);
+ }
+
+ @Test
+ public void testFactoryReset_forceDisallowed() throws Exception {
+ setFactoryResetRestriction(/* allowed= */ false);
+
+ FactoryResetter.factoryReset(mContext, SHUTDOWN, REASON, FORCE,
+ WIPE_EUICC, WIPE_ADOPTABLE_STORAGE, WIPE_FACTORY_RESET_PROTECTION);
+
+ verifyWipeAdoptableStorageCalled();
+ verifyWipeFactoryResetProtectionCalled();
+ verifyRebootWipeUserDataCalled(FORCE);
+ }
+
+ @Test
+ public void testFactoryReset_bothFalse() throws Exception {
+ FactoryResetter.factoryReset(mContext, SHUTDOWN, REASON, FORCE,
+ WIPE_EUICC, NO_WIPE_ADOPTABLE_STORAGE, NO_WIPE_FACTORY_RESET_PROTECTION);
+
+ verifyWipeAdoptableStorageNotCalled();
+ verifyWipeFactoryResetProtectionNotCalled();
+ verifyRebootWipeUserDataCalled(FORCE);
+ }
+
+ @Test
+ public void testFactoryReset_storageOnly() throws Exception {
+ FactoryResetter.factoryReset(mContext, SHUTDOWN, REASON, FORCE,
+ WIPE_EUICC, WIPE_ADOPTABLE_STORAGE, NO_WIPE_FACTORY_RESET_PROTECTION);
+
+ verifyWipeAdoptableStorageCalled();
+ verifyWipeFactoryResetProtectionNotCalled();
+ verifyRebootWipeUserDataCalled(FORCE);
+ }
+
+ @Test
+ public void testFactoryReset_frpOnly() throws Exception {
+ FactoryResetter.factoryReset(mContext, SHUTDOWN, REASON, FORCE,
+ WIPE_EUICC, NO_WIPE_ADOPTABLE_STORAGE, WIPE_FACTORY_RESET_PROTECTION);
+
+ verifyWipeAdoptableStorageNotCalled();
+ verifyWipeFactoryResetProtectionCalled();
+ verifyRebootWipeUserDataCalled(FORCE);
+ }
+
+ private void revokeMasterClearPermission() {
+ when(mContext.checkCallingOrSelfPermission(android.Manifest.permission.MASTER_CLEAR))
+ .thenReturn(PackageManager.PERMISSION_DENIED);
+ }
+
+ private void setFactoryResetRestriction(boolean allowed) {
+ when(mUm.hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET)).thenReturn(!allowed);
+ }
+
+ private void verifyRebootWipeUserDataNotCalled() {
+ verify(() -> RecoverySystem.rebootWipeUserData(any(), anyBoolean(), any(), anyBoolean(),
+ anyBoolean()), never());
+ }
+
+ private void verifyRebootWipeUserDataCalled(boolean force) {
+ verify(() -> RecoverySystem.rebootWipeUserData(mContext, SHUTDOWN, REASON, force,
+ WIPE_EUICC));
+ }
+
+ private void verifyWipeAdoptableStorageNotCalled() {
+ verify(mSm, never()).wipeAdoptableDisks();
+ }
+
+ private void verifyWipeAdoptableStorageCalled() {
+ verify(mSm).wipeAdoptableDisks();
+ }
+
+ private void verifyWipeFactoryResetProtectionNotCalled() {
+ verify(mPdbm, never()).wipe();
+ }
+
+ private void verifyWipeFactoryResetProtectionCalled() {
+ verify(mPdbm).wipe();
+ }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
index dbdee979..af4130d 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
@@ -19,11 +19,14 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.mockito.ArgumentMatchers.anyFloat;
+import static org.mockito.Mockito.never;
import android.content.Context;
import android.content.res.Resources;
@@ -40,7 +43,9 @@
import com.android.dx.mockito.inline.extended.StaticMockitoSession;
import com.android.server.LocalServices;
+import com.android.server.display.LocalDisplayAdapter.BacklightAdapter;
import com.android.server.lights.LightsManager;
+import com.android.server.lights.LogicalLight;
import com.google.common.truth.Truth;
@@ -78,6 +83,8 @@
private Resources mMockedResources;
@Mock
private LightsManager mMockedLightsManager;
+ @Mock
+ private LogicalLight mMockedBacklight;
private Handler mHandler;
@@ -492,6 +499,49 @@
waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
}
+ @Test
+ public void testBacklightAdapter_withSurfaceControlSupport() {
+ final Binder displayToken = new Binder();
+ doReturn(true).when(() -> SurfaceControl.getDisplayBrightnessSupport(displayToken));
+
+ // Test as default display
+ BacklightAdapter ba = new BacklightAdapter(displayToken, true /*isDefault*/);
+ ba.setBrightness(0.514f);
+ verify(() -> SurfaceControl.setDisplayBrightness(displayToken, 0.514f));
+
+ // Test as not default display
+ BacklightAdapter ba2 = new BacklightAdapter(displayToken,
+ false /*isDefault*/);
+ ba2.setBrightness(0.323f);
+ verify(() -> SurfaceControl.setDisplayBrightness(displayToken, 0.323f));
+ }
+
+ @Test
+ public void testBacklightAdapter_withoutSourceControlSupport_defaultDisplay() {
+ final Binder displayToken = new Binder();
+ doReturn(false).when(() -> SurfaceControl.getDisplayBrightnessSupport(displayToken));
+ doReturn(mMockedBacklight).when(mMockedLightsManager)
+ .getLight(LightsManager.LIGHT_ID_BACKLIGHT);
+
+ BacklightAdapter ba = new BacklightAdapter(displayToken, true /*isDefault*/);
+ ba.setBrightness(0.123f);
+ verify(mMockedBacklight).setBrightness(0.123f);
+ }
+
+ @Test
+ public void testBacklightAdapter_withoutSourceControlSupport_nonDefaultDisplay() {
+ final Binder displayToken = new Binder();
+ doReturn(false).when(() -> SurfaceControl.getDisplayBrightnessSupport(displayToken));
+ doReturn(mMockedBacklight).when(mMockedLightsManager)
+ .getLight(LightsManager.LIGHT_ID_BACKLIGHT);
+
+ BacklightAdapter ba = new BacklightAdapter(displayToken, false /*isDefault*/);
+ ba.setBrightness(0.456f);
+
+ // Adapter does not forward any brightness in this case.
+ verify(mMockedBacklight, never()).setBrightness(anyFloat());
+ }
+
private void assertDisplayDpi(DisplayDeviceInfo info, int expectedPort,
float expectedXdpi,
float expectedYDpi,
diff --git a/services/tests/servicestests/res/raw/a11y_three_finger_swipe_down_gesture.log b/services/tests/servicestests/res/raw/a11y_three_finger_swipe_down_gesture.log
new file mode 100644
index 0000000..cf791f2
--- /dev/null
+++ b/services/tests/servicestests/res/raw/a11y_three_finger_swipe_down_gesture.log
@@ -0,0 +1,29 @@
+ * Gesture6_id30:Swipe down with 3 finger
+MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=500.0, y[0]=696.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=5273700, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_POINTER_DOWN(1), actionButton=0, id[0]=0, x[0]=500.0, y[0]=696.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=764.0, y[1]=801.0, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=5273700, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=500.0, y[0]=696.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=764.0, y[1]=801.0, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=5273709, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_POINTER_DOWN(2), actionButton=0, id[0]=0, x[0]=500.0, y[0]=696.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=764.0, y[1]=801.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=294.0, y[2]=849.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273709, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=500.0, y[0]=696.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=766.0, y[1]=811.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=294.0, y[2]=849.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273715, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=503.0, y[0]=699.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=773.0, y[1]=838.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=294.0, y[2]=849.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273725, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=521.0, y[0]=728.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=776.0, y[1]=862.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=305.0, y[2]=876.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273734, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=535.0, y[0]=765.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=782.0, y[1]=898.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=313.0, y[2]=911.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273741, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=545.0, y[0]=795.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=786.0, y[1]=918.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=323.0, y[2]=941.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273750, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=555.0, y[0]=832.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=790.0, y[1]=959.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=333.0, y[2]=976.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273758, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=560.0, y[0]=870.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=794.0, y[1]=988.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=339.0, y[2]=1020.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273767, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=565.0, y[0]=909.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=797.0, y[1]=1031.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=345.0, y[2]=1052.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273776, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=568.0, y[0]=948.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=801.0, y[1]=1060.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=348.0, y[2]=1102.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273784, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=570.0, y[0]=985.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=804.0, y[1]=1103.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=352.0, y[2]=1130.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273793, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=571.0, y[0]=1028.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=807.0, y[1]=1133.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=355.0, y[2]=1178.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273801, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=572.0, y[0]=1061.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=809.0, y[1]=1175.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=358.0, y[2]=1212.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273810, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=574.0, y[0]=1108.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=811.0, y[1]=1206.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=360.0, y[2]=1260.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273822, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=575.0, y[0]=1141.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=812.0, y[1]=1249.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=363.0, y[2]=1294.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273831, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=576.0, y[0]=1191.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=815.0, y[1]=1281.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=364.0, y[2]=1343.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273836, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=578.0, y[0]=1227.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=816.0, y[1]=1324.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=368.0, y[2]=1374.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273844, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=581.0, y[0]=1276.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=820.0, y[1]=1360.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=371.0, y[2]=1421.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273853, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=581.0, y[0]=1324.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=823.0, y[1]=1406.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=372.0, y[2]=1464.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273862, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=584.0, y[0]=1369.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=824.0, y[1]=1445.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=379.0, y[2]=1506.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273870, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=586.0, y[0]=1417.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=826.0, y[1]=1493.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=387.0, y[2]=1553.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273879, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=586.0, y[0]=1417.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=826.0, y[1]=1493.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=387.0, y[2]=1553.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273888, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_POINTER_UP(0), actionButton=0, id[0]=0, x[0]=586.0, y[0]=1417.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=826.0, y[1]=1493.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=387.0, y[2]=1553.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273895, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_POINTER_UP(0), actionButton=0, id[0]=1, x[0]=826.0, y[0]=1493.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=2, x[1]=387.0, y[1]=1553.0, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=5273895, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_UP, actionButton=0, id[0]=2, x[0]=387.0, y[0]=1553.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=5273895, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
\ No newline at end of file
diff --git a/services/tests/servicestests/res/raw/a11y_touch_explore_gesture.log b/services/tests/servicestests/res/raw/a11y_touch_explore_gesture.log
new file mode 100644
index 0000000..3cfb0a7
--- /dev/null
+++ b/services/tests/servicestests/res/raw/a11y_touch_explore_gesture.log
@@ -0,0 +1,4 @@
+* Gesture4_id-2:Touch explore
+MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=825.0, y[0]=2028.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=5258108, downTime=5258108, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=825.0, y[0]=2028.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=5258133, downTime=5258108, deviceId=4, source=0x1002, displayId=0 }
+MotionEvent { action=ACTION_UP, actionButton=0, id[0]=0, x[0]=825.0, y[0]=2028.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=5258141, downTime=5258108, deviceId=4, source=0x1002, displayId=0 }
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java
index 89bd625..7bf0bb8 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java
@@ -35,7 +35,10 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.verify;
+import android.accessibilityservice.AccessibilityGestureEvent;
+import android.accessibilityservice.AccessibilityService;
import android.content.Context;
import android.graphics.PointF;
import android.os.Looper;
@@ -51,6 +54,7 @@
import com.android.server.accessibility.AccessibilityManagerService;
import com.android.server.accessibility.EventStreamTransformation;
+import com.android.server.accessibility.utils.GestureLogParser;
import com.android.server.testutils.OffsettableClock;
import org.junit.Before;
@@ -58,7 +62,15 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
@@ -93,6 +105,11 @@
private int mTouchSlop;
private long mLastDownTime = Integer.MIN_VALUE;
+ @Mock
+ private AccessibilityManagerService mMockAms;
+ @Captor
+ private ArgumentCaptor<AccessibilityGestureEvent> mGestureCaptor;
+
// mock package-private GestureManifold class
@Rule
public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
@@ -122,6 +139,7 @@
@Before
public void setUp() {
+ MockitoAnnotations.initMocks(this);
if (Looper.myLooper() == null) {
Looper.prepare();
}
@@ -130,7 +148,7 @@
AccessibilityManagerService ams = new AccessibilityManagerService(mContext);
mCaptor = new EventCaptor();
mHandler = new TestHandler();
- mTouchExplorer = new TouchExplorer(mContext, ams, null, mHandler);
+ mTouchExplorer = new TouchExplorer(mContext, mMockAms, null, mHandler);
mTouchExplorer.setNext(mCaptor);
}
@@ -395,6 +413,61 @@
mTouchExplorer.setMultiFingerGesturesEnabled(false);
}
+ @Test
+ public void testTouchExploreGestureLog() {
+ passInGesture(com.android.frameworks.servicestests.R.raw.a11y_touch_explore_gesture,
+ AccessibilityService.GESTURE_TOUCH_EXPLORATION);
+ }
+ @Test
+ public void testThreeFingerSwipeDownGestureLog() {
+ passInGesture(
+ com.android.frameworks.servicestests.R.raw.a11y_three_finger_swipe_down_gesture,
+ AccessibilityService.GESTURE_3_FINGER_SWIPE_DOWN);
+ }
+
+ /**
+ * Used to play back event data of a gesture by parsing the log into MotionEvents and sending
+ * them to TouchExplorer.
+ * @param resourceId a raw resource that corresponds to a text file
+ * @param gestureId the id of the gesture expected to be dispatched
+ */
+ private void passInGesture(int resourceId, int gestureId) {
+ mTouchExplorer.setMultiFingerGesturesEnabled(true);
+ mTouchExplorer.setSendMotionEventsEnabled(true);
+ mTouchExplorer.setTwoFingerPassthroughEnabled(true);
+ List<Integer> actions = new ArrayList<>();
+ try (
+ InputStream fis = mContext.getResources().openRawResource(resourceId);
+ InputStreamReader isr = new InputStreamReader(fis, Charset.forName("UTF-8"));
+ BufferedReader br = new BufferedReader(isr);
+ ) {
+ String line;
+ while ((line = br.readLine()) != null) {
+ if (line.isEmpty() || !line.contains("MotionEvent")) {
+ continue;
+ }
+
+ MotionEvent motionEvent = GestureLogParser.getMotionEventFromLogLine(line);
+ actions.add(motionEvent.getAction());
+ send(motionEvent);
+ }
+
+ // Fast forward to dispatch GESTURE_TOUCH_EXPLORATION
+ mHandler.fastForward(USER_INTENT_TIMEOUT);
+ } catch (IOException ioException) {
+ ioException.printStackTrace();
+ }
+
+ verify(mMockAms).onGesture(mGestureCaptor.capture());
+ AccessibilityGestureEvent gestureEvent = mGestureCaptor.getValue();
+ assertEquals(gestureId, gestureEvent.getGestureId());
+ List<MotionEvent> motionEvents = gestureEvent.getMotionEvents();
+ assertEquals(actions.size(), motionEvents.size());
+ for (int i = 0; i < actions.size(); i++) {
+ assertEquals((int) actions.get(i), motionEvents.get(i).getAction());
+ }
+ }
+
private static MotionEvent fromTouchscreen(MotionEvent ev) {
ev.setSource(InputDevice.SOURCE_TOUCHSCREEN);
return ev;
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/utils/GestureLogParser.java b/services/tests/servicestests/src/com/android/server/accessibility/utils/GestureLogParser.java
new file mode 100644
index 0000000..cd848f4
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/accessibility/utils/GestureLogParser.java
@@ -0,0 +1,169 @@
+/*
+ * 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.accessibility.utils;
+
+import android.view.MotionEvent;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * This class helps parse a gesture event log into its individual MotionEvents
+ */
+public class GestureLogParser {
+ /** Gets a MotionEvent from a log line */
+ public static MotionEvent getMotionEventFromLogLine(String line) {
+ final int downTime;
+ final int eventTime;
+ int action;
+ final int pointerCount;
+
+ final MotionEvent.PointerProperties[] properties;
+ final MotionEvent.PointerCoords[] pointerCoords;
+ final int metaState;
+ final int buttonState = 0;
+ final int xPrecision = 1;
+ final int yPrecision = 1;
+ final int deviceId;
+ final int edgeFlags;
+ final int source;
+ final int flags;
+ final int actionIndex;
+
+ downTime = findInt(line, "downTime=(\\d+)");
+ eventTime = findInt(line, "eventTime=(\\d+)");
+ action = stringToAction(findString(line, "action=(\\w+)"));
+
+ // For pointer indices
+ Pattern p = Pattern.compile("action=(\\w+)\\((\\d)");
+ Matcher matcher = p.matcher(line);
+ if (matcher.find()) {
+ actionIndex = Integer.decode(matcher.group(2));
+ action = action | (actionIndex << MotionEvent.ACTION_POINTER_INDEX_SHIFT);
+ }
+
+ pointerCount = findInt(line, "pointerCount=(\\d+)");
+ metaState = findInt(line, "metaState=(\\d+)");
+ deviceId = findInt(line, "deviceId=(\\d+)");
+ edgeFlags = Integer.decode(findString(line, "edgeFlags=(\\w+)"));
+ source = Integer.decode(findString(line, "source=(\\w+)"));
+ flags = Integer.decode(findString(line, "flags=(\\w+)"));
+ properties = findProperties(line, pointerCount);
+ pointerCoords = findCoordinates(line, pointerCount);
+
+ return MotionEvent.obtain(downTime, eventTime, action,
+ pointerCount, properties, pointerCoords, metaState, buttonState,
+ xPrecision, yPrecision, deviceId, edgeFlags, source, flags);
+ }
+
+ private static int findInt(String eventText, String pattern) {
+ final Pattern p = Pattern.compile(pattern);
+ final Matcher matcher = p.matcher(eventText);
+ matcher.find();
+ return Integer.decode(matcher.group(1));
+ }
+
+ private static float findFloat(String eventText, String pattern) {
+ final Pattern p = Pattern.compile(pattern);
+ final Matcher matcher = p.matcher(eventText);
+ matcher.find();
+ return Float.parseFloat(matcher.group(1));
+ }
+
+ private static String findString(String eventText, String pattern) {
+ final Pattern p = Pattern.compile(pattern);
+ final Matcher matcher = p.matcher(eventText);
+ matcher.find();
+ return matcher.group(1);
+ }
+
+ private static MotionEvent.PointerCoords[] findCoordinates(String eventText, int pointerCount) {
+ if (pointerCount == 0) {
+ return null;
+ }
+
+ final MotionEvent.PointerCoords[] coords = new MotionEvent.PointerCoords[pointerCount];
+ float x;
+ float y;
+ for (int i = 0; i < pointerCount; i++) {
+
+ x = findFloat(eventText, "x\\[" + i + "\\]=([\\d.]+)");
+ y = findFloat(eventText, "y\\[" + i + "\\]=([\\d.]+)");
+
+ MotionEvent.PointerCoords pointerCoords = new MotionEvent.PointerCoords();
+ pointerCoords.x = x;
+ pointerCoords.y = y;
+ pointerCoords.pressure = 1;
+ pointerCoords.size = 1;
+
+ coords[i] = pointerCoords;
+ }
+ return coords;
+ }
+
+ private static MotionEvent.PointerProperties[] findProperties(
+ String eventText, int pointerCount) {
+ if (pointerCount == 0) {
+ return null;
+ }
+
+ final MotionEvent.PointerProperties[] props =
+ new MotionEvent.PointerProperties[pointerCount];
+ int id;
+ for (int i = 0; i < pointerCount; i++) {
+ id = findInt(eventText, "id\\[" + i + "\\]=([\\d])");
+ MotionEvent.PointerProperties pointerProps = new MotionEvent.PointerProperties();
+ pointerProps.id = id;
+ pointerProps.toolType = MotionEvent.TOOL_TYPE_FINGER;
+ props[i] = pointerProps;
+ }
+ return props;
+ }
+
+ private static int stringToAction(String action) {
+ switch (action) {
+ case "ACTION_DOWN":
+ return MotionEvent.ACTION_DOWN;
+ case "ACTION_UP":
+ return MotionEvent.ACTION_UP;
+ case "ACTION_CANCEL":
+ return MotionEvent.ACTION_CANCEL;
+ case "ACTION_OUTSIDE":
+ return MotionEvent.ACTION_OUTSIDE;
+ case "ACTION_MOVE":
+ return MotionEvent.ACTION_MOVE;
+ case "ACTION_HOVER_MOVE":
+ return MotionEvent.ACTION_HOVER_MOVE;
+ case "ACTION_SCROLL":
+ return MotionEvent.ACTION_SCROLL;
+ case "ACTION_HOVER_ENTER":
+ return MotionEvent.ACTION_HOVER_ENTER;
+ case "ACTION_HOVER_EXIT":
+ return MotionEvent.ACTION_HOVER_EXIT;
+ case "ACTION_BUTTON_PRESS":
+ return MotionEvent.ACTION_BUTTON_PRESS;
+ case "ACTION_BUTTON_RELEASE":
+ return MotionEvent.ACTION_BUTTON_RELEASE;
+ case "ACTION_POINTER_DOWN":
+ return MotionEvent.ACTION_POINTER_DOWN;
+ case "ACTION_POINTER_UP":
+ return MotionEvent.ACTION_POINTER_UP;
+ default:
+ return -1;
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
index f38def8..f36ed4b 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
@@ -58,22 +58,21 @@
public void setUp() throws Exception {
mAppSearchImpl = AppSearchImpl.create(mTemporaryFolder.newFolder());
- AppSearchSchema visibilityAppSearchSchema =
+ AppSearchSchema visibilitySchema = VisibilityStore.SCHEMA;
+
+ // We need to rewrite the schema type to follow AppSearchImpl's prefixing scheme.
+ AppSearchSchema.Builder rewrittenVisibilitySchema =
new AppSearchSchema.Builder(
- VisibilityStore.DATABASE_NAME
- + AppSearchImpl.DATABASE_DELIMITER
- + VisibilityStore.SCHEMA_TYPE)
- .addProperty(
- new AppSearchSchema.PropertyConfig.Builder(
- VisibilityStore.NOT_PLATFORM_SURFACEABLE_PROPERTY)
- .setDataType(
- AppSearchSchema.PropertyConfig.DATA_TYPE_STRING)
- .setCardinality(
- AppSearchSchema.PropertyConfig.CARDINALITY_REPEATED)
- .build())
- .build();
+ AppSearchImpl.createPrefix(
+ VisibilityStore.PACKAGE_NAME, VisibilityStore.DATABASE_NAME)
+ + VisibilityStore.SCHEMA_TYPE);
+ List<AppSearchSchema.PropertyConfig> visibilityProperties =
+ visibilitySchema.getProperties();
+ for (AppSearchSchema.PropertyConfig property : visibilityProperties) {
+ rewrittenVisibilitySchema.addProperty(property);
+ }
mVisibilitySchemaProto =
- SchemaToProtoConverter.toSchemaTypeConfigProto(visibilityAppSearchSchema);
+ SchemaToProtoConverter.toSchemaTypeConfigProto(rewrittenVisibilitySchema.build());
}
/**
@@ -87,7 +86,7 @@
SchemaProto.newBuilder()
.addTypes(
SchemaTypeConfigProto.newBuilder()
- .setSchemaType("existingDatabase/Foo")
+ .setSchemaType("package$existingDatabase/Foo")
.build());
// Create a copy so we can modify it.
@@ -135,22 +134,25 @@
.build();
AppSearchImpl.RewrittenSchemaResults rewrittenSchemaResults =
- mAppSearchImpl.rewriteSchema("newDatabase", existingSchemaBuilder, newSchema);
+ mAppSearchImpl.rewriteSchema(
+ AppSearchImpl.createPrefix("package", "newDatabase"),
+ existingSchemaBuilder,
+ newSchema);
// We rewrote all the new types that were added. And nothing was removed.
- assertThat(rewrittenSchemaResults.mRewrittenQualifiedTypes)
- .containsExactly("newDatabase/Foo", "newDatabase/TestType");
- assertThat(rewrittenSchemaResults.mDeletedQualifiedTypes).isEmpty();
+ assertThat(rewrittenSchemaResults.mRewrittenPrefixedTypes)
+ .containsExactly("package$newDatabase/Foo", "package$newDatabase/TestType");
+ assertThat(rewrittenSchemaResults.mDeletedPrefixedTypes).isEmpty();
SchemaProto expectedSchema =
SchemaProto.newBuilder()
.addTypes(
SchemaTypeConfigProto.newBuilder()
- .setSchemaType("newDatabase/Foo")
+ .setSchemaType("package$newDatabase/Foo")
.build())
.addTypes(
SchemaTypeConfigProto.newBuilder()
- .setSchemaType("newDatabase/TestType")
+ .setSchemaType("package$newDatabase/TestType")
.addProperties(
PropertyConfigProto.newBuilder()
.setPropertyName("subject")
@@ -180,7 +182,8 @@
.setCardinality(
PropertyConfigProto.Cardinality.Code
.OPTIONAL)
- .setSchemaType("newDatabase/RefType")
+ .setSchemaType(
+ "package$newDatabase/RefType")
.build())
.build())
.build();
@@ -199,7 +202,7 @@
SchemaProto.newBuilder()
.addTypes(
SchemaTypeConfigProto.newBuilder()
- .setSchemaType("existingDatabase/Foo")
+ .setSchemaType("package$existingDatabase/Foo")
.build());
SchemaProto newSchema =
@@ -208,12 +211,15 @@
.build();
AppSearchImpl.RewrittenSchemaResults rewrittenSchemaResults =
- mAppSearchImpl.rewriteSchema("existingDatabase", existingSchemaBuilder, newSchema);
+ mAppSearchImpl.rewriteSchema(
+ AppSearchImpl.createPrefix("package", "existingDatabase"),
+ existingSchemaBuilder,
+ newSchema);
// Nothing was removed, but the method did rewrite the type name.
- assertThat(rewrittenSchemaResults.mRewrittenQualifiedTypes)
- .containsExactly("existingDatabase/Foo");
- assertThat(rewrittenSchemaResults.mDeletedQualifiedTypes).isEmpty();
+ assertThat(rewrittenSchemaResults.mRewrittenPrefixedTypes)
+ .containsExactly("package$existingDatabase/Foo");
+ assertThat(rewrittenSchemaResults.mDeletedPrefixedTypes).isEmpty();
// Same schema since nothing was added.
SchemaProto expectedSchema = existingSchemaBuilder.build();
@@ -231,7 +237,7 @@
SchemaProto.newBuilder()
.addTypes(
SchemaTypeConfigProto.newBuilder()
- .setSchemaType("existingDatabase/Foo")
+ .setSchemaType("package$existingDatabase/Foo")
.build());
SchemaProto newSchema =
@@ -240,21 +246,24 @@
.build();
AppSearchImpl.RewrittenSchemaResults rewrittenSchemaResults =
- mAppSearchImpl.rewriteSchema("existingDatabase", existingSchemaBuilder, newSchema);
+ mAppSearchImpl.rewriteSchema(
+ AppSearchImpl.createPrefix("package", "existingDatabase"),
+ existingSchemaBuilder,
+ newSchema);
// Bar type was rewritten, but Foo ended up being deleted since it wasn't included in the
// new schema.
- assertThat(rewrittenSchemaResults.mRewrittenQualifiedTypes)
- .containsExactly("existingDatabase/Bar");
- assertThat(rewrittenSchemaResults.mDeletedQualifiedTypes)
- .containsExactly("existingDatabase/Foo");
+ assertThat(rewrittenSchemaResults.mRewrittenPrefixedTypes)
+ .containsExactly("package$existingDatabase/Bar");
+ assertThat(rewrittenSchemaResults.mDeletedPrefixedTypes)
+ .containsExactly("package$existingDatabase/Foo");
// Same schema since nothing was added.
SchemaProto expectedSchema =
SchemaProto.newBuilder()
.addTypes(
SchemaTypeConfigProto.newBuilder()
- .setSchemaType("existingDatabase/Bar")
+ .setSchemaType("package$existingDatabase/Bar")
.build())
.build();
@@ -281,21 +290,22 @@
DocumentProto expectedInsideDocument =
DocumentProto.newBuilder()
.setUri("inside-uri")
- .setSchema("databaseName/type")
- .setNamespace("databaseName/namespace")
+ .setSchema("package$databaseName/type")
+ .setNamespace("package$databaseName/namespace")
.build();
DocumentProto expectedDocumentProto =
DocumentProto.newBuilder()
.setUri("uri")
- .setSchema("databaseName/type")
- .setNamespace("databaseName/namespace")
+ .setSchema("package$databaseName/type")
+ .setNamespace("package$databaseName/namespace")
.addProperties(
PropertyProto.newBuilder()
.addDocumentValues(expectedInsideDocument))
.build();
DocumentProto.Builder actualDocument = documentProto.toBuilder();
- mAppSearchImpl.addPrefixToDocument(actualDocument, "databaseName/");
+ mAppSearchImpl.addPrefixToDocument(
+ actualDocument, AppSearchImpl.createPrefix("package", "databaseName"));
assertThat(actualDocument.build()).isEqualTo(expectedDocumentProto);
}
@@ -304,14 +314,14 @@
DocumentProto insideDocument =
DocumentProto.newBuilder()
.setUri("inside-uri")
- .setSchema("databaseName1/type")
- .setNamespace("databaseName2/namespace")
+ .setSchema("package$databaseName1/type")
+ .setNamespace("package$databaseName2/namespace")
.build();
DocumentProto documentProto =
DocumentProto.newBuilder()
.setUri("uri")
- .setSchema("databaseName2/type")
- .setNamespace("databaseName3/namespace")
+ .setSchema("package$databaseName2/type")
+ .setNamespace("package$databaseName3/namespace")
.addProperties(PropertyProto.newBuilder().addDocumentValues(insideDocument))
.build();
@@ -321,7 +331,7 @@
.setSchema("type")
.setNamespace("namespace")
.build();
- // Since we don't pass in "databaseName3/" as a prefix to remove, it stays on the Document.
+
DocumentProto expectedDocumentProto =
DocumentProto.newBuilder()
.setUri("uri")
@@ -333,7 +343,7 @@
.build();
DocumentProto.Builder actualDocument = documentProto.toBuilder();
- mAppSearchImpl.removeDatabasesFromDocument(actualDocument);
+ mAppSearchImpl.removePrefixesFromDocument(actualDocument);
assertThat(actualDocument.build()).isEqualTo(expectedDocumentProto);
}
@@ -343,6 +353,7 @@
List<AppSearchSchema> schemas =
Collections.singletonList(new AppSearchSchema.Builder("type").build());
mAppSearchImpl.setSchema(
+ "package",
"database",
schemas,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
@@ -358,7 +369,7 @@
new GenericDocument.Builder<>("uri" + i, "type")
.setNamespace("namespace")
.build();
- mAppSearchImpl.putDocument("database", document);
+ mAppSearchImpl.putDocument("package", "database", document);
}
// Check optimize() will release 0 docs since there is no deletion.
@@ -368,7 +379,7 @@
// delete 999 documents , we will reach the threshold to trigger optimize() in next
// deletion.
for (int i = 0; i < AppSearchImpl.OPTIMIZE_THRESHOLD_DOC_COUNT - 1; i++) {
- mAppSearchImpl.remove("database", "namespace", "uri" + i);
+ mAppSearchImpl.remove("package", "database", "namespace", "uri" + i);
}
// optimize() still not be triggered since we are in the interval to call getOptimizeInfo()
@@ -382,7 +393,7 @@
< AppSearchImpl.OPTIMIZE_THRESHOLD_DOC_COUNT
+ AppSearchImpl.CHECK_OPTIMIZE_INTERVAL;
i++) {
- mAppSearchImpl.remove("database", "namespace", "uri" + i);
+ mAppSearchImpl.remove("package", "database", "namespace", "uri" + i);
}
// Verify optimize() is triggered
@@ -399,6 +410,7 @@
List<AppSearchSchema> schemas =
Collections.singletonList(new AppSearchSchema.Builder("type").build());
mAppSearchImpl.setSchema(
+ "package",
"database",
schemas,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
@@ -407,13 +419,16 @@
// Insert document
GenericDocument document =
new GenericDocument.Builder<>("uri", "type").setNamespace("namespace").build();
- mAppSearchImpl.putDocument("database", document);
+ mAppSearchImpl.putDocument("package", "database", document);
// Rewrite SearchSpec
- mAppSearchImpl.rewriteSearchSpecForDatabasesLocked(
- searchSpecProto, Collections.singleton("database"));
- assertThat(searchSpecProto.getSchemaTypeFiltersList()).containsExactly("database/type");
- assertThat(searchSpecProto.getNamespaceFiltersList()).containsExactly("database/namespace");
+ mAppSearchImpl.rewriteSearchSpecForPrefixesLocked(
+ searchSpecProto,
+ Collections.singleton(AppSearchImpl.createPrefix("package", "database")));
+ assertThat(searchSpecProto.getSchemaTypeFiltersList())
+ .containsExactly("package$database/type");
+ assertThat(searchSpecProto.getNamespaceFiltersList())
+ .containsExactly("package$database/namespace");
}
@Test
@@ -426,11 +441,13 @@
new AppSearchSchema.Builder("typeA").build(),
new AppSearchSchema.Builder("typeB").build());
mAppSearchImpl.setSchema(
+ "package",
"database1",
schemas,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*forceOverride=*/ false);
mAppSearchImpl.setSchema(
+ "package",
"database2",
schemas,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
@@ -439,27 +456,34 @@
// Insert documents
GenericDocument document1 =
new GenericDocument.Builder<>("uri", "typeA").setNamespace("namespace").build();
- mAppSearchImpl.putDocument("database1", document1);
+ mAppSearchImpl.putDocument("package", "database1", document1);
GenericDocument document2 =
new GenericDocument.Builder<>("uri", "typeB").setNamespace("namespace").build();
- mAppSearchImpl.putDocument("database2", document2);
+ mAppSearchImpl.putDocument("package", "database2", document2);
// Rewrite SearchSpec
- mAppSearchImpl.rewriteSearchSpecForDatabasesLocked(
- searchSpecProto, ImmutableSet.of("database1", "database2"));
+ mAppSearchImpl.rewriteSearchSpecForPrefixesLocked(
+ searchSpecProto,
+ ImmutableSet.of(
+ AppSearchImpl.createPrefix("package", "database1"),
+ AppSearchImpl.createPrefix("package", "database2")));
assertThat(searchSpecProto.getSchemaTypeFiltersList())
.containsExactly(
- "database1/typeA", "database1/typeB", "database2/typeA", "database2/typeB");
+ "package$database1/typeA",
+ "package$database1/typeB",
+ "package$database2/typeA",
+ "package$database2/typeB");
assertThat(searchSpecProto.getNamespaceFiltersList())
- .containsExactly("database1/namespace", "database2/namespace");
+ .containsExactly("package$database1/namespace", "package$database2/namespace");
}
@Test
public void testQueryEmptyDatabase() throws Exception {
SearchSpec searchSpec =
new SearchSpec.Builder().setTermMatch(TermMatchType.Code.PREFIX_VALUE).build();
- SearchResultPage searchResultPage = mAppSearchImpl.query("EmptyDatabase", "", searchSpec);
+ SearchResultPage searchResultPage =
+ mAppSearchImpl.query("package", "EmptyDatabase", "", searchSpec);
assertThat(searchResultPage.getResults()).isEmpty();
}
@@ -467,7 +491,7 @@
public void testGlobalQueryEmptyDatabase() throws Exception {
SearchSpec searchSpec =
new SearchSpec.Builder().setTermMatch(TermMatchType.Code.PREFIX_VALUE).build();
- SearchResultPage searchResultPage = mAppSearchImpl.query("EmptyDatabase", "", searchSpec);
+ SearchResultPage searchResultPage = mAppSearchImpl.globalQuery("", searchSpec);
assertThat(searchResultPage.getResults()).isEmpty();
}
@@ -478,17 +502,17 @@
.addSchemaType("FakeType")
.setTermMatch(TermMatchType.Code.PREFIX_VALUE)
.build();
- mAppSearchImpl.removeByQuery("EmptyDatabase", "", searchSpec);
+ mAppSearchImpl.removeByQuery("package", "EmptyDatabase", "", searchSpec);
searchSpec =
new SearchSpec.Builder()
.addNamespace("FakeNamespace")
.setTermMatch(TermMatchType.Code.PREFIX_VALUE)
.build();
- mAppSearchImpl.removeByQuery("EmptyDatabase", "", searchSpec);
+ mAppSearchImpl.removeByQuery("package", "EmptyDatabase", "", searchSpec);
searchSpec = new SearchSpec.Builder().setTermMatch(TermMatchType.Code.PREFIX_VALUE).build();
- mAppSearchImpl.removeByQuery("EmptyDatabase", "", searchSpec);
+ mAppSearchImpl.removeByQuery("package", "EmptyDatabase", "", searchSpec);
}
@Test
@@ -497,6 +521,7 @@
Collections.singletonList(new AppSearchSchema.Builder("Email").build());
// Set schema Email to AppSearch database1
mAppSearchImpl.setSchema(
+ "package",
"database1",
schemas,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
@@ -506,7 +531,8 @@
SchemaProto expectedProto =
SchemaProto.newBuilder()
.addTypes(
- SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Email"))
+ SchemaTypeConfigProto.newBuilder()
+ .setSchemaType("package$database1/Email"))
.build();
List<SchemaTypeConfigProto> expectedTypes = new ArrayList<>();
@@ -518,7 +544,9 @@
@Test
public void testSetSchema_existingSchemaRetainsVisibilitySetting() throws Exception {
+ String prefix = AppSearchImpl.createPrefix("package", "database");
mAppSearchImpl.setSchema(
+ "package",
"database",
Collections.singletonList(new AppSearchSchema.Builder("schema1").build()),
/*schemasNotPlatformSurfaceable=*/ Collections.singletonList("schema1"),
@@ -528,11 +556,12 @@
assertThat(
mAppSearchImpl
.getVisibilityStoreLocked()
- .getSchemasNotPlatformSurfaceable("database"))
- .containsExactly("database/schema1");
+ .isSchemaPlatformSurfaceable(prefix, prefix + "schema1"))
+ .isFalse();
// Add a new schema, and include the already-existing "schema1"
mAppSearchImpl.setSchema(
+ "package",
"database",
ImmutableList.of(
new AppSearchSchema.Builder("schema1").build(),
@@ -545,8 +574,13 @@
assertThat(
mAppSearchImpl
.getVisibilityStoreLocked()
- .getSchemasNotPlatformSurfaceable("database"))
- .containsExactly("database/schema1");
+ .isSchemaPlatformSurfaceable(prefix, prefix + "schema1"))
+ .isFalse();
+ assertThat(
+ mAppSearchImpl
+ .getVisibilityStoreLocked()
+ .isSchemaPlatformSurfaceable(prefix, prefix + "schema2"))
+ .isTrue();
}
@Test
@@ -557,6 +591,7 @@
new AppSearchSchema.Builder("Document").build());
// Set schema Email and Document to AppSearch database1
mAppSearchImpl.setSchema(
+ "package",
"database1",
schemas,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
@@ -566,10 +601,11 @@
SchemaProto expectedProto =
SchemaProto.newBuilder()
.addTypes(
- SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Email"))
+ SchemaTypeConfigProto.newBuilder()
+ .setSchemaType("package$database1/Email"))
.addTypes(
SchemaTypeConfigProto.newBuilder()
- .setSchemaType("database1/Document"))
+ .setSchemaType("package$database1/Document"))
.build();
// Check both schema Email and Document saved correctly.
@@ -587,15 +623,17 @@
AppSearchException.class,
() ->
mAppSearchImpl.setSchema(
+ "package",
"database1",
finalSchemas,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*forceOverride=*/ false));
assertThat(e).hasMessageThat().contains("Schema is incompatible");
- assertThat(e).hasMessageThat().contains("Deleted types: [database1/Document]");
+ assertThat(e).hasMessageThat().contains("Deleted types: [package$database1/Document]");
// ForceOverride to delete.
mAppSearchImpl.setSchema(
+ "package",
"database1",
finalSchemas,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
@@ -605,7 +643,8 @@
expectedProto =
SchemaProto.newBuilder()
.addTypes(
- SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Email"))
+ SchemaTypeConfigProto.newBuilder()
+ .setSchemaType("package$database1/Email"))
.build();
expectedTypes = new ArrayList<>();
@@ -625,11 +664,13 @@
// Set schema Email and Document to AppSearch database1 and 2
mAppSearchImpl.setSchema(
+ "package",
"database1",
schemas,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*forceOverride=*/ false);
mAppSearchImpl.setSchema(
+ "package",
"database2",
schemas,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
@@ -639,15 +680,17 @@
SchemaProto expectedProto =
SchemaProto.newBuilder()
.addTypes(
- SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Email"))
+ SchemaTypeConfigProto.newBuilder()
+ .setSchemaType("package$database1/Email"))
.addTypes(
SchemaTypeConfigProto.newBuilder()
- .setSchemaType("database1/Document"))
- .addTypes(
- SchemaTypeConfigProto.newBuilder().setSchemaType("database2/Email"))
+ .setSchemaType("package$database1/Document"))
.addTypes(
SchemaTypeConfigProto.newBuilder()
- .setSchemaType("database2/Document"))
+ .setSchemaType("package$database2/Email"))
+ .addTypes(
+ SchemaTypeConfigProto.newBuilder()
+ .setSchemaType("package$database2/Document"))
.build();
// Check Email and Document is saved in database 1 and 2 correctly.
@@ -660,6 +703,7 @@
// Save only Email to database1 this time.
schemas = Collections.singletonList(new AppSearchSchema.Builder("Email").build());
mAppSearchImpl.setSchema(
+ "package",
"database1",
schemas,
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
@@ -670,12 +714,14 @@
expectedProto =
SchemaProto.newBuilder()
.addTypes(
- SchemaTypeConfigProto.newBuilder().setSchemaType("database1/Email"))
- .addTypes(
- SchemaTypeConfigProto.newBuilder().setSchemaType("database2/Email"))
+ SchemaTypeConfigProto.newBuilder()
+ .setSchemaType("package$database1/Email"))
.addTypes(
SchemaTypeConfigProto.newBuilder()
- .setSchemaType("database2/Document"))
+ .setSchemaType("package$database2/Email"))
+ .addTypes(
+ SchemaTypeConfigProto.newBuilder()
+ .setSchemaType("package$database2/Document"))
.build();
// Check nothing changed in database2.
@@ -688,7 +734,9 @@
@Test
public void testRemoveSchema_removedFromVisibilityStore() throws Exception {
+ String prefix = AppSearchImpl.createPrefix("package", "database");
mAppSearchImpl.setSchema(
+ "package",
"database",
Collections.singletonList(new AppSearchSchema.Builder("schema1").build()),
/*schemasNotPlatformSurfaceable=*/ Collections.singletonList("schema1"),
@@ -698,11 +746,12 @@
assertThat(
mAppSearchImpl
.getVisibilityStoreLocked()
- .getSchemasNotPlatformSurfaceable("database"))
- .containsExactly("database/schema1");
+ .isSchemaPlatformSurfaceable(prefix, prefix + "schema1"))
+ .isFalse();
// Remove "schema1" by force overriding
mAppSearchImpl.setSchema(
+ "package",
"database",
Collections.emptyList(),
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
@@ -712,12 +761,13 @@
assertThat(
mAppSearchImpl
.getVisibilityStoreLocked()
- .getSchemasNotPlatformSurfaceable("database"))
- .isEmpty();
+ .isSchemaPlatformSurfaceable(prefix, prefix + "schema1"))
+ .isTrue();
// Add "schema1" back, it gets default visibility settings which means it's not platform
// hidden.
mAppSearchImpl.setSchema(
+ "package",
"database",
Collections.singletonList(new AppSearchSchema.Builder("schema1").build()),
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
@@ -725,13 +775,15 @@
assertThat(
mAppSearchImpl
.getVisibilityStoreLocked()
- .getSchemasNotPlatformSurfaceable("database"))
- .isEmpty();
+ .isSchemaPlatformSurfaceable(prefix, prefix + "schema1"))
+ .isTrue();
}
@Test
public void testSetSchema_defaultPlatformVisible() throws Exception {
+ String prefix = AppSearchImpl.createPrefix("package", "database");
mAppSearchImpl.setSchema(
+ "package",
"database",
Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
@@ -739,13 +791,15 @@
assertThat(
mAppSearchImpl
.getVisibilityStoreLocked()
- .getSchemasNotPlatformSurfaceable("database"))
- .isEmpty();
+ .isSchemaPlatformSurfaceable(prefix, prefix + "Schema"))
+ .isTrue();
}
@Test
public void testSetSchema_platformHidden() throws Exception {
+ String prefix = AppSearchImpl.createPrefix("package", "database");
mAppSearchImpl.setSchema(
+ "package",
"database",
Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
/*schemasNotPlatformSurfaceable=*/ Collections.singletonList("Schema"),
@@ -753,47 +807,60 @@
assertThat(
mAppSearchImpl
.getVisibilityStoreLocked()
- .getSchemasNotPlatformSurfaceable("database"))
- .containsExactly("database/Schema");
+ .isSchemaPlatformSurfaceable(prefix, prefix + "Schema"))
+ .isFalse();
}
@Test
public void testHasSchemaType() throws Exception {
// Nothing exists yet
- assertThat(mAppSearchImpl.hasSchemaTypeLocked("database", "Schema")).isFalse();
+ assertThat(mAppSearchImpl.hasSchemaTypeLocked("package", "database", "Schema")).isFalse();
mAppSearchImpl.setSchema(
+ "package",
"database",
Collections.singletonList(new AppSearchSchema.Builder("Schema").build()),
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*forceOverride=*/ false);
- assertThat(mAppSearchImpl.hasSchemaTypeLocked("database", "Schema")).isTrue();
+ assertThat(mAppSearchImpl.hasSchemaTypeLocked("package", "database", "Schema")).isTrue();
- assertThat(mAppSearchImpl.hasSchemaTypeLocked("database", "UnknownSchema")).isFalse();
+ assertThat(mAppSearchImpl.hasSchemaTypeLocked("package", "database", "UnknownSchema"))
+ .isFalse();
}
@Test
public void testGetDatabases() throws Exception {
// No client databases exist yet, but the VisibilityStore's does
- assertThat(mAppSearchImpl.getDatabasesLocked())
- .containsExactly(VisibilityStore.DATABASE_NAME);
+ assertThat(mAppSearchImpl.getPrefixesLocked())
+ .containsExactly(
+ AppSearchImpl.createPrefix(
+ VisibilityStore.PACKAGE_NAME, VisibilityStore.DATABASE_NAME));
// Has database1
mAppSearchImpl.setSchema(
+ "package",
"database1",
Collections.singletonList(new AppSearchSchema.Builder("schema").build()),
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*forceOverride=*/ false);
- assertThat(mAppSearchImpl.getDatabasesLocked())
- .containsExactly(VisibilityStore.DATABASE_NAME, "database1");
+ assertThat(mAppSearchImpl.getPrefixesLocked())
+ .containsExactly(
+ AppSearchImpl.createPrefix(
+ VisibilityStore.PACKAGE_NAME, VisibilityStore.DATABASE_NAME),
+ AppSearchImpl.createPrefix("package", "database1"));
// Has both databases
mAppSearchImpl.setSchema(
+ "package",
"database2",
Collections.singletonList(new AppSearchSchema.Builder("schema").build()),
/*schemasNotPlatformSurfaceable=*/ Collections.emptyList(),
/*forceOverride=*/ false);
- assertThat(mAppSearchImpl.getDatabasesLocked())
- .containsExactly(VisibilityStore.DATABASE_NAME, "database1", "database2");
+ assertThat(mAppSearchImpl.getPrefixesLocked())
+ .containsExactly(
+ AppSearchImpl.createPrefix(
+ VisibilityStore.PACKAGE_NAME, VisibilityStore.DATABASE_NAME),
+ AppSearchImpl.createPrefix("package", "database1"),
+ AppSearchImpl.createPrefix("package", "database2"));
}
}
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/VisibilityStoreTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/VisibilityStoreTest.java
index a1f575a..415c1f5 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/VisibilityStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/VisibilityStoreTest.java
@@ -18,13 +18,14 @@
import static com.google.common.truth.Truth.assertThat;
+import com.google.common.collect.ImmutableSet;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import java.util.Collections;
-import java.util.Set;
public class VisibilityStoreTest {
@@ -38,22 +39,78 @@
mVisibilityStore = mAppSearchImpl.getVisibilityStoreLocked();
}
+ /**
+ * Make sure that we don't conflict with any special characters that AppSearchImpl has reserved.
+ */
+ @Test
+ public void testValidPackageName() {
+ assertThat(VisibilityStore.PACKAGE_NAME)
+ .doesNotContain(
+ "" + AppSearchImpl.PACKAGE_DELIMITER); // Convert the chars to CharSequences
+ assertThat(VisibilityStore.PACKAGE_NAME)
+ .doesNotContain(
+ ""
+ + AppSearchImpl
+ .DATABASE_DELIMITER); // Convert the chars to CharSequences
+ }
+
+ /**
+ * Make sure that we don't conflict with any special characters that AppSearchImpl has reserved.
+ */
+ @Test
+ public void testValidDatabaseName() {
+ assertThat(VisibilityStore.DATABASE_NAME)
+ .doesNotContain(
+ "" + AppSearchImpl.PACKAGE_DELIMITER); // Convert the chars to CharSequences
+ assertThat(VisibilityStore.DATABASE_NAME)
+ .doesNotContain(
+ ""
+ + AppSearchImpl
+ .DATABASE_DELIMITER); // Convert the chars to CharSequences
+ }
+
@Test
public void testSetVisibility() throws Exception {
mVisibilityStore.setVisibility(
- "database", /*schemasNotPlatformSurfaceable=*/ Set.of("schema1", "schema2"));
- assertThat(mVisibilityStore.getSchemasNotPlatformSurfaceable("database"))
- .containsExactly("schema1", "schema2");
+ "prefix",
+ /*schemasNotPlatformSurfaceable=*/ ImmutableSet.of(
+ "prefix/schema1", "prefix/schema2"));
+ assertThat(mVisibilityStore.isSchemaPlatformSurfaceable("prefix", "prefix/schema1"))
+ .isFalse();
+ assertThat(mVisibilityStore.isSchemaPlatformSurfaceable("prefix", "prefix/schema2"))
+ .isFalse();
// New .setVisibility() call completely overrides previous visibility settings. So
- // "schema1" isn't preserved.
+ // "schema2" isn't preserved.
mVisibilityStore.setVisibility(
- "database", /*schemasNotPlatformSurfaceable=*/ Set.of("schema1", "schema3"));
- assertThat(mVisibilityStore.getSchemasNotPlatformSurfaceable("database"))
- .containsExactly("schema1", "schema3");
+ "prefix",
+ /*schemasNotPlatformSurfaceable=*/ ImmutableSet.of(
+ "prefix/schema1", "prefix/schema3"));
+ assertThat(mVisibilityStore.isSchemaPlatformSurfaceable("prefix", "prefix/schema1"))
+ .isFalse();
+ assertThat(mVisibilityStore.isSchemaPlatformSurfaceable("prefix", "prefix/schema2"))
+ .isTrue();
+ assertThat(mVisibilityStore.isSchemaPlatformSurfaceable("prefix", "prefix/schema3"))
+ .isFalse();
mVisibilityStore.setVisibility(
- "database", /*schemasNotPlatformSurfaceable=*/ Collections.emptySet());
- assertThat(mVisibilityStore.getSchemasNotPlatformSurfaceable("database")).isEmpty();
+ "prefix", /*schemasNotPlatformSurfaceable=*/ Collections.emptySet());
+ assertThat(mVisibilityStore.isSchemaPlatformSurfaceable("prefix", "prefix/schema1"))
+ .isTrue();
+ assertThat(mVisibilityStore.isSchemaPlatformSurfaceable("prefix", "prefix/schema2"))
+ .isTrue();
+ assertThat(mVisibilityStore.isSchemaPlatformSurfaceable("prefix", "prefix/schema3"))
+ .isTrue();
+ }
+
+ @Test
+ public void testEmptyPrefix() throws Exception {
+ mVisibilityStore.setVisibility(
+ /*prefix=*/ "",
+ /*schemasNotPlatformSurfaceable=*/ ImmutableSet.of("schema1", "schema2"));
+ assertThat(mVisibilityStore.isSchemaPlatformSurfaceable(/*prefix=*/ "", "schema1"))
+ .isFalse();
+ assertThat(mVisibilityStore.isSchemaPlatformSurfaceable(/*prefix=*/ "", "schema2"))
+ .isFalse();
}
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
index e2b48d4..17324ba 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -320,8 +320,10 @@
@Override
void recoverySystemRebootWipeUserData(boolean shutdown, String reason, boolean force,
- boolean wipeEuicc) throws IOException {
- services.recoverySystem.rebootWipeUserData(shutdown, reason, force, wipeEuicc);
+ boolean wipeEuicc, boolean wipeExtRequested, boolean wipeResetProtectionData)
+ throws IOException {
+ services.recoverySystem.rebootWipeUserData(shutdown, reason, force, wipeEuicc,
+ wipeExtRequested, wipeResetProtectionData);
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index d9daf17..1c7da3b 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -4681,9 +4681,8 @@
thenReturn("Just a test string.");
dpm.wipeData(0);
- verify(getServices().recoverySystem).rebootWipeUserData(
- /*shutdown=*/ eq(false), anyString(), /*force=*/ eq(true),
- /*wipeEuicc=*/ eq(false));
+
+ verifyRebootWipeUserData(/* wipeEuicc= */ false);
}
@Test
@@ -4697,9 +4696,8 @@
thenReturn("Just a test string.");
dpm.wipeData(WIPE_EUICC);
- verify(getServices().recoverySystem).rebootWipeUserData(
- /*shutdown=*/ eq(false), anyString(), /*force=*/ eq(true),
- /*wipeEuicc=*/ eq(true));
+
+ verifyRebootWipeUserData(/* wipeEuicc= */ true);
}
@Test
@@ -4802,9 +4800,7 @@
// The device should be wiped even if DISALLOW_FACTORY_RESET is enabled, because both the
// user restriction and the policy were set by the DO.
- verify(getServices().recoverySystem).rebootWipeUserData(
- /*shutdown=*/ eq(false), anyString(), /*force=*/ eq(true),
- /*wipeEuicc=*/ eq(false));
+ verifyRebootWipeUserData(/* wipeEuicc= */ false);
}
@Test
@@ -4863,9 +4859,7 @@
dpm.reportFailedPasswordAttempt(UserHandle.USER_SYSTEM);
// For managed profile on an organization owned device, the whole device should be wiped.
- verify(getServices().recoverySystem).rebootWipeUserData(
- /*shutdown=*/ eq(false), anyString(), /*force=*/ eq(true),
- /*wipeEuicc=*/ eq(false));
+ verifyRebootWipeUserData(/* wipeEuicc= */ false);
}
@Test
@@ -4907,9 +4901,7 @@
dpm.reportFailedPasswordAttempt(MANAGED_PROFILE_USER_ID);
// For managed profile on an organization owned device, the whole device should be wiped.
- verify(getServices().recoverySystem).rebootWipeUserData(
- /*shutdown=*/ eq(false), anyString(), /*force=*/ eq(true),
- /*wipeEuicc=*/ eq(false));
+ verifyRebootWipeUserData(/* wipeEuicc= */ false);
}
@Test
@@ -5788,6 +5780,12 @@
});
}
+ private void verifyRebootWipeUserData(boolean wipeEuicc) throws Exception {
+ verify(getServices().recoverySystem).rebootWipeUserData(/*shutdown=*/ eq(false),
+ /* reason= */ anyString(), /*force=*/ eq(true), eq(wipeEuicc),
+ /* wipeAdoptableStorage= */ eq(false), /* wipeFactoryResetProtection= */ eq(false));
+ }
+
private void assertAttestationFlags(int attestationFlags, int[] expectedFlags) {
int[] gotFlags = DevicePolicyManagerService.translateIdAttestationFlags(attestationFlags);
Arrays.sort(gotFlags);
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
index 34313b8..7d1de86 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
@@ -393,7 +393,8 @@
public static class RecoverySystemForMock {
public void rebootWipeUserData(boolean shutdown, String reason, boolean force,
- boolean wipeEuicc) throws IOException {
+ boolean wipeEuicc, boolean wipeExtRequested, boolean wipeResetProtectionData)
+ throws IOException {
}
}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java
index 0a3d545..42f88dc 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java
@@ -79,7 +79,7 @@
}
private HdmiCecController mHdmiCecController;
- private int mCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_b;
+ private int mCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_B;
private int mLogicalAddress = 16;
private AllocateAddressCallback mCallback =
new AllocateAddressCallback() {
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java
index ef77f32..ae59609 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java
@@ -284,7 +284,7 @@
public void handleCecVersion_isHandled() {
boolean result = mHdmiLocalDevice.onMessage(
HdmiCecMessageBuilder.buildCecVersion(ADDR_PLAYBACK_1, mHdmiLocalDevice.mAddress,
- HdmiControlManager.HDMI_CEC_VERSION_1_4_b));
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_B));
assertThat(result).isTrue();
}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageBuilderTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageBuilderTest.java
index 6496264..453303e 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageBuilderTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageBuilderTest.java
@@ -104,7 +104,7 @@
@Test
public void buildReportFeatures_basicTv_1_4() {
HdmiCecMessage message = HdmiCecMessageBuilder.buildReportFeatures(ADDR_TV,
- HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
Lists.newArrayList(HdmiDeviceInfo.DEVICE_TV), Constants.RC_PROFILE_TV,
Lists.newArrayList(Constants.RC_PROFILE_TV_NONE), Collections.emptyList());
@@ -114,7 +114,7 @@
@Test
public void buildReportFeatures_basicPlayback_1_4() {
HdmiCecMessage message = HdmiCecMessageBuilder.buildReportFeatures(ADDR_PLAYBACK_1,
- HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
Lists.newArrayList(HdmiDeviceInfo.DEVICE_PLAYBACK), Constants.RC_PROFILE_TV,
Lists.newArrayList(Constants.RC_PROFILE_TV_NONE), Collections.emptyList());
@@ -124,7 +124,7 @@
@Test
public void buildReportFeatures_basicPlaybackAudioSystem_1_4() {
HdmiCecMessage message = HdmiCecMessageBuilder.buildReportFeatures(ADDR_PLAYBACK_1,
- HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
Lists.newArrayList(HdmiDeviceInfo.DEVICE_PLAYBACK,
HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM), Constants.RC_PROFILE_TV,
Lists.newArrayList(Constants.RC_PROFILE_TV_NONE), Collections.emptyList());
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java
index e370018..b1998f5 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java
@@ -390,7 +390,7 @@
assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress);
assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo(updatedPowerStatus);
assertThat(cecDeviceInfo.getCecVersion()).isEqualTo(
- HdmiControlManager.HDMI_CEC_VERSION_1_4_b);
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
}
@Test
@@ -436,7 +436,7 @@
assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo(
HdmiControlManager.POWER_STATUS_UNKNOWN);
assertThat(cecDeviceInfo.getCecVersion()).isEqualTo(
- HdmiControlManager.HDMI_CEC_VERSION_1_4_b);
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
}
@Test
@@ -482,7 +482,7 @@
@Test
public void cecDevices_tracking_reportCecVersion_tracksCecVersion_cec14() {
int logicalAddress = Constants.ADDR_PLAYBACK_1;
- int cecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_b;
+ int cecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_B;
mHdmiCecNetwork.handleCecMessage(
HdmiCecMessageBuilder.buildCecVersion(logicalAddress, Constants.ADDR_BROADCAST,
cecVersion));
@@ -512,7 +512,7 @@
@Test
public void cecDevices_tracking_reportFeatures_tracksCecVersion_cec14() {
int logicalAddress = Constants.ADDR_PLAYBACK_1;
- int cecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_b;
+ int cecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_B;
mHdmiCecNetwork.handleCecMessage(
HdmiCecMessageBuilder.buildReportFeatures(logicalAddress,
cecVersion, Collections.emptyList(),
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecPowerStatusControllerTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecPowerStatusControllerTest.java
index 670d512..06373c2 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecPowerStatusControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecPowerStatusControllerTest.java
@@ -62,7 +62,7 @@
private FakeNativeWrapper mNativeWrapper;
private TestLooper mTestLooper = new TestLooper();
private ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>();
- private int mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_b;
+ private int mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_B;
@Mock
private IPowerManager mIPowerManagerMock;
@Mock
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 2513807..c2268c5 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
@@ -246,7 +246,7 @@
public void initialPowerStatus_normalBoot_goToStandby_doesNotBroadcastsPowerStatus_1_4() {
mHdmiControlService.getHdmiCecConfig().setIntValue(
HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION,
- HdmiControlManager.HDMI_CEC_VERSION_1_4_b);
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
mHdmiControlService.setControlEnabled(true);
mNativeWrapper.clearResultMessages();
@@ -442,17 +442,17 @@
null);
mHdmiControlService.setControlEnabled(true);
assertThat(mHdmiControlService.getCecVersion()).isEqualTo(
- HdmiControlManager.HDMI_CEC_VERSION_1_4_b);
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
}
@Test
public void getCecVersion_1_4() {
mHdmiControlService.getHdmiCecConfig().setIntValue(
HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION,
- HdmiControlManager.HDMI_CEC_VERSION_1_4_b);
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
mHdmiControlService.setControlEnabled(true);
assertThat(mHdmiControlService.getCecVersion()).isEqualTo(
- HdmiControlManager.HDMI_CEC_VERSION_1_4_b);
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
}
@Test
@@ -469,10 +469,10 @@
public void getCecVersion_change() {
mHdmiControlService.getHdmiCecConfig().setIntValue(
HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION,
- HdmiControlManager.HDMI_CEC_VERSION_1_4_b);
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
mHdmiControlService.setControlEnabled(true);
assertThat(mHdmiControlService.getCecVersion()).isEqualTo(
- HdmiControlManager.HDMI_CEC_VERSION_1_4_b);
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
mHdmiControlService.getHdmiCecConfig().setIntValue(
HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION,
@@ -486,7 +486,7 @@
public void handleGiveFeatures_cec14_featureAbort() {
mHdmiControlService.getHdmiCecConfig().setIntValue(
HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION,
- HdmiControlManager.HDMI_CEC_VERSION_1_4_b);
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
mHdmiControlService.setControlEnabled(true);
mTestLooper.dispatchAll();
@@ -526,7 +526,7 @@
mNativeWrapper.clearResultMessages();
mHdmiControlService.getHdmiCecConfig().setIntValue(
HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_VERSION,
- HdmiControlManager.HDMI_CEC_VERSION_1_4_b);
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_B);
mHdmiControlService.setControlEnabled(true);
mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
mTestLooper.dispatchAll();
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiUtilsTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiUtilsTest.java
index 5316ef6..9f0cdd5 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiUtilsTest.java
@@ -536,49 +536,49 @@
@Test
public void isEligibleAddressForCecVersion_1_4() {
assertThat(HdmiUtils.isEligibleAddressForCecVersion(
- HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
Constants.ADDR_TV)).isTrue();
assertThat(HdmiUtils.isEligibleAddressForCecVersion(
- HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
Constants.ADDR_RECORDER_1)).isTrue();
assertThat(HdmiUtils.isEligibleAddressForCecVersion(
- HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
Constants.ADDR_RECORDER_2)).isTrue();
assertThat(HdmiUtils.isEligibleAddressForCecVersion(
- HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
Constants.ADDR_TUNER_1)).isTrue();
assertThat(HdmiUtils.isEligibleAddressForCecVersion(
- HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
Constants.ADDR_PLAYBACK_1)).isTrue();
assertThat(HdmiUtils.isEligibleAddressForCecVersion(
- HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
Constants.ADDR_AUDIO_SYSTEM)).isTrue();
assertThat(HdmiUtils.isEligibleAddressForCecVersion(
- HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
Constants.ADDR_TUNER_2)).isTrue();
assertThat(HdmiUtils.isEligibleAddressForCecVersion(
- HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
Constants.ADDR_TUNER_3)).isTrue();
assertThat(HdmiUtils.isEligibleAddressForCecVersion(
- HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
Constants.ADDR_PLAYBACK_2)).isTrue();
assertThat(HdmiUtils.isEligibleAddressForCecVersion(
- HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
Constants.ADDR_RECORDER_3)).isTrue();
assertThat(HdmiUtils.isEligibleAddressForCecVersion(
- HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
Constants.ADDR_TUNER_4)).isTrue();
assertThat(HdmiUtils.isEligibleAddressForCecVersion(
- HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
Constants.ADDR_PLAYBACK_3)).isTrue();
assertThat(HdmiUtils.isEligibleAddressForCecVersion(
- HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
Constants.ADDR_BACKUP_1)).isFalse();
assertThat(HdmiUtils.isEligibleAddressForCecVersion(
- HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
Constants.ADDR_BACKUP_2)).isFalse();
assertThat(HdmiUtils.isEligibleAddressForCecVersion(
- HdmiControlManager.HDMI_CEC_VERSION_1_4_b,
+ HdmiControlManager.HDMI_CEC_VERSION_1_4_B,
Constants.ADDR_SPECIFIC_USE)).isTrue();
}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java
index c4d1211..98d6452 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java
@@ -95,13 +95,24 @@
static class MockInjector extends RebootEscrowManager.Injector {
private final IRebootEscrow mRebootEscrow;
+ private final RebootEscrowProviderInterface mRebootEscrowProvider;
private final UserManager mUserManager;
private final MockableRebootEscrowInjected mInjected;
- MockInjector(Context context, UserManager userManager, IRebootEscrow rebootEscrow,
+ MockInjector(Context context, UserManager userManager,
+ IRebootEscrow rebootEscrow,
MockableRebootEscrowInjected injected) {
super(context);
mRebootEscrow = rebootEscrow;
+
+ RebootEscrowProviderHalImpl.Injector halInjector =
+ new RebootEscrowProviderHalImpl.Injector() {
+ @Override
+ public IRebootEscrow getRebootEscrow() {
+ return mRebootEscrow;
+ }
+ };
+ mRebootEscrowProvider = new RebootEscrowProviderHalImpl(halInjector);
mUserManager = userManager;
mInjected = injected;
}
@@ -112,8 +123,8 @@
}
@Override
- public IRebootEscrow getRebootEscrow() {
- return mRebootEscrow;
+ public RebootEscrowProviderInterface getRebootEscrowProvider() {
+ return mRebootEscrowProvider;
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
index 11d00f0..5719dd2 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java
@@ -173,6 +173,7 @@
/* installSource */ installSource,
/* sessionParams */ params,
/* createdMillis */ 0L,
+ /* committedMillis */ 0L,
/* stageDir */ mTmpDir,
/* stageCid */ null,
/* files */ null,
diff --git a/services/tests/servicestests/src/com/android/server/pm/StagingManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/StagingManagerTest.java
new file mode 100644
index 0000000..4870c9e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/StagingManagerTest.java
@@ -0,0 +1,128 @@
+/*
+ * 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.pm;
+
+import android.content.Context;
+import android.content.pm.PackageInstaller;
+import android.os.storage.StorageManager;
+import android.platform.test.annotations.Presubmit;
+
+import com.android.internal.os.BackgroundThread;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.io.File;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertThrows;
+
+@Presubmit
+@RunWith(JUnit4.class)
+public class StagingManagerTest {
+ @Rule
+ public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
+
+ private File mTmpDir;
+ private StagingManager mStagingManager;
+
+ @Before
+ public void setup() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ StorageManager storageManager = Mockito.mock(StorageManager.class);
+ Context context = Mockito.mock(Context.class);
+ when(storageManager.isCheckpointSupported()).thenReturn(true);
+ when(context.getSystemService(eq(Context.POWER_SERVICE))).thenReturn(null);
+ when(context.getSystemService(eq(Context.STORAGE_SERVICE))).thenReturn(storageManager);
+
+ mTmpDir = mTemporaryFolder.newFolder("StagingManagerTest");
+ mStagingManager = new StagingManager(context, null);
+ }
+
+ /**
+ * Tests that sessions committed later shouldn't cause earlier ones to fail the overlapping
+ * check.
+ */
+ @Test
+ public void checkNonOverlappingWithStagedSessions_laterSessionShouldNotFailEarlierOnes()
+ throws Exception {
+ // Create 2 sessions with overlapping packages
+ PackageInstallerSession session1 = createSession(111, "com.foo", 1);
+ PackageInstallerSession session2 = createSession(222, "com.foo", 2);
+
+ mStagingManager.createSession(session1);
+ mStagingManager.createSession(session2);
+ // Session1 should not fail in spite of the overlapping packages
+ mStagingManager.checkNonOverlappingWithStagedSessions(session1);
+ // Session2 should fail due to overlapping packages
+ assertThrows(PackageManagerException.class,
+ () -> mStagingManager.checkNonOverlappingWithStagedSessions(session2));
+ }
+
+ private PackageInstallerSession createSession(int sessionId, String packageName,
+ long committedMillis) {
+ PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
+ PackageInstaller.SessionParams.MODE_FULL_INSTALL);
+ params.isStaged = true;
+
+ InstallSource installSource = InstallSource.create("testInstallInitiator",
+ "testInstallOriginator", "testInstaller", "testAttributionTag");
+
+ PackageInstallerSession session = new PackageInstallerSession(
+ /* callback */ null,
+ /* context */ null,
+ /* pm */ null,
+ /* sessionProvider */ null,
+ /* looper */ BackgroundThread.getHandler().getLooper(),
+ /* stagingManager */ null,
+ /* sessionId */ sessionId,
+ /* userId */ 456,
+ /* installerUid */ -1,
+ /* installSource */ installSource,
+ /* sessionParams */ params,
+ /* createdMillis */ 0L,
+ /* committedMillis */ committedMillis,
+ /* stageDir */ mTmpDir,
+ /* stageCid */ null,
+ /* files */ null,
+ /* checksums */ null,
+ /* prepared */ true,
+ /* committed */ true,
+ /* destroyed */ false,
+ /* sealed */ false, // Setting to true would trigger some PM logic.
+ /* childSessionIds */ null,
+ /* parentSessionId */ -1,
+ /* isReady */ false,
+ /* isFailed */ false,
+ /* isApplied */false,
+ /* stagedSessionErrorCode */ PackageInstaller.SessionInfo.STAGED_SESSION_NO_ERROR,
+ /* stagedSessionErrorMessage */ "no error");
+
+ session = spy(session);
+ doReturn(packageName).when(session).getPackageName();
+ return session;
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/OWNERS b/services/tests/servicestests/src/com/android/server/timedetector/OWNERS
index 09447a9..8f80897 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/OWNERS
+++ b/services/tests/servicestests/src/com/android/server/timedetector/OWNERS
@@ -1 +1,3 @@
-include /core/java/android/app/timezone/OWNERS
+# Bug component: 847766
+mingaleev@google.com
+include /core/java/android/app/timedetector/OWNERS
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 4a44005..5276ac4 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
@@ -28,6 +28,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.timedetector.GnssTimeSuggestion;
import android.app.timedetector.ManualTimeSuggestion;
import android.app.timedetector.NetworkTimeSuggestion;
import android.app.timedetector.TelephonyTimeSuggestion;
@@ -174,6 +175,36 @@
mStubbedTimeDetectorStrategy.verifySuggestNetworkTimeCalled(NetworkTimeSuggestion);
}
+ @Test(expected = SecurityException.class)
+ public void testSuggestGnssTime_withoutPermission() {
+ doThrow(new SecurityException("Mock"))
+ .when(mMockContext).enforceCallingOrSelfPermission(anyString(), any());
+ GnssTimeSuggestion gnssTimeSuggestion = createGnssTimeSuggestion();
+
+ try {
+ mTimeDetectorService.suggestGnssTime(gnssTimeSuggestion);
+ fail();
+ } finally {
+ verify(mMockContext).enforceCallingOrSelfPermission(
+ eq(android.Manifest.permission.SET_TIME), anyString());
+ }
+ }
+
+ @Test
+ public void testSuggestGnssTime() throws Exception {
+ doNothing().when(mMockContext).enforceCallingOrSelfPermission(anyString(), any());
+
+ GnssTimeSuggestion gnssTimeSuggestion = createGnssTimeSuggestion();
+ mTimeDetectorService.suggestGnssTime(gnssTimeSuggestion);
+ mTestHandler.assertTotalMessagesEnqueued(1);
+
+ verify(mMockContext).enforceCallingOrSelfPermission(
+ eq(android.Manifest.permission.SET_TIME), anyString());
+
+ mTestHandler.waitForMessagesToBeProcessed();
+ mStubbedTimeDetectorStrategy.verifySuggestGnssTimeCalled(gnssTimeSuggestion);
+ }
+
@Test
public void testDump() {
when(mMockContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP))
@@ -219,12 +250,18 @@
return new NetworkTimeSuggestion(timeValue);
}
+ private static GnssTimeSuggestion createGnssTimeSuggestion() {
+ TimestampedValue<Long> timeValue = new TimestampedValue<>(100L, 1_000_000L);
+ return new GnssTimeSuggestion(timeValue);
+ }
+
private static class StubbedTimeDetectorStrategy implements TimeDetectorStrategy {
// Call tracking.
private TelephonyTimeSuggestion mLastTelephonySuggestion;
private ManualTimeSuggestion mLastManualSuggestion;
private NetworkTimeSuggestion mLastNetworkSuggestion;
+ private GnssTimeSuggestion mLastGnssSuggestion;
private boolean mHandleAutoTimeDetectionChangedCalled;
private boolean mDumpCalled;
@@ -245,6 +282,11 @@
}
@Override
+ public void suggestGnssTime(GnssTimeSuggestion timeSuggestion) {
+ mLastGnssSuggestion = timeSuggestion;
+ }
+
+ @Override
public void handleAutoTimeConfigChanged() {
mHandleAutoTimeDetectionChangedCalled = true;
}
@@ -258,6 +300,7 @@
mLastTelephonySuggestion = null;
mLastManualSuggestion = null;
mLastNetworkSuggestion = null;
+ mLastGnssSuggestion = null;
mHandleAutoTimeDetectionChangedCalled = false;
mDumpCalled = false;
}
@@ -274,6 +317,10 @@
assertEquals(expectedSuggestion, mLastNetworkSuggestion);
}
+ void verifySuggestGnssTimeCalled(GnssTimeSuggestion expectedSuggestion) {
+ assertEquals(expectedSuggestion, mLastGnssSuggestion);
+ }
+
void verifyHandleAutoTimeDetectionChangedCalled() {
assertTrue(mHandleAutoTimeDetectionChangedCalled);
}
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 21396fd..b1adb0b 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,7 @@
package com.android.server.timedetector;
+import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_GNSS;
import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_NETWORK;
import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_TELEPHONY;
@@ -25,6 +26,7 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import android.app.timedetector.GnssTimeSuggestion;
import android.app.timedetector.ManualTimeSuggestion;
import android.app.timedetector.NetworkTimeSuggestion;
import android.app.timedetector.TelephonyTimeSuggestion;
@@ -569,7 +571,53 @@
}
@Test
- public void highPrioritySuggestionsShouldBeatLowerPrioritySuggestions() {
+ public void testSuggestGnssTime_autoTimeEnabled() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoOriginPriorities(ORIGIN_GNSS)
+ .pokeAutoTimeDetectionEnabled(true);
+
+ GnssTimeSuggestion timeSuggestion =
+ mScript.generateGnssTimeSuggestion(ARBITRARY_TEST_TIME);
+
+ mScript.simulateTimePassing();
+
+ long expectedSystemClockMillis =
+ mScript.calculateTimeInMillisForNow(timeSuggestion.getUtcTime());
+ mScript.simulateGnssTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis);
+ }
+
+ @Test
+ public void testSuggestGnssTime_autoTimeDisabled() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoOriginPriorities(ORIGIN_GNSS)
+ .pokeAutoTimeDetectionEnabled(false);
+
+ GnssTimeSuggestion timeSuggestion =
+ mScript.generateGnssTimeSuggestion(ARBITRARY_TEST_TIME);
+
+ mScript.simulateTimePassing()
+ .simulateGnssTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+ }
+
+ @Test
+ public void gnssTimeSuggestion_ignoredWhenReferencedTimeIsInThePast() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoOriginPriorities(ORIGIN_GNSS)
+ .pokeAutoTimeDetectionEnabled(true);
+
+ Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1));
+ GnssTimeSuggestion timeSuggestion = mScript
+ .generateGnssTimeSuggestion(suggestedTime);
+
+ mScript.simulateGnssTimeSuggestion(timeSuggestion)
+ .verifySystemClockWasNotSetAndResetCallTracking()
+ .assertLatestGnssSuggestion(null);
+ }
+
+ @Test
+ public void highPrioritySuggestionsBeatLowerPrioritySuggestions_telephonyNetworkOrigins() {
mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
.pokeAutoTimeDetectionEnabled(true)
.pokeAutoOriginPriorities(ORIGIN_TELEPHONY, ORIGIN_NETWORK);
@@ -672,22 +720,130 @@
}
@Test
+ public void highPrioritySuggestionsBeatLowerPrioritySuggestions_networkGnssOrigins() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoTimeDetectionEnabled(true)
+ .pokeAutoOriginPriorities(ORIGIN_NETWORK, ORIGIN_GNSS);
+
+ // Three obviously different times that could not be mistaken for each other.
+ Instant gnssTime1 = ARBITRARY_TEST_TIME;
+ Instant gnssTime2 = ARBITRARY_TEST_TIME.plus(Duration.ofDays(30));
+ Instant networkTime = 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 gnss suggestion is made. It should be used because there is no network suggestion.
+ GnssTimeSuggestion gnssTimeSuggestion1 =
+ mScript.generateGnssTimeSuggestion(gnssTime1);
+ mScript.simulateTimePassing(smallTimeIncrementMillis)
+ .simulateGnssTimeSuggestion(gnssTimeSuggestion1)
+ .verifySystemClockWasSetAndResetCallTracking(
+ mScript.calculateTimeInMillisForNow(gnssTimeSuggestion1.getUtcTime()));
+
+ // Check internal state.
+ mScript.assertLatestNetworkSuggestion(null)
+ .assertLatestGnssSuggestion(gnssTimeSuggestion1);
+ assertEquals(gnssTimeSuggestion1, mScript.peekLatestValidGnssSuggestion());
+ assertNull("No network suggestions were made:", mScript.peekLatestValidNetworkSuggestion());
+
+ // Simulate a little time passing.
+ mScript.simulateTimePassing(smallTimeIncrementMillis)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+
+ // Now a network suggestion is made. Network suggestions are prioritized over gnss
+ // suggestions so it should "win".
+ NetworkTimeSuggestion networkTimeSuggestion =
+ mScript.generateNetworkTimeSuggestion(networkTime);
+ mScript.simulateTimePassing(smallTimeIncrementMillis)
+ .simulateNetworkTimeSuggestion(networkTimeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(
+ mScript.calculateTimeInMillisForNow(networkTimeSuggestion.getUtcTime()));
+
+ // Check internal state.
+ mScript.assertLatestNetworkSuggestion(networkTimeSuggestion)
+ .assertLatestGnssSuggestion(gnssTimeSuggestion1);
+ assertEquals(gnssTimeSuggestion1, mScript.peekLatestValidGnssSuggestion());
+ assertEquals(networkTimeSuggestion, mScript.peekLatestValidNetworkSuggestion());
+
+ // Simulate some significant time passing: half the time allowed before a time signal
+ // becomes "too old to use".
+ mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_UTC_TIME_AGE_MILLIS / 2)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+
+ // Now another gnss suggestion is made. Network suggestions are prioritized over
+ // gnss suggestions so the latest network suggestion should still "win".
+ GnssTimeSuggestion gnssTimeSuggestion2 =
+ mScript.generateGnssTimeSuggestion(gnssTime2);
+ mScript.simulateTimePassing(smallTimeIncrementMillis)
+ .simulateGnssTimeSuggestion(gnssTimeSuggestion2)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+
+ // Check internal state.
+ mScript.assertLatestNetworkSuggestion(networkTimeSuggestion)
+ .assertLatestGnssSuggestion(gnssTimeSuggestion2);
+ assertEquals(gnssTimeSuggestion2, mScript.peekLatestValidGnssSuggestion());
+ assertEquals(networkTimeSuggestion, mScript.peekLatestValidNetworkSuggestion());
+
+ // Simulate some significant time passing: half the time allowed before a time signal
+ // becomes "too old to use". This should mean that telephonyTimeSuggestion is now too old to
+ // be used but networkTimeSuggestion2 is not.
+ mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_UTC_TIME_AGE_MILLIS / 2);
+
+ // NOTE: The TimeDetectorStrategyImpl doesn't set an alarm for the point when the last
+ // suggestion it used becomes too old: it requires a new suggestion or an auto-time toggle
+ // to re-run the detection logic. This may change in future but until then we rely on a
+ // steady stream of suggestions to re-evaluate.
+ mScript.verifySystemClockWasNotSetAndResetCallTracking();
+
+ // Check internal state.
+ mScript.assertLatestNetworkSuggestion(networkTimeSuggestion)
+ .assertLatestGnssSuggestion(gnssTimeSuggestion2);
+ assertEquals(gnssTimeSuggestion2, mScript.peekLatestValidGnssSuggestion());
+ assertNull(
+ "Network suggestion should be expired:",
+ mScript.peekLatestValidNetworkSuggestion());
+
+ // Toggle auto-time off and on to force the detection logic to run.
+ mScript.simulateAutoTimeDetectionToggle()
+ .simulateTimePassing(smallTimeIncrementMillis)
+ .simulateAutoTimeDetectionToggle();
+
+ // Verify the latest gnss time now wins.
+ mScript.verifySystemClockWasSetAndResetCallTracking(
+ mScript.calculateTimeInMillisForNow(gnssTimeSuggestion2.getUtcTime()));
+
+ // Check internal state.
+ mScript.assertLatestNetworkSuggestion(networkTimeSuggestion)
+ .assertLatestGnssSuggestion(gnssTimeSuggestion2);
+ assertEquals(gnssTimeSuggestion2, mScript.peekLatestValidGnssSuggestion());
+ assertNull(
+ "Network suggestion should still be expired:",
+ mScript.peekLatestValidNetworkSuggestion());
+ }
+
+ @Test
public void whenAllTimeSuggestionsAreAvailable_higherPriorityWins_lowerPriorityComesFirst() {
mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
.pokeAutoTimeDetectionEnabled(true)
- .pokeAutoOriginPriorities(ORIGIN_TELEPHONY, ORIGIN_NETWORK);
+ .pokeAutoOriginPriorities(ORIGIN_TELEPHONY, ORIGIN_NETWORK, ORIGIN_GNSS);
Instant networkTime = ARBITRARY_TEST_TIME;
- Instant telephonyTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(30));
+ Instant gnssTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(30));
+ Instant telephonyTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(60));
NetworkTimeSuggestion networkTimeSuggestion =
mScript.generateNetworkTimeSuggestion(networkTime);
+ GnssTimeSuggestion gnssTimeSuggestion =
+ mScript.generateGnssTimeSuggestion(gnssTime);
TelephonyTimeSuggestion telephonyTimeSuggestion =
mScript.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, telephonyTime);
mScript.simulateNetworkTimeSuggestion(networkTimeSuggestion)
+ .simulateGnssTimeSuggestion(gnssTimeSuggestion)
.simulateTelephonyTimeSuggestion(telephonyTimeSuggestion)
.assertLatestNetworkSuggestion(networkTimeSuggestion)
+ .assertLatestGnssSuggestion(gnssTimeSuggestion)
.assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(telephonyTime.toEpochMilli());
}
@@ -696,20 +852,25 @@
public void whenAllTimeSuggestionsAreAvailable_higherPriorityWins_higherPriorityComesFirst() {
mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
.pokeAutoTimeDetectionEnabled(true)
- .pokeAutoOriginPriorities(ORIGIN_TELEPHONY, ORIGIN_NETWORK);
+ .pokeAutoOriginPriorities(ORIGIN_TELEPHONY, ORIGIN_NETWORK, ORIGIN_GNSS);
Instant networkTime = ARBITRARY_TEST_TIME;
Instant telephonyTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(30));
+ Instant gnssTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(60));
NetworkTimeSuggestion networkTimeSuggestion =
mScript.generateNetworkTimeSuggestion(networkTime);
TelephonyTimeSuggestion telephonyTimeSuggestion =
mScript.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, telephonyTime);
+ GnssTimeSuggestion gnssTimeSuggestion =
+ mScript.generateGnssTimeSuggestion(gnssTime);
mScript.simulateTelephonyTimeSuggestion(telephonyTimeSuggestion)
.simulateNetworkTimeSuggestion(networkTimeSuggestion)
+ .simulateGnssTimeSuggestion(gnssTimeSuggestion)
.assertLatestNetworkSuggestion(networkTimeSuggestion)
.assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion)
+ .assertLatestGnssSuggestion(gnssTimeSuggestion)
.verifySystemClockWasSetAndResetCallTracking(telephonyTime.toEpochMilli());
}
@@ -728,7 +889,37 @@
}
@Test
- public void suggestionsFromSourceNotListedInPrioritiesList_areIgnored() {
+ public void whenHigherPrioritySuggestionsAreNotAvailable_fallbacksToNext() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoTimeDetectionEnabled(true)
+ .pokeAutoOriginPriorities(ORIGIN_TELEPHONY, ORIGIN_NETWORK, ORIGIN_GNSS);
+
+ GnssTimeSuggestion timeSuggestion =
+ mScript.generateGnssTimeSuggestion(ARBITRARY_TEST_TIME);
+
+ mScript.simulateGnssTimeSuggestion(timeSuggestion)
+ .assertLatestGnssSuggestion(timeSuggestion)
+ .verifySystemClockWasSetAndResetCallTracking(ARBITRARY_TEST_TIME.toEpochMilli());
+ }
+
+ @Test
+ public void suggestionsFromTelephonyOriginNotInPriorityList_areIgnored() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoTimeDetectionEnabled(true)
+ .pokeAutoOriginPriorities(ORIGIN_NETWORK);
+
+ int slotIndex = ARBITRARY_SLOT_INDEX;
+ Instant testTime = ARBITRARY_TEST_TIME;
+ TelephonyTimeSuggestion timeSuggestion =
+ mScript.generateTelephonyTimeSuggestion(slotIndex, testTime);
+
+ mScript.simulateTelephonyTimeSuggestion(timeSuggestion)
+ .assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, timeSuggestion)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+ }
+
+ @Test
+ public void suggestionsFromNetworkOriginNotInPriorityList_areIgnored() {
mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
.pokeAutoTimeDetectionEnabled(true)
.pokeAutoOriginPriorities(ORIGIN_TELEPHONY);
@@ -742,6 +933,20 @@
}
@Test
+ public void suggestionsFromGnssOriginNotInPriorityList_areIgnored() {
+ mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+ .pokeAutoTimeDetectionEnabled(true)
+ .pokeAutoOriginPriorities(ORIGIN_TELEPHONY);
+
+ GnssTimeSuggestion timeSuggestion = mScript.generateGnssTimeSuggestion(
+ ARBITRARY_TEST_TIME);
+
+ mScript.simulateGnssTimeSuggestion(timeSuggestion)
+ .assertLatestGnssSuggestion(timeSuggestion)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+ }
+
+ @Test
public void autoOriginPrioritiesList_doesNotAffectManualSuggestion() {
mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
.pokeAutoTimeDetectionEnabled(false)
@@ -945,6 +1150,11 @@
return this;
}
+ Script simulateGnssTimeSuggestion(GnssTimeSuggestion timeSuggestion) {
+ mTimeDetectorStrategy.suggestGnssTime(timeSuggestion);
+ return this;
+ }
+
Script simulateAutoTimeDetectionToggle() {
mFakeCallback.simulateAutoTimeZoneDetectionToggle();
mTimeDetectorStrategy.handleAutoTimeConfigChanged();
@@ -995,6 +1205,14 @@
}
/**
+ * White box test info: Asserts the latest gnss suggestion is as expected.
+ */
+ Script assertLatestGnssSuggestion(GnssTimeSuggestion expected) {
+ assertEquals(expected, mTimeDetectorStrategy.getLatestGnssSuggestion());
+ return this;
+ }
+
+ /**
* White box test info: Returns the telephony suggestion that would be used, if any, given
* the current elapsed real time clock and regardless of origin prioritization.
*/
@@ -1011,6 +1229,14 @@
}
/**
+ * White box test info: Returns the gnss suggestion that would be used, if any, given the
+ * current elapsed real time clock and regardless of origin prioritization.
+ */
+ GnssTimeSuggestion peekLatestValidGnssSuggestion() {
+ return mTimeDetectorStrategy.findLatestValidGnssSuggestionForTests();
+ }
+
+ /**
* Generates a ManualTimeSuggestion using the current elapsed realtime clock for the
* reference time.
*/
@@ -1057,6 +1283,18 @@
}
/**
+ * Generates a GnssTimeSuggestion using the current elapsed realtime clock for the
+ * reference time.
+ */
+ GnssTimeSuggestion generateGnssTimeSuggestion(Instant suggestedTime) {
+ TimestampedValue<Long> utcTime =
+ new TimestampedValue<>(
+ mFakeCallback.peekElapsedRealtimeMillis(),
+ suggestedTime.toEpochMilli());
+ return new GnssTimeSuggestion(utcTime);
+ }
+
+ /**
* Calculates what the supplied time would be when adjusted for the movement of the fake
* elapsed realtime clock.
*/
diff --git a/services/tests/servicestests/src/com/android/server/timezone/OWNERS b/services/tests/servicestests/src/com/android/server/timezone/OWNERS
index 09447a9..8f80897 100644
--- a/services/tests/servicestests/src/com/android/server/timezone/OWNERS
+++ b/services/tests/servicestests/src/com/android/server/timezone/OWNERS
@@ -1 +1,3 @@
-include /core/java/android/app/timezone/OWNERS
+# Bug component: 847766
+mingaleev@google.com
+include /core/java/android/app/timedetector/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/OWNERS b/services/tests/servicestests/src/com/android/server/timezonedetector/OWNERS
index 09447a9..8f80897 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/OWNERS
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/OWNERS
@@ -1 +1,3 @@
-include /core/java/android/app/timezone/OWNERS
+# Bug component: 847766
+mingaleev@google.com
+include /core/java/android/app/timedetector/OWNERS
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 45b6bce..f7c655f 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -1501,20 +1501,6 @@
}
@Test
- public void testCancelImmediatelyAfterEnqueueNotifiesListeners_ForegroundServiceFlag()
- throws Exception {
- final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
- sbn.getNotification().flags =
- Notification.FLAG_ONGOING_EVENT | FLAG_FOREGROUND_SERVICE;
- mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag",
- sbn.getId(), sbn.getNotification(), sbn.getUserId());
- mBinderService.cancelNotificationWithTag(PKG, PKG, "tag", sbn.getId(), sbn.getUserId());
- waitForIdle();
- verify(mListeners, times(1)).notifyPostedLocked(any(), any());
- verify(mListeners, times(1)).notifyRemovedLocked(any(), anyInt(), any());
- }
-
- @Test
public void testUserInitiatedClearAll_noLeak() throws Exception {
final NotificationRecord n = generateNotificationRecord(
mTestNotificationChannel, 1, "group", true);
diff --git a/services/tests/wmtests/Android.bp b/services/tests/wmtests/Android.bp
index 4ca5b9e..1ecf850 100644
--- a/services/tests/wmtests/Android.bp
+++ b/services/tests/wmtests/Android.bp
@@ -47,7 +47,6 @@
"testables",
"ub-uiautomator",
"hamcrest-library",
- "compatibility-device-util-axt",
],
libs: [
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
index f79e4cc..226c71a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
@@ -90,12 +90,9 @@
@Presubmit
@RunWith(WindowTestRunner.class)
public class RootActivityContainerTests extends WindowTestsBase {
- private Task mFullscreenStack;
@Before
public void setUp() throws Exception {
- mFullscreenStack = mRootWindowContainer.getDefaultTaskDisplayArea().createRootTask(
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
doNothing().when(mAtm).updateSleepIfNeededLocked();
}
@@ -117,50 +114,54 @@
*/
@Test
public void testReplacingTaskInPinnedStack() {
+ Task fullscreenTask = mRootWindowContainer.getDefaultTaskDisplayArea().createRootTask(
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
final ActivityRecord firstActivity = new ActivityBuilder(mAtm)
- .setTask(mFullscreenStack).build();
+ .setTask(fullscreenTask).build();
final ActivityRecord secondActivity = new ActivityBuilder(mAtm)
- .setTask(mFullscreenStack).build();
+ .setTask(fullscreenTask).build();
- mFullscreenStack.moveToFront("testReplacingTaskInPinnedStack");
+ fullscreenTask.moveToFront("testReplacingTaskInPinnedStack");
// Ensure full screen stack has both tasks.
- ensureStackPlacement(mFullscreenStack, firstActivity, secondActivity);
+ ensureStackPlacement(fullscreenTask, firstActivity, secondActivity);
// Move first activity to pinned stack.
mRootWindowContainer.moveActivityToPinnedRootTask(firstActivity, "initialMove");
- final TaskDisplayArea taskDisplayArea = mFullscreenStack.getDisplayArea();
+ final TaskDisplayArea taskDisplayArea = fullscreenTask.getDisplayArea();
Task pinnedStack = taskDisplayArea.getRootPinnedTask();
// Ensure a task has moved over.
ensureStackPlacement(pinnedStack, firstActivity);
- ensureStackPlacement(mFullscreenStack, secondActivity);
+ ensureStackPlacement(fullscreenTask, secondActivity);
// Move second activity to pinned stack.
mRootWindowContainer.moveActivityToPinnedRootTask(secondActivity, "secondMove");
// Need to get stacks again as a new instance might have been created.
pinnedStack = taskDisplayArea.getRootPinnedTask();
- mFullscreenStack = taskDisplayArea.getRootTask(WINDOWING_MODE_FULLSCREEN,
+ fullscreenTask = taskDisplayArea.getRootTask(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_STANDARD);
// Ensure stacks have swapped tasks.
ensureStackPlacement(pinnedStack, secondActivity);
- ensureStackPlacement(mFullscreenStack, firstActivity);
+ ensureStackPlacement(fullscreenTask, firstActivity);
}
@Test
public void testMovingBottomMostStackActivityToPinnedStack() {
+ final Task fullscreenTask = mRootWindowContainer.getDefaultTaskDisplayArea().createRootTask(
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
final ActivityRecord firstActivity = new ActivityBuilder(mAtm)
- .setTask(mFullscreenStack).build();
+ .setTask(fullscreenTask).build();
final Task task = firstActivity.getTask();
final ActivityRecord secondActivity = new ActivityBuilder(mAtm)
- .setTask(mFullscreenStack).build();
+ .setTask(fullscreenTask).build();
- mFullscreenStack.moveTaskToBack(task);
+ fullscreenTask.moveTaskToBack(task);
// Ensure full screen stack has both tasks.
- ensureStackPlacement(mFullscreenStack, firstActivity, secondActivity);
+ ensureStackPlacement(fullscreenTask, firstActivity, secondActivity);
assertEquals(task.getTopMostActivity(), secondActivity);
firstActivity.setState(STOPPED, "testMovingBottomMostStackActivityToPinnedStack");
@@ -171,21 +172,20 @@
assertTrue(firstActivity.mRequestForceTransition);
}
- private static void ensureStackPlacement(Task stack, ActivityRecord... activities) {
- final Task task = stack.getBottomMostTask();
- final ArrayList<ActivityRecord> stackActivities = new ArrayList<>();
+ private static void ensureStackPlacement(Task task, ActivityRecord... activities) {
+ final ArrayList<ActivityRecord> taskActivities = new ArrayList<>();
- task.forAllActivities((Consumer<ActivityRecord>) stackActivities::add, false);
+ task.forAllActivities((Consumer<ActivityRecord>) taskActivities::add, false);
- assertEquals("Expecting " + Arrays.deepToString(activities) + " got " + stackActivities,
- stackActivities.size(), activities != null ? activities.length : 0);
+ assertEquals("Expecting " + Arrays.deepToString(activities) + " got " + taskActivities,
+ taskActivities.size(), activities != null ? activities.length : 0);
if (activities == null) {
return;
}
for (ActivityRecord activity : activities) {
- assertTrue(stackActivities.contains(activity));
+ assertTrue(taskActivities.contains(activity));
}
}
@@ -419,19 +419,18 @@
*/
@Test
public void testFindTaskToMoveToFrontWhenRecentsOnOtherDisplay() {
- // Create stack/task on default display.
+ // Create tasks on default display.
final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
- final Task targetStack = taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN,
+ final Task targetRootTask = taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_STANDARD, false /* onTop */);
- final Task targetTask = new TaskBuilder(mSupervisor).setParentTask(targetStack).build();
+ final Task targetTask = new TaskBuilder(mSupervisor).setParentTask(targetRootTask).build();
// Create Recents on secondary display.
final TestDisplayContent secondDisplay = addNewDisplayContentAt(
DisplayContent.POSITION_TOP);
- final Task stack = secondDisplay.getDefaultTaskDisplayArea()
+ final Task rootTask = secondDisplay.getDefaultTaskDisplayArea()
.createRootTask(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_RECENTS, true /* onTop */);
- final Task task = new TaskBuilder(mSupervisor).setParentTask(stack).build();
- new ActivityBuilder(mAtm).setTask(task).build();
+ new ActivityBuilder(mAtm).setTask(rootTask).build();
final String reason = "findTaskToMoveToFront";
mSupervisor.findTaskToMoveToFront(targetTask, 0, ActivityOptions.makeBasic(), reason,
@@ -446,25 +445,24 @@
*/
@Test
public void testResumeActivityWhenNonTopmostStackIsTopFocused() {
- // Create a stack at bottom.
+ // Create a root task at bottom.
final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
- final Task targetStack = spy(taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN,
+ final Task rootTask = spy(taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_STANDARD, false /* onTop */));
- final Task task = new TaskBuilder(mSupervisor).setParentTask(targetStack).build();
- final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(task).build();
- taskDisplayArea.positionChildAt(POSITION_BOTTOM, targetStack, false /*includingParents*/);
+ final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(rootTask).build();
+ taskDisplayArea.positionChildAt(POSITION_BOTTOM, rootTask, false /*includingParents*/);
- // Assume the stack is not at the topmost position (e.g. behind always-on-top stacks) but it
- // is the current top focused stack.
- assertFalse(targetStack.isTopStackInDisplayArea());
- doReturn(targetStack).when(mRootWindowContainer).getTopDisplayFocusedRootTask();
+ // Assume the task is not at the topmost position (e.g. behind always-on-top stacks) but it
+ // is the current top focused task.
+ assertFalse(rootTask.isTopStackInDisplayArea());
+ doReturn(rootTask).when(mRootWindowContainer).getTopDisplayFocusedRootTask();
- // Use the stack as target to resume.
+ // Use the task as target to resume.
mRootWindowContainer.resumeFocusedTasksTopActivities(
- targetStack, activity, null /* targetOptions */);
+ rootTask, activity, null /* targetOptions */);
- // Verify the target stack should resume its activity.
- verify(targetStack, times(1)).resumeTopActivityUncheckedLocked(
+ // Verify the target task should resume its activity.
+ verify(rootTask, times(1)).resumeTopActivityUncheckedLocked(
eq(activity), eq(null /* targetOptions */));
}
@@ -474,7 +472,6 @@
*/
@Test
public void testResumeFocusedStacksStartsHomeActivity_NoActivities() {
- mFullscreenStack.removeIfPossible();
final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
taskDisplayArea.getRootHomeTask().removeIfPossible();
taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
@@ -496,7 +493,6 @@
*/
@Test
public void testResumeFocusedStacksStartsHomeActivity_ActivityOnSecondaryScreen() {
- mFullscreenStack.removeIfPossible();
final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
taskDisplayArea.getRootHomeTask().removeIfPossible();
taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
@@ -506,8 +502,7 @@
DisplayContent.POSITION_TOP);
final Task rootTask = secondDisplay.getDefaultTaskDisplayArea().createRootTask(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- final Task task = new TaskBuilder(mSupervisor).setParentTask(rootTask).build();
- new ActivityBuilder(mAtm).setTask(task).build();
+ new ActivityBuilder(mAtm).setTask(rootTask).build();
doReturn(true).when(mRootWindowContainer).resumeHomeActivity(any(), any(), any());
@@ -526,44 +521,44 @@
*/
@Test
public void testResumeActivityLingeringTransition() {
- // Create a stack at top.
+ // Create a root task at top.
final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
- final Task targetStack = spy(taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN,
+ final Task rootTask = spy(taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_STANDARD, false /* onTop */));
- final Task task = new TaskBuilder(mSupervisor).setParentTask(targetStack).build();
- final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(task).build();
+ final ActivityRecord activity = new ActivityBuilder(mAtm)
+ .setTask(rootTask).setOnTop(true).build();
activity.setState(ActivityState.RESUMED, "test");
- // Assume the stack is at the topmost position
- assertTrue(targetStack.isTopStackInDisplayArea());
+ // Assume the task is at the topmost position
+ assertTrue(rootTask.isTopStackInDisplayArea());
- // Use the stack as target to resume.
+ // Use the task as target to resume.
mRootWindowContainer.resumeFocusedTasksTopActivities();
// Verify the lingering app transition is being executed because it's already resumed
- verify(targetStack, times(1)).executeAppTransition(any());
+ verify(rootTask, times(1)).executeAppTransition(any());
}
@Test
public void testResumeActivityLingeringTransition_notExecuted() {
- // Create a stack at bottom.
+ // Create a root task at bottom.
final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
- final Task targetStack = spy(taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN,
+ final Task rootTask = spy(taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_STANDARD, false /* onTop */));
- final Task task = new TaskBuilder(mSupervisor).setParentTask(targetStack).build();
- final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(task).build();
+ final ActivityRecord activity = new ActivityBuilder(mAtm)
+ .setTask(rootTask).setOnTop(true).build();
activity.setState(ActivityState.RESUMED, "test");
- taskDisplayArea.positionChildAt(POSITION_BOTTOM, targetStack, false /*includingParents*/);
+ taskDisplayArea.positionChildAt(POSITION_BOTTOM, rootTask, false /*includingParents*/);
- // Assume the stack is at the topmost position
- assertFalse(targetStack.isTopStackInDisplayArea());
- doReturn(targetStack).when(mRootWindowContainer).getTopDisplayFocusedRootTask();
+ // Assume the task is at the topmost position
+ assertFalse(rootTask.isTopStackInDisplayArea());
+ doReturn(rootTask).when(mRootWindowContainer).getTopDisplayFocusedRootTask();
- // Use the stack as target to resume.
+ // Use the task as target to resume.
mRootWindowContainer.resumeFocusedTasksTopActivities();
// Verify the lingering app transition is being executed because it's already resumed
- verify(targetStack, never()).executeAppTransition(any());
+ verify(rootTask, never()).executeAppTransition(any());
}
/**
@@ -889,7 +884,9 @@
@Test
public void testSwitchUser_missingHomeRootTask() {
- doReturn(mFullscreenStack).when(mRootWindowContainer).getTopDisplayFocusedRootTask();
+ final Task fullscreenTask = mRootWindowContainer.getDefaultTaskDisplayArea().createRootTask(
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+ doReturn(fullscreenTask).when(mRootWindowContainer).getTopDisplayFocusedRootTask();
final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
Task homeStack = taskDisplayArea.getRootHomeTask();
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
index 788ef5a..6046c9b2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
@@ -20,20 +20,19 @@
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static com.android.server.wm.utils.CommonUtils.runWithShellPermissionIdentity;
+
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 android.app.Activity;
-import android.app.ActivityManager;
import android.app.ActivityManager.TaskDescription;
import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
import android.app.ActivityView;
-import android.app.IActivityManager;
import android.app.ITaskStackListener;
-import android.app.Instrumentation;
import android.app.Instrumentation.ActivityMonitor;
import android.app.TaskStackListener;
import android.content.ComponentName;
@@ -44,7 +43,6 @@
import android.os.RemoteException;
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
-import android.support.test.uiautomator.UiDevice;
import android.text.TextUtils;
import android.view.Display;
import android.view.ViewGroup;
@@ -52,10 +50,7 @@
import androidx.test.filters.FlakyTest;
import androidx.test.filters.MediumTest;
-import com.android.compatibility.common.util.SystemUtil;
-
import org.junit.After;
-import org.junit.Before;
import org.junit.Test;
import java.util.concurrent.ArrayBlockingQueue;
@@ -70,17 +65,11 @@
@MediumTest
public class TaskStackChangedListenerTest {
- private IActivityManager mService;
private ITaskStackListener mTaskStackListener;
private static final int WAIT_TIMEOUT_MS = 5000;
private static final Object sLock = new Object();
- @Before
- public void setUp() throws Exception {
- mService = ActivityManager.getService();
- }
-
@After
public void tearDown() throws Exception {
ActivityTaskManager.getService().unregisterTaskStackListener(mTaskStackListener);
@@ -374,7 +363,7 @@
final ActivityMonitor monitor = new ActivityMonitor(activityClass.getName(), null, false);
getInstrumentation().addMonitor(monitor);
final Context context = getInstrumentation().getContext();
- SystemUtil.runWithShellPermissionIdentity(() -> context.startActivity(
+ runWithShellPermissionIdentity(() -> context.startActivity(
new Intent(context, activityClass).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
options.toBundle()));
final TestActivity activity =
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
index 4041412..e58c162 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
@@ -47,7 +47,7 @@
import org.junit.runner.RunWith;
/**
- * Tests for the {@link ActivityStack} class.
+ * Tests for the {@link Task} class.
*
* Build/Install/Run:
* atest WmTests:TaskStackTests
@@ -82,36 +82,29 @@
}
@Test
- public void testClosingAppDifferentStackOrientation() {
- final Task stack = createTaskStackOnDisplay(mDisplayContent);
- final Task task1 = createTaskInStack(stack, 0 /* userId */);
- ActivityRecord activity1 = createNonAttachedActivityRecord(mDisplayContent);
- task1.addChild(activity1, 0);
+ public void testClosingAppDifferentTaskOrientation() {
+ final ActivityRecord activity1 = createActivityRecord(mDisplayContent);
activity1.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
- final Task task2 = createTaskInStack(stack, 1 /* userId */);
- ActivityRecord activity2 = createNonAttachedActivityRecord(mDisplayContent);
- task2.addChild(activity2, 0);
+ final ActivityRecord activity2 = createActivityRecord(mDisplayContent);
activity2.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
- assertEquals(SCREEN_ORIENTATION_PORTRAIT, stack.getOrientation());
+ final WindowContainer parent = activity1.getTask().getParent();
+ assertEquals(SCREEN_ORIENTATION_PORTRAIT, parent.getOrientation());
mDisplayContent.mClosingApps.add(activity2);
- assertEquals(SCREEN_ORIENTATION_LANDSCAPE, stack.getOrientation());
+ assertEquals(SCREEN_ORIENTATION_LANDSCAPE, parent.getOrientation());
}
@Test
- public void testMoveTaskToBackDifferentStackOrientation() {
- final Task stack = createTaskStackOnDisplay(mDisplayContent);
- final Task task1 = createTaskInStack(stack, 0 /* userId */);
- ActivityRecord activity1 = createNonAttachedActivityRecord(mDisplayContent);
- task1.addChild(activity1, 0);
+ public void testMoveTaskToBackDifferentTaskOrientation() {
+ final ActivityRecord activity1 = createActivityRecord(mDisplayContent);
activity1.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
- final Task task2 = createTaskInStack(stack, 1 /* userId */);
- ActivityRecord activity2 = createNonAttachedActivityRecord(mDisplayContent);
- task2.addChild(activity2, 0);
+ final ActivityRecord activity2 = createActivityRecord(mDisplayContent);
activity2.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
- assertEquals(SCREEN_ORIENTATION_PORTRAIT, stack.getOrientation());
+
+ final WindowContainer parent = activity1.getTask().getParent();
+ assertEquals(SCREEN_ORIENTATION_PORTRAIT, parent.getOrientation());
}
@Test
@@ -215,8 +208,7 @@
@Test
public void testActivityAndTaskGetsProperType() {
- final Task stack = createTaskStackOnDisplay(mDisplayContent);
- final Task task1 = createTaskInStack(stack, 0 /* userId */);
+ final Task task1 = new TaskBuilder(mSupervisor).build();
ActivityRecord activity1 = createNonAttachedActivityRecord(mDisplayContent);
// First activity should become standard
diff --git a/services/tests/wmtests/src/com/android/server/wm/utils/CommonUtils.java b/services/tests/wmtests/src/com/android/server/wm/utils/CommonUtils.java
new file mode 100644
index 0000000..99d73cf
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/utils/CommonUtils.java
@@ -0,0 +1,37 @@
+/*
+ * 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.wm.utils;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import android.app.UiAutomation;
+
+/** Provides common utility functions. */
+public class CommonUtils {
+ public static UiAutomation getUiAutomation() {
+ return getInstrumentation().getUiAutomation();
+ }
+
+ public static void runWithShellPermissionIdentity(Runnable runnable) {
+ getUiAutomation().adoptShellPermissionIdentity();
+ try {
+ runnable.run();
+ } finally {
+ getUiAutomation().dropShellPermissionIdentity();
+ }
+ }
+}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index aa36e47..3815326 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -184,10 +184,12 @@
private static class ActivityData {
private final String mTaskRootPackage;
private final String mTaskRootClass;
+ private final String mUsageSourcePackage;
public int lastEvent = Event.NONE;
- private ActivityData(String taskRootPackage, String taskRootClass) {
+ private ActivityData(String taskRootPackage, String taskRootClass, String sourcePackage) {
mTaskRootPackage = taskRootPackage;
mTaskRootClass = taskRootClass;
+ mUsageSourcePackage = sourcePackage;
}
}
@@ -840,23 +842,25 @@
.APP_USAGE_EVENT_OCCURRED__EVENT_TYPE__MOVE_TO_FOREGROUND);
// check if this activity has already been resumed
if (mVisibleActivities.get(event.mInstanceId) != null) break;
- final ActivityData resumedData = new ActivityData(event.mTaskRootPackage,
- event.mTaskRootClass);
- resumedData.lastEvent = Event.ACTIVITY_RESUMED;
- mVisibleActivities.put(event.mInstanceId, resumedData);
+ final String usageSourcePackage;
+ switch(mUsageSource) {
+ case USAGE_SOURCE_CURRENT_ACTIVITY:
+ usageSourcePackage = event.mPackage;
+ break;
+ case USAGE_SOURCE_TASK_ROOT_ACTIVITY:
+ default:
+ usageSourcePackage = event.mTaskRootPackage;
+ break;
+ }
try {
- switch(mUsageSource) {
- case USAGE_SOURCE_CURRENT_ACTIVITY:
- mAppTimeLimit.noteUsageStart(event.mPackage, userId);
- break;
- case USAGE_SOURCE_TASK_ROOT_ACTIVITY:
- default:
- mAppTimeLimit.noteUsageStart(event.mTaskRootPackage, userId);
- break;
- }
+ mAppTimeLimit.noteUsageStart(usageSourcePackage, userId);
} catch (IllegalArgumentException iae) {
Slog.e(TAG, "Failed to note usage start", iae);
}
+ final ActivityData resumedData = new ActivityData(event.mTaskRootPackage,
+ event.mTaskRootClass, usageSourcePackage);
+ resumedData.lastEvent = Event.ACTIVITY_RESUMED;
+ mVisibleActivities.put(event.mInstanceId, resumedData);
break;
case Event.ACTIVITY_PAUSED:
final ActivityData pausedData = mVisibleActivities.get(event.mInstanceId);
@@ -928,15 +932,7 @@
event.mTaskRootClass = prevData.mTaskRootClass;
}
try {
- switch(mUsageSource) {
- case USAGE_SOURCE_CURRENT_ACTIVITY:
- mAppTimeLimit.noteUsageStop(event.mPackage, userId);
- break;
- case USAGE_SOURCE_TASK_ROOT_ACTIVITY:
- default:
- mAppTimeLimit.noteUsageStop(event.mTaskRootPackage, userId);
- break;
- }
+ mAppTimeLimit.noteUsageStop(prevData.mUsageSourcePackage, userId);
} catch (IllegalArgumentException iae) {
Slog.w(TAG, "Failed to note usage stop", iae);
}
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/OWNERS b/services/voiceinteraction/java/com/android/server/soundtrigger/OWNERS
new file mode 100644
index 0000000..e5d0370
--- /dev/null
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/OWNERS
@@ -0,0 +1,2 @@
+ytai@google.com
+elaurent@google.com
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
index 4bf93a2..283fae5 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
@@ -1038,6 +1038,7 @@
if (mModule != null) {
mModule.detach();
mModule = null;
+ mServiceDisabled = false;
}
}
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index df0b9ac..31a1249 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -1516,6 +1516,16 @@
public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL = 4;
/**
+ * Used as an int value for {@link #EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE}
+ * to indicate that default subscription for data/sms/voice is now determined, that
+ * it should dismiss any dialog or pop-ups that is asking user to select default sub.
+ * This is used when, for example, opportunistic subscription is configured. At that
+ * time the primary becomes default sub there's no need to ask user to select anymore.
+ * @hide
+ */
+ public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DISMISS = 5;
+
+ /**
* Integer intent extra to be used with {@link #ACTION_PRIMARY_SUBSCRIPTION_LIST_CHANGED}
* to indicate if the SIM combination in DSDS has limitation or compatible issue.
* e.g. two CDMA SIMs may disrupt each other's voice call in certain scenarios.
diff --git a/test-mock/src/android/test/mock/OWNERS b/test-mock/src/android/test/mock/OWNERS
new file mode 100644
index 0000000..36d9cb2
--- /dev/null
+++ b/test-mock/src/android/test/mock/OWNERS
@@ -0,0 +1 @@
+set noparent
diff --git a/tests/Compatibility/Android.bp b/tests/Compatibility/Android.bp
index 7dc44fa..c14e705 100644
--- a/tests/Compatibility/Android.bp
+++ b/tests/Compatibility/Android.bp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-android_test {
+android_test_helper_app {
name: "AppCompatibilityTest",
static_libs: ["androidx.test.rules"],
// Include all test java files.
diff --git a/tests/net/common/java/android/net/TcpKeepalivePacketDataTest.kt b/tests/net/common/java/android/net/TcpKeepalivePacketDataTest.kt
new file mode 100644
index 0000000..6770066
--- /dev/null
+++ b/tests/net/common/java/android/net/TcpKeepalivePacketDataTest.kt
@@ -0,0 +1,106 @@
+/*
+ * 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.net
+
+import android.net.InetAddresses.parseNumericAddress
+import android.os.Build
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.DevSdkIgnoreRunner
+import com.android.testutils.assertFieldCountEquals
+import com.android.testutils.assertParcelSane
+import org.junit.Test
+import org.junit.runner.RunWith
+import java.net.InetAddress
+import kotlin.test.assertEquals
+import kotlin.test.assertNotEquals
+import kotlin.test.assertTrue
+
+@RunWith(DevSdkIgnoreRunner::class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R) // TcpKeepalivePacketData added to SDK in S
+class TcpKeepalivePacketDataTest {
+ private fun makeData(
+ srcAddress: InetAddress = parseNumericAddress("192.0.2.123"),
+ srcPort: Int = 1234,
+ dstAddress: InetAddress = parseNumericAddress("192.0.2.231"),
+ dstPort: Int = 4321,
+ data: ByteArray = byteArrayOf(1, 2, 3),
+ tcpSeq: Int = 135,
+ tcpAck: Int = 246,
+ tcpWnd: Int = 1234,
+ tcpWndScale: Int = 2,
+ ipTos: Int = 0x12,
+ ipTtl: Int = 10
+ ) = TcpKeepalivePacketData(srcAddress, srcPort, dstAddress, dstPort, data, tcpSeq, tcpAck,
+ tcpWnd, tcpWndScale, ipTos, ipTtl)
+
+ @Test
+ fun testEquals() {
+ val data1 = makeData()
+ val data2 = makeData()
+ assertEquals(data1, data2)
+ assertEquals(data1.hashCode(), data2.hashCode())
+ }
+
+ @Test
+ fun testNotEquals() {
+ assertNotEquals(makeData(srcAddress = parseNumericAddress("192.0.2.124")), makeData())
+ assertNotEquals(makeData(srcPort = 1235), makeData())
+ assertNotEquals(makeData(dstAddress = parseNumericAddress("192.0.2.232")), makeData())
+ assertNotEquals(makeData(dstPort = 4322), makeData())
+ // .equals does not test .packet, as it should be generated from the other fields
+ assertNotEquals(makeData(tcpSeq = 136), makeData())
+ assertNotEquals(makeData(tcpAck = 247), makeData())
+ assertNotEquals(makeData(tcpWnd = 1235), makeData())
+ assertNotEquals(makeData(tcpWndScale = 3), makeData())
+ assertNotEquals(makeData(ipTos = 0x14), makeData())
+ assertNotEquals(makeData(ipTtl = 11), makeData())
+
+ // Update above assertions if field is added
+ assertFieldCountEquals(5, KeepalivePacketData::class.java)
+ assertFieldCountEquals(6, TcpKeepalivePacketData::class.java)
+ }
+
+ @Test
+ fun testParcelUnparcel() {
+ assertParcelSane(makeData(), fieldCount = 6) { a, b ->
+ // .equals() does not verify .packet
+ a == b && a.packet contentEquals b.packet
+ }
+ }
+
+ @Test
+ fun testToString() {
+ val data = makeData()
+ val str = data.toString()
+
+ assertTrue(str.contains(data.srcAddress.hostAddress))
+ assertTrue(str.contains(data.srcPort.toString()))
+ assertTrue(str.contains(data.dstAddress.hostAddress))
+ assertTrue(str.contains(data.dstPort.toString()))
+ // .packet not included in toString()
+ assertTrue(str.contains(data.tcpSeq.toString()))
+ assertTrue(str.contains(data.tcpAck.toString()))
+ assertTrue(str.contains(data.tcpWindow.toString()))
+ assertTrue(str.contains(data.tcpWindowScale.toString()))
+ assertTrue(str.contains(data.ipTos.toString()))
+ assertTrue(str.contains(data.ipTtl.toString()))
+
+ // Update above assertions if field is added
+ assertFieldCountEquals(5, KeepalivePacketData::class.java)
+ assertFieldCountEquals(6, TcpKeepalivePacketData::class.java)
+ }
+}
\ No newline at end of file
diff --git a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java b/tests/net/java/android/net/KeepalivePacketDataUtilTest.java
similarity index 65%
rename from tests/net/java/android/net/TcpKeepalivePacketDataTest.java
rename to tests/net/java/android/net/KeepalivePacketDataUtilTest.java
index c5b25bd..fc739fb 100644
--- a/tests/net/java/android/net/TcpKeepalivePacketDataTest.java
+++ b/tests/net/java/android/net/KeepalivePacketDataUtilTest.java
@@ -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.
@@ -20,8 +20,11 @@
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import android.net.util.KeepalivePacketDataUtil;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -31,7 +34,7 @@
import java.nio.ByteBuffer;
@RunWith(JUnit4.class)
-public final class TcpKeepalivePacketDataTest {
+public final class KeepalivePacketDataUtilTest {
private static final byte[] IPV4_KEEPALIVE_SRC_ADDR = {10, 0, 0, 1};
private static final byte[] IPV4_KEEPALIVE_DST_ADDR = {10, 0, 0, 5};
@@ -39,7 +42,7 @@
public void setUp() {}
@Test
- public void testV4TcpKeepalivePacket() throws Exception {
+ public void testFromTcpKeepaliveStableParcelable() throws Exception {
final int srcPort = 1234;
final int dstPort = 4321;
final int seq = 0x11111111;
@@ -61,7 +64,7 @@
testInfo.tos = tos;
testInfo.ttl = ttl;
try {
- resultData = TcpKeepalivePacketData.tcpKeepalivePacket(testInfo);
+ resultData = KeepalivePacketDataUtil.fromStableParcelable(testInfo);
} catch (InvalidPacketException e) {
fail("InvalidPacketException: " + e);
}
@@ -72,8 +75,8 @@
assertEquals(testInfo.dstPort, resultData.getDstPort());
assertEquals(testInfo.seq, resultData.tcpSeq);
assertEquals(testInfo.ack, resultData.tcpAck);
- assertEquals(testInfo.rcvWnd, resultData.tcpWnd);
- assertEquals(testInfo.rcvWndScale, resultData.tcpWndScale);
+ assertEquals(testInfo.rcvWnd, resultData.tcpWindow);
+ assertEquals(testInfo.rcvWndScale, resultData.tcpWindowScale);
assertEquals(testInfo.tos, resultData.ipTos);
assertEquals(testInfo.ttl, resultData.ipTtl);
@@ -113,7 +116,7 @@
//TODO: add ipv6 test when ipv6 supported
@Test
- public void testParcel() throws Exception {
+ public void testToTcpKeepaliveStableParcelable() throws Exception {
final int srcPort = 1234;
final int dstPort = 4321;
final int sequence = 0x11111111;
@@ -135,8 +138,8 @@
testInfo.ttl = ttl;
TcpKeepalivePacketData testData = null;
TcpKeepalivePacketDataParcelable resultData = null;
- testData = TcpKeepalivePacketData.tcpKeepalivePacket(testInfo);
- resultData = testData.toStableParcelable();
+ testData = KeepalivePacketDataUtil.fromStableParcelable(testInfo);
+ resultData = KeepalivePacketDataUtil.toStableParcelable(testData);
assertArrayEquals(resultData.srcAddress, IPV4_KEEPALIVE_SRC_ADDR);
assertArrayEquals(resultData.dstAddress, IPV4_KEEPALIVE_DST_ADDR);
assertEquals(resultData.srcPort, srcPort);
@@ -154,4 +157,49 @@
+ " ack: 572662306, rcvWnd: 48000, rcvWndScale: 2, tos: 4, ttl: 64}";
assertEquals(expected, resultData.toString());
}
+
+ @Test
+ public void testParseTcpKeepalivePacketData() throws Exception {
+ final int srcPort = 1234;
+ final int dstPort = 4321;
+ final int sequence = 0x11111111;
+ final int ack = 0x22222222;
+ final int wnd = 4800;
+ final int wndScale = 2;
+ final int tos = 4;
+ final int ttl = 64;
+ final TcpKeepalivePacketDataParcelable testParcel = new TcpKeepalivePacketDataParcelable();
+ testParcel.srcAddress = IPV4_KEEPALIVE_SRC_ADDR;
+ testParcel.srcPort = srcPort;
+ testParcel.dstAddress = IPV4_KEEPALIVE_DST_ADDR;
+ testParcel.dstPort = dstPort;
+ testParcel.seq = sequence;
+ testParcel.ack = ack;
+ testParcel.rcvWnd = wnd;
+ testParcel.rcvWndScale = wndScale;
+ testParcel.tos = tos;
+ testParcel.ttl = ttl;
+
+ final KeepalivePacketData testData =
+ KeepalivePacketDataUtil.fromStableParcelable(testParcel);
+ final TcpKeepalivePacketDataParcelable parsedParcelable =
+ KeepalivePacketDataUtil.parseTcpKeepalivePacketData(testData);
+ final TcpKeepalivePacketData roundTripData =
+ KeepalivePacketDataUtil.fromStableParcelable(parsedParcelable);
+
+ // Generated packet is the same, but rcvWnd / wndScale will differ if scale is non-zero
+ assertTrue(testData.getPacket().length > 0);
+ assertArrayEquals(testData.getPacket(), roundTripData.getPacket());
+
+ testParcel.rcvWndScale = 0;
+ final KeepalivePacketData noScaleTestData =
+ KeepalivePacketDataUtil.fromStableParcelable(testParcel);
+ final TcpKeepalivePacketDataParcelable noScaleParsedParcelable =
+ KeepalivePacketDataUtil.parseTcpKeepalivePacketData(noScaleTestData);
+ final TcpKeepalivePacketData noScaleRoundTripData =
+ KeepalivePacketDataUtil.fromStableParcelable(noScaleParsedParcelable);
+ assertEquals(noScaleTestData, noScaleRoundTripData);
+ assertTrue(noScaleTestData.getPacket().length > 0);
+ assertArrayEquals(noScaleTestData.getPacket(), noScaleRoundTripData.getPacket());
+ }
}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 6cd08c3..b3bdd60 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -4954,8 +4954,8 @@
expectForceUpdateIfaces(onlyCell, MOBILE_IFNAME);
reset(mStatsService);
- // Captive portal change shouldn't update ifaces
- mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL);
+ // Temp metered change shouldn't update ifaces
+ mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED);
waitForIdle();
verify(mStatsService, never())
.forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
@@ -5471,6 +5471,7 @@
final Network wifi = mWiFiNetworkAgent.getNetwork();
final NetworkCapabilities initialCaps = new NetworkCapabilities();
+ initialCaps.addTransportType(TRANSPORT_VPN);
initialCaps.addCapability(NET_CAPABILITY_INTERNET);
initialCaps.removeCapability(NET_CAPABILITY_NOT_VPN);
@@ -5502,44 +5503,45 @@
withWifiAndMobileUnderlying.setLinkDownstreamBandwidthKbps(10);
withWifiAndMobileUnderlying.setLinkUpstreamBandwidthKbps(20);
+ final NetworkCapabilities initialCapsNotMetered = new NetworkCapabilities(initialCaps);
+ initialCapsNotMetered.addCapability(NET_CAPABILITY_NOT_METERED);
+
NetworkCapabilities caps = new NetworkCapabilities(initialCaps);
- final boolean notDeclaredMetered = false;
- mService.applyUnderlyingCapabilities(new Network[]{}, caps, notDeclaredMetered);
+ mService.applyUnderlyingCapabilities(new Network[]{}, initialCapsNotMetered, caps);
assertEquals(withNoUnderlying, caps);
caps = new NetworkCapabilities(initialCaps);
- mService.applyUnderlyingCapabilities(new Network[]{null}, caps, notDeclaredMetered);
+ mService.applyUnderlyingCapabilities(new Network[]{null}, initialCapsNotMetered, caps);
assertEquals(withNoUnderlying, caps);
caps = new NetworkCapabilities(initialCaps);
- mService.applyUnderlyingCapabilities(new Network[]{mobile}, caps, notDeclaredMetered);
+ mService.applyUnderlyingCapabilities(new Network[]{mobile}, initialCapsNotMetered, caps);
assertEquals(withMobileUnderlying, caps);
- mService.applyUnderlyingCapabilities(new Network[]{wifi}, caps, notDeclaredMetered);
+ mService.applyUnderlyingCapabilities(new Network[]{wifi}, initialCapsNotMetered, caps);
assertEquals(withWifiUnderlying, caps);
- final boolean isDeclaredMetered = true;
withWifiUnderlying.removeCapability(NET_CAPABILITY_NOT_METERED);
caps = new NetworkCapabilities(initialCaps);
- mService.applyUnderlyingCapabilities(new Network[]{wifi}, caps, isDeclaredMetered);
+ mService.applyUnderlyingCapabilities(new Network[]{wifi}, initialCaps, caps);
assertEquals(withWifiUnderlying, caps);
caps = new NetworkCapabilities(initialCaps);
- mService.applyUnderlyingCapabilities(new Network[]{mobile, wifi}, caps, isDeclaredMetered);
+ mService.applyUnderlyingCapabilities(new Network[]{mobile, wifi}, initialCaps, caps);
assertEquals(withWifiAndMobileUnderlying, caps);
withWifiUnderlying.addCapability(NET_CAPABILITY_NOT_METERED);
caps = new NetworkCapabilities(initialCaps);
mService.applyUnderlyingCapabilities(new Network[]{null, mobile, null, wifi},
- caps, notDeclaredMetered);
+ initialCapsNotMetered, caps);
assertEquals(withWifiAndMobileUnderlying, caps);
caps = new NetworkCapabilities(initialCaps);
mService.applyUnderlyingCapabilities(new Network[]{null, mobile, null, wifi},
- caps, notDeclaredMetered);
+ initialCapsNotMetered, caps);
assertEquals(withWifiAndMobileUnderlying, caps);
- mService.applyUnderlyingCapabilities(null, caps, notDeclaredMetered);
+ mService.applyUnderlyingCapabilities(null, initialCapsNotMetered, caps);
assertEquals(withWifiUnderlying, caps);
}
diff --git a/tools/split-select/OWNERS b/tools/split-select/OWNERS
new file mode 100644
index 0000000..6c50ede
--- /dev/null
+++ b/tools/split-select/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/content/res/OWNERS
\ No newline at end of file
diff --git a/tools/stats_log_api_gen/.clang-format b/tools/stats_log_api_gen/.clang-format
deleted file mode 100644
index cead3a0..0000000
--- a/tools/stats_log_api_gen/.clang-format
+++ /dev/null
@@ -1,17 +0,0 @@
-BasedOnStyle: Google
-AllowShortIfStatementsOnASingleLine: true
-AllowShortFunctionsOnASingleLine: false
-AllowShortLoopsOnASingleLine: true
-BinPackArguments: true
-BinPackParameters: true
-ColumnLimit: 100
-CommentPragmas: NOLINT:.*
-ContinuationIndentWidth: 8
-DerivePointerAlignment: false
-IndentWidth: 4
-PointerAlignment: Left
-TabWidth: 4
-AccessModifierOffset: -4
-IncludeCategories:
- - Regex: '^"Log\.h"'
- Priority: -1
diff --git a/tools/stats_log_api_gen/Android.bp b/tools/stats_log_api_gen/Android.bp
deleted file mode 100644
index ab8702b..0000000
--- a/tools/stats_log_api_gen/Android.bp
+++ /dev/null
@@ -1,150 +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.
-//
-
-// ==========================================================
-// Build the host executable: stats-log-api-gen
-// ==========================================================
-cc_binary_host {
- name: "stats-log-api-gen",
- srcs: [
- "Collation.cpp",
- "java_writer.cpp",
- "java_writer_q.cpp",
- "main.cpp",
- "native_writer.cpp",
- "utils.cpp",
- ],
- cflags: [
- "-Wall",
- "-Werror",
- ],
-
- shared_libs: [
- "libstats_proto_host",
- "libprotobuf-cpp-full",
- "libbase",
- ],
-
- proto: {
- type: "full",
- },
-}
-
-// ==========================================================
-// Build the host test executable: stats-log-api-gen
-// ==========================================================
-cc_test_host {
- name: "stats-log-api-gen-test",
- cflags: [
- "-Wall",
- "-Wextra",
- "-Werror",
- "-g",
- "-DUNIT_TEST",
- ],
- srcs: [
- "Collation.cpp",
- "test_collation.cpp",
- "test.proto",
- ],
-
- static_libs: [
- "libgmock_host",
- ],
-
- shared_libs: [
- "libstats_proto_host",
- "libprotobuf-cpp-full",
- ],
-
- proto: {
- type: "full",
- include_dirs: [
- "external/protobuf/src",
- ],
- },
-}
-
-// ==========================================================
-// Native library
-// ==========================================================
-genrule {
- name: "statslog.h",
- tools: ["stats-log-api-gen"],
- cmd: "$(location stats-log-api-gen) --header $(genDir)/statslog.h",
- out: [
- "statslog.h",
- ],
-}
-
-genrule {
- name: "statslog.cpp",
- tools: ["stats-log-api-gen"],
- cmd: "$(location stats-log-api-gen) --cpp $(genDir)/statslog.cpp",
- out: [
- "statslog.cpp",
- ],
-}
-
-cc_library {
- name: "libstatslog",
- host_supported: true,
- generated_sources: [
- "statslog.cpp",
- ],
- generated_headers: [
- "statslog.h"
- ],
- cflags: [
- "-Wall",
- "-Werror",
- ],
- export_generated_headers: [
- "statslog.h"
- ],
- shared_libs: [
- "liblog",
- "libcutils",
- ],
- target: {
- android: {
- shared_libs: [
- "libstatssocket",
- "libstatspull",
- ],
- export_shared_lib_headers: [
- "libstatssocket",
- "libstatspull",
- ],
- },
- host: {
- static_libs: [
- "libstatssocket",
- "libstatspull",
- "statsd-aidl-ndk_platform",
- ],
- shared_libs: ["libbinder_ndk"],
- export_static_lib_headers: [
- "libstatssocket",
- "libstatspull",
- ],
- },
- darwin: {
- enabled: false,
- },
- },
-}
-
diff --git a/tools/stats_log_api_gen/Collation.cpp b/tools/stats_log_api_gen/Collation.cpp
deleted file mode 100644
index 56f4db0..0000000
--- a/tools/stats_log_api_gen/Collation.cpp
+++ /dev/null
@@ -1,601 +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.
- */
-
-#include "Collation.h"
-
-#include <stdio.h>
-
-#include <map>
-
-#include "frameworks/proto_logging/stats/atoms.pb.h"
-
-namespace android {
-namespace stats_log_api_gen {
-
-using google::protobuf::OneofDescriptor;
-using google::protobuf::EnumDescriptor;
-using google::protobuf::FieldDescriptor;
-using google::protobuf::FileDescriptor;
-using google::protobuf::SourceLocation;
-using std::make_shared;
-using std::map;
-
-const bool dbg = false;
-
-//
-// AtomDecl class
-//
-
-AtomDecl::AtomDecl() : code(0), name() {
-}
-
-AtomDecl::AtomDecl(const AtomDecl& that)
- : code(that.code),
- name(that.name),
- message(that.message),
- fields(that.fields),
- fieldNumberToAnnotations(that.fieldNumberToAnnotations),
- primaryFields(that.primaryFields),
- exclusiveField(that.exclusiveField),
- defaultState(that.defaultState),
- triggerStateReset(that.triggerStateReset),
- nested(that.nested),
- uidField(that.uidField) {
-}
-
-AtomDecl::AtomDecl(int c, const string& n, const string& m) : code(c), name(n), message(m) {
-}
-
-AtomDecl::~AtomDecl() {
-}
-
-/**
- * Print an error message for a FieldDescriptor, including the file name and
- * line number.
- */
-static void print_error(const FieldDescriptor* field, const char* format, ...) {
- const Descriptor* message = field->containing_type();
- const FileDescriptor* file = message->file();
-
- SourceLocation loc;
- if (field->GetSourceLocation(&loc)) {
- // TODO(b/162454173): this will work if we can figure out how to pass
- // --include_source_info to protoc
- fprintf(stderr, "%s:%d: ", file->name().c_str(), loc.start_line);
- } else {
- fprintf(stderr, "%s: ", file->name().c_str());
- }
- va_list args;
- va_start(args, format);
- vfprintf(stderr, format, args);
- va_end(args);
-}
-
-/**
- * Convert a protobuf type into a java type.
- */
-static java_type_t java_type(const FieldDescriptor* field) {
- int protoType = field->type();
- switch (protoType) {
- case FieldDescriptor::TYPE_DOUBLE:
- return JAVA_TYPE_DOUBLE;
- case FieldDescriptor::TYPE_FLOAT:
- return JAVA_TYPE_FLOAT;
- case FieldDescriptor::TYPE_INT64:
- return JAVA_TYPE_LONG;
- case FieldDescriptor::TYPE_UINT64:
- return JAVA_TYPE_LONG;
- case FieldDescriptor::TYPE_INT32:
- return JAVA_TYPE_INT;
- case FieldDescriptor::TYPE_FIXED64:
- return JAVA_TYPE_LONG;
- case FieldDescriptor::TYPE_FIXED32:
- return JAVA_TYPE_INT;
- case FieldDescriptor::TYPE_BOOL:
- return JAVA_TYPE_BOOLEAN;
- case FieldDescriptor::TYPE_STRING:
- return JAVA_TYPE_STRING;
- case FieldDescriptor::TYPE_GROUP:
- return JAVA_TYPE_UNKNOWN;
- case FieldDescriptor::TYPE_MESSAGE:
- if (field->message_type()->full_name() == "android.os.statsd.AttributionNode") {
- return JAVA_TYPE_ATTRIBUTION_CHAIN;
- } else if (field->message_type()->full_name() == "android.os.statsd.KeyValuePair") {
- return JAVA_TYPE_KEY_VALUE_PAIR;
- } else if (field->options().GetExtension(os::statsd::log_mode) ==
- os::statsd::LogMode::MODE_BYTES) {
- return JAVA_TYPE_BYTE_ARRAY;
- } else {
- return JAVA_TYPE_OBJECT;
- }
- case FieldDescriptor::TYPE_BYTES:
- return JAVA_TYPE_BYTE_ARRAY;
- case FieldDescriptor::TYPE_UINT32:
- return JAVA_TYPE_INT;
- case FieldDescriptor::TYPE_ENUM:
- return JAVA_TYPE_ENUM;
- case FieldDescriptor::TYPE_SFIXED32:
- return JAVA_TYPE_INT;
- case FieldDescriptor::TYPE_SFIXED64:
- return JAVA_TYPE_LONG;
- case FieldDescriptor::TYPE_SINT32:
- return JAVA_TYPE_INT;
- case FieldDescriptor::TYPE_SINT64:
- return JAVA_TYPE_LONG;
- default:
- return JAVA_TYPE_UNKNOWN;
- }
-}
-
-/**
- * Gather the enums info.
- */
-void collate_enums(const EnumDescriptor& enumDescriptor, AtomField* atomField) {
- for (int i = 0; i < enumDescriptor.value_count(); i++) {
- atomField->enumValues[enumDescriptor.value(i)->number()] =
- enumDescriptor.value(i)->name();
- }
-}
-
-static void addAnnotationToAtomDecl(AtomDecl* atomDecl, const int fieldNumber,
- const AnnotationId annotationId,
- const AnnotationType annotationType,
- const AnnotationValue annotationValue) {
- if (dbg) {
- printf(" Adding annotation to %s: [%d] = {id: %d, type: %d}\n", atomDecl->name.c_str(),
- fieldNumber, annotationId, annotationType);
- }
- atomDecl->fieldNumberToAnnotations[fieldNumber].insert(
- make_shared<Annotation>(annotationId, atomDecl->code, annotationType, annotationValue));
-}
-
-static int collate_field_annotations(AtomDecl* atomDecl, const FieldDescriptor* field,
- const int fieldNumber, const java_type_t& javaType) {
- int errorCount = 0;
-
- if (field->options().HasExtension(os::statsd::state_field_option)) {
- const os::statsd::StateAtomFieldOption& stateFieldOption =
- field->options().GetExtension(os::statsd::state_field_option);
- const bool primaryField = stateFieldOption.primary_field();
- const bool exclusiveState = stateFieldOption.exclusive_state();
- const bool primaryFieldFirstUid = stateFieldOption.primary_field_first_uid();
-
- // Check the field is only one of primaryField, exclusiveState, or primaryFieldFirstUid.
- if (primaryField + primaryFieldFirstUid + exclusiveState > 1) {
- print_error(field,
- "Field can be max 1 of primary_field, exclusive_state, "
- "or primary_field_first_uid: '%s'\n",
- atomDecl->message.c_str());
- errorCount++;
- }
-
- if (primaryField) {
- if (javaType == JAVA_TYPE_UNKNOWN || javaType == JAVA_TYPE_ATTRIBUTION_CHAIN ||
- javaType == JAVA_TYPE_OBJECT || javaType == JAVA_TYPE_BYTE_ARRAY) {
- print_error(field, "Invalid primary state field: '%s'\n",
- atomDecl->message.c_str());
- errorCount++;
- } else {
- atomDecl->primaryFields.push_back(fieldNumber);
- addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_PRIMARY_FIELD,
- ANNOTATION_TYPE_BOOL, AnnotationValue(true));
- }
- }
-
- if (primaryFieldFirstUid) {
- if (javaType != JAVA_TYPE_ATTRIBUTION_CHAIN) {
- print_error(field,
- "PRIMARY_FIELD_FIRST_UID annotation is only for AttributionChains: "
- "'%s'\n",
- atomDecl->message.c_str());
- errorCount++;
- } else {
- atomDecl->primaryFields.push_back(FIRST_UID_IN_CHAIN_ID);
- addAnnotationToAtomDecl(atomDecl, fieldNumber,
- ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, ANNOTATION_TYPE_BOOL,
- AnnotationValue(true));
- }
- }
-
- if (exclusiveState) {
- if (javaType == JAVA_TYPE_UNKNOWN || javaType == JAVA_TYPE_ATTRIBUTION_CHAIN ||
- javaType == JAVA_TYPE_OBJECT || javaType == JAVA_TYPE_BYTE_ARRAY) {
- print_error(field, "Invalid exclusive state field: '%s'\n",
- atomDecl->message.c_str());
- errorCount++;
- }
-
- if (atomDecl->exclusiveField != 0) {
- print_error(field,
- "Cannot have more than one exclusive state field in an "
- "atom: '%s'\n",
- atomDecl->message.c_str());
- errorCount++;
- } else {
- atomDecl->exclusiveField = fieldNumber;
- addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_EXCLUSIVE_STATE,
- ANNOTATION_TYPE_BOOL, AnnotationValue(true));
- }
-
- if (stateFieldOption.has_default_state_value()) {
- const int defaultState = stateFieldOption.default_state_value();
- atomDecl->defaultState = defaultState;
-
- addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_DEFAULT_STATE,
- ANNOTATION_TYPE_INT, AnnotationValue(defaultState));
- }
-
- if (stateFieldOption.has_trigger_state_reset_value()) {
- const int triggerStateReset = stateFieldOption.trigger_state_reset_value();
-
- atomDecl->triggerStateReset = triggerStateReset;
- addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_TRIGGER_STATE_RESET,
- ANNOTATION_TYPE_INT, AnnotationValue(triggerStateReset));
- }
-
- if (stateFieldOption.has_nested()) {
- const bool nested = stateFieldOption.nested();
- atomDecl->nested = nested;
-
- addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_STATE_NESTED,
- ANNOTATION_TYPE_BOOL, AnnotationValue(nested));
- }
- }
- }
-
- if (field->options().GetExtension(os::statsd::is_uid) == true) {
- if (javaType != JAVA_TYPE_INT) {
- print_error(field, "is_uid annotation can only be applied to int32 fields: '%s'\n",
- atomDecl->message.c_str());
- errorCount++;
- }
-
- if (atomDecl->uidField == 0) {
- atomDecl->uidField = fieldNumber;
-
- addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_IS_UID,
- ANNOTATION_TYPE_BOOL, AnnotationValue(true));
- } else {
- print_error(field,
- "Cannot have more than one field in an atom with is_uid "
- "annotation: '%s'\n",
- atomDecl->message.c_str());
- errorCount++;
- }
- }
-
- return errorCount;
-}
-
-/**
- * Gather the info about an atom proto.
- */
-int collate_atom(const Descriptor* atom, AtomDecl* atomDecl, vector<java_type_t>* signature) {
- int errorCount = 0;
-
- // Build a sorted list of the fields. Descriptor has them in source file
- // order.
- map<int, const FieldDescriptor*> fields;
- for (int j = 0; j < atom->field_count(); j++) {
- const FieldDescriptor* field = atom->field(j);
- fields[field->number()] = field;
- }
-
- // Check that the parameters start at 1 and go up sequentially.
- int expectedNumber = 1;
- for (map<int, const FieldDescriptor*>::const_iterator it = fields.begin(); it != fields.end();
- it++) {
- const int number = it->first;
- const FieldDescriptor* field = it->second;
- if (number != expectedNumber) {
- print_error(field,
- "Fields must be numbered consecutively starting at 1:"
- " '%s' is %d but should be %d\n",
- field->name().c_str(), number, expectedNumber);
- errorCount++;
- expectedNumber = number;
- continue;
- }
- expectedNumber++;
- }
-
- // Check that only allowed types are present. Remove any invalid ones.
- for (map<int, const FieldDescriptor*>::const_iterator it = fields.begin(); it != fields.end();
- it++) {
- const FieldDescriptor* field = it->second;
- bool isBinaryField = field->options().GetExtension(os::statsd::log_mode) ==
- os::statsd::LogMode::MODE_BYTES;
-
- java_type_t javaType = java_type(field);
-
- if (javaType == JAVA_TYPE_UNKNOWN) {
- print_error(field, "Unknown type for field: %s\n", field->name().c_str());
- errorCount++;
- continue;
- } else if (javaType == JAVA_TYPE_OBJECT && atomDecl->code < PULL_ATOM_START_ID) {
- // Allow attribution chain, but only at position 1.
- print_error(field, "Message type not allowed for field in pushed atoms: %s\n",
- field->name().c_str());
- errorCount++;
- continue;
- } else if (javaType == JAVA_TYPE_BYTE_ARRAY && !isBinaryField) {
- print_error(field, "Raw bytes type not allowed for field: %s\n", field->name().c_str());
- errorCount++;
- continue;
- }
-
- if (isBinaryField && javaType != JAVA_TYPE_BYTE_ARRAY) {
- print_error(field, "Cannot mark field %s as bytes.\n", field->name().c_str());
- errorCount++;
- continue;
- }
-
- // Doubles are not supported yet.
- if (javaType == JAVA_TYPE_DOUBLE) {
- print_error(field,
- "Doubles are not supported in atoms. Please change field %s "
- "to float\n",
- field->name().c_str());
- errorCount++;
- continue;
- }
-
- if (field->is_repeated() &&
- !(javaType == JAVA_TYPE_ATTRIBUTION_CHAIN || javaType == JAVA_TYPE_KEY_VALUE_PAIR)) {
- print_error(field,
- "Repeated fields are not supported in atoms. Please make "
- "field %s not "
- "repeated.\n",
- field->name().c_str());
- errorCount++;
- continue;
- }
- }
-
- // Check that if there's an attribution chain, it's at position 1.
- for (map<int, const FieldDescriptor*>::const_iterator it = fields.begin(); it != fields.end();
- it++) {
- int number = it->first;
- if (number != 1) {
- const FieldDescriptor* field = it->second;
- java_type_t javaType = java_type(field);
- if (javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- print_error(field,
- "AttributionChain fields must have field id 1, in message: '%s'\n",
- atom->name().c_str());
- errorCount++;
- }
- }
- }
-
- // Build the type signature and the atom data.
- for (map<int, const FieldDescriptor*>::const_iterator it = fields.begin(); it != fields.end();
- it++) {
- const FieldDescriptor* field = it->second;
- java_type_t javaType = java_type(field);
- bool isBinaryField = field->options().GetExtension(os::statsd::log_mode) ==
- os::statsd::LogMode::MODE_BYTES;
-
- AtomField atField(field->name(), javaType);
-
- if (javaType == JAVA_TYPE_ENUM) {
- // All enums are treated as ints when it comes to function signatures.
- collate_enums(*field->enum_type(), &atField);
- }
-
- // Generate signature for atom.
- if (javaType == JAVA_TYPE_ENUM) {
- // All enums are treated as ints when it comes to function signatures.
- signature->push_back(JAVA_TYPE_INT);
- } else if (javaType == JAVA_TYPE_OBJECT && isBinaryField) {
- signature->push_back(JAVA_TYPE_BYTE_ARRAY);
- } else {
- signature->push_back(javaType);
- }
-
- atomDecl->fields.push_back(atField);
-
- errorCount += collate_field_annotations(atomDecl, field, it->first, javaType);
- }
-
- return errorCount;
-}
-
-// This function flattens the fields of the AttributionNode proto in an Atom
-// proto and generates the corresponding atom decl and signature.
-bool get_non_chained_node(const Descriptor* atom, AtomDecl* atomDecl,
- vector<java_type_t>* signature) {
- // Build a sorted list of the fields. Descriptor has them in source file
- // order.
- map<int, const FieldDescriptor*> fields;
- for (int j = 0; j < atom->field_count(); j++) {
- const FieldDescriptor* field = atom->field(j);
- fields[field->number()] = field;
- }
-
- AtomDecl attributionDecl;
- vector<java_type_t> attributionSignature;
- collate_atom(android::os::statsd::AttributionNode::descriptor(), &attributionDecl,
- &attributionSignature);
-
- // Build the type signature and the atom data.
- bool has_attribution_node = false;
- for (map<int, const FieldDescriptor*>::const_iterator it = fields.begin(); it != fields.end();
- it++) {
- const FieldDescriptor* field = it->second;
- java_type_t javaType = java_type(field);
- if (javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- atomDecl->fields.insert(atomDecl->fields.end(), attributionDecl.fields.begin(),
- attributionDecl.fields.end());
- signature->insert(signature->end(), attributionSignature.begin(),
- attributionSignature.end());
- has_attribution_node = true;
-
- } else {
- AtomField atField(field->name(), javaType);
- if (javaType == JAVA_TYPE_ENUM) {
- // All enums are treated as ints when it comes to function signatures.
- signature->push_back(JAVA_TYPE_INT);
- collate_enums(*field->enum_type(), &atField);
- } else {
- signature->push_back(javaType);
- }
- atomDecl->fields.push_back(atField);
- }
- }
- return has_attribution_node;
-}
-
-static void populateFieldNumberToAtomDeclSet(const shared_ptr<AtomDecl>& atomDecl,
- FieldNumberToAtomDeclSet* fieldNumberToAtomDeclSet) {
- for (FieldNumberToAnnotations::const_iterator it = atomDecl->fieldNumberToAnnotations.begin();
- it != atomDecl->fieldNumberToAnnotations.end(); it++) {
- const int fieldNumber = it->first;
- (*fieldNumberToAtomDeclSet)[fieldNumber].insert(atomDecl);
- }
-}
-
-/**
- * Gather the info about the atoms.
- */
-int collate_atoms(const Descriptor* descriptor, const string& moduleName, Atoms* atoms) {
- int errorCount = 0;
-
- for (int i = 0; i < descriptor->field_count(); i++) {
- const FieldDescriptor* atomField = descriptor->field(i);
-
- if (moduleName != DEFAULT_MODULE_NAME) {
- const int moduleCount = atomField->options().ExtensionSize(os::statsd::module);
- int j;
- for (j = 0; j < moduleCount; ++j) {
- const string atomModuleName =
- atomField->options().GetExtension(os::statsd::module, j);
- if (atomModuleName == moduleName) {
- break;
- }
- }
-
- // This atom is not in the module we're interested in; skip it.
- if (moduleCount == j) {
- if (dbg) {
- printf(" Skipping %s (%d)\n", atomField->name().c_str(), atomField->number());
- }
- continue;
- }
- }
-
- if (dbg) {
- printf(" %s (%d)\n", atomField->name().c_str(), atomField->number());
- }
-
- // StatsEvent only has one oneof, which contains only messages. Don't allow
- // other types.
- if (atomField->type() != FieldDescriptor::TYPE_MESSAGE) {
- print_error(atomField,
- "Bad type for atom. StatsEvent can only have message type "
- "fields: %s\n",
- atomField->name().c_str());
- errorCount++;
- continue;
- }
-
- const Descriptor* atom = atomField->message_type();
- shared_ptr<AtomDecl> atomDecl =
- make_shared<AtomDecl>(atomField->number(), atomField->name(), atom->name());
-
- if (atomField->options().GetExtension(os::statsd::truncate_timestamp)) {
- addAnnotationToAtomDecl(atomDecl.get(), ATOM_ID_FIELD_NUMBER,
- ANNOTATION_ID_TRUNCATE_TIMESTAMP, ANNOTATION_TYPE_BOOL,
- AnnotationValue(true));
- if (dbg) {
- printf("%s can have timestamp truncated\n", atomField->name().c_str());
- }
- }
-
- vector<java_type_t> signature;
- errorCount += collate_atom(atom, atomDecl.get(), &signature);
- if (!atomDecl->primaryFields.empty() && atomDecl->exclusiveField == 0) {
- print_error(atomField, "Cannot have a primary field without an exclusive field: %s\n",
- atomField->name().c_str());
- errorCount++;
- continue;
- }
-
- const OneofDescriptor* oneofAtom = atomField->containing_oneof();
- if (oneofAtom == nullptr) {
- print_error(atomField, "Atom is not declared in a `oneof` field: %s\n",
- atomField->name().c_str());
- errorCount++;
- continue;
- } else if ((oneofAtom->name() != ONEOF_PUSHED_ATOM_NAME) &&
- (oneofAtom->name() != ONEOF_PULLED_ATOM_NAME)) {
- print_error(atomField, "Atom is neither a pushed nor pulled atom: %s\n",
- atomField->name().c_str());
- errorCount++;
- continue;
- }
-
- FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet = oneofAtom->name() ==
- ONEOF_PUSHED_ATOM_NAME ? atoms->signatureInfoMap[signature] :
- atoms->pulledAtomsSignatureInfoMap[signature];
- populateFieldNumberToAtomDeclSet(atomDecl, &fieldNumberToAtomDeclSet);
-
- atoms->decls.insert(atomDecl);
-
- shared_ptr<AtomDecl> nonChainedAtomDecl =
- make_shared<AtomDecl>(atomField->number(), atomField->name(), atom->name());
- vector<java_type_t> nonChainedSignature;
- if (get_non_chained_node(atom, nonChainedAtomDecl.get(), &nonChainedSignature)) {
- FieldNumberToAtomDeclSet& nonChainedFieldNumberToAtomDeclSet =
- atoms->nonChainedSignatureInfoMap[nonChainedSignature];
- populateFieldNumberToAtomDeclSet(nonChainedAtomDecl,
- &nonChainedFieldNumberToAtomDeclSet);
-
- atoms->non_chained_decls.insert(nonChainedAtomDecl);
- }
- }
-
- if (dbg) {
- // Signatures for pushed atoms.
- printf("signatures = [\n");
- for (SignatureInfoMap::const_iterator it = atoms->signatureInfoMap.begin();
- it != atoms->signatureInfoMap.end(); it++) {
- printf(" ");
- for (vector<java_type_t>::const_iterator jt = it->first.begin(); jt != it->first.end();
- jt++) {
- printf(" %d", static_cast<int>(*jt));
- }
- printf("\n");
- }
-
- // Signatures for pull atoms.
- for (SignatureInfoMap::const_iterator it = atoms->pulledAtomsSignatureInfoMap.begin();
- it != atoms->pulledAtomsSignatureInfoMap.end(); it++) {
- printf(" ");
- for (vector<java_type_t>::const_iterator jt = it->first.begin(); jt != it->first.end();
- jt++) {
- printf(" %d", static_cast<int>(*jt));
- }
- printf("\n");
- }
- printf("]\n");
- }
-
- return errorCount;
-}
-
-} // namespace stats_log_api_gen
-} // namespace android
diff --git a/tools/stats_log_api_gen/Collation.h b/tools/stats_log_api_gen/Collation.h
deleted file mode 100644
index b13851c..0000000
--- a/tools/stats_log_api_gen/Collation.h
+++ /dev/null
@@ -1,211 +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.
- */
-
-#ifndef ANDROID_STATS_LOG_API_GEN_COLLATION_H
-#define ANDROID_STATS_LOG_API_GEN_COLLATION_H
-
-#include <google/protobuf/descriptor.h>
-#include <stdint.h>
-
-#include <map>
-#include <set>
-#include <vector>
-
-#include "frameworks/proto_logging/stats/atom_field_options.pb.h"
-
-namespace android {
-namespace stats_log_api_gen {
-
-using google::protobuf::OneofDescriptor;
-using google::protobuf::Descriptor;
-using google::protobuf::FieldDescriptor;
-using std::map;
-using std::set;
-using std::shared_ptr;
-using std::string;
-using std::vector;
-
-const int PULL_ATOM_START_ID = 10000;
-
-const int FIRST_UID_IN_CHAIN_ID = 0;
-
-/**
- * The types of oneof atoms.
- *
- * `OneofDescriptor::name()` returns the name of the oneof.
- */
-const char ONEOF_PUSHED_ATOM_NAME[] = "pushed";
-const char ONEOF_PULLED_ATOM_NAME[] = "pulled";
-
-enum AnnotationId : uint8_t {
- ANNOTATION_ID_IS_UID = 1,
- ANNOTATION_ID_TRUNCATE_TIMESTAMP = 2,
- ANNOTATION_ID_PRIMARY_FIELD = 3,
- ANNOTATION_ID_EXCLUSIVE_STATE = 4,
- ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID = 5,
- ANNOTATION_ID_DEFAULT_STATE = 6,
- ANNOTATION_ID_TRIGGER_STATE_RESET = 7,
- ANNOTATION_ID_STATE_NESTED = 8,
-};
-
-const int ATOM_ID_FIELD_NUMBER = -1;
-
-const char DEFAULT_MODULE_NAME[] = "DEFAULT";
-
-/**
- * The types for atom parameters.
- */
-typedef enum {
- JAVA_TYPE_UNKNOWN = 0,
-
- JAVA_TYPE_ATTRIBUTION_CHAIN = 1,
- JAVA_TYPE_BOOLEAN = 2,
- JAVA_TYPE_INT = 3,
- JAVA_TYPE_LONG = 4,
- JAVA_TYPE_FLOAT = 5,
- JAVA_TYPE_DOUBLE = 6,
- JAVA_TYPE_STRING = 7,
- JAVA_TYPE_ENUM = 8,
- JAVA_TYPE_KEY_VALUE_PAIR = 9,
-
- JAVA_TYPE_OBJECT = -1,
- JAVA_TYPE_BYTE_ARRAY = -2,
-} java_type_t;
-
-enum AnnotationType {
- ANNOTATION_TYPE_UNKNOWN = 0,
- ANNOTATION_TYPE_INT = 1,
- ANNOTATION_TYPE_BOOL = 2,
-};
-
-union AnnotationValue {
- int intValue;
- bool boolValue;
-
- explicit AnnotationValue(const int value) : intValue(value) {
- }
- explicit AnnotationValue(const bool value) : boolValue(value) {
- }
-};
-
-struct Annotation {
- const AnnotationId annotationId;
- const int atomId;
- AnnotationType type;
- AnnotationValue value;
-
- inline Annotation(AnnotationId annotationId, int atomId, AnnotationType type,
- AnnotationValue value)
- : annotationId(annotationId), atomId(atomId), type(type), value(value) {
- }
- inline ~Annotation() {
- }
-
- inline bool operator<(const Annotation& that) const {
- return atomId == that.atomId ? annotationId < that.annotationId : atomId < that.atomId;
- }
-};
-
-struct SharedComparator {
- template <typename T>
- inline bool operator()(const shared_ptr<T>& lhs, const shared_ptr<T>& rhs) const {
- return (*lhs) < (*rhs);
- }
-};
-
-using AnnotationSet = set<shared_ptr<Annotation>, SharedComparator>;
-
-using FieldNumberToAnnotations = map<int, AnnotationSet>;
-
-/**
- * The name and type for an atom field.
- */
-struct AtomField {
- string name;
- java_type_t javaType;
-
- // If the field is of type enum, the following map contains the list of enum
- // values.
- map<int /* numeric value */, string /* value name */> enumValues;
-
- inline AtomField() : name(), javaType(JAVA_TYPE_UNKNOWN) {
- }
- inline AtomField(const AtomField& that)
- : name(that.name), javaType(that.javaType), enumValues(that.enumValues) {
- }
-
- inline AtomField(string n, java_type_t jt) : name(n), javaType(jt) {
- }
- inline ~AtomField() {
- }
-};
-
-/**
- * The name and code for an atom.
- */
-struct AtomDecl {
- int code;
- string name;
-
- string message;
- vector<AtomField> fields;
-
- FieldNumberToAnnotations fieldNumberToAnnotations;
-
- vector<int> primaryFields;
- int exclusiveField = 0;
- int defaultState = INT_MAX;
- int triggerStateReset = INT_MAX;
- bool nested = true;
-
- int uidField = 0;
-
- AtomDecl();
- AtomDecl(const AtomDecl& that);
- AtomDecl(int code, const string& name, const string& message);
- ~AtomDecl();
-
- inline bool operator<(const AtomDecl& that) const {
- return (code == that.code) ? (name < that.name) : (code < that.code);
- }
-};
-
-using AtomDeclSet = set<shared_ptr<AtomDecl>, SharedComparator>;
-
-// Maps a field number to a set of atoms that have annotation(s) for their field with that field
-// number.
-using FieldNumberToAtomDeclSet = map<int, AtomDeclSet>;
-
-using SignatureInfoMap = map<vector<java_type_t>, FieldNumberToAtomDeclSet>;
-
-struct Atoms {
- SignatureInfoMap signatureInfoMap;
- SignatureInfoMap pulledAtomsSignatureInfoMap;
- AtomDeclSet decls;
- AtomDeclSet non_chained_decls;
- SignatureInfoMap nonChainedSignatureInfoMap;
-};
-
-/**
- * Gather the information about the atoms. Returns the number of errors.
- */
-int collate_atoms(const Descriptor* descriptor, const string& moduleName, Atoms* atoms);
-int collate_atom(const Descriptor* atom, AtomDecl* atomDecl, vector<java_type_t>* signature);
-
-} // namespace stats_log_api_gen
-} // namespace android
-
-#endif // ANDROID_STATS_LOG_API_GEN_COLLATION_H
diff --git a/tools/stats_log_api_gen/OWNERS b/tools/stats_log_api_gen/OWNERS
deleted file mode 100644
index 41a0c95..0000000
--- a/tools/stats_log_api_gen/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-yro@google.com
diff --git a/tools/stats_log_api_gen/java_writer.cpp b/tools/stats_log_api_gen/java_writer.cpp
deleted file mode 100644
index 6fcf267..0000000
--- a/tools/stats_log_api_gen/java_writer.cpp
+++ /dev/null
@@ -1,384 +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.
- */
-
-#include "java_writer.h"
-
-#include "java_writer_q.h"
-#include "utils.h"
-
-namespace android {
-namespace stats_log_api_gen {
-
-static int write_java_q_logger_class(FILE* out, const SignatureInfoMap& signatureInfoMap,
- const AtomDecl& attributionDecl) {
- fprintf(out, "\n");
- fprintf(out, " // Write logging helper methods for statsd in Q and earlier.\n");
- fprintf(out, " private static class QLogger {\n");
-
- write_java_q_logging_constants(out, " ");
-
- // Print Q write methods.
- fprintf(out, "\n");
- fprintf(out, " // Write methods.\n");
- write_java_methods_q_schema(out, signatureInfoMap, attributionDecl, " ");
-
- fprintf(out, " }\n");
- return 0;
-}
-
-static void write_java_annotation_constants(FILE* out) {
- fprintf(out, " // Annotation constants.\n");
-
- const map<AnnotationId, string>& ANNOTATION_ID_CONSTANTS = get_annotation_id_constants();
- for (const auto& [id, name] : ANNOTATION_ID_CONSTANTS) {
- fprintf(out, " public static final byte %s = %hhu;\n", name.c_str(), id);
- }
- fprintf(out, "\n");
-}
-
-static void write_annotations(FILE* out, int argIndex,
- const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet) {
- FieldNumberToAtomDeclSet::const_iterator fieldNumberToAtomDeclSetIt =
- fieldNumberToAtomDeclSet.find(argIndex);
- if (fieldNumberToAtomDeclSet.end() == fieldNumberToAtomDeclSetIt) {
- return;
- }
- const AtomDeclSet& atomDeclSet = fieldNumberToAtomDeclSetIt->second;
- const map<AnnotationId, string>& ANNOTATION_ID_CONSTANTS = get_annotation_id_constants();
- for (const shared_ptr<AtomDecl>& atomDecl : atomDeclSet) {
- const string atomConstant = make_constant_name(atomDecl->name);
- fprintf(out, " if (%s == code) {\n", atomConstant.c_str());
- const AnnotationSet& annotations = atomDecl->fieldNumberToAnnotations.at(argIndex);
- int resetState = -1;
- int defaultState = -1;
- for (const shared_ptr<Annotation>& annotation : annotations) {
- const string& annotationConstant = ANNOTATION_ID_CONSTANTS.at(annotation->annotationId);
- switch (annotation->type) {
- case ANNOTATION_TYPE_INT:
- if (ANNOTATION_ID_TRIGGER_STATE_RESET == annotation->annotationId) {
- resetState = annotation->value.intValue;
- } else if (ANNOTATION_ID_DEFAULT_STATE == annotation->annotationId) {
- defaultState = annotation->value.intValue;
- } else {
- fprintf(out, " builder.addIntAnnotation(%s, %d);\n",
- annotationConstant.c_str(), annotation->value.intValue);
- }
- break;
- case ANNOTATION_TYPE_BOOL:
- fprintf(out, " builder.addBooleanAnnotation(%s, %s);\n",
- annotationConstant.c_str(),
- annotation->value.boolValue ? "true" : "false");
- break;
- default:
- break;
- }
- }
- if (defaultState != -1 && resetState != -1) {
- const string& annotationConstant =
- ANNOTATION_ID_CONSTANTS.at(ANNOTATION_ID_TRIGGER_STATE_RESET);
- fprintf(out, " if (arg%d == %d) {\n", argIndex, resetState);
- fprintf(out, " builder.addIntAnnotation(%s, %d);\n",
- annotationConstant.c_str(), defaultState);
- fprintf(out, " }\n");
- }
- fprintf(out, " }\n");
- }
-}
-
-static void write_method_signature(FILE* out, const vector<java_type_t>& signature,
- const AtomDecl& attributionDecl) {
- int argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end();
- arg++) {
- if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- for (const auto& chainField : attributionDecl.fields) {
- fprintf(out, ", %s[] %s", java_type_name(chainField.javaType),
- chainField.name.c_str());
- }
- } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
- fprintf(out, ", android.util.SparseArray<Object> valueMap");
- } else {
- fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex);
- }
- argIndex++;
- }
-}
-
-static int write_method_body(FILE* out, const vector<java_type_t>& signature,
- const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet,
- const AtomDecl& attributionDecl, const string& indent) {
- // Start StatsEvent.Builder.
- fprintf(out,
- "%s final StatsEvent.Builder builder = "
- "StatsEvent.newBuilder();\n",
- indent.c_str());
-
- // Write atom code.
- fprintf(out, "%s builder.setAtomId(code);\n", indent.c_str());
- write_annotations(out, ATOM_ID_FIELD_NUMBER, fieldNumberToAtomDeclSet);
-
- // Write the args.
- int argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end();
- arg++) {
- switch (*arg) {
- case JAVA_TYPE_BOOLEAN:
- fprintf(out, "%s builder.writeBoolean(arg%d);\n", indent.c_str(),
- argIndex);
- break;
- case JAVA_TYPE_INT:
- case JAVA_TYPE_ENUM:
- fprintf(out, "%s builder.writeInt(arg%d);\n", indent.c_str(), argIndex);
- break;
- case JAVA_TYPE_FLOAT:
- fprintf(out, "%s builder.writeFloat(arg%d);\n", indent.c_str(),
- argIndex);
- break;
- case JAVA_TYPE_LONG:
- fprintf(out, "%s builder.writeLong(arg%d);\n", indent.c_str(), argIndex);
- break;
- case JAVA_TYPE_STRING:
- fprintf(out, "%s builder.writeString(arg%d);\n", indent.c_str(),
- argIndex);
- break;
- case JAVA_TYPE_BYTE_ARRAY:
- fprintf(out,
- "%s builder.writeByteArray(null == arg%d ? new byte[0] : "
- "arg%d);\n",
- indent.c_str(), argIndex, argIndex);
- break;
- case JAVA_TYPE_ATTRIBUTION_CHAIN: {
- const char* uidName = attributionDecl.fields.front().name.c_str();
- const char* tagName = attributionDecl.fields.back().name.c_str();
-
- fprintf(out, "%s builder.writeAttributionChain(\n", indent.c_str());
- fprintf(out, "%s null == %s ? new int[0] : %s,\n",
- indent.c_str(), uidName, uidName);
- fprintf(out, "%s null == %s ? new String[0] : %s);\n",
- indent.c_str(), tagName, tagName);
- break;
- }
- case JAVA_TYPE_KEY_VALUE_PAIR:
- fprintf(out, "\n");
- fprintf(out, "%s // Write KeyValuePairs.\n", indent.c_str());
- fprintf(out, "%s final int count = valueMap.size();\n", indent.c_str());
- fprintf(out, "%s android.util.SparseIntArray intMap = null;\n",
- indent.c_str());
- fprintf(out, "%s android.util.SparseLongArray longMap = null;\n",
- indent.c_str());
- fprintf(out, "%s android.util.SparseArray<String> stringMap = null;\n",
- indent.c_str());
- fprintf(out, "%s android.util.SparseArray<Float> floatMap = null;\n",
- indent.c_str());
- fprintf(out, "%s for (int i = 0; i < count; i++) {\n", indent.c_str());
- fprintf(out, "%s final int key = valueMap.keyAt(i);\n",
- indent.c_str());
- fprintf(out, "%s final Object value = valueMap.valueAt(i);\n",
- indent.c_str());
- fprintf(out, "%s if (value instanceof Integer) {\n", indent.c_str());
- fprintf(out, "%s if (null == intMap) {\n", indent.c_str());
- fprintf(out,
- "%s intMap = new "
- "android.util.SparseIntArray();\n",
- indent.c_str());
- fprintf(out, "%s }\n", indent.c_str());
- fprintf(out, "%s intMap.put(key, (Integer) value);\n",
- indent.c_str());
- fprintf(out, "%s } else if (value instanceof Long) {\n",
- indent.c_str());
- fprintf(out, "%s if (null == longMap) {\n", indent.c_str());
- fprintf(out,
- "%s longMap = new "
- "android.util.SparseLongArray();\n",
- indent.c_str());
- fprintf(out, "%s }\n", indent.c_str());
- fprintf(out, "%s longMap.put(key, (Long) value);\n",
- indent.c_str());
- fprintf(out, "%s } else if (value instanceof String) {\n",
- indent.c_str());
- fprintf(out, "%s if (null == stringMap) {\n", indent.c_str());
- fprintf(out,
- "%s stringMap = new "
- "android.util.SparseArray<>();\n",
- indent.c_str());
- fprintf(out, "%s }\n", indent.c_str());
- fprintf(out, "%s stringMap.put(key, (String) value);\n",
- indent.c_str());
- fprintf(out, "%s } else if (value instanceof Float) {\n",
- indent.c_str());
- fprintf(out, "%s if (null == floatMap) {\n", indent.c_str());
- fprintf(out,
- "%s floatMap = new "
- "android.util.SparseArray<>();\n",
- indent.c_str());
- fprintf(out, "%s }\n", indent.c_str());
- fprintf(out, "%s floatMap.put(key, (Float) value);\n",
- indent.c_str());
- fprintf(out, "%s }\n", indent.c_str());
- fprintf(out, "%s }\n", indent.c_str());
- fprintf(out,
- "%s builder.writeKeyValuePairs("
- "intMap, longMap, stringMap, floatMap);\n",
- indent.c_str());
- break;
- default:
- // Unsupported types: OBJECT, DOUBLE.
- fprintf(stderr, "Encountered unsupported type.");
- return 1;
- }
- write_annotations(out, argIndex, fieldNumberToAtomDeclSet);
- argIndex++;
- }
- return 0;
-}
-
-static int write_java_pushed_methods(FILE* out, const SignatureInfoMap& signatureInfoMap,
- const AtomDecl& attributionDecl, const bool supportQ) {
- for (auto signatureInfoMapIt = signatureInfoMap.begin();
- signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) {
- // Print method signature.
- fprintf(out, " public static void write(int code");
- const vector<java_type_t>& signature = signatureInfoMapIt->first;
- const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet = signatureInfoMapIt->second;
- write_method_signature(out, signature, attributionDecl);
- fprintf(out, ") {\n");
-
- // Print method body.
- string indent("");
- if (supportQ) {
- fprintf(out, " if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {\n");
- indent = " ";
- }
-
- int ret = write_method_body(out, signature, fieldNumberToAtomDeclSet,
- attributionDecl, indent);
- if (ret != 0) {
- return ret;
- }
- fprintf(out, "\n");
-
- fprintf(out, "%s builder.usePooledBuffer();\n", indent.c_str());
- fprintf(out, "%s StatsLog.write(builder.build());\n", indent.c_str());
-
- // Add support for writing using Q schema if this is not the default module.
- if (supportQ) {
- fprintf(out, " } else {\n");
- fprintf(out, " QLogger.write(code");
- int argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- const char* uidName = attributionDecl.fields.front().name.c_str();
- const char* tagName = attributionDecl.fields.back().name.c_str();
- fprintf(out, ", %s, %s", uidName, tagName);
- } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
- // Module logging does not yet support key value pair.
- fprintf(stderr, "Module logging does not yet support key value pair.\n");
- return 1;
- } else {
- fprintf(out, ", arg%d", argIndex);
- }
- argIndex++;
- }
- fprintf(out, ");\n");
- fprintf(out, " }\n"); // if
- }
-
- fprintf(out, " }\n"); // method
- fprintf(out, "\n");
- }
- return 0;
-}
-
-static int write_java_pulled_methods(FILE* out, const SignatureInfoMap& signatureInfoMap,
- const AtomDecl& attributionDecl) {
- for (auto signatureInfoMapIt = signatureInfoMap.begin();
- signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) {
- // Print method signature.
- fprintf(out, " public static StatsEvent buildStatsEvent(int code");
- const vector<java_type_t>& signature = signatureInfoMapIt->first;
- const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet = signatureInfoMapIt->second;
- write_method_signature(out, signature, attributionDecl);
- fprintf(out, ") {\n");
-
- // Print method body.
- string indent("");
- int ret = write_method_body(out, signature, fieldNumberToAtomDeclSet,
- attributionDecl, indent);
- if (ret != 0) {
- return ret;
- }
- fprintf(out, "\n");
-
- fprintf(out, "%s return builder.build();\n", indent.c_str());
-
- fprintf(out, " }\n"); // method
- fprintf(out, "\n");
- }
- return 0;
-}
-
-int write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl,
- const string& javaClass, const string& javaPackage, const bool supportQ,
- const bool supportWorkSource) {
- // Print prelude
- fprintf(out, "// This file is autogenerated\n");
- fprintf(out, "\n");
- fprintf(out, "package %s;\n", javaPackage.c_str());
- fprintf(out, "\n");
- fprintf(out, "\n");
- if (supportQ) {
- fprintf(out, "import android.os.Build;\n");
- fprintf(out, "import android.os.SystemClock;\n");
- }
-
- fprintf(out, "import android.util.StatsEvent;\n");
- fprintf(out, "import android.util.StatsLog;\n");
-
- fprintf(out, "\n");
- fprintf(out, "\n");
- fprintf(out, "/**\n");
- fprintf(out, " * Utility class for logging statistics events.\n");
- fprintf(out, " */\n");
- fprintf(out, "public class %s {\n", javaClass.c_str());
-
- write_java_atom_codes(out, atoms);
- write_java_enum_values(out, atoms);
- write_java_annotation_constants(out);
-
- int errors = 0;
-
- // Print write methods.
- fprintf(out, " // Write methods\n");
- errors += write_java_pushed_methods(out, atoms.signatureInfoMap, attributionDecl, supportQ);
- errors += write_java_non_chained_methods(out, atoms.nonChainedSignatureInfoMap);
- errors += write_java_pulled_methods(out, atoms.pulledAtomsSignatureInfoMap,
- attributionDecl);
- if (supportWorkSource) {
- errors += write_java_work_source_methods(out, atoms.signatureInfoMap);
- }
-
- if (supportQ) {
- errors += write_java_q_logger_class(out, atoms.signatureInfoMap, attributionDecl);
- }
-
- fprintf(out, "}\n");
-
- return errors;
-}
-
-} // namespace stats_log_api_gen
-} // namespace android
diff --git a/tools/stats_log_api_gen/java_writer.h b/tools/stats_log_api_gen/java_writer.h
deleted file mode 100644
index afd992b..0000000
--- a/tools/stats_log_api_gen/java_writer.h
+++ /dev/null
@@ -1,39 +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.
- */
-
-#ifndef ANDROID_STATS_LOG_API_GEN_JAVA_WRITER_H
-#define ANDROID_STATS_LOG_API_GEN_JAVA_WRITER_H
-
-#include <stdio.h>
-#include <string.h>
-
-#include <map>
-#include <set>
-#include <vector>
-
-#include "Collation.h"
-
-namespace android {
-namespace stats_log_api_gen {
-
-int write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl,
- const string& javaClass, const string& javaPackage, const bool supportQ,
- const bool supportWorkSource);
-
-} // namespace stats_log_api_gen
-} // namespace android
-
-#endif // ANDROID_STATS_LOG_API_GEN_JAVA_WRITER_H
diff --git a/tools/stats_log_api_gen/java_writer_q.cpp b/tools/stats_log_api_gen/java_writer_q.cpp
deleted file mode 100644
index be7cb4a..0000000
--- a/tools/stats_log_api_gen/java_writer_q.cpp
+++ /dev/null
@@ -1,601 +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.
- */
-
-#include "java_writer_q.h"
-
-#include "utils.h"
-
-namespace android {
-namespace stats_log_api_gen {
-
-void write_java_q_logging_constants(FILE* out, const string& indent) {
- fprintf(out, "%s// Payload limits.\n", indent.c_str());
- fprintf(out, "%sprivate static final int LOGGER_ENTRY_MAX_PAYLOAD = 4068;\n", indent.c_str());
- fprintf(out,
- "%sprivate static final int MAX_EVENT_PAYLOAD = "
- "LOGGER_ENTRY_MAX_PAYLOAD - 4;\n",
- indent.c_str());
-
- // Value types. Must match with EventLog.java and log.h.
- fprintf(out, "\n");
- fprintf(out, "%s// Value types.\n", indent.c_str());
- fprintf(out, "%sprivate static final byte INT_TYPE = 0;\n", indent.c_str());
- fprintf(out, "%sprivate static final byte LONG_TYPE = 1;\n", indent.c_str());
- fprintf(out, "%sprivate static final byte STRING_TYPE = 2;\n", indent.c_str());
- fprintf(out, "%sprivate static final byte LIST_TYPE = 3;\n", indent.c_str());
- fprintf(out, "%sprivate static final byte FLOAT_TYPE = 4;\n", indent.c_str());
-
- // Size of each value type.
- // Booleans, ints, floats, and enums take 5 bytes, 1 for the type and 4 for
- // the value.
- fprintf(out, "\n");
- fprintf(out, "%s// Size of each value type.\n", indent.c_str());
- fprintf(out, "%sprivate static final int INT_TYPE_SIZE = 5;\n", indent.c_str());
- fprintf(out, "%sprivate static final int FLOAT_TYPE_SIZE = 5;\n", indent.c_str());
- // Longs take 9 bytes, 1 for the type and 8 for the value.
- fprintf(out, "%sprivate static final int LONG_TYPE_SIZE = 9;\n", indent.c_str());
- // Strings take 5 metadata bytes: 1 byte is for the type, 4 are for the
- // length.
- fprintf(out, "%sprivate static final int STRING_TYPE_OVERHEAD = 5;\n", indent.c_str());
- fprintf(out, "%sprivate static final int LIST_TYPE_OVERHEAD = 2;\n", indent.c_str());
-}
-
-int write_java_methods_q_schema(FILE* out, const SignatureInfoMap& signatureInfoMap,
- const AtomDecl& attributionDecl, const string& indent) {
- int requiredHelpers = 0;
- for (auto signatureInfoMapIt = signatureInfoMap.begin();
- signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) {
- // Print method signature.
- vector<java_type_t> signature = signatureInfoMapIt->first;
- fprintf(out, "%spublic static void write(int code", indent.c_str());
- int argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end();
- arg++) {
- if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- for (const auto& chainField : attributionDecl.fields) {
- fprintf(out, ", %s[] %s", java_type_name(chainField.javaType),
- chainField.name.c_str());
- }
- } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
- fprintf(out, ", android.util.SparseArray<Object> valueMap");
- } else {
- fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex);
- }
- argIndex++;
- }
- fprintf(out, ") {\n");
-
- // Calculate the size of the buffer.
- fprintf(out, "%s // Initial overhead of the list, timestamp, and atom tag.\n",
- indent.c_str());
- fprintf(out,
- "%s int needed = LIST_TYPE_OVERHEAD + LONG_TYPE_SIZE + "
- "INT_TYPE_SIZE;\n",
- indent.c_str());
- argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end();
- arg++) {
- switch (*arg) {
- case JAVA_TYPE_BOOLEAN:
- case JAVA_TYPE_INT:
- case JAVA_TYPE_FLOAT:
- case JAVA_TYPE_ENUM:
- fprintf(out, "%s needed += INT_TYPE_SIZE;\n", indent.c_str());
- break;
- case JAVA_TYPE_LONG:
- // Longs take 9 bytes, 1 for the type and 8 for the value.
- fprintf(out, "%s needed += LONG_TYPE_SIZE;\n", indent.c_str());
- break;
- case JAVA_TYPE_STRING:
- // Strings take 5 metadata bytes + length of byte encoded string.
- fprintf(out, "%s if (arg%d == null) {\n", indent.c_str(), argIndex);
- fprintf(out, "%s arg%d = \"\";\n", indent.c_str(), argIndex);
- fprintf(out, "%s }\n", indent.c_str());
- fprintf(out,
- "%s byte[] arg%dBytes = "
- "arg%d.getBytes(java.nio.charset.StandardCharsets.UTF_8);\n",
- indent.c_str(), argIndex, argIndex);
- fprintf(out, "%s needed += STRING_TYPE_OVERHEAD + arg%dBytes.length;\n",
- indent.c_str(), argIndex);
- break;
- case JAVA_TYPE_BYTE_ARRAY:
- // Byte arrays take 5 metadata bytes + length of byte array.
- fprintf(out, "%s if (arg%d == null) {\n", indent.c_str(), argIndex);
- fprintf(out, "%s arg%d = new byte[0];\n", indent.c_str(), argIndex);
- fprintf(out, "%s }\n", indent.c_str());
- fprintf(out, "%s needed += STRING_TYPE_OVERHEAD + arg%d.length;\n",
- indent.c_str(), argIndex);
- break;
- case JAVA_TYPE_ATTRIBUTION_CHAIN: {
- const char* uidName = attributionDecl.fields.front().name.c_str();
- const char* tagName = attributionDecl.fields.back().name.c_str();
- // Null checks on the params.
- fprintf(out, "%s if (%s == null) {\n", indent.c_str(), uidName);
- fprintf(out, "%s %s = new %s[0];\n", indent.c_str(), uidName,
- java_type_name(attributionDecl.fields.front().javaType));
- fprintf(out, "%s }\n", indent.c_str());
- fprintf(out, "%s if (%s == null) {\n", indent.c_str(), tagName);
- fprintf(out, "%s %s = new %s[0];\n", indent.c_str(), tagName,
- java_type_name(attributionDecl.fields.back().javaType));
- fprintf(out, "%s }\n", indent.c_str());
-
- // First check that the lengths of the uid and tag arrays are the
- // same.
- fprintf(out, "%s if (%s.length != %s.length) {\n", indent.c_str(), uidName,
- tagName);
- fprintf(out, "%s return;\n", indent.c_str());
- fprintf(out, "%s }\n", indent.c_str());
- fprintf(out, "%s int attrSize = LIST_TYPE_OVERHEAD;\n", indent.c_str());
- fprintf(out, "%s for (int i = 0; i < %s.length; i++) {\n", indent.c_str(),
- tagName);
- fprintf(out, "%s String str%d = (%s[i] == null) ? \"\" : %s[i];\n",
- indent.c_str(), argIndex, tagName, tagName);
- fprintf(out,
- "%s int str%dlen = "
- "str%d.getBytes(java.nio.charset.StandardCharsets.UTF_8)."
- "length;\n",
- indent.c_str(), argIndex, argIndex);
- fprintf(out,
- "%s attrSize += "
- "LIST_TYPE_OVERHEAD + INT_TYPE_SIZE + STRING_TYPE_OVERHEAD + "
- "str%dlen;\n",
- indent.c_str(), argIndex);
- fprintf(out, "%s }\n", indent.c_str());
- fprintf(out, "%s needed += attrSize;\n", indent.c_str());
- break;
- }
- case JAVA_TYPE_KEY_VALUE_PAIR: {
- fprintf(out, "%s // Calculate bytes needed by Key Value Pairs.\n",
- indent.c_str());
- fprintf(out, "%s final int count = valueMap.size();\n", indent.c_str());
- fprintf(out, "%s android.util.SparseIntArray intMap = null;\n",
- indent.c_str());
- fprintf(out, "%s android.util.SparseLongArray longMap = null;\n",
- indent.c_str());
- fprintf(out, "%s android.util.SparseArray<String> stringMap = null;\n",
- indent.c_str());
- fprintf(out, "%s android.util.SparseArray<Float> floatMap = null;\n",
- indent.c_str());
- fprintf(out, "%s int keyValuePairSize = LIST_TYPE_OVERHEAD;\n",
- indent.c_str());
- fprintf(out, "%s for (int i = 0; i < count; i++) {\n", indent.c_str());
- fprintf(out, "%s final int key = valueMap.keyAt(i);\n", indent.c_str());
- fprintf(out, "%s final Object value = valueMap.valueAt(i);\n",
- indent.c_str());
- fprintf(out, "%s if (value instanceof Integer) {\n", indent.c_str());
- fprintf(out, "%s keyValuePairSize += LIST_TYPE_OVERHEAD\n",
- indent.c_str());
- fprintf(out, "%s + INT_TYPE_SIZE + INT_TYPE_SIZE;\n",
- indent.c_str());
- fprintf(out, "%s if (null == intMap) {\n", indent.c_str());
- fprintf(out, "%s intMap = new android.util.SparseIntArray();\n",
- indent.c_str());
- fprintf(out, "%s }\n", indent.c_str());
- fprintf(out, "%s intMap.put(key, (Integer) value);\n",
- indent.c_str());
- fprintf(out, "%s } else if (value instanceof Long) {\n", indent.c_str());
- fprintf(out, "%s keyValuePairSize += LIST_TYPE_OVERHEAD\n",
- indent.c_str());
- fprintf(out, "%s + INT_TYPE_SIZE + LONG_TYPE_SIZE;\n",
- indent.c_str());
- fprintf(out, "%s if (null == longMap) {\n", indent.c_str());
- fprintf(out,
- "%s longMap = new "
- "android.util.SparseLongArray();\n",
- indent.c_str());
- fprintf(out, "%s }\n", indent.c_str());
- fprintf(out, "%s longMap.put(key, (Long) value);\n", indent.c_str());
- fprintf(out, "%s } else if (value instanceof String) {\n",
- indent.c_str());
- fprintf(out,
- "%s final String str = (value == null) ? \"\" : "
- "(String) value;\n",
- indent.c_str());
- fprintf(out,
- "%s final int len = "
- "str.getBytes(java.nio.charset.StandardCharsets.UTF_8).length;\n",
- indent.c_str());
- fprintf(out,
- "%s keyValuePairSize += LIST_TYPE_OVERHEAD + "
- "INT_TYPE_SIZE\n",
- indent.c_str());
- fprintf(out, "%s + STRING_TYPE_OVERHEAD + len;\n",
- indent.c_str());
- fprintf(out, "%s if (null == stringMap) {\n", indent.c_str());
- fprintf(out,
- "%s stringMap = new "
- "android.util.SparseArray<>();\n",
- indent.c_str());
- fprintf(out, "%s }\n", indent.c_str());
- fprintf(out, "%s stringMap.put(key, str);\n", indent.c_str());
- fprintf(out, "%s } else if (value instanceof Float) {\n",
- indent.c_str());
- fprintf(out, "%s keyValuePairSize += LIST_TYPE_OVERHEAD\n",
- indent.c_str());
- fprintf(out, "%s + INT_TYPE_SIZE + FLOAT_TYPE_SIZE;\n",
- indent.c_str());
- fprintf(out, "%s if (null == floatMap) {\n", indent.c_str());
- fprintf(out,
- "%s floatMap = new "
- "android.util.SparseArray<>();\n",
- indent.c_str());
- fprintf(out, "%s }\n", indent.c_str());
- fprintf(out, "%s floatMap.put(key, (Float) value);\n",
- indent.c_str());
- fprintf(out, "%s }\n", indent.c_str());
- fprintf(out, "%s }\n", indent.c_str());
- fprintf(out, "%s needed += keyValuePairSize;\n", indent.c_str());
- break;
- }
- default:
- // Unsupported types: OBJECT, DOUBLE.
- fprintf(stderr, "Module logging does not yet support Object and Double.\n");
- return 1;
- }
- argIndex++;
- }
-
- // Now we have the size that is needed. Check for overflow and return if
- // needed.
- fprintf(out, "%s if (needed > MAX_EVENT_PAYLOAD) {\n", indent.c_str());
- fprintf(out, "%s return;\n", indent.c_str());
- fprintf(out, "%s }\n", indent.c_str());
-
- // Create new buffer, and associated data types.
- fprintf(out, "%s byte[] buff = new byte[needed];\n", indent.c_str());
- fprintf(out, "%s int pos = 0;\n", indent.c_str());
-
- // Initialize the buffer with list data type.
- fprintf(out, "%s buff[pos] = LIST_TYPE;\n", indent.c_str());
- fprintf(out, "%s buff[pos + 1] = %zu;\n", indent.c_str(), signature.size() + 2);
- fprintf(out, "%s pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
-
- // Write timestamp.
- fprintf(out, "%s long elapsedRealtime = SystemClock.elapsedRealtimeNanos();\n",
- indent.c_str());
- fprintf(out, "%s buff[pos] = LONG_TYPE;\n", indent.c_str());
- fprintf(out, "%s copyLong(buff, pos + 1, elapsedRealtime);\n", indent.c_str());
- fprintf(out, "%s pos += LONG_TYPE_SIZE;\n", indent.c_str());
-
- // Write atom code.
- fprintf(out, "%s buff[pos] = INT_TYPE;\n", indent.c_str());
- fprintf(out, "%s copyInt(buff, pos + 1, code);\n", indent.c_str());
- fprintf(out, "%s pos += INT_TYPE_SIZE;\n", indent.c_str());
-
- // Write the args.
- argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end();
- arg++) {
- switch (*arg) {
- case JAVA_TYPE_BOOLEAN:
- fprintf(out, "%s buff[pos] = INT_TYPE;\n", indent.c_str());
- fprintf(out, "%s copyInt(buff, pos + 1, arg%d? 1 : 0);\n", indent.c_str(),
- argIndex);
- fprintf(out, "%s pos += INT_TYPE_SIZE;\n", indent.c_str());
- break;
- case JAVA_TYPE_INT:
- case JAVA_TYPE_ENUM:
- fprintf(out, "%s buff[pos] = INT_TYPE;\n", indent.c_str());
- fprintf(out, "%s copyInt(buff, pos + 1, arg%d);\n", indent.c_str(),
- argIndex);
- fprintf(out, "%s pos += INT_TYPE_SIZE;\n", indent.c_str());
- break;
- case JAVA_TYPE_FLOAT:
- requiredHelpers |= JAVA_MODULE_REQUIRES_FLOAT;
- fprintf(out, "%s buff[pos] = FLOAT_TYPE;\n", indent.c_str());
- fprintf(out, "%s copyFloat(buff, pos + 1, arg%d);\n", indent.c_str(),
- argIndex);
- fprintf(out, "%s pos += FLOAT_TYPE_SIZE;\n", indent.c_str());
- break;
- case JAVA_TYPE_LONG:
- fprintf(out, "%s buff[pos] = LONG_TYPE;\n", indent.c_str());
- fprintf(out, "%s copyLong(buff, pos + 1, arg%d);\n", indent.c_str(),
- argIndex);
- fprintf(out, "%s pos += LONG_TYPE_SIZE;\n", indent.c_str());
- break;
- case JAVA_TYPE_STRING:
- fprintf(out, "%s buff[pos] = STRING_TYPE;\n", indent.c_str());
- fprintf(out, "%s copyInt(buff, pos + 1, arg%dBytes.length);\n",
- indent.c_str(), argIndex);
- fprintf(out,
- "%s System.arraycopy("
- "arg%dBytes, 0, buff, pos + STRING_TYPE_OVERHEAD, "
- "arg%dBytes.length);\n",
- indent.c_str(), argIndex, argIndex);
- fprintf(out, "%s pos += STRING_TYPE_OVERHEAD + arg%dBytes.length;\n",
- indent.c_str(), argIndex);
- break;
- case JAVA_TYPE_BYTE_ARRAY:
- fprintf(out, "%s buff[pos] = STRING_TYPE;\n", indent.c_str());
- fprintf(out, "%s copyInt(buff, pos + 1, arg%d.length);\n", indent.c_str(),
- argIndex);
- fprintf(out,
- "%s System.arraycopy("
- "arg%d, 0, buff, pos + STRING_TYPE_OVERHEAD, arg%d.length);\n",
- indent.c_str(), argIndex, argIndex);
- fprintf(out, "%s pos += STRING_TYPE_OVERHEAD + arg%d.length;\n",
- indent.c_str(), argIndex);
- break;
- case JAVA_TYPE_ATTRIBUTION_CHAIN: {
- requiredHelpers |= JAVA_MODULE_REQUIRES_ATTRIBUTION;
- const char* uidName = attributionDecl.fields.front().name.c_str();
- const char* tagName = attributionDecl.fields.back().name.c_str();
-
- fprintf(out, "%s writeAttributionChain(buff, pos, %s, %s);\n",
- indent.c_str(), uidName, tagName);
- fprintf(out, "%s pos += attrSize;\n", indent.c_str());
- break;
- }
- case JAVA_TYPE_KEY_VALUE_PAIR:
- requiredHelpers |= JAVA_MODULE_REQUIRES_FLOAT;
- requiredHelpers |= JAVA_MODULE_REQUIRES_KEY_VALUE_PAIRS;
- fprintf(out,
- "%s writeKeyValuePairs(buff, pos, (byte) count, intMap, "
- "longMap, "
- "stringMap, floatMap);\n",
- indent.c_str());
- fprintf(out, "%s pos += keyValuePairSize;\n", indent.c_str());
- break;
- default:
- // Unsupported types: OBJECT, DOUBLE.
- fprintf(stderr, "Object and Double are not supported in module logging");
- return 1;
- }
- argIndex++;
- }
-
- fprintf(out, "%s StatsLog.writeRaw(buff, pos);\n", indent.c_str());
- fprintf(out, "%s}\n", indent.c_str());
- fprintf(out, "\n");
- }
-
- write_java_helpers_for_q_schema_methods(out, attributionDecl, requiredHelpers, indent);
-
- return 0;
-}
-
-void write_java_helpers_for_q_schema_methods(FILE* out, const AtomDecl& attributionDecl,
- const int requiredHelpers, const string& indent) {
- fprintf(out, "\n");
- fprintf(out, "%s// Helper methods for copying primitives\n", indent.c_str());
- fprintf(out, "%sprivate static void copyInt(byte[] buff, int pos, int val) {\n",
- indent.c_str());
- fprintf(out, "%s buff[pos] = (byte) (val);\n", indent.c_str());
- fprintf(out, "%s buff[pos + 1] = (byte) (val >> 8);\n", indent.c_str());
- fprintf(out, "%s buff[pos + 2] = (byte) (val >> 16);\n", indent.c_str());
- fprintf(out, "%s buff[pos + 3] = (byte) (val >> 24);\n", indent.c_str());
- fprintf(out, "%s return;\n", indent.c_str());
- fprintf(out, "%s}\n", indent.c_str());
- fprintf(out, "\n");
-
- fprintf(out, "%sprivate static void copyLong(byte[] buff, int pos, long val) {\n",
- indent.c_str());
- fprintf(out, "%s buff[pos] = (byte) (val);\n", indent.c_str());
- fprintf(out, "%s buff[pos + 1] = (byte) (val >> 8);\n", indent.c_str());
- fprintf(out, "%s buff[pos + 2] = (byte) (val >> 16);\n", indent.c_str());
- fprintf(out, "%s buff[pos + 3] = (byte) (val >> 24);\n", indent.c_str());
- fprintf(out, "%s buff[pos + 4] = (byte) (val >> 32);\n", indent.c_str());
- fprintf(out, "%s buff[pos + 5] = (byte) (val >> 40);\n", indent.c_str());
- fprintf(out, "%s buff[pos + 6] = (byte) (val >> 48);\n", indent.c_str());
- fprintf(out, "%s buff[pos + 7] = (byte) (val >> 56);\n", indent.c_str());
- fprintf(out, "%s return;\n", indent.c_str());
- fprintf(out, "%s}\n", indent.c_str());
- fprintf(out, "\n");
-
- if (requiredHelpers & JAVA_MODULE_REQUIRES_FLOAT) {
- fprintf(out, "%sprivate static void copyFloat(byte[] buff, int pos, float val) {\n",
- indent.c_str());
- fprintf(out, "%s copyInt(buff, pos, Float.floatToIntBits(val));\n", indent.c_str());
- fprintf(out, "%s return;\n", indent.c_str());
- fprintf(out, "%s}\n", indent.c_str());
- fprintf(out, "\n");
- }
-
- if (requiredHelpers & JAVA_MODULE_REQUIRES_ATTRIBUTION) {
- fprintf(out, "%sprivate static void writeAttributionChain(byte[] buff, int pos",
- indent.c_str());
- for (const auto& chainField : attributionDecl.fields) {
- fprintf(out, ", %s[] %s", java_type_name(chainField.javaType), chainField.name.c_str());
- }
- fprintf(out, ") {\n");
-
- const char* uidName = attributionDecl.fields.front().name.c_str();
- const char* tagName = attributionDecl.fields.back().name.c_str();
-
- // Write the first list begin.
- fprintf(out, "%s buff[pos] = LIST_TYPE;\n", indent.c_str());
- fprintf(out, "%s buff[pos + 1] = (byte) (%s.length);\n", indent.c_str(), tagName);
- fprintf(out, "%s pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
-
- // Iterate through the attribution chain and write the nodes.
- fprintf(out, "%s for (int i = 0; i < %s.length; i++) {\n", indent.c_str(), tagName);
- // Write the list begin.
- fprintf(out, "%s buff[pos] = LIST_TYPE;\n", indent.c_str());
- fprintf(out, "%s buff[pos + 1] = %lu;\n", indent.c_str(),
- attributionDecl.fields.size());
- fprintf(out, "%s pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
-
- // Write the uid.
- fprintf(out, "%s buff[pos] = INT_TYPE;\n", indent.c_str());
- fprintf(out, "%s copyInt(buff, pos + 1, %s[i]);\n", indent.c_str(), uidName);
- fprintf(out, "%s pos += INT_TYPE_SIZE;\n", indent.c_str());
-
- // Write the tag.
- fprintf(out, "%s String %sStr = (%s[i] == null) ? \"\" : %s[i];\n", indent.c_str(),
- tagName, tagName, tagName);
- fprintf(out,
- "%s byte[] %sByte = "
- "%sStr.getBytes(java.nio.charset.StandardCharsets.UTF_8);\n",
- indent.c_str(), tagName, tagName);
- fprintf(out, "%s buff[pos] = STRING_TYPE;\n", indent.c_str());
- fprintf(out, "%s copyInt(buff, pos + 1, %sByte.length);\n", indent.c_str(), tagName);
- fprintf(out,
- "%s System.arraycopy("
- "%sByte, 0, buff, pos + STRING_TYPE_OVERHEAD, %sByte.length);\n",
- indent.c_str(), tagName, tagName);
- fprintf(out, "%s pos += STRING_TYPE_OVERHEAD + %sByte.length;\n", indent.c_str(),
- tagName);
- fprintf(out, "%s }\n", indent.c_str());
- fprintf(out, "%s}\n", indent.c_str());
- fprintf(out, "\n");
- }
-
- if (requiredHelpers & JAVA_MODULE_REQUIRES_KEY_VALUE_PAIRS) {
- fprintf(out,
- "%sprivate static void writeKeyValuePairs(byte[] buff, int pos, "
- "byte numPairs,\n",
- indent.c_str());
- fprintf(out, "%s final android.util.SparseIntArray intMap,\n", indent.c_str());
- fprintf(out, "%s final android.util.SparseLongArray longMap,\n", indent.c_str());
- fprintf(out, "%s final android.util.SparseArray<String> stringMap,\n",
- indent.c_str());
- fprintf(out, "%s final android.util.SparseArray<Float> floatMap) {\n",
- indent.c_str());
-
- // Start list of lists.
- fprintf(out, "%s buff[pos] = LIST_TYPE;\n", indent.c_str());
- fprintf(out, "%s buff[pos + 1] = (byte) numPairs;\n", indent.c_str());
- fprintf(out, "%s pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
-
- // Write integers.
- fprintf(out, "%s final int intMapSize = null == intMap ? 0 : intMap.size();\n",
- indent.c_str());
- fprintf(out, "%s for (int i = 0; i < intMapSize; i++) {\n", indent.c_str());
- fprintf(out, "%s buff[pos] = LIST_TYPE;\n", indent.c_str());
- fprintf(out, "%s buff[pos + 1] = (byte) 2;\n", indent.c_str());
- fprintf(out, "%s pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
- fprintf(out, "%s final int key = intMap.keyAt(i);\n", indent.c_str());
- fprintf(out, "%s final int value = intMap.valueAt(i);\n", indent.c_str());
- fprintf(out, "%s buff[pos] = INT_TYPE;\n", indent.c_str());
- fprintf(out, "%s copyInt(buff, pos + 1, key);\n", indent.c_str());
- fprintf(out, "%s pos += INT_TYPE_SIZE;\n", indent.c_str());
- fprintf(out, "%s buff[pos] = INT_TYPE;\n", indent.c_str());
- fprintf(out, "%s copyInt(buff, pos + 1, value);\n", indent.c_str());
- fprintf(out, "%s pos += INT_TYPE_SIZE;\n", indent.c_str());
- fprintf(out, "%s }\n", indent.c_str());
-
- // Write longs.
- fprintf(out, "%s final int longMapSize = null == longMap ? 0 : longMap.size();\n",
- indent.c_str());
- fprintf(out, "%s for (int i = 0; i < longMapSize; i++) {\n", indent.c_str());
- fprintf(out, "%s buff[pos] = LIST_TYPE;\n", indent.c_str());
- fprintf(out, "%s buff[pos + 1] = (byte) 2;\n", indent.c_str());
- fprintf(out, "%s pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
- fprintf(out, "%s final int key = longMap.keyAt(i);\n", indent.c_str());
- fprintf(out, "%s final long value = longMap.valueAt(i);\n", indent.c_str());
- fprintf(out, "%s buff[pos] = INT_TYPE;\n", indent.c_str());
- fprintf(out, "%s copyInt(buff, pos + 1, key);\n", indent.c_str());
- fprintf(out, "%s pos += INT_TYPE_SIZE;\n", indent.c_str());
- fprintf(out, "%s buff[pos] = LONG_TYPE;\n", indent.c_str());
- fprintf(out, "%s copyLong(buff, pos + 1, value);\n", indent.c_str());
- fprintf(out, "%s pos += LONG_TYPE_SIZE;\n", indent.c_str());
- fprintf(out, "%s }\n", indent.c_str());
-
- // Write Strings.
- fprintf(out,
- "%s final int stringMapSize = null == stringMap ? 0 : "
- "stringMap.size();\n",
- indent.c_str());
- fprintf(out, "%s for (int i = 0; i < stringMapSize; i++) {\n", indent.c_str());
- fprintf(out, "%s buff[pos] = LIST_TYPE;\n", indent.c_str());
- fprintf(out, "%s buff[pos + 1] = (byte) 2;\n", indent.c_str());
- fprintf(out, "%s pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
- fprintf(out, "%s final int key = stringMap.keyAt(i);\n", indent.c_str());
- fprintf(out, "%s final String value = stringMap.valueAt(i);\n", indent.c_str());
- fprintf(out,
- "%s final byte[] valueBytes = "
- "value.getBytes(java.nio.charset.StandardCharsets.UTF_8);\n",
- indent.c_str());
- fprintf(out, "%s buff[pos] = INT_TYPE;\n", indent.c_str());
- fprintf(out, "%s copyInt(buff, pos + 1, key);\n", indent.c_str());
- fprintf(out, "%s pos += INT_TYPE_SIZE;\n", indent.c_str());
- fprintf(out, "%s buff[pos] = STRING_TYPE;\n", indent.c_str());
- fprintf(out, "%s copyInt(buff, pos + 1, valueBytes.length);\n", indent.c_str());
- fprintf(out,
- "%s System.arraycopy("
- "valueBytes, 0, buff, pos + STRING_TYPE_OVERHEAD, "
- "valueBytes.length);\n",
- indent.c_str());
- fprintf(out, "%s pos += STRING_TYPE_OVERHEAD + valueBytes.length;\n",
- indent.c_str());
- fprintf(out, "%s }\n", indent.c_str());
-
- // Write floats.
- fprintf(out,
- "%s final int floatMapSize = null == floatMap ? 0 : "
- "floatMap.size();\n",
- indent.c_str());
- fprintf(out, "%s for (int i = 0; i < floatMapSize; i++) {\n", indent.c_str());
- fprintf(out, "%s buff[pos] = LIST_TYPE;\n", indent.c_str());
- fprintf(out, "%s buff[pos + 1] = (byte) 2;\n", indent.c_str());
- fprintf(out, "%s pos += LIST_TYPE_OVERHEAD;\n", indent.c_str());
- fprintf(out, "%s final int key = floatMap.keyAt(i);\n", indent.c_str());
- fprintf(out, "%s final float value = floatMap.valueAt(i);\n", indent.c_str());
- fprintf(out, "%s buff[pos] = INT_TYPE;\n", indent.c_str());
- fprintf(out, "%s copyInt(buff, pos + 1, key);\n", indent.c_str());
- fprintf(out, "%s pos += INT_TYPE_SIZE;\n", indent.c_str());
- fprintf(out, "%s buff[pos] = FLOAT_TYPE;\n", indent.c_str());
- fprintf(out, "%s copyFloat(buff, pos + 1, value);\n", indent.c_str());
- fprintf(out, "%s pos += FLOAT_TYPE_SIZE;\n", indent.c_str());
- fprintf(out, "%s }\n", indent.c_str());
- fprintf(out, "%s}\n", indent.c_str());
- fprintf(out, "\n");
- }
-}
-
-// This method is called in main.cpp to generate StatsLog for modules that's
-// compatible with Q at compile-time.
-int write_stats_log_java_q_for_module(FILE* out, const Atoms& atoms,
- const AtomDecl& attributionDecl, const string& javaClass,
- const string& javaPackage, const bool supportWorkSource) {
- // Print prelude
- fprintf(out, "// This file is autogenerated\n");
- fprintf(out, "\n");
- fprintf(out, "package %s;\n", javaPackage.c_str());
- fprintf(out, "\n");
- fprintf(out, "import static java.nio.charset.StandardCharsets.UTF_8;\n");
- fprintf(out, "\n");
- fprintf(out, "import android.util.StatsLog;\n");
- fprintf(out, "import android.os.SystemClock;\n");
- fprintf(out, "\n");
- fprintf(out, "\n");
- fprintf(out, "/**\n");
- fprintf(out, " * Utility class for logging statistics events.\n");
- fprintf(out, " */\n");
- fprintf(out, "public class %s {\n", javaClass.c_str());
-
- write_java_q_logging_constants(out, " ");
-
- write_java_atom_codes(out, atoms);
-
- write_java_enum_values(out, atoms);
-
- int errors = 0;
- // Print write methods
- fprintf(out, " // Write methods\n");
- errors += write_java_methods_q_schema(out, atoms.signatureInfoMap, attributionDecl, " ");
- errors += write_java_non_chained_methods(out, atoms.nonChainedSignatureInfoMap);
- if (supportWorkSource) {
- errors += write_java_work_source_methods(out, atoms.signatureInfoMap);
- }
-
- fprintf(out, "}\n");
-
- return errors;
-}
-
-} // namespace stats_log_api_gen
-} // namespace android
diff --git a/tools/stats_log_api_gen/java_writer_q.h b/tools/stats_log_api_gen/java_writer_q.h
deleted file mode 100644
index 622ef3e..0000000
--- a/tools/stats_log_api_gen/java_writer_q.h
+++ /dev/null
@@ -1,47 +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.
- */
-
-#ifndef ANDROID_STATS_LOG_API_GEN_JAVA_WRITER_Q_H
-#define ANDROID_STATS_LOG_API_GEN_JAVA_WRITER_Q_H
-
-#include <stdio.h>
-#include <string.h>
-
-#include <map>
-#include <set>
-#include <vector>
-
-#include "Collation.h"
-
-namespace android {
-namespace stats_log_api_gen {
-
-void write_java_q_logging_constants(FILE* out, const string& indent);
-
-int write_java_methods_q_schema(FILE* out, const SignatureInfoMap& signatureInfoMap,
- const AtomDecl& attributionDecl, const string& indent);
-
-void write_java_helpers_for_q_schema_methods(FILE* out, const AtomDecl& attributionDecl,
- const int requiredHelpers, const string& indent);
-
-int write_stats_log_java_q_for_module(FILE* out, const Atoms& atoms,
- const AtomDecl& attributionDecl, const string& javaClass,
- const string& javaPackage, const bool supportWorkSource);
-
-} // namespace stats_log_api_gen
-} // namespace android
-
-#endif // ANDROID_STATS_LOG_API_GEN_JAVA_WRITER_Q_H
diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp
deleted file mode 100644
index 50f81760..0000000
--- a/tools/stats_log_api_gen/main.cpp
+++ /dev/null
@@ -1,261 +0,0 @@
-
-#include <getopt.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <map>
-#include <set>
-#include <vector>
-
-#include "Collation.h"
-#include "frameworks/proto_logging/stats/atoms.pb.h"
-#include "java_writer.h"
-#include "java_writer_q.h"
-#include "native_writer.h"
-#include "utils.h"
-
-namespace android {
-namespace stats_log_api_gen {
-
-using android::os::statsd::Atom;
-
-static void print_usage() {
- fprintf(stderr, "usage: stats-log-api-gen OPTIONS\n");
- fprintf(stderr, "\n");
- fprintf(stderr, "OPTIONS\n");
- fprintf(stderr, " --cpp FILENAME the header file to output for write helpers\n");
- fprintf(stderr, " --header FILENAME the cpp file to output for write helpers\n");
- fprintf(stderr, " --help this message\n");
- fprintf(stderr, " --java FILENAME the java file to output\n");
- fprintf(stderr, " --module NAME optional, module name to generate outputs for\n");
- fprintf(stderr,
- " --namespace COMMA,SEP,NAMESPACE required for cpp/header with "
- "module\n");
- fprintf(stderr,
- " comma separated namespace of "
- "the files\n");
- fprintf(stderr,
- " --importHeader NAME required for cpp/jni to say which header to "
- "import "
- "for write helpers\n");
- fprintf(stderr, " --javaPackage PACKAGE the package for the java file.\n");
- fprintf(stderr, " required for java with module\n");
- fprintf(stderr, " --javaClass CLASS the class name of the java class.\n");
- fprintf(stderr, " Optional for Java with module.\n");
- fprintf(stderr, " Default is \"StatsLogInternal\"\n");
- fprintf(stderr, " --supportQ Include runtime support for Android Q.\n");
- fprintf(stderr,
- " --worksource Include support for logging WorkSource "
- "objects.\n");
- fprintf(stderr,
- " --compileQ Include compile-time support for Android Q "
- "(Java only).\n");
-}
-
-/**
- * Do the argument parsing and execute the tasks.
- */
-static int run(int argc, char const* const* argv) {
- string cppFilename;
- string headerFilename;
- string javaFilename;
- string javaPackage;
- string javaClass;
-
- string moduleName = DEFAULT_MODULE_NAME;
- string cppNamespace = DEFAULT_CPP_NAMESPACE;
- string cppHeaderImport = DEFAULT_CPP_HEADER_IMPORT;
- bool supportQ = false;
- bool supportWorkSource = false;
- bool compileQ = false;
-
- int index = 1;
- while (index < argc) {
- if (0 == strcmp("--help", argv[index])) {
- print_usage();
- return 0;
- } else if (0 == strcmp("--cpp", argv[index])) {
- index++;
- if (index >= argc) {
- print_usage();
- return 1;
- }
- cppFilename = argv[index];
- } else if (0 == strcmp("--header", argv[index])) {
- index++;
- if (index >= argc) {
- print_usage();
- return 1;
- }
- headerFilename = argv[index];
- } else if (0 == strcmp("--java", argv[index])) {
- index++;
- if (index >= argc) {
- print_usage();
- return 1;
- }
- javaFilename = argv[index];
- } else if (0 == strcmp("--module", argv[index])) {
- index++;
- if (index >= argc) {
- print_usage();
- return 1;
- }
- moduleName = argv[index];
- } else if (0 == strcmp("--namespace", argv[index])) {
- index++;
- if (index >= argc) {
- print_usage();
- return 1;
- }
- cppNamespace = argv[index];
- } else if (0 == strcmp("--importHeader", argv[index])) {
- index++;
- if (index >= argc) {
- print_usage();
- return 1;
- }
- cppHeaderImport = argv[index];
- } else if (0 == strcmp("--javaPackage", argv[index])) {
- index++;
- if (index >= argc) {
- print_usage();
- return 1;
- }
- javaPackage = argv[index];
- } else if (0 == strcmp("--javaClass", argv[index])) {
- index++;
- if (index >= argc) {
- print_usage();
- return 1;
- }
- javaClass = argv[index];
- } else if (0 == strcmp("--supportQ", argv[index])) {
- supportQ = true;
- } else if (0 == strcmp("--worksource", argv[index])) {
- supportWorkSource = true;
- } else if (0 == strcmp("--compileQ", argv[index])) {
- compileQ = true;
- }
-
- index++;
- }
-
- if (cppFilename.empty() && headerFilename.empty() && javaFilename.empty()) {
- print_usage();
- return 1;
- }
-
- if (DEFAULT_MODULE_NAME == moduleName && (supportQ || compileQ)) {
- // Support for Q schema is not needed for default module.
- fprintf(stderr, "%s cannot support Q schema\n", moduleName.c_str());
- return 1;
- }
-
- if (supportQ && compileQ) {
- // Runtime Q support is redundant if compile-time Q support is required.
- fprintf(stderr, "Cannot specify compileQ and supportQ simultaneously.\n");
- return 1;
- }
-
- // Collate the parameters
- Atoms atoms;
- int errorCount = collate_atoms(Atom::descriptor(), moduleName, &atoms);
- if (errorCount != 0) {
- return 1;
- }
-
- AtomDecl attributionDecl;
- vector<java_type_t> attributionSignature;
- collate_atom(android::os::statsd::AttributionNode::descriptor(), &attributionDecl,
- &attributionSignature);
-
- // Write the .cpp file
- if (!cppFilename.empty()) {
- FILE* out = fopen(cppFilename.c_str(), "w");
- if (out == nullptr) {
- fprintf(stderr, "Unable to open file for write: %s\n", cppFilename.c_str());
- return 1;
- }
- // If this is for a specific module, the namespace must also be provided.
- if (moduleName != DEFAULT_MODULE_NAME && cppNamespace == DEFAULT_CPP_NAMESPACE) {
- fprintf(stderr, "Must supply --namespace if supplying a specific module\n");
- return 1;
- }
- // If this is for a specific module, the header file to import must also be
- // provided.
- if (moduleName != DEFAULT_MODULE_NAME && cppHeaderImport == DEFAULT_CPP_HEADER_IMPORT) {
- fprintf(stderr, "Must supply --headerImport if supplying a specific module\n");
- return 1;
- }
- errorCount = android::stats_log_api_gen::write_stats_log_cpp(
- out, atoms, attributionDecl, cppNamespace, cppHeaderImport, supportQ);
- fclose(out);
- }
-
- // Write the .h file
- if (!headerFilename.empty()) {
- FILE* out = fopen(headerFilename.c_str(), "w");
- if (out == nullptr) {
- fprintf(stderr, "Unable to open file for write: %s\n", headerFilename.c_str());
- return 1;
- }
- // If this is for a specific module, the namespace must also be provided.
- if (moduleName != DEFAULT_MODULE_NAME && cppNamespace == DEFAULT_CPP_NAMESPACE) {
- fprintf(stderr, "Must supply --namespace if supplying a specific module\n");
- }
- errorCount = android::stats_log_api_gen::write_stats_log_header(out, atoms, attributionDecl,
- cppNamespace);
- fclose(out);
- }
-
- // Write the .java file
- if (!javaFilename.empty()) {
- if (javaClass.empty()) {
- fprintf(stderr, "Must supply --javaClass if supplying a Java filename");
- return 1;
- }
-
- if (javaPackage.empty()) {
- fprintf(stderr, "Must supply --javaPackage if supplying a Java filename");
- return 1;
- }
-
- if (moduleName.empty()) {
- fprintf(stderr, "Must supply --module if supplying a Java filename");
- return 1;
- }
-
- FILE* out = fopen(javaFilename.c_str(), "w");
- if (out == nullptr) {
- fprintf(stderr, "Unable to open file for write: %s\n", javaFilename.c_str());
- return 1;
- }
-
- if (compileQ) {
- errorCount = android::stats_log_api_gen::write_stats_log_java_q_for_module(
- out, atoms, attributionDecl, javaClass, javaPackage, supportWorkSource);
- } else {
- errorCount = android::stats_log_api_gen::write_stats_log_java(
- out, atoms, attributionDecl, javaClass, javaPackage, supportQ,
- supportWorkSource);
- }
-
- fclose(out);
- }
-
- return errorCount;
-}
-
-} // namespace stats_log_api_gen
-} // namespace android
-
-/**
- * Main.
- */
-int main(int argc, char const* const* argv) {
- GOOGLE_PROTOBUF_VERIFY_VERSION;
-
- return android::stats_log_api_gen::run(argc, argv);
-}
diff --git a/tools/stats_log_api_gen/native_writer.cpp b/tools/stats_log_api_gen/native_writer.cpp
deleted file mode 100644
index b4fb8dd..0000000
--- a/tools/stats_log_api_gen/native_writer.cpp
+++ /dev/null
@@ -1,423 +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.
- */
-
-#include "native_writer.h"
-
-#include "utils.h"
-
-namespace android {
-namespace stats_log_api_gen {
-
-static void write_native_annotation_constants(FILE* out) {
- fprintf(out, "// Annotation constants.\n");
-
- const map<AnnotationId, string>& ANNOTATION_ID_CONSTANTS = get_annotation_id_constants();
- for (const auto& [id, name] : ANNOTATION_ID_CONSTANTS) {
- fprintf(out, "const uint8_t %s = %hhu;\n", name.c_str(), id);
- }
- fprintf(out, "\n");
-}
-
-static void write_annotations(FILE* out, int argIndex,
- const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet,
- const string& methodPrefix, const string& methodSuffix) {
- FieldNumberToAtomDeclSet::const_iterator fieldNumberToAtomDeclSetIt =
- fieldNumberToAtomDeclSet.find(argIndex);
- if (fieldNumberToAtomDeclSet.end() == fieldNumberToAtomDeclSetIt) {
- return;
- }
- const AtomDeclSet& atomDeclSet = fieldNumberToAtomDeclSetIt->second;
- const map<AnnotationId, string>& ANNOTATION_ID_CONSTANTS = get_annotation_id_constants();
- for (const shared_ptr<AtomDecl>& atomDecl : atomDeclSet) {
- const string atomConstant = make_constant_name(atomDecl->name);
- fprintf(out, " if (%s == code) {\n", atomConstant.c_str());
- const AnnotationSet& annotations = atomDecl->fieldNumberToAnnotations.at(argIndex);
- int resetState = -1;
- int defaultState = -1;
- for (const shared_ptr<Annotation>& annotation : annotations) {
- const string& annotationConstant = ANNOTATION_ID_CONSTANTS.at(annotation->annotationId);
- switch (annotation->type) {
- case ANNOTATION_TYPE_INT:
- if (ANNOTATION_ID_TRIGGER_STATE_RESET == annotation->annotationId) {
- resetState = annotation->value.intValue;
- } else if (ANNOTATION_ID_DEFAULT_STATE == annotation->annotationId) {
- defaultState = annotation->value.intValue;
- } else {
- fprintf(out, " %saddInt32Annotation(%s%s, %d);\n",
- methodPrefix.c_str(), methodSuffix.c_str(),
- annotationConstant.c_str(), annotation->value.intValue);
- }
- break;
- case ANNOTATION_TYPE_BOOL:
- fprintf(out, " %saddBoolAnnotation(%s%s, %s);\n", methodPrefix.c_str(),
- methodSuffix.c_str(), annotationConstant.c_str(),
- annotation->value.boolValue ? "true" : "false");
- break;
- default:
- break;
- }
- }
- if (defaultState != -1 && resetState != -1) {
- const string& annotationConstant =
- ANNOTATION_ID_CONSTANTS.at(ANNOTATION_ID_TRIGGER_STATE_RESET);
- fprintf(out, " if (arg%d == %d) {\n", argIndex, resetState);
- fprintf(out, " %saddInt32Annotation(%s%s, %d);\n", methodPrefix.c_str(),
- methodSuffix.c_str(), annotationConstant.c_str(), defaultState);
- fprintf(out, " }\n");
- }
- fprintf(out, " }\n");
- }
-}
-
-static int write_native_method_body(FILE* out, vector<java_type_t>& signature,
- const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet,
- const AtomDecl& attributionDecl) {
- int argIndex = 1;
- fprintf(out, " AStatsEvent_setAtomId(event, code);\n");
- write_annotations(out, ATOM_ID_FIELD_NUMBER, fieldNumberToAtomDeclSet, "AStatsEvent_",
- "event, ");
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- switch (*arg) {
- case JAVA_TYPE_ATTRIBUTION_CHAIN: {
- const char* uidName = attributionDecl.fields.front().name.c_str();
- const char* tagName = attributionDecl.fields.back().name.c_str();
- fprintf(out,
- " AStatsEvent_writeAttributionChain(event, "
- "reinterpret_cast<const uint32_t*>(%s), %s.data(), "
- "static_cast<uint8_t>(%s_length));\n",
- uidName, tagName, uidName);
- break;
- }
- case JAVA_TYPE_BYTE_ARRAY:
- fprintf(out,
- " AStatsEvent_writeByteArray(event, "
- "reinterpret_cast<const uint8_t*>(arg%d.arg), "
- "arg%d.arg_length);\n",
- argIndex, argIndex);
- break;
- case JAVA_TYPE_BOOLEAN:
- fprintf(out, " AStatsEvent_writeBool(event, arg%d);\n", argIndex);
- break;
- case JAVA_TYPE_INT: // Fall through.
- case JAVA_TYPE_ENUM:
- fprintf(out, " AStatsEvent_writeInt32(event, arg%d);\n", argIndex);
- break;
- case JAVA_TYPE_FLOAT:
- fprintf(out, " AStatsEvent_writeFloat(event, arg%d);\n", argIndex);
- break;
- case JAVA_TYPE_LONG:
- fprintf(out, " AStatsEvent_writeInt64(event, arg%d);\n", argIndex);
- break;
- case JAVA_TYPE_STRING:
- fprintf(out, " AStatsEvent_writeString(event, arg%d);\n", argIndex);
- break;
- default:
- // Unsupported types: OBJECT, DOUBLE, KEY_VALUE_PAIRS
- fprintf(stderr, "Encountered unsupported type.");
- return 1;
- }
- write_annotations(out, argIndex, fieldNumberToAtomDeclSet, "AStatsEvent_",
- "event, ");
- argIndex++;
- }
- return 0;
-}
-
-static int write_native_stats_write_methods(FILE* out, const SignatureInfoMap& signatureInfoMap,
- const AtomDecl& attributionDecl, const bool supportQ) {
- fprintf(out, "\n");
- for (auto signatureInfoMapIt = signatureInfoMap.begin();
- signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) {
- vector<java_type_t> signature = signatureInfoMapIt->first;
- const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet = signatureInfoMapIt->second;
- // Key value pairs not supported in native.
- if (std::find(signature.begin(), signature.end(), JAVA_TYPE_KEY_VALUE_PAIR) !=
- signature.end()) {
- continue;
- }
- write_native_method_signature(out, "int stats_write(", signature, attributionDecl, " {");
-
- // Write method body.
- if (supportQ) {
- int argIndex = 1;
- fprintf(out, " StatsEventCompat event;\n");
- fprintf(out, " event.setAtomId(code);\n");
- write_annotations(out, ATOM_ID_FIELD_NUMBER, fieldNumberToAtomDeclSet, "event.", "");
- for (vector<java_type_t>::const_iterator arg = signature.begin();
- arg != signature.end(); arg++) {
- switch (*arg) {
- case JAVA_TYPE_ATTRIBUTION_CHAIN: {
- const char* uidName = attributionDecl.fields.front().name.c_str();
- const char* tagName = attributionDecl.fields.back().name.c_str();
- fprintf(out, " event.writeAttributionChain(%s, %s_length, %s);\n",
- uidName, uidName, tagName);
- break;
- }
- case JAVA_TYPE_BYTE_ARRAY:
- fprintf(out, " event.writeByteArray(arg%d.arg, arg%d.arg_length);\n",
- argIndex, argIndex);
- break;
- case JAVA_TYPE_BOOLEAN:
- fprintf(out, " event.writeBool(arg%d);\n", argIndex);
- break;
- case JAVA_TYPE_INT: // Fall through.
- case JAVA_TYPE_ENUM:
- fprintf(out, " event.writeInt32(arg%d);\n", argIndex);
- break;
- case JAVA_TYPE_FLOAT:
- fprintf(out, " event.writeFloat(arg%d);\n", argIndex);
- break;
- case JAVA_TYPE_LONG:
- fprintf(out, " event.writeInt64(arg%d);\n", argIndex);
- break;
- case JAVA_TYPE_STRING:
- fprintf(out, " event.writeString(arg%d);\n", argIndex);
- break;
- default:
- // Unsupported types: OBJECT, DOUBLE, KEY_VALUE_PAIRS.
- fprintf(stderr, "Encountered unsupported type.");
- return 1;
- }
- write_annotations(out, argIndex, fieldNumberToAtomDeclSet, "event.", "");
- argIndex++;
- }
- fprintf(out, " return event.writeToSocket();\n"); // end method body.
- } else {
- fprintf(out, " AStatsEvent* event = AStatsEvent_obtain();\n");
- int ret = write_native_method_body(out, signature, fieldNumberToAtomDeclSet,
- attributionDecl);
- if (ret != 0) {
- return ret;
- }
- fprintf(out, " const int ret = AStatsEvent_write(event);\n");
- fprintf(out, " AStatsEvent_release(event);\n");
- fprintf(out, " return ret;\n"); // end method body.
- }
- fprintf(out, "}\n\n"); // end method.
- }
- return 0;
-}
-
-static void write_native_stats_write_non_chained_methods(FILE* out,
- const SignatureInfoMap& signatureInfoMap,
- const AtomDecl& attributionDecl) {
- fprintf(out, "\n");
- for (auto signature_it = signatureInfoMap.begin();
- signature_it != signatureInfoMap.end(); signature_it++) {
- vector<java_type_t> signature = signature_it->first;
- // Key value pairs not supported in native.
- if (std::find(signature.begin(), signature.end(), JAVA_TYPE_KEY_VALUE_PAIR) !=
- signature.end()) {
- continue;
- }
-
- write_native_method_signature(out, "int stats_write_non_chained(", signature,
- attributionDecl, " {");
-
- vector<java_type_t> newSignature;
-
- // First two args form the attribution node so size goes down by 1.
- newSignature.reserve(signature.size() - 1);
-
- // First arg is Attribution Chain.
- newSignature.push_back(JAVA_TYPE_ATTRIBUTION_CHAIN);
-
- // Followed by the originial signature except the first 2 args.
- newSignature.insert(newSignature.end(), signature.begin() + 2, signature.end());
-
- const char* uidName = attributionDecl.fields.front().name.c_str();
- const char* tagName = attributionDecl.fields.back().name.c_str();
- fprintf(out, " const int32_t* %s = &arg1;\n", uidName);
- fprintf(out, " const size_t %s_length = 1;\n", uidName);
- fprintf(out, " const std::vector<char const*> %s(1, arg2);\n", tagName);
- fprintf(out, " return ");
- write_native_method_call(out, "stats_write", newSignature, attributionDecl, 2);
-
- fprintf(out, "}\n\n");
- }
-}
-
-static int write_native_build_stats_event_methods(FILE* out,
- const SignatureInfoMap& signatureInfoMap,
- const AtomDecl& attributionDecl) {
- fprintf(out, "\n");
- for (auto signatureInfoMapIt = signatureInfoMap.begin();
- signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) {
- vector<java_type_t> signature = signatureInfoMapIt->first;
- const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet = signatureInfoMapIt->second;
- // Key value pairs not supported in native.
- if (std::find(signature.begin(), signature.end(), JAVA_TYPE_KEY_VALUE_PAIR) !=
- signature.end()) {
- continue;
- }
- write_native_method_signature(out, "void addAStatsEvent(AStatsEventList* pulled_data, ",
- signature, attributionDecl, " {");
-
- fprintf(out, " AStatsEvent* event = AStatsEventList_addStatsEvent(pulled_data);\n");
- int ret = write_native_method_body(out, signature, fieldNumberToAtomDeclSet,
- attributionDecl);
- if (ret != 0) {
- return ret;
- }
- fprintf(out, " AStatsEvent_build(event);\n"); // end method body.
-
- fprintf(out, "}\n\n"); // end method.
- }
- return 0;
-}
-
-static void write_native_method_header(FILE* out, const string& methodName,
- const SignatureInfoMap& signatureInfoMap,
- const AtomDecl& attributionDecl) {
- for (auto signatureInfoMapIt = signatureInfoMap.begin();
- signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) {
- vector<java_type_t> signature = signatureInfoMapIt->first;
-
- // Key value pairs not supported in native.
- if (std::find(signature.begin(), signature.end(), JAVA_TYPE_KEY_VALUE_PAIR) !=
- signature.end()) {
- continue;
- }
- write_native_method_signature(out, methodName, signature, attributionDecl, ";");
- }
-}
-
-int write_stats_log_cpp(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl,
- const string& cppNamespace, const string& importHeader,
- const bool supportQ) {
- // Print prelude
- fprintf(out, "// This file is autogenerated\n");
- fprintf(out, "\n");
-
- fprintf(out, "#include <%s>\n", importHeader.c_str());
- if (supportQ) {
- fprintf(out, "#include <StatsEventCompat.h>\n");
- } else {
- fprintf(out, "#include <stats_event.h>\n");
-
- if (!atoms.pulledAtomsSignatureInfoMap.empty()) {
- fprintf(out, "#include <stats_pull_atom_callback.h>\n");
- }
- }
-
-
-
- fprintf(out, "\n");
- write_namespace(out, cppNamespace);
-
- write_native_stats_write_methods(out, atoms.signatureInfoMap, attributionDecl, supportQ);
- write_native_stats_write_non_chained_methods(out, atoms.nonChainedSignatureInfoMap,
- attributionDecl);
- write_native_build_stats_event_methods(out, atoms.pulledAtomsSignatureInfoMap,
- attributionDecl);
-
- // Print footer
- fprintf(out, "\n");
- write_closing_namespace(out, cppNamespace);
-
- return 0;
-}
-
-int write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl,
- const string& cppNamespace) {
- // Print prelude
- fprintf(out, "// This file is autogenerated\n");
- fprintf(out, "\n");
- fprintf(out, "#pragma once\n");
- fprintf(out, "\n");
- fprintf(out, "#include <stdint.h>\n");
- fprintf(out, "#include <vector>\n");
- fprintf(out, "#include <map>\n");
- fprintf(out, "#include <set>\n");
- if (!atoms.pulledAtomsSignatureInfoMap.empty()) {
- fprintf(out, "#include <stats_pull_atom_callback.h>\n");
- }
- fprintf(out, "\n");
-
- write_namespace(out, cppNamespace);
- fprintf(out, "\n");
- fprintf(out, "/*\n");
- fprintf(out, " * API For logging statistics events.\n");
- fprintf(out, " */\n");
- fprintf(out, "\n");
-
- write_native_atom_constants(out, atoms, attributionDecl);
-
- // Print constants for the enum values.
- fprintf(out, "//\n");
- fprintf(out, "// Constants for enum values\n");
- fprintf(out, "//\n\n");
- for (AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); atomIt != atoms.decls.end();
- atomIt++) {
- for (vector<AtomField>::const_iterator field = (*atomIt)->fields.begin();
- field != (*atomIt)->fields.end(); field++) {
- if (field->javaType == JAVA_TYPE_ENUM) {
- fprintf(out, "// Values for %s.%s\n", (*atomIt)->message.c_str(),
- field->name.c_str());
- for (map<int, string>::const_iterator value = field->enumValues.begin();
- value != field->enumValues.end(); value++) {
- fprintf(out, "const int32_t %s__%s__%s = %d;\n",
- make_constant_name((*atomIt)->message).c_str(),
- make_constant_name(field->name).c_str(),
- make_constant_name(value->second).c_str(), value->first);
- }
- fprintf(out, "\n");
- }
- }
- }
-
- write_native_annotation_constants(out);
-
- fprintf(out, "struct BytesField {\n");
- fprintf(out,
- " BytesField(char const* array, size_t len) : arg(array), "
- "arg_length(len) {}\n");
- fprintf(out, " char const* arg;\n");
- fprintf(out, " size_t arg_length;\n");
- fprintf(out, "};\n");
- fprintf(out, "\n");
-
- // Print write methods
- fprintf(out, "//\n");
- fprintf(out, "// Write methods\n");
- fprintf(out, "//\n");
- write_native_method_header(out, "int stats_write(", atoms.signatureInfoMap, attributionDecl);
- fprintf(out, "\n");
-
- fprintf(out, "//\n");
- fprintf(out, "// Write flattened methods\n");
- fprintf(out, "//\n");
- write_native_method_header(out, "int stats_write_non_chained(", atoms.nonChainedSignatureInfoMap,
- attributionDecl);
- fprintf(out, "\n");
-
- // Print pulled atoms methods.
- fprintf(out, "//\n");
- fprintf(out, "// Add AStatsEvent methods\n");
- fprintf(out, "//\n");
- write_native_method_header(out, "void addAStatsEvent(AStatsEventList* pulled_data, ",
- atoms.pulledAtomsSignatureInfoMap,
- attributionDecl);
-
- fprintf(out, "\n");
- write_closing_namespace(out, cppNamespace);
-
- return 0;
-}
-
-} // namespace stats_log_api_gen
-} // namespace android
diff --git a/tools/stats_log_api_gen/native_writer.h b/tools/stats_log_api_gen/native_writer.h
deleted file mode 100644
index 4e42d1f..0000000
--- a/tools/stats_log_api_gen/native_writer.h
+++ /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.
- */
-
-#ifndef ANDROID_STATS_LOG_API_GEN_NATIVE_WRITER_H
-#define ANDROID_STATS_LOG_API_GEN_NATIVE_WRITER_H
-
-#include <stdio.h>
-#include <string.h>
-
-#include "Collation.h"
-
-namespace android {
-namespace stats_log_api_gen {
-
-int write_stats_log_cpp(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl,
- const string& cppNamespace, const string& importHeader,
- const bool supportQ);
-
-int write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl,
- const string& cppNamespace);
-
-} // namespace stats_log_api_gen
-} // namespace android
-
-#endif // ANDROID_STATS_LOG_API_GEN_NATIVE_WRITER_H
diff --git a/tools/stats_log_api_gen/test.proto b/tools/stats_log_api_gen/test.proto
deleted file mode 100644
index 18c52bf..0000000
--- a/tools/stats_log_api_gen/test.proto
+++ /dev/null
@@ -1,236 +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";
-
-import "frameworks/proto_logging/stats/atoms.proto";
-import "frameworks/proto_logging/stats/atom_field_options.proto";
-
-package android.stats_log_api_gen;
-
-message IntAtom {
- optional int32 field1 = 1;
-}
-
-message AnotherIntAtom {
- optional int32 field1 = 1;
-}
-
-message OutOfOrderAtom {
- optional int32 field2 = 2;
- optional int32 field1 = 1;
-}
-
-enum AnEnum {
- VALUE0 = 0;
- VALUE1 = 1;
-}
-
-message AllTypesAtom {
- repeated android.os.statsd.AttributionNode attribution_chain = 1;
- optional float float_field = 2;
- optional int64 int64_field = 3;
- optional uint64 uint64_field = 4;
- optional int32 int32_field = 5;
- optional fixed64 fixed64_field = 6;
- optional fixed32 fixed32_field = 7;
- optional bool bool_field = 8;
- optional string string_field = 9;
- optional uint32 uint32_field = 10;
- optional AnEnum enum_field = 11;
- optional sfixed32 sfixed32_field = 12;
- optional sfixed64 sfixed64_field = 13;
- optional sint32 sint32_field = 14;
- optional sint64 sint64_field = 15;
-}
-
-message Event {
- oneof pushed {
- OutOfOrderAtom out_of_order_atom = 2;
- IntAtom int_atom = 1;
- AnotherIntAtom another_int_atom = 3;
- AllTypesAtom all_types_atom = 4;
- }
-}
-
-message BadTypesAtom {
- optional IntAtom bad_int_atom = 1;
- optional bytes bad_bytes = 2;
- repeated int32 repeated_field = 3;
- optional double double_field = 4;
-}
-
-message BadTypesEvent {
- oneof pushed {
- BadTypesAtom bad_types_atom = 1;
- }
-}
-
-message BadSkippedFieldSingleAtom {
- optional int32 field2 = 2;
-}
-
-message BadSkippedFieldSingle {
- oneof pushed {
- BadSkippedFieldSingleAtom bad = 1;
- }
-}
-
-message BadSkippedFieldMultipleAtom {
- optional int32 field1 = 1;
- optional int32 field3 = 3;
- optional int32 field5 = 5;
-}
-
-message BadSkippedFieldMultiple {
- oneof pushed {
- BadSkippedFieldMultipleAtom bad = 1;
- }
-}
-
-message BadAttributionNodePositionAtom {
- optional int32 field1 = 1;
- repeated android.os.statsd.AttributionNode attribution = 2;
-}
-
-message BadAttributionNodePosition {
- oneof pushed { BadAttributionNodePositionAtom bad = 1; }
-}
-
-message GoodEventWithBinaryFieldAtom {
- oneof pushed { GoodBinaryFieldAtom field1 = 1; }
-}
-
-message ComplexField {
- optional string str = 1;
-}
-
-message GoodBinaryFieldAtom {
- optional int32 field1 = 1;
- optional ComplexField bf = 2 [(android.os.statsd.log_mode) = MODE_BYTES];
-}
-
-message BadEventWithBinaryFieldAtom {
- oneof pushed { BadBinaryFieldAtom field1 = 1; }
-}
-
-message BadBinaryFieldAtom {
- optional int32 field1 = 1;
- optional ComplexField bf = 2;
-}
-
-message BadStateAtoms {
- oneof pushed {
- BadStateAtom1 bad1 = 1;
- BadStateAtom2 bad2 = 2;
- BadStateAtom3 bad3 = 3;
- }
-}
-
-message GoodStateAtoms {
- oneof pushed {
- GoodStateAtom1 good1 = 1;
- GoodStateAtom2 good2 = 2;
- }
-}
-
-// The atom has only primary field but no exclusive state field.
-message BadStateAtom1 {
- optional int32 uid = 1 [(android.os.statsd.state_field_option).primary_field = true];
-}
-
-// Only primative types can be annotated.
-message BadStateAtom2 {
- repeated android.os.statsd.AttributionNode attribution = 1
- [(android.os.statsd.state_field_option).primary_field = true];
- optional int32 state = 2 [(android.os.statsd.state_field_option).exclusive_state = true];
-}
-
-// Having 2 exclusive state field in the atom means the atom is badly designed.
-// E.g., putting bluetooth state and wifi state in the same atom.
-message BadStateAtom3 {
- optional int32 uid = 1 [(android.os.statsd.state_field_option).primary_field = true];
- optional int32 state = 2 [(android.os.statsd.state_field_option).exclusive_state = true];
- optional int32 state2 = 3 [(android.os.statsd.state_field_option).exclusive_state = true];
-}
-
-message GoodStateAtom1 {
- optional int32 uid = 1 [(android.os.statsd.state_field_option).primary_field = true];
- optional int32 state = 2 [(android.os.statsd.state_field_option).exclusive_state = true];
-}
-
-// Atoms can have exclusive state field, but no primary field. That means
-// the state is globally exclusive (e.g., DisplayState).
-message GoodStateAtom2 {
- optional int32 uid = 1;
- optional int32 state = 2 [(android.os.statsd.state_field_option).exclusive_state = true];
-}
-
-// We can have more than one primary fields. That means their combination is a
-// primary key.
-message GoodStateAtom3 {
- optional int32 uid = 1 [(android.os.statsd.state_field_option).primary_field = true];
- optional int32 tid = 2 [(android.os.statsd.state_field_option).primary_field = true];
- optional int32 state = 3 [(android.os.statsd.state_field_option).exclusive_state = true];
-}
-
-message ModuleOneAtom {
- optional int32 field = 1 [(android.os.statsd.is_uid) = true];
-}
-
-message ModuleTwoAtom {
- optional int32 field = 1;
-}
-
-message ModuleOneAndTwoAtom {
- optional int32 field = 1 [(android.os.statsd.state_field_option).exclusive_state = true];
-}
-
-message NoModuleAtom {
- optional string field = 1;
-}
-
-message ModuleAtoms {
- oneof pushed {
- ModuleOneAtom module_one_atom = 1 [(android.os.statsd.module) = "module1"];
- ModuleTwoAtom module_two_atom = 2 [(android.os.statsd.module) = "module2"];
- ModuleOneAndTwoAtom module_one_and_two_atom = 3 [
- (android.os.statsd.module) = "module1", (android.os.statsd.module) = "module2"
- ];
- NoModuleAtom no_module_atom = 4;
- }
-}
-
-message NotAPushNorPullAtom {
- oneof event {
- IntAtom int_atom = 1;
- }
-}
-
-message AtomNotInAOneof {
- optional IntAtom int_atom = 1;
-}
-
-message PushedAndPulledAtoms {
- oneof pushed {
- IntAtom int_atom_1 = 1;
- }
-
- oneof pulled {
- OutOfOrderAtom out_of_order_atom = 11;
- AnotherIntAtom another_int_atom = 10;
- }
-}
diff --git a/tools/stats_log_api_gen/test_collation.cpp b/tools/stats_log_api_gen/test_collation.cpp
deleted file mode 100644
index 6f78921..0000000
--- a/tools/stats_log_api_gen/test_collation.cpp
+++ /dev/null
@@ -1,432 +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.
- */
-
-#include <gtest/gtest.h>
-#include <stdio.h>
-
-#include "Collation.h"
-#include "frameworks/base/tools/stats_log_api_gen/test.pb.h"
-
-namespace android {
-namespace stats_log_api_gen {
-
-using std::map;
-using std::vector;
-
-/**
- * Return whether the map contains a vector of the elements provided.
- */
-static bool map_contains_vector(const SignatureInfoMap& s, int count, ...) {
- va_list args;
- vector<java_type_t> v(count);
-
- va_start(args, count);
- for (int i = 0; i < count; i++) {
- v[i] = static_cast<java_type_t>(va_arg(args, int));
- }
- va_end(args);
-
- return s.find(v) != s.end();
-}
-
-/**
- * Expect that the provided map contains the elements provided.
- */
-#define EXPECT_MAP_CONTAINS_SIGNATURE(s, ...) \
- do { \
- int count = sizeof((int[]){__VA_ARGS__}) / sizeof(int); \
- EXPECT_TRUE(map_contains_vector(s, count, __VA_ARGS__)); \
- } while (0)
-
-/** Expects that the provided atom has no enum values for any field. */
-#define EXPECT_NO_ENUM_FIELD(atom) \
- do { \
- for (vector<AtomField>::const_iterator field = atom->fields.begin(); \
- field != atom->fields.end(); field++) { \
- EXPECT_TRUE(field->enumValues.empty()); \
- } \
- } while (0)
-
-/** Expects that exactly one specific field has expected enum values. */
-#define EXPECT_HAS_ENUM_FIELD(atom, field_name, values) \
- do { \
- for (vector<AtomField>::const_iterator field = atom->fields.begin(); \
- field != atom->fields.end(); field++) { \
- if (field->name == field_name) { \
- EXPECT_EQ(field->enumValues, values); \
- } else { \
- EXPECT_TRUE(field->enumValues.empty()); \
- } \
- } \
- } while (0)
-
-/**
- * Test a correct collation, with all the types.
- */
-TEST(CollationTest, CollateStats) {
- Atoms atoms;
- int errorCount = collate_atoms(Event::descriptor(), DEFAULT_MODULE_NAME, &atoms);
-
- EXPECT_EQ(0, errorCount);
- EXPECT_EQ(3ul, atoms.signatureInfoMap.size());
-
- // IntAtom, AnotherIntAtom
- EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_INT);
-
- // OutOfOrderAtom
- EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_INT, JAVA_TYPE_INT);
-
- // AllTypesAtom
- EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap,
- JAVA_TYPE_ATTRIBUTION_CHAIN, // AttributionChain
- JAVA_TYPE_FLOAT, // float
- JAVA_TYPE_LONG, // int64
- JAVA_TYPE_LONG, // uint64
- JAVA_TYPE_INT, // int32
- JAVA_TYPE_LONG, // fixed64
- JAVA_TYPE_INT, // fixed32
- JAVA_TYPE_BOOLEAN, // bool
- JAVA_TYPE_STRING, // string
- JAVA_TYPE_INT, // uint32
- JAVA_TYPE_INT, // AnEnum
- JAVA_TYPE_INT, // sfixed32
- JAVA_TYPE_LONG, // sfixed64
- JAVA_TYPE_INT, // sint32
- JAVA_TYPE_LONG // sint64
- );
-
- EXPECT_EQ(4ul, atoms.decls.size());
-
- AtomDeclSet::const_iterator atomIt = atoms.decls.begin();
- EXPECT_EQ(1, (*atomIt)->code);
- EXPECT_EQ("int_atom", (*atomIt)->name);
- EXPECT_EQ("IntAtom", (*atomIt)->message);
- EXPECT_NO_ENUM_FIELD((*atomIt));
- atomIt++;
-
- EXPECT_EQ(2, (*atomIt)->code);
- EXPECT_EQ("out_of_order_atom", (*atomIt)->name);
- EXPECT_EQ("OutOfOrderAtom", (*atomIt)->message);
- EXPECT_NO_ENUM_FIELD((*atomIt));
- atomIt++;
-
- EXPECT_EQ(3, (*atomIt)->code);
- EXPECT_EQ("another_int_atom", (*atomIt)->name);
- EXPECT_EQ("AnotherIntAtom", (*atomIt)->message);
- EXPECT_NO_ENUM_FIELD((*atomIt));
- atomIt++;
-
- EXPECT_EQ(4, (*atomIt)->code);
- EXPECT_EQ("all_types_atom", (*atomIt)->name);
- EXPECT_EQ("AllTypesAtom", (*atomIt)->message);
- map<int, string> enumValues;
- enumValues[0] = "VALUE0";
- enumValues[1] = "VALUE1";
- EXPECT_HAS_ENUM_FIELD((*atomIt), "enum_field", enumValues);
- atomIt++;
-
- EXPECT_EQ(atoms.decls.end(), atomIt);
-}
-
-/**
- * Test that event class that contains stuff other than the atoms is rejected.
- */
-TEST(CollationTest, NonMessageTypeFails) {
- Atoms atoms;
- int errorCount = collate_atoms(IntAtom::descriptor(), DEFAULT_MODULE_NAME, &atoms);
-
- EXPECT_EQ(1, errorCount);
-}
-
-/**
- * Test that atoms that have non-primitive types or repeated fields are
- * rejected.
- */
-TEST(CollationTest, FailOnBadTypes) {
- Atoms atoms;
- int errorCount = collate_atoms(BadTypesEvent::descriptor(), DEFAULT_MODULE_NAME, &atoms);
-
- EXPECT_EQ(4, errorCount);
-}
-
-/**
- * Test that atoms that skip field numbers (in the first position) are rejected.
- */
-TEST(CollationTest, FailOnSkippedFieldsSingle) {
- Atoms atoms;
- int errorCount =
- collate_atoms(BadSkippedFieldSingle::descriptor(), DEFAULT_MODULE_NAME, &atoms);
-
- EXPECT_EQ(1, errorCount);
-}
-
-/**
- * Test that atoms that skip field numbers (not in the first position, and
- * multiple times) are rejected.
- */
-TEST(CollationTest, FailOnSkippedFieldsMultiple) {
- Atoms atoms;
- int errorCount =
- collate_atoms(BadSkippedFieldMultiple::descriptor(), DEFAULT_MODULE_NAME, &atoms);
-
- EXPECT_EQ(2, errorCount);
-}
-
-/**
- * Test that atoms that have an attribution chain not in the first position are
- * rejected.
- */
-TEST(CollationTest, FailBadAttributionNodePosition) {
- Atoms atoms;
- int errorCount =
- collate_atoms(BadAttributionNodePosition::descriptor(), DEFAULT_MODULE_NAME, &atoms);
-
- EXPECT_EQ(1, errorCount);
-}
-
-TEST(CollationTest, FailOnBadStateAtomOptions) {
- Atoms atoms;
- int errorCount = collate_atoms(BadStateAtoms::descriptor(), DEFAULT_MODULE_NAME, &atoms);
-
- EXPECT_EQ(3, errorCount);
-}
-
-TEST(CollationTest, PassOnGoodStateAtomOptions) {
- Atoms atoms;
- int errorCount = collate_atoms(GoodStateAtoms::descriptor(), DEFAULT_MODULE_NAME, &atoms);
- EXPECT_EQ(0, errorCount);
-}
-
-TEST(CollationTest, PassOnGoodBinaryFieldAtom) {
- Atoms atoms;
- int errorCount =
- collate_atoms(GoodEventWithBinaryFieldAtom::descriptor(), DEFAULT_MODULE_NAME, &atoms);
- EXPECT_EQ(0, errorCount);
-}
-
-TEST(CollationTest, FailOnBadBinaryFieldAtom) {
- Atoms atoms;
- int errorCount =
- collate_atoms(BadEventWithBinaryFieldAtom::descriptor(), DEFAULT_MODULE_NAME, &atoms);
- EXPECT_GT(errorCount, 0);
-}
-
-TEST(CollationTest, PassOnLogFromModuleAtom) {
- Atoms atoms;
- int errorCount = collate_atoms(ModuleAtoms::descriptor(), DEFAULT_MODULE_NAME, &atoms);
- EXPECT_EQ(errorCount, 0);
- EXPECT_EQ(atoms.decls.size(), 4ul);
-}
-
-TEST(CollationTest, RecognizeModuleAtom) {
- Atoms atoms;
- int errorCount = collate_atoms(ModuleAtoms::descriptor(), DEFAULT_MODULE_NAME, &atoms);
- EXPECT_EQ(errorCount, 0);
- EXPECT_EQ(atoms.decls.size(), 4ul);
- EXPECT_EQ(atoms.signatureInfoMap.size(), 2u);
- EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_INT);
- EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_STRING);
-
- SignatureInfoMap::const_iterator signatureInfoMapIt;
- const vector<java_type_t>* signature;
- const FieldNumberToAtomDeclSet* fieldNumberToAtomDeclSet;
- FieldNumberToAtomDeclSet::const_iterator fieldNumberToAtomDeclSetIt;
- const AtomDeclSet* atomDeclSet;
- AtomDeclSet::const_iterator atomDeclSetIt;
- AtomDecl* atomDecl;
- FieldNumberToAnnotations* fieldNumberToAnnotations;
- FieldNumberToAnnotations::const_iterator fieldNumberToAnnotationsIt;
- const AnnotationSet* annotationSet;
- AnnotationSet::const_iterator annotationSetIt;
- Annotation* annotation;
-
- signatureInfoMapIt = atoms.signatureInfoMap.begin();
- signature = &(signatureInfoMapIt->first);
- fieldNumberToAtomDeclSet = &signatureInfoMapIt->second;
- EXPECT_EQ(1ul, signature->size());
- EXPECT_EQ(JAVA_TYPE_INT, signature->at(0));
- EXPECT_EQ(1ul, fieldNumberToAtomDeclSet->size());
- fieldNumberToAtomDeclSetIt = fieldNumberToAtomDeclSet->begin();
- EXPECT_EQ(1, fieldNumberToAtomDeclSetIt->first);
- atomDeclSet = &fieldNumberToAtomDeclSetIt->second;
- EXPECT_EQ(2ul, atomDeclSet->size());
- atomDeclSetIt = atomDeclSet->begin();
- atomDecl = atomDeclSetIt->get();
- EXPECT_EQ(1, atomDecl->code);
- fieldNumberToAnnotations = &atomDecl->fieldNumberToAnnotations;
- fieldNumberToAnnotationsIt = fieldNumberToAnnotations->find(1);
- EXPECT_NE(fieldNumberToAnnotations->end(), fieldNumberToAnnotationsIt);
- annotationSet = &fieldNumberToAnnotationsIt->second;
- EXPECT_EQ(1ul, annotationSet->size());
- annotationSetIt = annotationSet->begin();
- annotation = annotationSetIt->get();
- EXPECT_EQ(ANNOTATION_ID_IS_UID, annotation->annotationId);
- EXPECT_EQ(1, annotation->atomId);
- EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type);
- EXPECT_TRUE(annotation->value.boolValue);
-
- atomDeclSetIt++;
- atomDecl = atomDeclSetIt->get();
- EXPECT_EQ(3, atomDecl->code);
- fieldNumberToAnnotations = &atomDecl->fieldNumberToAnnotations;
- fieldNumberToAnnotationsIt = fieldNumberToAnnotations->find(1);
- EXPECT_NE(fieldNumberToAnnotations->end(), fieldNumberToAnnotationsIt);
- annotationSet = &fieldNumberToAnnotationsIt->second;
- EXPECT_EQ(1ul, annotationSet->size());
- annotationSetIt = annotationSet->begin();
- annotation = annotationSetIt->get();
- EXPECT_EQ(ANNOTATION_ID_EXCLUSIVE_STATE, annotation->annotationId);
- EXPECT_EQ(3, annotation->atomId);
- EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type);
- EXPECT_TRUE(annotation->value.boolValue);
-
- signatureInfoMapIt++;
- signature = &signatureInfoMapIt->first;
- fieldNumberToAtomDeclSet = &signatureInfoMapIt->second;
- EXPECT_EQ(1ul, signature->size());
- EXPECT_EQ(JAVA_TYPE_STRING, signature->at(0));
- EXPECT_EQ(0ul, fieldNumberToAtomDeclSet->size());
-}
-
-TEST(CollationTest, RecognizeModule1Atom) {
- Atoms atoms;
- const string moduleName = "module1";
- int errorCount = collate_atoms(ModuleAtoms::descriptor(), moduleName, &atoms);
- EXPECT_EQ(errorCount, 0);
- EXPECT_EQ(atoms.decls.size(), 2ul);
- EXPECT_EQ(atoms.signatureInfoMap.size(), 1u);
- EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_INT);
-
- SignatureInfoMap::const_iterator signatureInfoMapIt;
- const vector<java_type_t>* signature;
- const FieldNumberToAtomDeclSet* fieldNumberToAtomDeclSet;
- FieldNumberToAtomDeclSet::const_iterator fieldNumberToAtomDeclSetIt;
- const AtomDeclSet* atomDeclSet;
- AtomDeclSet::const_iterator atomDeclSetIt;
- AtomDecl* atomDecl;
- FieldNumberToAnnotations* fieldNumberToAnnotations;
- FieldNumberToAnnotations::const_iterator fieldNumberToAnnotationsIt;
- const AnnotationSet* annotationSet;
- AnnotationSet::const_iterator annotationSetIt;
- Annotation* annotation;
-
- signatureInfoMapIt = atoms.signatureInfoMap.begin();
- signature = &(signatureInfoMapIt->first);
- fieldNumberToAtomDeclSet = &signatureInfoMapIt->second;
- EXPECT_EQ(1ul, signature->size());
- EXPECT_EQ(JAVA_TYPE_INT, signature->at(0));
- EXPECT_EQ(1ul, fieldNumberToAtomDeclSet->size());
- fieldNumberToAtomDeclSetIt = fieldNumberToAtomDeclSet->begin();
- EXPECT_EQ(1, fieldNumberToAtomDeclSetIt->first);
- atomDeclSet = &fieldNumberToAtomDeclSetIt->second;
- EXPECT_EQ(2ul, atomDeclSet->size());
- atomDeclSetIt = atomDeclSet->begin();
- atomDecl = atomDeclSetIt->get();
- EXPECT_EQ(1, atomDecl->code);
- fieldNumberToAnnotations = &atomDecl->fieldNumberToAnnotations;
- fieldNumberToAnnotationsIt = fieldNumberToAnnotations->find(1);
- EXPECT_NE(fieldNumberToAnnotations->end(), fieldNumberToAnnotationsIt);
- annotationSet = &fieldNumberToAnnotationsIt->second;
- EXPECT_EQ(1ul, annotationSet->size());
- annotationSetIt = annotationSet->begin();
- annotation = annotationSetIt->get();
- EXPECT_EQ(ANNOTATION_ID_IS_UID, annotation->annotationId);
- EXPECT_EQ(1, annotation->atomId);
- EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type);
- EXPECT_TRUE(annotation->value.boolValue);
-
- atomDeclSetIt++;
- atomDecl = atomDeclSetIt->get();
- EXPECT_EQ(3, atomDecl->code);
- fieldNumberToAnnotations = &atomDecl->fieldNumberToAnnotations;
- fieldNumberToAnnotationsIt = fieldNumberToAnnotations->find(1);
- EXPECT_NE(fieldNumberToAnnotations->end(), fieldNumberToAnnotationsIt);
- annotationSet = &fieldNumberToAnnotationsIt->second;
- EXPECT_EQ(1ul, annotationSet->size());
- annotationSetIt = annotationSet->begin();
- annotation = annotationSetIt->get();
- EXPECT_EQ(ANNOTATION_ID_EXCLUSIVE_STATE, annotation->annotationId);
- EXPECT_EQ(3, annotation->atomId);
- EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type);
- EXPECT_TRUE(annotation->value.boolValue);
-}
-
-/**
- * Test that an atom is not a pushed nor pulled atom.
- */
-TEST(CollationTest, InvalidAtomType) {
- Atoms atoms;
- int errorCount = collate_atoms(NotAPushNorPullAtom::descriptor(), DEFAULT_MODULE_NAME, &atoms);
-
- EXPECT_EQ(1, errorCount);
-}
-
-/**
- * Test that an atom was not declared in a `oneof` field.
- */
-TEST(CollationTest, AtomNotDeclaredInAOneof) {
- Atoms atoms;
- int errorCount = collate_atoms(AtomNotInAOneof::descriptor(), DEFAULT_MODULE_NAME, &atoms);
-
- EXPECT_EQ(1, errorCount);
-}
-
-/**
- * Test a correct collation with pushed and pulled atoms.
- */
-TEST(CollationTest, CollatePushedAndPulledAtoms) {
- Atoms atoms;
- int errorCount = collate_atoms(PushedAndPulledAtoms::descriptor(), DEFAULT_MODULE_NAME, &atoms);
-
- EXPECT_EQ(0, errorCount);
- EXPECT_EQ(1ul, atoms.signatureInfoMap.size());
- EXPECT_EQ(2ul, atoms.pulledAtomsSignatureInfoMap.size());
-
- // IntAtom
- EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_INT);
-
- // AnotherIntAtom
- EXPECT_MAP_CONTAINS_SIGNATURE(atoms.pulledAtomsSignatureInfoMap, JAVA_TYPE_INT);
-
- // OutOfOrderAtom
- EXPECT_MAP_CONTAINS_SIGNATURE(atoms.pulledAtomsSignatureInfoMap, JAVA_TYPE_INT, JAVA_TYPE_INT);
-
- EXPECT_EQ(3ul, atoms.decls.size());
-
- AtomDeclSet::const_iterator atomIt = atoms.decls.begin();
- EXPECT_EQ(1, (*atomIt)->code);
- EXPECT_EQ("int_atom_1", (*atomIt)->name);
- EXPECT_EQ("IntAtom", (*atomIt)->message);
- EXPECT_NO_ENUM_FIELD((*atomIt));
- atomIt++;
-
- EXPECT_EQ(10, (*atomIt)->code);
- EXPECT_EQ("another_int_atom", (*atomIt)->name);
- EXPECT_EQ("AnotherIntAtom", (*atomIt)->message);
- EXPECT_NO_ENUM_FIELD((*atomIt));
- atomIt++;
-
- EXPECT_EQ(11, (*atomIt)->code);
- EXPECT_EQ("out_of_order_atom", (*atomIt)->name);
- EXPECT_EQ("OutOfOrderAtom", (*atomIt)->message);
- EXPECT_NO_ENUM_FIELD((*atomIt));
- atomIt++;
-
- EXPECT_EQ(atoms.decls.end(), atomIt);
-}
-
-} // namespace stats_log_api_gen
-} // namespace android
diff --git a/tools/stats_log_api_gen/utils.cpp b/tools/stats_log_api_gen/utils.cpp
deleted file mode 100644
index 1eaf42a..0000000
--- a/tools/stats_log_api_gen/utils.cpp
+++ /dev/null
@@ -1,467 +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.
- */
-
-#include "utils.h"
-
-namespace android {
-namespace stats_log_api_gen {
-
-/**
- * Inlining this method because "android-base/strings.h" is not available on
- * google3.
- */
-static vector<string> Split(const string& s, const string& delimiters) {
- GOOGLE_CHECK_NE(delimiters.size(), 0U);
-
- vector<string> result;
-
- size_t base = 0;
- size_t found;
- while (true) {
- found = s.find_first_of(delimiters, base);
- result.push_back(s.substr(base, found - base));
- if (found == s.npos) break;
- base = found + 1;
- }
-
- return result;
-}
-
-static void build_non_chained_decl_map(const Atoms& atoms,
- std::map<int, AtomDeclSet::const_iterator>* decl_map) {
- for (AtomDeclSet::const_iterator atomIt = atoms.non_chained_decls.begin();
- atomIt != atoms.non_chained_decls.end(); atomIt++) {
- decl_map->insert(std::make_pair((*atomIt)->code, atomIt));
- }
-}
-
-const map<AnnotationId, string>& get_annotation_id_constants() {
- static const map<AnnotationId, string>* ANNOTATION_ID_CONSTANTS =
- new map<AnnotationId, string>{
- {ANNOTATION_ID_IS_UID, "ANNOTATION_ID_IS_UID"},
- {ANNOTATION_ID_TRUNCATE_TIMESTAMP, "ANNOTATION_ID_TRUNCATE_TIMESTAMP"},
- {ANNOTATION_ID_PRIMARY_FIELD, "ANNOTATION_ID_PRIMARY_FIELD"},
- {ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, "ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID"},
- {ANNOTATION_ID_EXCLUSIVE_STATE, "ANNOTATION_ID_EXCLUSIVE_STATE"},
- {ANNOTATION_ID_TRIGGER_STATE_RESET, "ANNOTATION_ID_TRIGGER_STATE_RESET"},
- {ANNOTATION_ID_STATE_NESTED, "ANNOTATION_ID_STATE_NESTED"}};
-
- return *ANNOTATION_ID_CONSTANTS;
-}
-
-/**
- * Turn lower and camel case into upper case with underscores.
- */
-string make_constant_name(const string& str) {
- string result;
- const int N = str.size();
- bool underscore_next = false;
- for (int i = 0; i < N; i++) {
- char c = str[i];
- if (c >= 'A' && c <= 'Z') {
- if (underscore_next) {
- result += '_';
- underscore_next = false;
- }
- } else if (c >= 'a' && c <= 'z') {
- c = 'A' + c - 'a';
- underscore_next = true;
- } else if (c == '_') {
- underscore_next = false;
- }
- result += c;
- }
- return result;
-}
-
-const char* cpp_type_name(java_type_t type) {
- switch (type) {
- case JAVA_TYPE_BOOLEAN:
- return "bool";
- case JAVA_TYPE_INT:
- case JAVA_TYPE_ENUM:
- return "int32_t";
- case JAVA_TYPE_LONG:
- return "int64_t";
- case JAVA_TYPE_FLOAT:
- return "float";
- case JAVA_TYPE_DOUBLE:
- return "double";
- case JAVA_TYPE_STRING:
- return "char const*";
- case JAVA_TYPE_BYTE_ARRAY:
- return "const BytesField&";
- default:
- return "UNKNOWN";
- }
-}
-
-const char* java_type_name(java_type_t type) {
- switch (type) {
- case JAVA_TYPE_BOOLEAN:
- return "boolean";
- case JAVA_TYPE_INT:
- case JAVA_TYPE_ENUM:
- return "int";
- case JAVA_TYPE_LONG:
- return "long";
- case JAVA_TYPE_FLOAT:
- return "float";
- case JAVA_TYPE_DOUBLE:
- return "double";
- case JAVA_TYPE_STRING:
- return "java.lang.String";
- case JAVA_TYPE_BYTE_ARRAY:
- return "byte[]";
- default:
- return "UNKNOWN";
- }
-}
-
-// Native
-// Writes namespaces for the cpp and header files, returning the number of
-// namespaces written.
-void write_namespace(FILE* out, const string& cppNamespaces) {
- vector<string> cppNamespaceVec = Split(cppNamespaces, ",");
- for (const string& cppNamespace : cppNamespaceVec) {
- fprintf(out, "namespace %s {\n", cppNamespace.c_str());
- }
-}
-
-// Writes namespace closing brackets for cpp and header files.
-void write_closing_namespace(FILE* out, const string& cppNamespaces) {
- vector<string> cppNamespaceVec = Split(cppNamespaces, ",");
- for (auto it = cppNamespaceVec.rbegin(); it != cppNamespaceVec.rend(); ++it) {
- fprintf(out, "} // namespace %s\n", it->c_str());
- }
-}
-
-static void write_cpp_usage(FILE* out, const string& method_name, const string& atom_code_name,
- const shared_ptr<AtomDecl> atom, const AtomDecl& attributionDecl) {
- fprintf(out, " * Usage: %s(StatsLog.%s", method_name.c_str(), atom_code_name.c_str());
-
- for (vector<AtomField>::const_iterator field = atom->fields.begin();
- field != atom->fields.end(); field++) {
- if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- for (const auto& chainField : attributionDecl.fields) {
- if (chainField.javaType == JAVA_TYPE_STRING) {
- fprintf(out, ", const std::vector<%s>& %s", cpp_type_name(chainField.javaType),
- chainField.name.c_str());
- } else {
- fprintf(out, ", const %s* %s, size_t %s_length",
- cpp_type_name(chainField.javaType), chainField.name.c_str(),
- chainField.name.c_str());
- }
- }
- } else if (field->javaType == JAVA_TYPE_KEY_VALUE_PAIR) {
- fprintf(out,
- ", const std::map<int, int32_t>& %s_int"
- ", const std::map<int, int64_t>& %s_long"
- ", const std::map<int, char const*>& %s_str"
- ", const std::map<int, float>& %s_float",
- field->name.c_str(), field->name.c_str(), field->name.c_str(),
- field->name.c_str());
- } else {
- fprintf(out, ", %s %s", cpp_type_name(field->javaType), field->name.c_str());
- }
- }
- fprintf(out, ");\n");
-}
-
-void write_native_atom_constants(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl) {
- fprintf(out, "/**\n");
- fprintf(out, " * Constants for atom codes.\n");
- fprintf(out, " */\n");
- fprintf(out, "enum {\n");
-
- std::map<int, AtomDeclSet::const_iterator> atom_code_to_non_chained_decl_map;
- build_non_chained_decl_map(atoms, &atom_code_to_non_chained_decl_map);
-
- size_t i = 0;
- // Print atom constants
- for (AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); atomIt != atoms.decls.end();
- atomIt++) {
- string constant = make_constant_name((*atomIt)->name);
- fprintf(out, "\n");
- fprintf(out, " /**\n");
- fprintf(out, " * %s %s\n", (*atomIt)->message.c_str(), (*atomIt)->name.c_str());
- write_cpp_usage(out, "stats_write", constant, *atomIt, attributionDecl);
-
- auto non_chained_decl = atom_code_to_non_chained_decl_map.find((*atomIt)->code);
- if (non_chained_decl != atom_code_to_non_chained_decl_map.end()) {
- write_cpp_usage(out, "stats_write_non_chained", constant, *non_chained_decl->second,
- attributionDecl);
- }
- fprintf(out, " */\n");
- char const* const comma = (i == atoms.decls.size() - 1) ? "" : ",";
- fprintf(out, " %s = %d%s\n", constant.c_str(), (*atomIt)->code, comma);
- i++;
- }
- fprintf(out, "\n");
- fprintf(out, "};\n");
- fprintf(out, "\n");
-}
-
-void write_native_method_signature(FILE* out, const string& signaturePrefix,
- const vector<java_type_t>& signature,
- const AtomDecl& attributionDecl, const string& closer) {
- fprintf(out, "%sint32_t code", signaturePrefix.c_str());
- int argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end();
- arg++) {
- if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- for (const auto& chainField : attributionDecl.fields) {
- if (chainField.javaType == JAVA_TYPE_STRING) {
- fprintf(out, ", const std::vector<%s>& %s", cpp_type_name(chainField.javaType),
- chainField.name.c_str());
- } else {
- fprintf(out, ", const %s* %s, size_t %s_length",
- cpp_type_name(chainField.javaType), chainField.name.c_str(),
- chainField.name.c_str());
- }
- }
- } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
- fprintf(out,
- ", const std::map<int, int32_t>& arg%d_1, "
- "const std::map<int, int64_t>& arg%d_2, "
- "const std::map<int, char const*>& arg%d_3, "
- "const std::map<int, float>& arg%d_4",
- argIndex, argIndex, argIndex, argIndex);
- } else {
- fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex);
- }
- argIndex++;
- }
- fprintf(out, ")%s\n", closer.c_str());
-}
-
-void write_native_method_call(FILE* out, const string& methodName,
- const vector<java_type_t>& signature, const AtomDecl& attributionDecl,
- int argIndex) {
- fprintf(out, "%s(code", methodName.c_str());
- for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end();
- arg++) {
- if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- for (const auto& chainField : attributionDecl.fields) {
- if (chainField.javaType == JAVA_TYPE_STRING) {
- fprintf(out, ", %s", chainField.name.c_str());
- } else {
- fprintf(out, ", %s, %s_length", chainField.name.c_str(),
- chainField.name.c_str());
- }
- }
- } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
- fprintf(out, ", arg%d_1, arg%d_2, arg%d_3, arg%d_4", argIndex, argIndex, argIndex,
- argIndex);
- } else {
- fprintf(out, ", arg%d", argIndex);
- }
- argIndex++;
- }
- fprintf(out, ");\n");
-}
-
-// Java
-void write_java_atom_codes(FILE* out, const Atoms& atoms) {
- fprintf(out, " // Constants for atom codes.\n");
-
- std::map<int, AtomDeclSet::const_iterator> atom_code_to_non_chained_decl_map;
- build_non_chained_decl_map(atoms, &atom_code_to_non_chained_decl_map);
-
- // Print constants for the atom codes.
- for (AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); atomIt != atoms.decls.end();
- atomIt++) {
- string constant = make_constant_name((*atomIt)->name);
- fprintf(out, "\n");
- fprintf(out, " /**\n");
- fprintf(out, " * %s %s<br>\n", (*atomIt)->message.c_str(), (*atomIt)->name.c_str());
- write_java_usage(out, "write", constant, **atomIt);
- auto non_chained_decl = atom_code_to_non_chained_decl_map.find((*atomIt)->code);
- if (non_chained_decl != atom_code_to_non_chained_decl_map.end()) {
- write_java_usage(out, "write_non_chained", constant, **(non_chained_decl->second));
- }
- fprintf(out, " */\n");
- fprintf(out, " public static final int %s = %d;\n", constant.c_str(), (*atomIt)->code);
- }
- fprintf(out, "\n");
-}
-
-void write_java_enum_values(FILE* out, const Atoms& atoms) {
- fprintf(out, " // Constants for enum values.\n\n");
- for (AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); atomIt != atoms.decls.end();
- atomIt++) {
- for (vector<AtomField>::const_iterator field = (*atomIt)->fields.begin();
- field != (*atomIt)->fields.end(); field++) {
- if (field->javaType == JAVA_TYPE_ENUM) {
- fprintf(out, " // Values for %s.%s\n", (*atomIt)->message.c_str(),
- field->name.c_str());
- for (map<int, string>::const_iterator value = field->enumValues.begin();
- value != field->enumValues.end(); value++) {
- fprintf(out, " public static final int %s__%s__%s = %d;\n",
- make_constant_name((*atomIt)->message).c_str(),
- make_constant_name(field->name).c_str(),
- make_constant_name(value->second).c_str(), value->first);
- }
- fprintf(out, "\n");
- }
- }
- }
-}
-
-void write_java_usage(FILE* out, const string& method_name, const string& atom_code_name,
- const AtomDecl& atom) {
- fprintf(out, " * Usage: StatsLog.%s(StatsLog.%s", method_name.c_str(),
- atom_code_name.c_str());
- for (vector<AtomField>::const_iterator field = atom.fields.begin(); field != atom.fields.end();
- field++) {
- if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- fprintf(out, ", android.os.WorkSource workSource");
- } else if (field->javaType == JAVA_TYPE_KEY_VALUE_PAIR) {
- fprintf(out, ", android.util.SparseArray<Object> value_map");
- } else if (field->javaType == JAVA_TYPE_BYTE_ARRAY) {
- fprintf(out, ", byte[] %s", field->name.c_str());
- } else {
- fprintf(out, ", %s %s", java_type_name(field->javaType), field->name.c_str());
- }
- }
- fprintf(out, ");<br>\n");
-}
-
-int write_java_non_chained_methods(FILE* out, const SignatureInfoMap& signatureInfoMap) {
- for (auto signatureInfoMapIt = signatureInfoMap.begin();
- signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) {
- // Print method signature.
- fprintf(out, " public static void write_non_chained(int code");
- vector<java_type_t> signature = signatureInfoMapIt->first;
- int argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end();
- arg++) {
- if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- fprintf(stderr, "Non chained signatures should not have attribution chains.\n");
- return 1;
- } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
- fprintf(stderr, "Module logging does not yet support key value pair.\n");
- return 1;
- } else {
- fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex);
- }
- argIndex++;
- }
- fprintf(out, ") {\n");
-
- fprintf(out, " write(code");
- argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end();
- arg++) {
- // First two args are uid and tag of attribution chain.
- if (argIndex == 1) {
- fprintf(out, ", new int[] {arg%d}", argIndex);
- } else if (argIndex == 2) {
- fprintf(out, ", new java.lang.String[] {arg%d}", argIndex);
- } else {
- fprintf(out, ", arg%d", argIndex);
- }
- argIndex++;
- }
- fprintf(out, ");\n");
- fprintf(out, " }\n");
- fprintf(out, "\n");
- }
- return 0;
-}
-
-int write_java_work_source_methods(FILE* out, const SignatureInfoMap& signatureInfoMap) {
- fprintf(out, " // WorkSource methods.\n");
- for (auto signatureInfoMapIt = signatureInfoMap.begin();
- signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) {
- vector<java_type_t> signature = signatureInfoMapIt->first;
- // Determine if there is Attribution in this signature.
- int attributionArg = -1;
- int argIndexMax = 0;
- for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end();
- arg++) {
- argIndexMax++;
- if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- if (attributionArg > -1) {
- fprintf(stderr, "An atom contains multiple AttributionNode fields.\n");
- fprintf(stderr, "This is not supported. Aborting WorkSource method writing.\n");
- fprintf(out,
- "\n// Invalid for WorkSource: more than one attribution "
- "chain.\n");
- return 1;
- }
- attributionArg = argIndexMax;
- }
- }
- if (attributionArg < 0) {
- continue;
- }
-
- fprintf(out, "\n");
- // Method header (signature)
- fprintf(out, " public static void write(int code");
- int argIndex = 1;
- for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end();
- arg++) {
- if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- fprintf(out, ", android.os.WorkSource ws");
- } else {
- fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex);
- }
- argIndex++;
- }
- fprintf(out, ") {\n");
-
- // write_non_chained() component. TODO: Remove when flat uids are no longer
- // needed.
- fprintf(out, " for (int i = 0; i < ws.size(); ++i) {\n");
- fprintf(out, " write_non_chained(code");
- for (int argIndex = 1; argIndex <= argIndexMax; argIndex++) {
- if (argIndex == attributionArg) {
- fprintf(out, ", ws.getUid(i), ws.getPackageName(i)");
- } else {
- fprintf(out, ", arg%d", argIndex);
- }
- }
- fprintf(out, ");\n");
- fprintf(out, " }\n"); // close for-loop
-
- // write() component.
- fprintf(out,
- " java.util.List<android.os.WorkSource.WorkChain> workChains = "
- "ws.getWorkChains();\n");
- fprintf(out, " if (workChains != null) {\n");
- fprintf(out,
- " for (android.os.WorkSource.WorkChain wc : workChains) "
- "{\n");
- fprintf(out, " write(code");
- for (int argIndex = 1; argIndex <= argIndexMax; argIndex++) {
- if (argIndex == attributionArg) {
- fprintf(out, ", wc.getUids(), wc.getTags()");
- } else {
- fprintf(out, ", arg%d", argIndex);
- }
- }
- fprintf(out, ");\n");
- fprintf(out, " }\n"); // close for-loop
- fprintf(out, " }\n"); // close if
- fprintf(out, " }\n"); // close method
- }
- return 0;
-}
-
-} // namespace stats_log_api_gen
-} // namespace android
diff --git a/tools/stats_log_api_gen/utils.h b/tools/stats_log_api_gen/utils.h
deleted file mode 100644
index 13a7e2d..0000000
--- a/tools/stats_log_api_gen/utils.h
+++ /dev/null
@@ -1,77 +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.
- */
-
-#ifndef ANDROID_STATS_LOG_API_GEN_UTILS_H
-#define ANDROID_STATS_LOG_API_GEN_UTILS_H
-
-#include <stdio.h>
-#include <string.h>
-
-#include <map>
-#include <set>
-#include <vector>
-
-#include "Collation.h"
-
-namespace android {
-namespace stats_log_api_gen {
-
-const char DEFAULT_CPP_NAMESPACE[] = "android,util";
-const char DEFAULT_CPP_HEADER_IMPORT[] = "statslog.h";
-
-const int JAVA_MODULE_REQUIRES_FLOAT = 0x01;
-const int JAVA_MODULE_REQUIRES_ATTRIBUTION = 0x02;
-const int JAVA_MODULE_REQUIRES_KEY_VALUE_PAIRS = 0x04;
-
-const map<AnnotationId, string>& get_annotation_id_constants();
-
-string make_constant_name(const string& str);
-
-const char* cpp_type_name(java_type_t type);
-
-const char* java_type_name(java_type_t type);
-
-// Common Native helpers
-void write_namespace(FILE* out, const string& cppNamespaces);
-
-void write_closing_namespace(FILE* out, const string& cppNamespaces);
-
-void write_native_atom_constants(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl);
-
-void write_native_method_signature(FILE* out, const string& signaturePrefix,
- const vector<java_type_t>& signature,
- const AtomDecl& attributionDecl, const string& closer);
-
-void write_native_method_call(FILE* out, const string& methodName,
- const vector<java_type_t>& signature, const AtomDecl& attributionDecl,
- int argIndex = 1);
-
-// Common Java helpers.
-void write_java_atom_codes(FILE* out, const Atoms& atoms);
-
-void write_java_enum_values(FILE* out, const Atoms& atoms);
-
-void write_java_usage(FILE* out, const string& method_name, const string& atom_code_name,
- const AtomDecl& atom);
-
-int write_java_non_chained_methods(FILE* out, const SignatureInfoMap& signatureInfoMap);
-
-int write_java_work_source_methods(FILE* out, const SignatureInfoMap& signatureInfoMap);
-
-} // namespace stats_log_api_gen
-} // namespace android
-
-#endif // ANDROID_STATS_LOG_API_GEN_UTILS_H
diff --git a/wifi/Android.bp b/wifi/Android.bp
index 7a9ca60..c05f52c 100644
--- a/wifi/Android.bp
+++ b/wifi/Android.bp
@@ -43,6 +43,7 @@
srcs: [
":framework-wifi-updatable-java-sources",
":framework-wifi-updatable-exported-aidl-sources",
+ ":module-utils-os-aidls",
],
}
@@ -85,13 +86,14 @@
"framework-wifi-util-lib",
"android.hardware.wifi-V1.0-java-constants",
"modules-utils-build",
+ "modules-utils-os",
],
libs: [
"unsupportedappusage", // for android.compat.annotation.UnsupportedAppUsage
],
srcs: [
":framework-wifi-updatable-sources",
- ":framework-wifi-util-lib-aidls",
+ ":module-utils-os-aidls",
],
}
diff --git a/wifi/api/system-current.txt b/wifi/api/system-current.txt
index e15d0f1..257f9d5 100644
--- a/wifi/api/system-current.txt
+++ b/wifi/api/system-current.txt
@@ -398,6 +398,8 @@
method @Deprecated public boolean hasEverConnected();
field @Deprecated public static final int DISABLED_ASSOCIATION_REJECTION = 1; // 0x1
field @Deprecated public static final int DISABLED_AUTHENTICATION_FAILURE = 2; // 0x2
+ field @Deprecated public static final int DISABLED_AUTHENTICATION_FAILURE_CARRIER_SPECIFIC = 10; // 0xa
+ field @Deprecated public static final int DISABLED_AUTHENTICATION_FAILURE_GENERIC = 2; // 0x2
field @Deprecated public static final int DISABLED_AUTHENTICATION_NO_CREDENTIALS = 5; // 0x5
field @Deprecated public static final int DISABLED_AUTHENTICATION_NO_SUBSCRIPTION = 9; // 0x9
field @Deprecated public static final int DISABLED_BY_WIFI_MANAGER = 7; // 0x7
diff --git a/wifi/jarjar-rules.txt b/wifi/jarjar-rules.txt
index dc96df6..2331c2f 100644
--- a/wifi/jarjar-rules.txt
+++ b/wifi/jarjar-rules.txt
@@ -21,6 +21,7 @@
rule android.net.ResolverParamsParcel* com.android.wifi.x.@0
rule android.net.RouteInfoParcel* com.android.wifi.x.@0
rule android.net.ScanResultInfoParcelable* com.android.wifi.x.@0
+rule android.net.TcpKeepalivePacketDataParcelable* com.android.wifi.x.@0
rule android.net.TetherConfigParcel* com.android.wifi.x.@0
rule android.net.TetherOffloadRuleParcel* com.android.wifi.x.@0
rule android.net.TetherStatsParcel* com.android.wifi.x.@0
@@ -43,7 +44,6 @@
rule android.net.InterfaceConfiguration* com.android.wifi.x.@0
rule android.net.IpMemoryStore* com.android.wifi.x.@0
rule android.net.NetworkMonitorManager* com.android.wifi.x.@0
-rule android.net.TcpKeepalivePacketData* com.android.wifi.x.@0
rule android.net.NetworkFactory* com.android.wifi.x.@0
rule android.net.ip.IpClientCallbacks* com.android.wifi.x.@0
rule android.net.ip.IpClientManager* com.android.wifi.x.@0
@@ -110,8 +110,6 @@
rule fi.iki.elonen.** com.android.wifi.x.@0
## used by both framework-wifi and service-wifi ##
-rule android.content.pm.BaseParceledListSlice* com.android.wifi.x.@0
-rule android.content.pm.ParceledListSlice* com.android.wifi.x.@0
rule android.os.HandlerExecutor* com.android.wifi.x.@0
rule android.telephony.Annotation* com.android.wifi.x.@0
rule com.android.internal.util.AsyncChannel* com.android.wifi.x.@0
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index e7b8475..0d4e9c3 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -16,8 +16,6 @@
package android.net.wifi;
-import android.content.pm.ParceledListSlice;
-
import android.net.wifi.hotspot2.OsuProvider;
import android.net.wifi.hotspot2.PasspointConfiguration;
import android.net.wifi.hotspot2.IProvisioningCallback;
@@ -47,6 +45,8 @@
import android.os.ResultReceiver;
import android.os.WorkSource;
+import com.android.modules.utils.ParceledListSlice;
+
/**
* Interface that allows controlling and querying Wi-Fi connectivity.
*
diff --git a/wifi/java/android/net/wifi/SecurityParams.java b/wifi/java/android/net/wifi/SecurityParams.java
index 157d1c5..0ab6f57 100644
--- a/wifi/java/android/net/wifi/SecurityParams.java
+++ b/wifi/java/android/net/wifi/SecurityParams.java
@@ -16,6 +16,7 @@
package android.net.wifi;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.net.wifi.WifiConfiguration.AuthAlgorithm;
import android.net.wifi.WifiConfiguration.GroupCipher;
@@ -27,6 +28,8 @@
import android.net.wifi.WifiConfiguration.SuiteBCipher;
import android.os.Parcel;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.BitSet;
import java.util.Objects;
@@ -37,6 +40,23 @@
public class SecurityParams {
private static final String TAG = "SecurityParams";
+ /** Passpoint Release 1 */
+ public static final int PASSPOINT_R1 = 1;
+
+ /** Passpoint Release 2 */
+ public static final int PASSPOINT_R2 = 2;
+
+ /** Passpoint Release 3 */
+ public static final int PASSPOINT_R3 = 3;
+
+ @IntDef(prefix = { "PASSPOINT_" }, value = {
+ PASSPOINT_R1,
+ PASSPOINT_R2,
+ PASSPOINT_R3,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PasspointRelease {}
+
private @SecurityType int mSecurityType = WifiConfiguration.SECURITY_TYPE_PSK;
/**
@@ -99,6 +119,8 @@
*/
private boolean mRequirePmf = false;
+ private @PasspointRelease int mPasspointRelease = PASSPOINT_R2;
+
/** Indicate that this SAE security type only accepts H2E (Hash-to-Element) mode. */
private boolean mIsSaeH2eOnlyMode = false;
@@ -562,11 +584,22 @@
}
/**
- * Create EAP security params for Passpoint.
+ * Create Passpoint security params.
*/
- public static @NonNull SecurityParams createPasspointParams(boolean requirePmf) {
+ public static @NonNull SecurityParams createPasspointParams(@PasspointRelease int release) {
SecurityParams params = new SecurityParams();
- params.mSecurityType = WifiConfiguration.SECURITY_TYPE_EAP;
+ switch (release) {
+ case PASSPOINT_R1:
+ case PASSPOINT_R2:
+ params.mSecurityType = WifiConfiguration.SECURITY_TYPE_PASSPOINT_R1_R2;
+ break;
+ case PASSPOINT_R3:
+ params.mSecurityType = WifiConfiguration.SECURITY_TYPE_PASSPOINT_R3;
+ params.mRequirePmf = true;
+ break;
+ default:
+ throw new IllegalArgumentException("invalid passpoint release " + release);
+ }
params.mAllowedKeyManagement.set(KeyMgmt.WPA_EAP);
params.mAllowedKeyManagement.set(KeyMgmt.IEEE8021X);
@@ -574,12 +607,9 @@
params.mAllowedProtocols.set(Protocol.RSN);
params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP);
- params.mAllowedPairwiseCiphers.set(PairwiseCipher.TKIP);
params.mAllowedGroupCiphers.set(GroupCipher.CCMP);
- params.mAllowedGroupCiphers.set(GroupCipher.TKIP);
- params.mRequirePmf = requirePmf;
return params;
}
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index f8b824c..ba4a54f 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -502,6 +502,20 @@
* @hide
*/
public static final int SECURITY_TYPE_OSEN = 10;
+ /**
+ * Security type for a Passpoint R1/R2 network.
+ * Passpoint R1/R2 uses Enterprise security, where TKIP and WEP are not allowed.
+ * @hide
+ */
+ public static final int SECURITY_TYPE_PASSPOINT_R1_R2 = 11;
+
+ /**
+ * Security type for a Passpoint R3 network.
+ * Passpoint R3 uses Enterprise security, where TKIP and WEP are not allowed,
+ * and PMF must be set to Required.
+ * @hide
+ */
+ public static final int SECURITY_TYPE_PASSPOINT_R3 = 12;
/**
* Security types we support.
@@ -520,6 +534,8 @@
SECURITY_TYPE_WAPI_CERT,
SECURITY_TYPE_EAP_WPA3_ENTERPRISE,
SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT,
+ SECURITY_TYPE_PASSPOINT_R1_R2,
+ SECURITY_TYPE_PASSPOINT_R3,
})
public @interface SecurityType {}
@@ -546,7 +562,7 @@
* {@link #SECURITY_TYPE_WAPI_PSK},
* {@link #SECURITY_TYPE_WAPI_CERT},
* {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE},
- * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT}
+ * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT},
*/
public void setSecurityParams(@SecurityType int securityType) {
// Clear existing data.
@@ -580,7 +596,7 @@
* {@link #SECURITY_TYPE_WAPI_PSK},
* {@link #SECURITY_TYPE_WAPI_CERT},
* {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE},
- * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT}
+ * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT},
*
* @hide
*/
@@ -627,6 +643,12 @@
case SECURITY_TYPE_OSEN:
params = SecurityParams.createOsenParams();
break;
+ case SECURITY_TYPE_PASSPOINT_R1_R2:
+ params = SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R2);
+ break;
+ case SECURITY_TYPE_PASSPOINT_R3:
+ params = SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R3);
+ break;
default:
throw new IllegalArgumentException("unknown security type " + securityType);
}
@@ -719,7 +741,7 @@
* {@link #SECURITY_TYPE_WAPI_PSK},
* {@link #SECURITY_TYPE_WAPI_CERT},
* {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE},
- * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT}
+ * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT},
*
* @hide
*/
@@ -743,7 +765,7 @@
* {@link #SECURITY_TYPE_WAPI_PSK},
* {@link #SECURITY_TYPE_WAPI_CERT},
* {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE},
- * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT}
+ * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT},
*
* @return the copy of specific security params if found; otherwise null.
* @hide
@@ -769,7 +791,7 @@
* {@link #SECURITY_TYPE_WAPI_PSK},
* {@link #SECURITY_TYPE_WAPI_CERT},
* {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE},
- * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT}
+ * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT},
*
* @return true if there is a security params matches the type.
* @hide
@@ -1686,7 +1708,9 @@
DISABLED_NO_INTERNET_PERMANENT,
DISABLED_BY_WIFI_MANAGER,
DISABLED_BY_WRONG_PASSWORD,
- DISABLED_AUTHENTICATION_NO_SUBSCRIPTION})
+ DISABLED_AUTHENTICATION_NO_SUBSCRIPTION,
+ DISABLED_AUTHENTICATION_FAILURE_GENERIC,
+ DISABLED_AUTHENTICATION_FAILURE_CARRIER_SPECIFIC})
public @interface NetworkSelectionDisableReason {}
// Quality Network disabled reasons
@@ -1699,8 +1723,16 @@
public static final int NETWORK_SELECTION_DISABLED_STARTING_INDEX = 1;
/** This network is temporarily disabled because of multiple association rejections. */
public static final int DISABLED_ASSOCIATION_REJECTION = 1;
- /** This network is temporarily disabled because of multiple authentication failure. */
- public static final int DISABLED_AUTHENTICATION_FAILURE = 2;
+ /** This network is disabled due to generic authentication failure. */
+ public static final int DISABLED_AUTHENTICATION_FAILURE_GENERIC = 2;
+ /** Separate DISABLED_AUTHENTICATION_FAILURE into DISABLED_AUTHENTICATION_FAILURE_GENERIC
+ * and DISABLED_AUTHENTICATION_FAILURE_CARRIER_SPECIFIC
+ * @deprecated Use the {@link #DISABLED_AUTHENTICATION_FAILURE_GENERIC} constant
+ * (which is the same value).
+ */
+ @Deprecated
+ public static final int DISABLED_AUTHENTICATION_FAILURE =
+ DISABLED_AUTHENTICATION_FAILURE_GENERIC;
/** This network is temporarily disabled because of multiple DHCP failure. */
public static final int DISABLED_DHCP_FAILURE = 3;
/** This network is temporarily disabled because it has no Internet access. */
@@ -1718,11 +1750,13 @@
public static final int DISABLED_BY_WRONG_PASSWORD = 8;
/** This network is permanently disabled because service is not subscribed. */
public static final int DISABLED_AUTHENTICATION_NO_SUBSCRIPTION = 9;
+ /** This network is disabled due to carrier specific EAP failure. */
+ public static final int DISABLED_AUTHENTICATION_FAILURE_CARRIER_SPECIFIC = 10;
/**
* All other disable reasons should be strictly less than this value.
* @hide
*/
- public static final int NETWORK_SELECTION_DISABLED_MAX = 10;
+ public static final int NETWORK_SELECTION_DISABLED_MAX = 11;
/**
* Get an integer that is equal to the maximum integer value of all the
@@ -1862,6 +1896,18 @@
1,
Integer.MAX_VALUE));
+ reasons.append(DISABLED_AUTHENTICATION_FAILURE_GENERIC,
+ new DisableReasonInfo(
+ "NETWORK_SELECTION_DISABLED_AUTHENTICATION_FAILURE_GENERIC",
+ 5,
+ 5 * 60 * 1000));
+
+ reasons.append(DISABLED_AUTHENTICATION_FAILURE_CARRIER_SPECIFIC,
+ new DisableReasonInfo(
+ "NETWORK_SELECTION_DISABLED_AUTHENTICATION_FAILURE_CARRIER_SPECIFIC",
+ 1,
+ Integer.MAX_VALUE));
+
return reasons;
}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 0311498..bccb241 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -34,7 +34,6 @@
import android.app.ActivityManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
-import android.content.pm.ParceledListSlice;
import android.net.ConnectivityManager;
import android.net.DhcpInfo;
import android.net.MacAddress;
@@ -63,6 +62,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.modules.utils.ParceledListSlice;
import com.android.modules.utils.build.SdkLevel;
import java.lang.annotation.Retention;
diff --git a/wifi/tests/src/android/net/wifi/SecurityParamsTest.java b/wifi/tests/src/android/net/wifi/SecurityParamsTest.java
index e581b77..2f6b724 100644
--- a/wifi/tests/src/android/net/wifi/SecurityParamsTest.java
+++ b/wifi/tests/src/android/net/wifi/SecurityParamsTest.java
@@ -85,11 +85,11 @@
expectedAllowedGroupCiphers, expectedRequirePmf);
}
- /** Verify EAP Passpoint params creator. */
+ /** Verify Passpoint R1 params creator. */
@Test
- public void testEapPasspointCreator() throws Exception {
- SecurityParams p = SecurityParams.createPasspointParams(false);
- int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_EAP;
+ public void testEapPasspointR1Creator() throws Exception {
+ SecurityParams p = SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R1);
+ int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_PASSPOINT_R1_R2;
int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WPA_EAP, KeyMgmt.IEEE8021X};
int[] expectedAllowedProtocols = new int[] {};
int[] expectedAllowedAuthAlgorithms = new int[] {};
@@ -100,9 +100,36 @@
expectedAllowedKeyManagement, expectedAllowedProtocols,
expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers,
expectedAllowedGroupCiphers, expectedRequirePmf);
+ }
- p = SecurityParams.createPasspointParams(true);
- expectedRequirePmf = true;
+ /** Verify Passpoint R2 params creator. */
+ @Test
+ public void testEapPasspointR2Creator() throws Exception {
+ SecurityParams p = SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R2);
+ int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_PASSPOINT_R1_R2;
+ int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WPA_EAP, KeyMgmt.IEEE8021X};
+ int[] expectedAllowedProtocols = new int[] {};
+ int[] expectedAllowedAuthAlgorithms = new int[] {};
+ int[] expectedAllowedPairwiseCiphers = new int[] {};
+ int[] expectedAllowedGroupCiphers = new int[] {};
+ boolean expectedRequirePmf = false;
+ verifySecurityParams(p, expectedSecurityType,
+ expectedAllowedKeyManagement, expectedAllowedProtocols,
+ expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers,
+ expectedAllowedGroupCiphers, expectedRequirePmf);
+ }
+
+ /** Verify Passpoint R3 params creator. */
+ @Test
+ public void testEapPasspointR3Creator() throws Exception {
+ SecurityParams p = SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R3);
+ int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_PASSPOINT_R3;
+ int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WPA_EAP, KeyMgmt.IEEE8021X};
+ int[] expectedAllowedProtocols = new int[] {};
+ int[] expectedAllowedAuthAlgorithms = new int[] {};
+ int[] expectedAllowedPairwiseCiphers = new int[] {};
+ int[] expectedAllowedGroupCiphers = new int[] {};
+ boolean expectedRequirePmf = true;
verifySecurityParams(p, expectedSecurityType,
expectedAllowedKeyManagement, expectedAllowedProtocols,
expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers,
@@ -408,7 +435,9 @@
SecurityParams[] nonOpenSecurityParams = new SecurityParams[] {
SecurityParams.createWpaWpa2EnterpriseParams(),
- SecurityParams.createPasspointParams(false),
+ SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R1),
+ SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R2),
+ SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R3),
SecurityParams.createOsenParams(),
SecurityParams.createWapiCertParams(),
SecurityParams.createWapiPskParams(),
@@ -428,7 +457,9 @@
public void testIsEnterpriseNetwork() {
SecurityParams[] enterpriseSecurityParams = new SecurityParams[] {
SecurityParams.createWpaWpa2EnterpriseParams(),
- SecurityParams.createPasspointParams(false),
+ SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R1),
+ SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R2),
+ SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R3),
SecurityParams.createWapiCertParams(),
SecurityParams.createWpa3Enterprise192BitParams(),
SecurityParams.createWpa3EnterpriseParams(),