Merge "Keep changed focus data after service disable"
diff --git a/Android.bp b/Android.bp
index 598f4fc..62ac6e7 100644
--- a/Android.bp
+++ b/Android.bp
@@ -349,6 +349,7 @@
":framework-telecomm-sources",
":framework-telephony-common-sources",
":framework-telephony-sources",
+ ":framework-vcn-util-sources",
":framework-wifi-annotations",
":framework-wifi-non-updatable-sources",
":PacProcessor-aidl-sources",
@@ -627,7 +628,6 @@
// in favor of an API stubs dependency in java_library "framework" below.
"mimemap",
"av-types-aidl-java",
- "mediatranscoding_aidl_interface-java",
"soundtrigger_middleware-aidl-java",
"modules-utils-os",
],
@@ -1373,7 +1373,6 @@
// TODO(b/145644363): move this to under StubLibraries.bp or ApiDocs.bp
metalava_framework_docs_args = "--manifest $(location core/res/AndroidManifest.xml) " +
- "--ignore-classes-on-classpath " +
"--hide-package com.android.server " +
"--hide-package android.audio.policy.configuration.V7_0 " +
"--error UnhiddenSystemApi " +
diff --git a/ApiDocs.bp b/ApiDocs.bp
index 3d6bdbf..5f4f3c2 100644
--- a/ApiDocs.bp
+++ b/ApiDocs.bp
@@ -96,7 +96,9 @@
arg_files: [
"core/res/AndroidManifest.xml",
],
- args: metalava_framework_docs_args,
+ args: metalava_framework_docs_args +
+ // Needed for hidden libcore annotations for now.
+ " --ignore-classes-on-classpath ",
write_sdk_values: true,
}
@@ -106,7 +108,10 @@
arg_files: [
"core/res/AndroidManifest.xml",
],
- args: metalava_framework_docs_args + " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\) ",
+ args: metalava_framework_docs_args +
+ // Needed for hidden libcore annotations for now.
+ " --ignore-classes-on-classpath " +
+ " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS\\) ",
write_sdk_values: true,
}
diff --git a/StubLibraries.bp b/StubLibraries.bp
index 12ee889..0596755 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -50,7 +50,9 @@
":art.module.public.api{.public.stubs.source}",
"**/package.html",
],
- sdk_version: "core_platform",
+ sdk_version: "none",
+ system_modules: "none",
+ java_version: "1.8",
arg_files: ["core/res/AndroidManifest.xml"],
// TODO(b/147699819, b/169090544): remove below aidl includes.
aidl: {
@@ -80,6 +82,7 @@
"android.hardware.usb.gadget-V1.0-java",
"android.hardware.vibrator-V1.3-java",
"framework-protos",
+ "stable.core.platform.api.stubs",
// There are a few classes from modules used as type arguments that
// need to be resolved by metalava. For now, we can use a previously
// finalized stub library to resolve them. If a new class gets added,
diff --git a/apct-tests/perftests/windowmanager/src/android/wm/RecentsAnimationPerfTest.java b/apct-tests/perftests/windowmanager/src/android/wm/RecentsAnimationPerfTest.java
index 2aea61f..98b5938 100644
--- a/apct-tests/perftests/windowmanager/src/android/wm/RecentsAnimationPerfTest.java
+++ b/apct-tests/perftests/windowmanager/src/android/wm/RecentsAnimationPerfTest.java
@@ -24,8 +24,8 @@
import static org.hamcrest.core.Is.is;
import android.app.ActivityManager;
-import android.app.ActivityManager.TaskSnapshot;
import android.app.ActivityTaskManager;
+import android.window.TaskSnapshot;
import android.app.IActivityTaskManager;
import android.content.ComponentName;
import android.content.Context;
diff --git a/apex/Android.bp b/apex/Android.bp
index 4e80acb..77ff6db 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -12,6 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ default_visibility: [":__subpackages__"],
+}
+
mainline_stubs_args =
"--error UnhiddenSystemApi " +
"--hide BroadcastBehavior " +
@@ -136,6 +140,13 @@
enabled: true,
sdk_version: "module_current",
},
+ defaults_visibility: [
+ ":__subpackages__",
+ "//frameworks/base/libs/hwui",
+ "//frameworks/base/wifi",
+ "//packages/modules:__subpackages__",
+ "//packages/providers/MediaProvider:__subpackages__",
+ ],
}
// Defaults for mainline module system server provided java_sdk_library instances.
@@ -147,6 +158,10 @@
enabled: true,
sdk_version: "module_current",
},
+ defaults_visibility: [
+ ":__subpackages__",
+ "//packages/modules:__subpackages__",
+ ],
}
stubs_defaults {
diff --git a/apex/appsearch/framework/Android.bp b/apex/appsearch/framework/Android.bp
index 12afde4..b3eb911 100644
--- a/apex/appsearch/framework/Android.bp
+++ b/apex/appsearch/framework/Android.bp
@@ -19,6 +19,7 @@
"java/**/*.aidl",
],
path: "java",
+ visibility: ["//frameworks/base"],
}
java_sdk_library {
diff --git a/apex/appsearch/service/Android.bp b/apex/appsearch/service/Android.bp
index fc1d707..2fd5c73 100644
--- a/apex/appsearch/service/Android.bp
+++ b/apex/appsearch/service/Android.bp
@@ -28,5 +28,11 @@
"libicing",
],
jarjar_rules: "jarjar-rules.txt",
+ visibility: [
+ "//frameworks/base/apex/appsearch:__subpackages__",
+ // These are required until appsearch is properly unbundled.
+ "//frameworks/base/services/tests/mockingservicestests",
+ "//frameworks/base/services/tests/servicestests",
+ ],
apex_available: ["com.android.appsearch"],
}
diff --git a/apex/appsearch/testing/Android.bp b/apex/appsearch/testing/Android.bp
new file mode 100644
index 0000000..54d5039
--- /dev/null
+++ b/apex/appsearch/testing/Android.bp
@@ -0,0 +1,25 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+java_library {
+ name: "AppSearchTestUtils",
+ srcs: ["java/**/*.java"],
+ libs: [
+ "androidx.test.ext.junit",
+ "framework",
+ "framework-appsearch",
+ "guava",
+ "truth-prebuilt",
+ ],
+ visibility: ["//cts/tests/appsearch"],
+}
diff --git a/apex/appsearch/testing/java/com/android/server/appsearch/testing/AppSearchSessionShim.java b/apex/appsearch/testing/java/com/android/server/appsearch/testing/AppSearchSessionShim.java
new file mode 100644
index 0000000..b1e760a
--- /dev/null
+++ b/apex/appsearch/testing/java/com/android/server/appsearch/testing/AppSearchSessionShim.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.appsearch.testing;
+
+import android.annotation.NonNull;
+import android.app.appsearch.AppSearchBatchResult;
+import android.app.appsearch.AppSearchManager;
+import android.app.appsearch.AppSearchResult;
+import android.app.appsearch.AppSearchSession;
+import android.app.appsearch.BatchResultCallback;
+import android.app.appsearch.GenericDocument;
+import android.app.appsearch.GetByUriRequest;
+import android.app.appsearch.PutDocumentsRequest;
+import android.app.appsearch.RemoveByUriRequest;
+import android.app.appsearch.SearchResults;
+import android.app.appsearch.SearchSpec;
+import android.app.appsearch.SetSchemaRequest;
+import android.content.Context;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * This test class adapts the AppSearch Framework API to ListenableFuture, so it can be tested via
+ * a consistent interface.
+ * @hide
+ */
+public class AppSearchSessionShim {
+ private final AppSearchSession mAppSearchSession;
+ private final ExecutorService mExecutor;
+
+ @NonNull
+ public static ListenableFuture<AppSearchResult<AppSearchSessionShim>> createSearchSession(
+ @NonNull AppSearchManager.SearchContext searchContext) {
+ Context context = ApplicationProvider.getApplicationContext();
+ AppSearchManager appSearchManager = context.getSystemService(AppSearchManager.class);
+ SettableFuture<AppSearchResult<AppSearchSession>> future = SettableFuture.create();
+ ExecutorService executor = Executors.newCachedThreadPool();
+ appSearchManager.createSearchSession(searchContext, executor, future::set);
+ return Futures.transform(future, (instance) -> {
+ if (!instance.isSuccess()) {
+ return AppSearchResult.newFailedResult(
+ instance.getResultCode(), instance.getErrorMessage());
+ }
+ AppSearchSession searchSession = instance.getResultValue();
+ AppSearchSessionShim shim = new AppSearchSessionShim(searchSession, executor);
+ return AppSearchResult.newSuccessfulResult(shim);
+ }, executor);
+ }
+
+ private AppSearchSessionShim(
+ @NonNull AppSearchSession session, @NonNull ExecutorService executor) {
+ mAppSearchSession = Preconditions.checkNotNull(session);
+ mExecutor = Preconditions.checkNotNull(executor);
+ }
+
+ @NonNull
+ public ListenableFuture<AppSearchResult<Void>> setSchema(@NonNull SetSchemaRequest request) {
+ SettableFuture<AppSearchResult<Void>> future = SettableFuture.create();
+ mAppSearchSession.setSchema(request, mExecutor, future::set);
+ return future;
+ }
+
+ @NonNull
+ public ListenableFuture<AppSearchBatchResult<String, Void>> putDocuments(
+ @NonNull PutDocumentsRequest request) {
+ SettableFuture<AppSearchBatchResult<String, Void>> future = SettableFuture.create();
+ mAppSearchSession.putDocuments(
+ request, mExecutor, new BatchResultCallbackAdapter<>(future));
+ return future;
+ }
+
+ @NonNull
+ public ListenableFuture<AppSearchBatchResult<String, GenericDocument>> getByUri(
+ @NonNull GetByUriRequest request) {
+ SettableFuture<AppSearchBatchResult<String, GenericDocument>> future =
+ SettableFuture.create();
+ mAppSearchSession.getByUri(request, mExecutor, new BatchResultCallbackAdapter<>(future));
+ return future;
+ }
+
+ @NonNull
+ public SearchResultsShim query(
+ @NonNull String queryExpression, @NonNull SearchSpec searchSpec) {
+ SearchResults searchResults =
+ mAppSearchSession.query(queryExpression, searchSpec, mExecutor);
+ return new SearchResultsShim(searchResults);
+ }
+
+ @NonNull
+ public ListenableFuture<AppSearchBatchResult<String, Void>> removeByUri(
+ @NonNull RemoveByUriRequest request) {
+ SettableFuture<AppSearchBatchResult<String, Void>> future = SettableFuture.create();
+ mAppSearchSession.removeByUri(request, mExecutor, new BatchResultCallbackAdapter<>(future));
+ return future;
+ }
+
+ @NonNull
+ public ListenableFuture<AppSearchResult<Void>> removeByQuery(
+ @NonNull String queryExpression, @NonNull SearchSpec searchSpec) {
+ SettableFuture<AppSearchResult<Void>> future = SettableFuture.create();
+ mAppSearchSession.removeByQuery(queryExpression, searchSpec, mExecutor, future::set);
+ return future;
+ }
+
+ private static final class BatchResultCallbackAdapter<K, V>
+ implements BatchResultCallback<K, V> {
+ private final SettableFuture<AppSearchBatchResult<K, V>> mFuture;
+
+ BatchResultCallbackAdapter(SettableFuture<AppSearchBatchResult<K, V>> future) {
+ mFuture = future;
+ }
+
+ @Override
+ public void onResult(AppSearchBatchResult<K, V> result) {
+ mFuture.set(result);
+ }
+
+ @Override
+ public void onSystemError(Throwable t) {
+ mFuture.setException(t);
+ }
+ }
+}
diff --git a/apex/appsearch/testing/java/com/android/server/appsearch/testing/GlobalSearchSessionShim.java b/apex/appsearch/testing/java/com/android/server/appsearch/testing/GlobalSearchSessionShim.java
new file mode 100644
index 0000000..5146426
--- /dev/null
+++ b/apex/appsearch/testing/java/com/android/server/appsearch/testing/GlobalSearchSessionShim.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.appsearch.testing;
+
+import android.annotation.NonNull;
+import android.app.appsearch.AppSearchManager;
+import android.app.appsearch.AppSearchResult;
+import android.app.appsearch.GlobalSearchSession;
+import android.app.appsearch.SearchResults;
+import android.app.appsearch.SearchSpec;
+import android.content.Context;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * This test class adapts the AppSearch Framework API to ListenableFuture, so it can be tested via
+ * a consistent interface.
+ * @hide
+ */
+public class GlobalSearchSessionShim {
+ private final GlobalSearchSession mGlobalSearchSession;
+ private final ExecutorService mExecutor;
+
+ @NonNull
+ public static ListenableFuture<AppSearchResult<GlobalSearchSessionShim>>
+ createGlobalSearchSession() {
+ Context context = ApplicationProvider.getApplicationContext();
+ AppSearchManager appSearchManager = context.getSystemService(AppSearchManager.class);
+ SettableFuture<AppSearchResult<GlobalSearchSession>> future = SettableFuture.create();
+ ExecutorService executor = Executors.newCachedThreadPool();
+ appSearchManager.createGlobalSearchSession(executor, future::set);
+ return Futures.transform(future, (instance) -> {
+ if (!instance.isSuccess()) {
+ return AppSearchResult.newFailedResult(
+ instance.getResultCode(), instance.getErrorMessage());
+ }
+ GlobalSearchSession searchSession = instance.getResultValue();
+ GlobalSearchSessionShim shim = new GlobalSearchSessionShim(searchSession, executor);
+ return AppSearchResult.newSuccessfulResult(shim);
+ }, executor);
+ }
+
+ private GlobalSearchSessionShim(
+ @NonNull GlobalSearchSession session, @NonNull ExecutorService executor) {
+ mGlobalSearchSession = Preconditions.checkNotNull(session);
+ mExecutor = Preconditions.checkNotNull(executor);
+ }
+
+ @NonNull
+ public SearchResultsShim query(
+ @NonNull String queryExpression, @NonNull SearchSpec searchSpec) {
+ SearchResults searchResults =
+ mGlobalSearchSession.query(queryExpression, searchSpec, mExecutor);
+ return new SearchResultsShim(searchResults);
+ }
+}
diff --git a/apex/appsearch/testing/java/com/android/server/appsearch/testing/SearchResultsShim.java b/apex/appsearch/testing/java/com/android/server/appsearch/testing/SearchResultsShim.java
new file mode 100644
index 0000000..cf43401
--- /dev/null
+++ b/apex/appsearch/testing/java/com/android/server/appsearch/testing/SearchResultsShim.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.appsearch.testing;
+
+import android.annotation.NonNull;
+import android.app.appsearch.AppSearchResult;
+import android.app.appsearch.SearchResult;
+import android.app.appsearch.SearchResults;
+
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.SettableFuture;
+
+import java.io.Closeable;
+import java.util.List;
+
+/**
+ * This test class adapts the AppSearch Framework API to ListenableFuture, so it can be tested via
+ * a consistent interface.
+ * @hide
+ */
+public class SearchResultsShim implements Closeable {
+ private final SearchResults mSearchResults;
+
+ SearchResultsShim(@NonNull SearchResults searchResults) {
+ mSearchResults = Preconditions.checkNotNull(searchResults);
+ }
+
+ @NonNull
+ public ListenableFuture<AppSearchResult<List<SearchResult>>> getNextPage() {
+ SettableFuture<AppSearchResult<List<SearchResult>>> future = SettableFuture.create();
+ mSearchResults.getNextPage(future::set);
+ return future;
+ }
+
+ @Override
+ public void close() {
+ mSearchResults.close();
+ }
+}
diff --git a/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchTestUtils.java b/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchTestUtils.java
new file mode 100644
index 0000000..907509c
--- /dev/null
+++ b/apex/appsearch/testing/java/com/android/server/appsearch/testing/external/AppSearchTestUtils.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.appsearch.testing;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.appsearch.AppSearchBatchResult;
+import android.app.appsearch.AppSearchManager;
+import android.app.appsearch.AppSearchResult;
+import android.app.appsearch.GenericDocument;
+import android.app.appsearch.GetByUriRequest;
+import android.app.appsearch.SearchResult;
+import android.app.appsearch.SetSchemaRequest;
+import android.content.Context;
+
+import com.google.common.collect.ImmutableList;
+
+import junit.framework.AssertionFailedError;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Future;
+
+public class AppSearchTestUtils {
+
+ // List of databases that may be used in tests. Keeping them in a centralized location helps
+ // #cleanup know which databases to clear.
+ public static final String DEFAULT_DATABASE = AppSearchManager.DEFAULT_DATABASE_NAME;
+ public static final String DB_1 = "testDb1";
+ public static final String DB_2 = "testDb2";
+
+ public static void cleanup(Context context) throws Exception {
+ List<String> databases = ImmutableList.of(DEFAULT_DATABASE, DB_1, DB_2);
+ for (String database : databases) {
+ AppSearchSessionShim session = checkIsResultSuccess(
+ AppSearchSessionShim.createSearchSession(
+ new AppSearchManager.SearchContext.Builder()
+ .setDatabaseName(database).build()));
+ checkIsResultSuccess(session.setSchema(
+ new SetSchemaRequest.Builder().setForceOverride(true).build()));
+ }
+ }
+
+ public static <V> V checkIsResultSuccess(Future<AppSearchResult<V>> future) throws Exception {
+ AppSearchResult<V> result = future.get();
+ if (!result.isSuccess()) {
+ throw new AssertionFailedError("AppSearchResult not successful: " + result);
+ }
+ return result.getResultValue();
+ }
+
+ public static <K, V> AppSearchBatchResult<K, V> checkIsBatchResultSuccess(
+ Future<AppSearchBatchResult<K, V>> future) throws Exception {
+ AppSearchBatchResult<K, V> result = future.get();
+ if (!result.isSuccess()) {
+ throw new AssertionFailedError("AppSearchBatchResult not successful: " + result);
+ }
+ return result;
+ }
+
+ public static List<GenericDocument> doGet(
+ AppSearchSessionShim session, String namespace, String... uris) throws Exception {
+ AppSearchBatchResult<String, GenericDocument> result = checkIsBatchResultSuccess(
+ session.getByUri(
+ new GetByUriRequest.Builder()
+ .setNamespace(namespace).addUri(uris).build()));
+ assertThat(result.getSuccesses()).hasSize(uris.length);
+ assertThat(result.getFailures()).isEmpty();
+ List<GenericDocument> list = new ArrayList<>(uris.length);
+ for (String uri : uris) {
+ list.add(result.getSuccesses().get(uri));
+ }
+ return list;
+ }
+
+ public static List<GenericDocument> convertSearchResultsToDocuments(
+ SearchResultsShim searchResults) throws Exception {
+ List<SearchResult> results = checkIsResultSuccess(searchResults.getNextPage());
+ List<GenericDocument> documents = new ArrayList<>();
+ while (results.size() > 0) {
+ for (SearchResult result : results) {
+ documents.add(result.getDocument());
+ }
+ results = checkIsResultSuccess(searchResults.getNextPage());
+ }
+ return documents;
+ }
+}
diff --git a/apex/appsearch/testing/java/com/android/server/appsearch/testing/package-info.java b/apex/appsearch/testing/java/com/android/server/appsearch/testing/package-info.java
new file mode 100644
index 0000000..5c919b4
--- /dev/null
+++ b/apex/appsearch/testing/java/com/android/server/appsearch/testing/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/**
+ * @hide
+ */
+package com.android.server.appsearch.testing;
diff --git a/apex/blobstore/framework/Android.bp b/apex/blobstore/framework/Android.bp
index 2469351..3499553 100644
--- a/apex/blobstore/framework/Android.bp
+++ b/apex/blobstore/framework/Android.bp
@@ -19,6 +19,7 @@
"java/**/*.aidl"
],
path: "java",
+ visibility: ["//frameworks/base"],
}
java_library {
diff --git a/apex/blobstore/service/Android.bp b/apex/blobstore/service/Android.bp
index 22b0cbe..f6cbac1 100644
--- a/apex/blobstore/service/Android.bp
+++ b/apex/blobstore/service/Android.bp
@@ -25,4 +25,9 @@
"services.core",
"services.usage",
],
+ visibility: [
+ // These are required until blobstore is properly unbundled.
+ "//frameworks/base/services",
+ "//frameworks/base/services/tests/mockingservicestests",
+ ],
}
diff --git a/apex/jobscheduler/OWNERS b/apex/jobscheduler/OWNERS
index d004eed..c77ea33 100644
--- a/apex/jobscheduler/OWNERS
+++ b/apex/jobscheduler/OWNERS
@@ -1,6 +1,7 @@
-yamasani@google.com
-omakoto@google.com
ctate@android.com
ctate@google.com
+dplotnikov@google.com
kwekua@google.com
-suprabh@google.com
\ No newline at end of file
+omakoto@google.com
+suprabh@google.com
+yamasani@google.com
diff --git a/apex/jobscheduler/framework/Android.bp b/apex/jobscheduler/framework/Android.bp
index dab295b..6650e67 100644
--- a/apex/jobscheduler/framework/Android.bp
+++ b/apex/jobscheduler/framework/Android.bp
@@ -5,6 +5,7 @@
"java/**/*.aidl",
],
path: "java",
+ visibility: ["//frameworks/base"],
}
java_library {
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
index 5c4cb3b..6eb44a7 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
@@ -1472,6 +1472,7 @@
* <li>Run as soon as possible</li>
* <li>Be exempted from Doze and battery saver restrictions</li>
* <li>Have network access</li>
+ * <li>Less likely to be killed than regular jobs</li>
* </ol>
*
* Since these jobs have stronger guarantees than regular jobs, they will be subject to
@@ -1483,10 +1484,11 @@
* will immediately return {@link JobScheduler#RESULT_FAILURE} if the app does not have
* available quota (and the job will not be successfully scheduled).
*
- * Expedited jobs may only set network constraints. No other constraints are allowed.
+ * Expedited jobs may only set network, storage-not-low, and persistence constraints.
+ * No other constraints are allowed.
*
* Note: Even though expedited jobs are meant to run as soon as possible, they may be
- * deferred if the system is under heavy load or the network constraint is satisfied
+ * deferred if the system is under heavy load or requested constraints are not satisfied.
*
* @see JobInfo#isExpedited()
*/
@@ -1666,12 +1668,10 @@
if (isPeriodic) {
throw new IllegalArgumentException("An expedited job cannot be periodic");
}
- if (isPersisted) {
- throw new IllegalArgumentException("An expedited job cannot be persisted");
- }
- if (constraintFlags != 0 || (flags & ~FLAG_EXPEDITED) != 0) {
+ if ((constraintFlags & ~CONSTRAINT_FLAG_STORAGE_NOT_LOW) != 0
+ || (flags & ~FLAG_EXPEDITED) != 0) {
throw new IllegalArgumentException(
- "An expedited job can only have network constraints");
+ "An expedited job can only have network and storage-not-low constraints");
}
if (triggerContentUris != null && triggerContentUris.length > 0) {
throw new IllegalArgumentException(
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobParameters.java b/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
index d4c78a0..0d3e001 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
@@ -202,6 +202,8 @@
* {@code true}. This will return {@code false} if the job that wasn't requested to run as a
* expedited job, or if it was requested to run as an expedited job but the app didn't have
* any remaining expedited job quota at the time of execution.
+ *
+ * @see JobInfo.Builder#setExpedited(boolean)
*/
public boolean isExpeditedJob() {
return mIsExpedited;
diff --git a/apex/jobscheduler/service/Android.bp b/apex/jobscheduler/service/Android.bp
index 8aa88c2..35bd317 100644
--- a/apex/jobscheduler/service/Android.bp
+++ b/apex/jobscheduler/service/Android.bp
@@ -23,4 +23,12 @@
required: [
"libalarm_jni",
],
+ visibility: [
+ "//frameworks/base/apex/jobscheduler:__subpackages__",
+ // These are required until jobscheduler is properly unbundled.
+ "//frameworks/base/services",
+ "//frameworks/base/services/tests/mockingservicestests",
+ "//frameworks/base/services/tests/servicestests",
+ "//frameworks/base/tests/JobSchedulerPerfTests",
+ ],
}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
index 655fd80..7b87dfb 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
@@ -1563,11 +1563,11 @@
standbyBucket);
final long remainingEJQuota = getRemainingEJExecutionTimeLocked(userId, packageName);
- if (stats.executionTimeInWindowMs < mAllowedTimePerPeriodMs
+ final boolean inRegularQuota = stats.executionTimeInWindowMs < mAllowedTimePerPeriodMs
&& stats.executionTimeInMaxPeriodMs < mMaxExecutionTimeMs
&& isUnderJobCountQuota
- && isUnderTimingSessionCountQuota
- && remainingEJQuota > 0) {
+ && isUnderTimingSessionCountQuota;
+ if (inRegularQuota && remainingEJQuota > 0) {
// Already in quota. Why was this method called?
if (DEBUG) {
Slog.e(TAG, "maybeScheduleStartAlarmLocked called for " + pkgString
@@ -1582,10 +1582,7 @@
long inRegularQuotaTimeElapsed = Long.MAX_VALUE;
long inEJQuotaTimeElapsed = Long.MAX_VALUE;
- if (!(stats.executionTimeInWindowMs < mAllowedTimePerPeriodMs
- && stats.executionTimeInMaxPeriodMs < mMaxExecutionTimeMs
- && isUnderJobCountQuota
- && isUnderTimingSessionCountQuota)) {
+ if (!inRegularQuota) {
// The time this app will have quota again.
long inQuotaTimeElapsed = stats.inQuotaTimeElapsed;
if (!isUnderJobCountQuota && stats.bgJobCountInWindow < stats.jobCountLimit) {
@@ -1603,18 +1600,35 @@
}
if (remainingEJQuota <= 0) {
final long limitMs = mEJLimitsMs[standbyBucket] - mQuotaBufferMs;
- List<TimingSession> timingSessions = mEJTimingSessions.get(userId, packageName);
long sumMs = 0;
- for (int i = timingSessions.size() - 1; i >= 0; --i) {
- TimingSession ts = timingSessions.get(i);
- final long durationMs = ts.endTimeElapsed - ts.startTimeElapsed;
- sumMs += durationMs;
+ final Timer ejTimer = mEJPkgTimers.get(userId, packageName);
+ if (ejTimer != null && ejTimer.isActive()) {
+ final long nowElapsed = sElapsedRealtimeClock.millis();
+ sumMs += ejTimer.getCurrentDuration(nowElapsed);
if (sumMs >= limitMs) {
- inEJQuotaTimeElapsed =
- ts.startTimeElapsed + (sumMs - limitMs) + mEJLimitWindowSizeMs;
- break;
+ inEJQuotaTimeElapsed = (nowElapsed - limitMs) + mEJLimitWindowSizeMs;
}
}
+ List<TimingSession> timingSessions = mEJTimingSessions.get(userId, packageName);
+ if (timingSessions != null) {
+ for (int i = timingSessions.size() - 1; i >= 0; --i) {
+ TimingSession ts = timingSessions.get(i);
+ final long durationMs = ts.endTimeElapsed - ts.startTimeElapsed;
+ sumMs += durationMs;
+ if (sumMs >= limitMs) {
+ inEJQuotaTimeElapsed =
+ ts.startTimeElapsed + (sumMs - limitMs) + mEJLimitWindowSizeMs;
+ break;
+ }
+ }
+ } else if ((ejTimer == null || !ejTimer.isActive()) && inRegularQuota) {
+ // In some strange cases, an app may end be in the NEVER bucket but could have run
+ // some regular jobs. This results in no EJ timing sessions and QC having a bad
+ // time.
+ Slog.wtf(TAG,
+ string(userId, packageName) + " has 0 EJ quota without running anything");
+ return;
+ }
}
long inQuotaTimeElapsed = Math.min(inRegularQuotaTimeElapsed, inEJQuotaTimeElapsed);
diff --git a/apex/jobscheduler/service/jni/Android.bp b/apex/jobscheduler/service/jni/Android.bp
index c502867..4bcc165 100644
--- a/apex/jobscheduler/service/jni/Android.bp
+++ b/apex/jobscheduler/service/jni/Android.bp
@@ -29,8 +29,7 @@
":arctimersrcs",
],
}
- }
-
+ },
}
filegroup {
@@ -38,4 +37,8 @@
srcs: [
"com_android_server_alarm_AlarmManagerService.cpp",
],
+ visibility: [
+ // TODO: remove this
+ "//vendor:__subpackages__",
+ ],
}
diff --git a/apex/media/Android.bp b/apex/media/Android.bp
new file mode 100644
index 0000000..5f1bd37
--- /dev/null
+++ b/apex/media/Android.bp
@@ -0,0 +1,20 @@
+// 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 {
+ default_visibility: [
+ ":__subpackages__",
+ "//frameworks/av/apex",
+ "//frameworks/av/apex/testing",
+ ],
+}
diff --git a/apex/media/framework/Android.bp b/apex/media/framework/Android.bp
index b3c9a9a..60dea07 100644
--- a/apex/media/framework/Android.bp
+++ b/apex/media/framework/Android.bp
@@ -36,7 +36,8 @@
"framework_media_annotation",
],
static_libs: [
- "exoplayer2-extractor"
+ "exoplayer2-extractor",
+ "mediatranscoding_aidl_interface-java",
],
jarjar_rules: "jarjar_rules.txt",
@@ -48,16 +49,23 @@
"test_com.android.media",
],
min_sdk_version: "29",
+ visibility: [
+ "//frameworks/av/apex:__subpackages__",
+ "//frameworks/base", // For framework-all
+ ],
}
filegroup {
name: "updatable-media-srcs",
srcs: [
+ "java/android/media/MediaFrameworkInitializer.java",
":media-aidl-srcs",
":mediaparceledlistslice-java-srcs",
":mediaparser-srcs",
":mediasession2-java-srcs",
+ ":mediatranscoding-srcs",
],
+ visibility: ["//frameworks/base"],
}
filegroup {
@@ -93,6 +101,17 @@
path: "java",
}
+filegroup {
+ name: "mediatranscoding-srcs",
+ srcs: [
+ "java/android/media/ApplicationMediaCapabilities.java",
+ "java/android/media/MediaFeature.java",
+ "java/android/media/MediaTranscodeManager.java",
+ "java/android/media/MediaTranscodingException.java",
+ ],
+ path: "java",
+}
+
java_sdk_library {
name: "framework-media",
defaults: ["framework-module-defaults"],
diff --git a/apex/media/framework/api/current.txt b/apex/media/framework/api/current.txt
index 0cc8e52..ce3bcbe 100644
--- a/apex/media/framework/api/current.txt
+++ b/apex/media/framework/api/current.txt
@@ -1,6 +1,26 @@
// Signature format: 2.0
package android.media {
+ public final class ApplicationMediaCapabilities implements android.os.Parcelable {
+ method @NonNull public static android.media.ApplicationMediaCapabilities createFromXml(@NonNull org.xmlpull.v1.XmlPullParser);
+ method public int describeContents();
+ method @NonNull public java.util.List<java.lang.String> getSupportedHdrTypes();
+ method @NonNull public java.util.List<java.lang.String> getSupportedVideoMimeTypes();
+ method public boolean isHdrTypeSupported(@NonNull String);
+ method public boolean isSlowMotionSupported();
+ method public boolean isVideoMimeTypeSupported(@NonNull String);
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.media.ApplicationMediaCapabilities> CREATOR;
+ }
+
+ public static final class ApplicationMediaCapabilities.Builder {
+ ctor public ApplicationMediaCapabilities.Builder();
+ method @NonNull public android.media.ApplicationMediaCapabilities.Builder addSupportedHdrType(@NonNull String);
+ method @NonNull public android.media.ApplicationMediaCapabilities.Builder addSupportedVideoMimeType(@NonNull String);
+ method @NonNull public android.media.ApplicationMediaCapabilities build();
+ method @NonNull public android.media.ApplicationMediaCapabilities.Builder setSlowMotionSupported(boolean);
+ }
+
public class MediaController2 implements java.lang.AutoCloseable {
method public void cancelSessionCommand(@NonNull Object);
method public void close();
@@ -25,6 +45,17 @@
method @Nullable public android.media.Session2Command.Result onSessionCommand(@NonNull android.media.MediaController2, @NonNull android.media.Session2Command, @Nullable android.os.Bundle);
}
+ public final class MediaFeature {
+ ctor public MediaFeature();
+ }
+
+ public static final class MediaFeature.HdrType {
+ field public static final String DOLBY_VISION = "android.media.feature.hdr.dolby_vision";
+ field public static final String HDR10 = "android.media.feature.hdr.hdr10";
+ field public static final String HDR10_PLUS = "android.media.feature.hdr.hdr10_plus";
+ field public static final String HLG = "android.media.feature.hdr.hlg";
+ }
+
public final class MediaParser {
method public boolean advance(@NonNull android.media.MediaParser.SeekableInputReader) throws java.io.IOException;
method @NonNull public static android.media.MediaParser create(@NonNull android.media.MediaParser.OutputConsumer, @NonNull java.lang.String...);
@@ -170,6 +201,12 @@
method public int getNotificationId();
}
+ public class MediaTranscodingException extends java.lang.Exception {
+ }
+
+ public static final class MediaTranscodingException.ServiceNotAvailableException extends android.media.MediaTranscodingException {
+ }
+
public final class Session2Command implements android.os.Parcelable {
ctor public Session2Command(int);
ctor public Session2Command(@NonNull String, @Nullable android.os.Bundle);
diff --git a/apex/media/framework/api/module-lib-current.txt b/apex/media/framework/api/module-lib-current.txt
index 2b69863..ad9114f 100644
--- a/apex/media/framework/api/module-lib-current.txt
+++ b/apex/media/framework/api/module-lib-current.txt
@@ -1,6 +1,11 @@
// Signature format: 2.0
package android.media {
+ public class MediaFrameworkInitializer {
+ method public static void registerServiceWrappers();
+ method public static void setMediaServiceManager(@NonNull android.media.MediaServiceManager);
+ }
+
@Deprecated public final class MediaParceledListSlice<T extends android.os.Parcelable> implements android.os.Parcelable {
ctor @Deprecated public MediaParceledListSlice(@NonNull java.util.List<T>);
method @Deprecated public int describeContents();
diff --git a/apex/media/framework/api/system-current.txt b/apex/media/framework/api/system-current.txt
index d802177..89cf77c 100644
--- a/apex/media/framework/api/system-current.txt
+++ b/apex/media/framework/api/system-current.txt
@@ -1 +1,67 @@
// Signature format: 2.0
+package android.media {
+
+ public final class MediaTranscodeManager {
+ method @NonNull public android.media.MediaTranscodeManager.TranscodingSession enqueueRequest(@NonNull android.media.MediaTranscodeManager.TranscodingRequest, @NonNull java.util.concurrent.Executor, @NonNull android.media.MediaTranscodeManager.OnTranscodingFinishedListener) throws java.io.FileNotFoundException, android.media.MediaTranscodingException.ServiceNotAvailableException;
+ field public static final int PRIORITY_REALTIME = 1; // 0x1
+ field public static final int TRANSCODING_TYPE_VIDEO = 1; // 0x1
+ }
+
+ @java.lang.FunctionalInterface public static interface MediaTranscodeManager.OnTranscodingFinishedListener {
+ method public void onTranscodingFinished(@NonNull android.media.MediaTranscodeManager.TranscodingSession);
+ }
+
+ public static final class MediaTranscodeManager.TranscodingRequest {
+ method public int getClientPid();
+ method public int getClientUid();
+ method @NonNull public android.net.Uri getDestinationUri();
+ method public int getPriority();
+ method @NonNull public android.net.Uri getSourceUri();
+ method public int getType();
+ method @Nullable public android.media.MediaFormat getVideoTrackFormat();
+ }
+
+ public static final class MediaTranscodeManager.TranscodingRequest.Builder {
+ ctor public MediaTranscodeManager.TranscodingRequest.Builder();
+ method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest build();
+ method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setClientPid(int);
+ method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setClientUid(int);
+ method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setDestinationUri(@NonNull android.net.Uri);
+ method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setPriority(int);
+ method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setSourceUri(@NonNull android.net.Uri);
+ method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setType(int);
+ method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setVideoTrackFormat(@NonNull android.media.MediaFormat);
+ }
+
+ public static class MediaTranscodeManager.TranscodingRequest.MediaFormatResolver {
+ ctor public MediaTranscodeManager.TranscodingRequest.MediaFormatResolver();
+ method @Nullable public android.media.MediaFormat resolveVideoFormat();
+ method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.MediaFormatResolver setClientCapabilities(@NonNull android.media.ApplicationMediaCapabilities);
+ method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.MediaFormatResolver setSourceVideoFormatHint(@NonNull android.media.MediaFormat);
+ method public boolean shouldTranscode();
+ }
+
+ public static final class MediaTranscodeManager.TranscodingSession {
+ method public void cancel();
+ method @IntRange(from=0, to=100) public int getProgress();
+ method public int getResult();
+ method public int getSessionId();
+ method public int getStatus();
+ method public void setOnProgressUpdateListener(@NonNull java.util.concurrent.Executor, @Nullable android.media.MediaTranscodeManager.TranscodingSession.OnProgressUpdateListener);
+ method public void setOnProgressUpdateListener(int, @NonNull java.util.concurrent.Executor, @Nullable android.media.MediaTranscodeManager.TranscodingSession.OnProgressUpdateListener);
+ field public static final int RESULT_CANCELED = 4; // 0x4
+ field public static final int RESULT_ERROR = 3; // 0x3
+ field public static final int RESULT_NONE = 1; // 0x1
+ field public static final int RESULT_SUCCESS = 2; // 0x2
+ field public static final int STATUS_FINISHED = 3; // 0x3
+ field public static final int STATUS_PAUSED = 4; // 0x4
+ field public static final int STATUS_PENDING = 1; // 0x1
+ field public static final int STATUS_RUNNING = 2; // 0x2
+ }
+
+ @java.lang.FunctionalInterface public static interface MediaTranscodeManager.TranscodingSession.OnProgressUpdateListener {
+ method public void onProgressUpdate(@NonNull android.media.MediaTranscodeManager.TranscodingSession, @IntRange(from=0, to=100) int);
+ }
+
+}
+
diff --git a/media/java/android/media/ApplicationMediaCapabilities.java b/apex/media/framework/java/android/media/ApplicationMediaCapabilities.java
similarity index 100%
rename from media/java/android/media/ApplicationMediaCapabilities.java
rename to apex/media/framework/java/android/media/ApplicationMediaCapabilities.java
diff --git a/media/java/android/media/MediaFeature.java b/apex/media/framework/java/android/media/MediaFeature.java
similarity index 100%
rename from media/java/android/media/MediaFeature.java
rename to apex/media/framework/java/android/media/MediaFeature.java
diff --git a/media/java/android/media/MediaFrameworkInitializer.java b/apex/media/framework/java/android/media/MediaFrameworkInitializer.java
similarity index 73%
copy from media/java/android/media/MediaFrameworkInitializer.java
copy to apex/media/framework/java/android/media/MediaFrameworkInitializer.java
index 577442e..813ad7b 100644
--- a/media/java/android/media/MediaFrameworkInitializer.java
+++ b/apex/media/framework/java/android/media/MediaFrameworkInitializer.java
@@ -17,20 +17,18 @@
package android.media;
import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.annotation.SystemApi.Client;
+import android.media.MediaTranscodeManager;
import android.app.SystemServiceRegistry;
import android.content.Context;
-import android.media.session.MediaSessionManager;
-
-import com.android.internal.util.Preconditions;
-
-import java.util.Objects;
/**
- * Class for performing registration for all media services
+ * Class for performing registration for all media services on com.android.media apex.
*
- * TODO (b/160513103): Move this class when moving media service code to APEX
* @hide
*/
+@SystemApi(client = Client.MODULE_LIBRARIES)
public class MediaFrameworkInitializer {
private MediaFrameworkInitializer() {
}
@@ -47,9 +45,15 @@
*/
public static void setMediaServiceManager(
@NonNull MediaServiceManager mediaServiceManager) {
- Preconditions.checkState(sMediaServiceManager == null,
- "setMediaServiceManager called twice!");
- sMediaServiceManager = Objects.requireNonNull(mediaServiceManager);
+ if (sMediaServiceManager != null) {
+ throw new IllegalStateException("setMediaServiceManager called twice!");
+ }
+
+ if (mediaServiceManager == null) {
+ throw new NullPointerException("mediaServiceManager is null!");
+ }
+
+ sMediaServiceManager = mediaServiceManager;
}
/** @hide */
@@ -66,9 +70,9 @@
*/
public static void registerServiceWrappers() {
SystemServiceRegistry.registerContextAwareService(
- Context.MEDIA_SESSION_SERVICE,
- MediaSessionManager.class,
- context -> new MediaSessionManager(context)
+ Context.MEDIA_TRANSCODING_SERVICE,
+ MediaTranscodeManager.class,
+ context -> new MediaTranscodeManager(context)
);
}
}
diff --git a/media/java/android/media/MediaTranscodeManager.java b/apex/media/framework/java/android/media/MediaTranscodeManager.java
similarity index 99%
rename from media/java/android/media/MediaTranscodeManager.java
rename to apex/media/framework/java/android/media/MediaTranscodeManager.java
index 705da19..d449289 100644
--- a/media/java/android/media/MediaTranscodeManager.java
+++ b/apex/media/framework/java/android/media/MediaTranscodeManager.java
@@ -28,7 +28,6 @@
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.ServiceSpecificException;
import android.system.Os;
import android.util.Log;
@@ -104,8 +103,6 @@
public final class MediaTranscodeManager {
private static final String TAG = "MediaTranscodeManager";
- private static final String MEDIA_TRANSCODING_SERVICE = "media.transcoding";
-
/** Maximum number of retry to connect to the service. */
private static final int CONNECT_SERVICE_RETRY_COUNT = 100;
@@ -281,7 +278,10 @@
for (int count = 1; count <= retryCount; count++) {
Log.d(TAG, "Trying to connect to service. Try count: " + count);
IMediaTranscodingService service = IMediaTranscodingService.Stub.asInterface(
- ServiceManager.getService(MEDIA_TRANSCODING_SERVICE));
+ MediaFrameworkInitializer
+ .getMediaServiceManager()
+ .getMediaTranscodingServiceRegisterer()
+ .get());
if (service != null) {
return service;
}
diff --git a/media/java/android/media/MediaTranscodingException.java b/apex/media/framework/java/android/media/MediaTranscodingException.java
similarity index 100%
rename from media/java/android/media/MediaTranscodingException.java
rename to apex/media/framework/java/android/media/MediaTranscodingException.java
diff --git a/apex/permission/framework/Android.bp b/apex/permission/framework/Android.bp
index c0560f6..36b5dec 100644
--- a/apex/permission/framework/Android.bp
+++ b/apex/permission/framework/Android.bp
@@ -19,6 +19,7 @@
"java/**/*.aidl",
],
path: "java",
+ visibility: ["//frameworks/base"],
}
java_sdk_library {
diff --git a/apex/permission/service/Android.bp b/apex/permission/service/Android.bp
index b7d8433..f6c3156 100644
--- a/apex/permission/service/Android.bp
+++ b/apex/permission/service/Android.bp
@@ -18,6 +18,7 @@
"java/**/*.java",
],
path: "java",
+ visibility: ["//frameworks/base/services"],
}
java_sdk_library {
diff --git a/cmds/idmap2/idmap2/Lookup.cpp b/cmds/idmap2/idmap2/Lookup.cpp
index 8323d0b..437180d 100644
--- a/cmds/idmap2/idmap2/Lookup.cpp
+++ b/cmds/idmap2/idmap2/Lookup.cpp
@@ -71,7 +71,7 @@
}
// next, try to parse as a package:type/name string
- if (auto resid = am.GetResourceId(res, "", fallback_package)) {
+ if (auto resid = am.GetResourceId(res, "", fallback_package); resid.ok()) {
return *resid;
}
@@ -94,7 +94,7 @@
case Res_value::TYPE_STRING: {
const ResStringPool* pool = am->GetStringPoolForCookie(value.cookie);
out->append("\"");
- if (auto str = pool->string8ObjectAt(value.data)) {
+ if (auto str = pool->string8ObjectAt(value.data); str.ok()) {
out->append(*str);
}
} break;
diff --git a/cmds/idmap2/libidmap2/XmlParser.cpp b/cmds/idmap2/libidmap2/XmlParser.cpp
index 7c55b64..4030b83 100644
--- a/cmds/idmap2/libidmap2/XmlParser.cpp
+++ b/cmds/idmap2/libidmap2/XmlParser.cpp
@@ -98,7 +98,7 @@
switch ((*value).dataType) {
case Res_value::TYPE_STRING: {
- if (auto str = parser_.getStrings().string8ObjectAt((*value).data)) {
+ if (auto str = parser_.getStrings().string8ObjectAt((*value).data); str.ok()) {
return std::string(str->string());
}
break;
diff --git a/config/preloaded-classes b/config/preloaded-classes
index 8d2f143..6f818a9 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -14027,7 +14027,6 @@
libcore.util.SneakyThrow
libcore.util.XmlObjectFactory
libcore.util.ZoneInfo
-org.apache.harmony.dalvik.NativeTestTarget
org.apache.harmony.dalvik.ddmc.Chunk
org.apache.harmony.dalvik.ddmc.ChunkHandler
org.apache.harmony.dalvik.ddmc.DdmServer
diff --git a/core/api/current.txt b/core/api/current.txt
index 779cb44..c11d2bc 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -1149,6 +1149,7 @@
field public static final int reqNavigation = 16843306; // 0x101022a
field public static final int reqTouchScreen = 16843303; // 0x1010227
field public static final int requestLegacyExternalStorage = 16844291; // 0x1010603
+ field public static final int requireDeviceScreenOn = 16844315; // 0x101061b
field public static final int requireDeviceUnlock = 16843756; // 0x10103ec
field public static final int required = 16843406; // 0x101028e
field public static final int requiredAccountType = 16843734; // 0x10103d6
@@ -10133,6 +10134,7 @@
method public abstract android.content.Context createDisplayContext(@NonNull android.view.Display);
method public abstract android.content.Context createPackageContext(String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method @NonNull public android.content.Context createWindowContext(int, @Nullable android.os.Bundle);
+ method @NonNull public android.content.Context createWindowContext(@NonNull android.view.Display, int, @Nullable android.os.Bundle);
method public abstract String[] databaseList();
method public abstract boolean deleteDatabase(String);
method public abstract boolean deleteFile(String);
@@ -19068,6 +19070,20 @@
field public static final int STATE_UNKNOWN = 0; // 0x0
}
+ public final class GnssMeasurementRequest implements android.os.Parcelable {
+ method public int describeContents();
+ method public boolean isFullTracking();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssMeasurementRequest> CREATOR;
+ }
+
+ public static final class GnssMeasurementRequest.Builder {
+ ctor public GnssMeasurementRequest.Builder();
+ ctor public GnssMeasurementRequest.Builder(@NonNull android.location.GnssMeasurementRequest);
+ method @NonNull public android.location.GnssMeasurementRequest build();
+ method @NonNull public android.location.GnssMeasurementRequest.Builder setFullTracking(boolean);
+ }
+
public final class GnssMeasurementsEvent implements android.os.Parcelable {
method public int describeContents();
method @NonNull public android.location.GnssClock getClock();
@@ -19294,6 +19310,7 @@
method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback);
method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback, @Nullable android.os.Handler);
method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
method @Deprecated public boolean registerGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback);
method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback, @Nullable android.os.Handler);
method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssNavigationMessageCallback(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssNavigationMessage.Callback);
@@ -19429,26 +19446,6 @@
package android.media {
- public final class ApplicationMediaCapabilities implements android.os.Parcelable {
- method @NonNull public static android.media.ApplicationMediaCapabilities createFromXml(@NonNull org.xmlpull.v1.XmlPullParser);
- method public int describeContents();
- method @NonNull public java.util.List<java.lang.String> getSupportedHdrTypes();
- method @NonNull public java.util.List<java.lang.String> getSupportedVideoMimeTypes();
- method public boolean isHdrTypeSupported(@NonNull String);
- method public boolean isSlowMotionSupported();
- method public boolean isVideoMimeTypeSupported(@NonNull String);
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.media.ApplicationMediaCapabilities> CREATOR;
- }
-
- public static final class ApplicationMediaCapabilities.Builder {
- ctor public ApplicationMediaCapabilities.Builder();
- method @NonNull public android.media.ApplicationMediaCapabilities.Builder addSupportedHdrType(@NonNull String);
- method @NonNull public android.media.ApplicationMediaCapabilities.Builder addSupportedVideoMimeType(@NonNull String);
- method @NonNull public android.media.ApplicationMediaCapabilities build();
- method @NonNull public android.media.ApplicationMediaCapabilities.Builder setSlowMotionSupported(boolean);
- }
-
public class AsyncPlayer {
ctor public AsyncPlayer(String);
method @Deprecated public void play(android.content.Context, android.net.Uri, boolean, int);
@@ -19669,15 +19666,18 @@
public class AudioManager {
method @Deprecated public int abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener);
method public int abandonAudioFocusRequest(@NonNull android.media.AudioFocusRequest);
+ method public void addOnCommunicationDeviceChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.OnCommunicationDeviceChangedListener);
method public void adjustStreamVolume(int, int, int);
method public void adjustSuggestedStreamVolume(int, int, int);
method public void adjustVolume(int, int);
+ method public void clearDeviceForCommunication();
method public void dispatchMediaKeyEvent(android.view.KeyEvent);
method public int generateAudioSessionId();
method @NonNull public java.util.List<android.media.AudioPlaybackConfiguration> getActivePlaybackConfigurations();
method @NonNull public java.util.List<android.media.AudioRecordingConfiguration> getActiveRecordingConfigurations();
method public int getAllowedCapturePolicy();
method public int getAudioHwSyncForSession(int);
+ method @Nullable public android.media.AudioDeviceInfo getDeviceForCommunication();
method public android.media.AudioDeviceInfo[] getDevices(int);
method public java.util.List<android.media.MicrophoneInfo> getMicrophones() throws java.io.IOException;
method public int getMode();
@@ -19713,11 +19713,13 @@
method @Deprecated public void registerMediaButtonEventReceiver(android.app.PendingIntent);
method @Deprecated public void registerRemoteControlClient(android.media.RemoteControlClient);
method @Deprecated public boolean registerRemoteController(android.media.RemoteController);
+ method public void removeOnCommunicationDeviceChangedListener(@NonNull android.media.AudioManager.OnCommunicationDeviceChangedListener);
method @Deprecated public int requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int);
method public int requestAudioFocus(@NonNull android.media.AudioFocusRequest);
method public void setAllowedCapturePolicy(int);
method @Deprecated public void setBluetoothA2dpOn(boolean);
method public void setBluetoothScoOn(boolean);
+ method public boolean setDeviceForCommunication(@NonNull android.media.AudioDeviceInfo);
method public void setMicrophoneMute(boolean);
method public void setMode(int);
method public void setParameters(String);
@@ -19855,6 +19857,10 @@
method public void onAudioFocusChange(int);
}
+ public static interface AudioManager.OnCommunicationDeviceChangedListener {
+ method public void onCommunicationDeviceChanged(@Nullable android.media.AudioDeviceInfo);
+ }
+
public final class AudioMetadata {
method @NonNull public static android.media.AudioMetadataMap createMap();
}
@@ -21559,17 +21565,6 @@
field public static final String TRACKS = "android.media.mediaextractor.ntrk";
}
- public final class MediaFeature {
- ctor public MediaFeature();
- }
-
- public static final class MediaFeature.HdrType {
- field public static final String DOLBY_VISION = "android.media.feature.hdr.dolby_vision";
- field public static final String HDR10 = "android.media.feature.hdr.hdr10";
- field public static final String HDR10_PLUS = "android.media.feature.hdr.hdr10_plus";
- field public static final String HLG = "android.media.feature.hdr.hlg";
- }
-
public final class MediaFormat {
ctor public MediaFormat();
ctor public MediaFormat(@NonNull android.media.MediaFormat);
@@ -22590,12 +22585,6 @@
field public static final android.media.MediaTimestamp TIMESTAMP_UNKNOWN;
}
- public class MediaTranscodingException extends java.lang.Exception {
- }
-
- public static final class MediaTranscodingException.ServiceNotAvailableException extends android.media.MediaTranscodingException {
- }
-
public interface MicrophoneDirection {
method public boolean setPreferredMicrophoneDirection(int);
method public boolean setPreferredMicrophoneFieldDimension(@FloatRange(from=-1.0, to=1.0) float);
@@ -33609,8 +33598,8 @@
}
protected static interface ContactsContract.DataColumns {
- field public static final String CARRIER_PRESENCE = "carrier_presence";
- field public static final int CARRIER_PRESENCE_VT_CAPABLE = 1; // 0x1
+ field @Deprecated public static final String CARRIER_PRESENCE = "carrier_presence";
+ field @Deprecated public static final int CARRIER_PRESENCE_VT_CAPABLE = 1; // 0x1
field public static final String DATA1 = "data1";
field public static final String DATA10 = "data10";
field public static final String DATA11 = "data11";
@@ -40660,9 +40649,10 @@
field public static final String KEY_TREAT_DOWNGRADED_VIDEO_CALLS_AS_VIDEO_CALLS_BOOL = "treat_downgraded_video_calls_as_video_calls_bool";
field public static final String KEY_TTY_SUPPORTED_BOOL = "tty_supported_bool";
field public static final String KEY_UNLOGGABLE_NUMBERS_STRING_ARRAY = "unloggable_numbers_string_array";
+ field public static final String KEY_USE_ACS_FOR_RCS_BOOL = "use_acs_for_rcs_bool";
field public static final String KEY_USE_HFA_FOR_PROVISIONING_BOOL = "use_hfa_for_provisioning_bool";
field public static final String KEY_USE_OTASP_FOR_PROVISIONING_BOOL = "use_otasp_for_provisioning_bool";
- field public static final String KEY_USE_RCS_PRESENCE_BOOL = "use_rcs_presence_bool";
+ field @Deprecated public static final String KEY_USE_RCS_PRESENCE_BOOL = "use_rcs_presence_bool";
field public static final String KEY_USE_RCS_SIP_OPTIONS_BOOL = "use_rcs_sip_options_bool";
field public static final String KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL = "use_wfc_home_network_mode_in_roaming_network_bool";
field public static final String KEY_VOICEMAIL_NOTIFICATION_PERSISTENT_BOOL = "voicemail_notification_persistent_bool";
@@ -40702,12 +40692,79 @@
}
public static final class CarrierConfigManager.Ims {
+ field public static final String KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL = "ims.enable_presence_capability_exchange_bool";
+ field public static final String KEY_ENABLE_PRESENCE_GROUP_SUBSCRIBE_BOOL = "ims.enable_presence_group_subscribe_bool";
field public static final String KEY_ENABLE_PRESENCE_PUBLISH_BOOL = "ims.enable_presence_publish_bool";
field public static final String KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL = "ims.ims_single_registration_required_bool";
field public static final String KEY_PREFIX = "ims.";
+ field public static final String KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL = "ims.rcs_bulk_capability_exchange_bool";
field public static final String KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT = "ims.wifi_off_deferring_time_millis_int";
}
+ public static final class CarrierConfigManager.Iwlan {
+ field public static final int AUTHENTICATION_METHOD_CERT = 1; // 0x1
+ field public static final int AUTHENTICATION_METHOD_EAP_ONLY = 0; // 0x0
+ field public static final int DH_GROUP_1024_BIT_MODP = 2; // 0x2
+ field public static final int DH_GROUP_1536_BIT_MODP = 5; // 0x5
+ field public static final int DH_GROUP_2048_BIT_MODP = 14; // 0xe
+ field public static final int DH_GROUP_3072_BIT_MODP = 15; // 0xf
+ field public static final int DH_GROUP_4096_BIT_MODP = 16; // 0x10
+ field public static final int DH_GROUP_NONE = 0; // 0x0
+ field public static final int ENCRYPTION_ALGORITHM_AES_CBC = 12; // 0xc
+ field public static final int ENCRYPTION_ALGORITHM_AES_CTR = 13; // 0xd
+ field public static final int EPDG_ADDRESS_CELLULAR_LOC = 3; // 0x3
+ field public static final int EPDG_ADDRESS_PCO = 2; // 0x2
+ field public static final int EPDG_ADDRESS_PLMN = 1; // 0x1
+ field public static final int EPDG_ADDRESS_STATIC = 0; // 0x0
+ field public static final int ID_TYPE_FQDN = 2; // 0x2
+ field public static final int ID_TYPE_KEY_ID = 11; // 0xb
+ field public static final int ID_TYPE_RFC822_ADDR = 3; // 0x3
+ field public static final int INTEGRITY_ALGORITHM_AES_XCBC_96 = 5; // 0x5
+ field public static final int INTEGRITY_ALGORITHM_HMAC_SHA1_96 = 2; // 0x2
+ field public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_256_128 = 12; // 0xc
+ field public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_384_192 = 13; // 0xd
+ field public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_512_256 = 14; // 0xe
+ field public static final int INTEGRITY_ALGORITHM_NONE = 0; // 0x0
+ field public static final String KEY_ADD_KE_TO_CHILD_SESSION_REKEY_BOOL = "iwlan.add_ke_to_child_session_rekey_bool";
+ field public static final String KEY_ADD_WIFI_MAC_ADDR_TO_NAI_BOOL = "iwlan.add_wifi_mac_addr_to_nai_bool";
+ field public static final String KEY_CHILD_SA_REKEY_HARD_TIMER_SEC_INT = "iwlan.child_sa_rekey_hard_timer_sec_int";
+ field public static final String KEY_CHILD_SA_REKEY_SOFT_TIMER_SEC_INT = "iwlan.child_sa_rekey_soft_timer_sec_int";
+ field public static final String KEY_CHILD_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY = "iwlan.child_session_aes_cbc_key_size_int_array";
+ field public static final String KEY_CHILD_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY = "iwlan.child_session_aes_ctr_key_size_int_array";
+ field public static final String KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY = "iwlan.diffie_hellman_groups_int_array";
+ field public static final String KEY_DPD_TIMER_SEC_INT = "iwlan.dpd_timer_sec_int";
+ field public static final String KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY = "iwlan.epdg_address_priority_int_array";
+ field public static final String KEY_EPDG_AUTHENTICATION_METHOD_INT = "iwlan.epdg_authentication_method_int";
+ field public static final String KEY_EPDG_PCO_ID_IPV4_INT = "iwlan.epdg_pco_id_ipv4_int";
+ field public static final String KEY_EPDG_PCO_ID_IPV6_INT = "iwlan.epdg_pco_id_ipv6_int";
+ field public static final String KEY_EPDG_STATIC_ADDRESS_ROAMING_STRING = "iwlan.epdg_static_address_roaming_string";
+ field public static final String KEY_EPDG_STATIC_ADDRESS_STRING = "iwlan.epdg_static_address_string";
+ field public static final String KEY_IKE_LOCAL_ID_TYPE_INT = "iwlan.ike_local_id_type_int";
+ field public static final String KEY_IKE_REKEY_HARD_TIMER_SEC_INT = "iwlan.ike_rekey_hard_timer_in_sec";
+ field public static final String KEY_IKE_REKEY_SOFT_TIMER_SEC_INT = "iwlan.ike_rekey_soft_timer_sec_int";
+ field public static final String KEY_IKE_REMOTE_ID_TYPE_INT = "iwlan.ike_remote_id_type_int";
+ field public static final String KEY_IKE_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY = "iwlan.ike_session_encryption_aes_cbc_key_size_int_array";
+ field public static final String KEY_IKE_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY = "iwlan.ike_session_encryption_aes_ctr_key_size_int_array";
+ field public static final int KEY_LEN_AES_128 = 128; // 0x80
+ field public static final int KEY_LEN_AES_192 = 192; // 0xc0
+ field public static final int KEY_LEN_AES_256 = 256; // 0x100
+ field public static final int KEY_LEN_UNUSED = 0; // 0x0
+ field public static final String KEY_MAX_RETRIES_INT = "iwlan.max_retries_int";
+ field public static final String KEY_MCC_MNCS_STRING_ARRAY = "iwlan.mcc_mncs_string_array";
+ field public static final String KEY_NATT_KEEP_ALIVE_TIMER_SEC_INT = "iwlan.natt_keep_alive_timer_sec_int";
+ field public static final String KEY_PREFIX = "iwlan.";
+ field public static final String KEY_RETRANSMIT_TIMER_MSEC_INT_ARRAY = "iwlan.retransmit_timer_sec_int_array";
+ field public static final String KEY_SUPPORTED_CHILD_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY = "iwlan.supported_child_session_encryption_algorithms_int_array";
+ field public static final String KEY_SUPPORTED_IKE_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY = "iwlan.supported_ike_session_encryption_algorithms_int_array";
+ field public static final String KEY_SUPPORTED_INTEGRITY_ALGORITHMS_INT_ARRAY = "iwlan.supported_integrity_algorithms_int_array";
+ field public static final String KEY_SUPPORTED_PRF_ALGORITHMS_INT_ARRAY = "iwlan.supported_prf_algorithms_int_array";
+ field public static final int PSEUDORANDOM_FUNCTION_AES128_XCBC = 4; // 0x4
+ field public static final int PSEUDORANDOM_FUNCTION_HMAC_SHA1 = 2; // 0x2
+ field public static final int PSEUDORANDOM_FUNCTION_SHA2_256 = 5; // 0x5
+ field public static final int PSEUDORANDOM_FUNCTION_SHA2_384 = 6; // 0x6
+ field public static final int PSEUDORANDOM_FUNCTION_SHA2_512 = 7; // 0x7
+ }
+
public abstract class CellIdentity implements android.os.Parcelable {
method public int describeContents();
method @Nullable public CharSequence getOperatorAlphaLong();
@@ -40912,7 +40969,8 @@
public final class CellSignalStrengthLte extends android.telephony.CellSignalStrength implements android.os.Parcelable {
method public int describeContents();
method public int getAsuLevel();
- method public int getCqi();
+ method @IntRange(from=0, to=15) public int getCqi();
+ method @IntRange(from=1, to=6) public int getCqiTableIndex();
method public int getDbm();
method @IntRange(from=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN, to=android.telephony.CellSignalStrength.SIGNAL_STRENGTH_GREAT) public int getLevel();
method public int getRsrp();
@@ -40927,6 +40985,8 @@
public final class CellSignalStrengthNr extends android.telephony.CellSignalStrength implements android.os.Parcelable {
method public int describeContents();
method public int getAsuLevel();
+ method @IntRange(from=0, to=15) @NonNull public java.util.List<java.lang.Integer> getCsiCqiReport();
+ method @IntRange(from=1, to=3) public int getCsiCqiTableIndex();
method public int getCsiRsrp();
method public int getCsiRsrq();
method public int getCsiSinr();
@@ -41293,6 +41353,7 @@
field public static final int SERVICE_OPTION_OUT_OF_ORDER = 34; // 0x22
field public static final int SIGNAL_LOST = -3; // 0xfffffffd
field public static final int SIM_CARD_CHANGED = 2043; // 0x7fb
+ field public static final int SLICE_REJECTED = 2252; // 0x8cc
field public static final int SYNCHRONIZATION_FAILURE = 2184; // 0x888
field public static final int TEST_LOOPBACK_REGULAR_DEACTIVATION = 2196; // 0x894
field public static final int TETHERED_CALL_ACTIVE = -6; // 0xfffffffa
@@ -42202,6 +42263,7 @@
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean doesSwitchMultiSimConfigTriggerReboot();
method public int getActiveModemCount();
method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public java.util.List<android.telephony.CellInfo> getAllCellInfo();
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public int getCallComposerStatus();
method public int getCallState();
method public int getCardIdForDefaultEuicc();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) @WorkerThread public android.os.PersistableBundle getCarrierConfig();
@@ -42298,6 +42360,7 @@
method @Deprecated public String sendEnvelopeWithStatus(String);
method @RequiresPermission(android.Manifest.permission.CALL_PHONE) public void sendUssdRequest(String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler);
method public void sendVisualVoicemailSms(String, int, String, android.app.PendingIntent);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCallComposerStatus(int);
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabledForReason(int, boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setForbiddenPlmns(@NonNull java.util.List<java.lang.String>);
@@ -42338,6 +42401,8 @@
field public static final int APPTYPE_USIM = 2; // 0x2
field public static final int AUTHTYPE_EAP_AKA = 129; // 0x81
field public static final int AUTHTYPE_EAP_SIM = 128; // 0x80
+ field public static final int CALL_COMPOSER_STATUS_OFF = 0; // 0x0
+ field public static final int CALL_COMPOSER_STATUS_ON = 1; // 0x1
field public static final int CALL_STATE_IDLE = 0; // 0x0
field public static final int CALL_STATE_OFFHOOK = 2; // 0x2
field public static final int CALL_STATE_RINGING = 1; // 0x1
@@ -46295,7 +46360,6 @@
method public int getFlags();
method @Nullable public android.net.Uri getLinkUri();
method public int getSource();
- method @NonNull public android.util.Pair<android.view.ContentInfo,android.view.ContentInfo> partition(@NonNull java.util.function.Predicate<android.content.ClipData.Item>);
field public static final int FLAG_CONVERT_TO_PLAIN_TEXT = 1; // 0x1
field public static final int SOURCE_APP = 0; // 0x0
field public static final int SOURCE_AUTOFILL = 4; // 0x4
@@ -46611,6 +46675,7 @@
method public java.util.List<android.view.InputDevice.MotionRange> getMotionRanges();
method public String getName();
method public int getProductId();
+ method @NonNull public android.hardware.SensorManager getSensorManager();
method public int getSources();
method public int getVendorId();
method public android.os.Vibrator getVibrator();
@@ -51196,6 +51261,7 @@
method public boolean performContextMenuAction(int);
method public boolean performEditorAction(int);
method public boolean performPrivateCommand(String, android.os.Bundle);
+ method public default boolean performSpellCheck();
method public boolean reportFullscreenMode(boolean);
method public boolean requestCursorUpdates(int);
method public boolean sendKeyEvent(android.view.KeyEvent);
@@ -52080,6 +52146,7 @@
method public void setCookieAndSequence(int, int);
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.view.textservice.SuggestionsInfo> CREATOR;
+ field public static final int RESULT_ATTR_DONT_SHOW_UI_FOR_SUGGESTIONS = 16; // 0x10
field public static final int RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS = 4; // 0x4
field public static final int RESULT_ATTR_IN_THE_DICTIONARY = 1; // 0x1
field public static final int RESULT_ATTR_LOOKS_LIKE_GRAMMAR_ERROR = 8; // 0x8
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index cbb3bea..94a6576 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -80,6 +80,17 @@
public class MediaMetadataRetriever implements java.lang.AutoCloseable {
field public static final int METADATA_KEY_VIDEO_CODEC_MIME_TYPE = 40; // 0x28
+ field public static final int METADATA_KEY_XMP_LENGTH = 42; // 0x2a
+ field public static final int METADATA_KEY_XMP_OFFSET = 41; // 0x29
+ }
+
+ public class MediaServiceManager {
+ method @NonNull public android.media.MediaServiceManager.ServiceRegisterer getMediaSessionServiceRegisterer();
+ method @NonNull public android.media.MediaServiceManager.ServiceRegisterer getMediaTranscodingServiceRegisterer();
+ }
+
+ public static final class MediaServiceManager.ServiceRegisterer {
+ method @Nullable public android.os.IBinder get();
}
}
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 58606d2..70400b1 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -60,6 +60,7 @@
field public static final String CAMERA_OPEN_CLOSE_LISTENER = "android.permission.CAMERA_OPEN_CLOSE_LISTENER";
field public static final String CAPTURE_AUDIO_HOTWORD = "android.permission.CAPTURE_AUDIO_HOTWORD";
field public static final String CAPTURE_MEDIA_OUTPUT = "android.permission.CAPTURE_MEDIA_OUTPUT";
+ field public static final String CAPTURE_TUNER_AUDIO_INPUT = "android.permission.CAPTURE_TUNER_AUDIO_INPUT";
field public static final String CAPTURE_TV_INPUT = "android.permission.CAPTURE_TV_INPUT";
field public static final String CAPTURE_VOICE_COMMUNICATION_OUTPUT = "android.permission.CAPTURE_VOICE_COMMUNICATION_OUTPUT";
field public static final String CHANGE_APP_IDLE_STATE = "android.permission.CHANGE_APP_IDLE_STATE";
@@ -1932,6 +1933,7 @@
field public static final String EUICC_CARD_SERVICE = "euicc_card";
field public static final String HDMI_CONTROL_SERVICE = "hdmi_control";
field public static final String MEDIA_TRANSCODING_SERVICE = "media_transcoding";
+ field public static final String MUSIC_RECOGNITION_SERVICE = "music_recognition";
field public static final String NETD_SERVICE = "netd";
field public static final String NETWORK_SCORE_SERVICE = "network_score";
field public static final String OEM_LOCK_SERVICE = "oem_lock";
@@ -2120,6 +2122,9 @@
public class ApplicationInfo extends android.content.pm.PackageItemInfo implements android.os.Parcelable {
method public boolean isEncryptionAware();
method public boolean isInstantApp();
+ method public boolean isOem();
+ method public boolean isProduct();
+ method public boolean isVendor();
field public String credentialProtectedDataDir;
field public int targetSandboxVersion;
}
@@ -4311,7 +4316,7 @@
method @Deprecated @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public boolean isProviderPackage(@NonNull String);
method @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public boolean isProviderPackage(@Nullable String, @NonNull String);
method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.LOCATION_HARDWARE, android.Manifest.permission.UPDATE_APP_OPS_STATS}) public boolean registerGnssBatchedLocationCallback(long, boolean, @NonNull android.location.BatchedLocationCallback, @Nullable android.os.Handler);
- method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.LOCATION_HARDWARE}) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.app.PendingIntent);
@@ -4588,68 +4593,6 @@
field @RequiresPermission(android.Manifest.permission.CAPTURE_AUDIO_OUTPUT) public static final int RADIO_TUNER = 1998; // 0x7ce
}
- public final class MediaTranscodeManager {
- method @NonNull public android.media.MediaTranscodeManager.TranscodingSession enqueueRequest(@NonNull android.media.MediaTranscodeManager.TranscodingRequest, @NonNull java.util.concurrent.Executor, @NonNull android.media.MediaTranscodeManager.OnTranscodingFinishedListener) throws java.io.FileNotFoundException, android.media.MediaTranscodingException.ServiceNotAvailableException;
- field public static final int PRIORITY_REALTIME = 1; // 0x1
- field public static final int TRANSCODING_TYPE_VIDEO = 1; // 0x1
- }
-
- @java.lang.FunctionalInterface public static interface MediaTranscodeManager.OnTranscodingFinishedListener {
- method public void onTranscodingFinished(@NonNull android.media.MediaTranscodeManager.TranscodingSession);
- }
-
- public static final class MediaTranscodeManager.TranscodingRequest {
- method public int getClientPid();
- method public int getClientUid();
- method @NonNull public android.net.Uri getDestinationUri();
- method public int getPriority();
- method @NonNull public android.net.Uri getSourceUri();
- method public int getType();
- method @Nullable public android.media.MediaFormat getVideoTrackFormat();
- }
-
- public static final class MediaTranscodeManager.TranscodingRequest.Builder {
- ctor public MediaTranscodeManager.TranscodingRequest.Builder();
- method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest build();
- method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setClientPid(int);
- method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setClientUid(int);
- method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setDestinationUri(@NonNull android.net.Uri);
- method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setPriority(int);
- method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setSourceUri(@NonNull android.net.Uri);
- method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setType(int);
- method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.Builder setVideoTrackFormat(@NonNull android.media.MediaFormat);
- }
-
- public static class MediaTranscodeManager.TranscodingRequest.MediaFormatResolver {
- ctor public MediaTranscodeManager.TranscodingRequest.MediaFormatResolver();
- method @Nullable public android.media.MediaFormat resolveVideoFormat();
- method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.MediaFormatResolver setClientCapabilities(@NonNull android.media.ApplicationMediaCapabilities);
- method @NonNull public android.media.MediaTranscodeManager.TranscodingRequest.MediaFormatResolver setSourceVideoFormatHint(@NonNull android.media.MediaFormat);
- method public boolean shouldTranscode();
- }
-
- public static final class MediaTranscodeManager.TranscodingSession {
- method public void cancel();
- method @IntRange(from=0, to=100) public int getProgress();
- method public int getResult();
- method public int getSessionId();
- method public int getStatus();
- method public void setOnProgressUpdateListener(@NonNull java.util.concurrent.Executor, @Nullable android.media.MediaTranscodeManager.TranscodingSession.OnProgressUpdateListener);
- method public void setOnProgressUpdateListener(int, @NonNull java.util.concurrent.Executor, @Nullable android.media.MediaTranscodeManager.TranscodingSession.OnProgressUpdateListener);
- field public static final int RESULT_CANCELED = 4; // 0x4
- field public static final int RESULT_ERROR = 3; // 0x3
- field public static final int RESULT_NONE = 1; // 0x1
- field public static final int RESULT_SUCCESS = 2; // 0x2
- field public static final int STATUS_FINISHED = 3; // 0x3
- field public static final int STATUS_PAUSED = 4; // 0x4
- field public static final int STATUS_PENDING = 1; // 0x1
- field public static final int STATUS_RUNNING = 2; // 0x2
- }
-
- @java.lang.FunctionalInterface public static interface MediaTranscodeManager.TranscodingSession.OnProgressUpdateListener {
- method public void onProgressUpdate(@NonNull android.media.MediaTranscodeManager.TranscodingSession, @IntRange(from=0, to=100) int);
- }
-
public class PlayerProxy {
method public void pause();
method public void setPan(float);
@@ -8051,12 +7994,14 @@
public class RecoverySystem {
method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void cancelScheduledUpdate(android.content.Context) throws java.io.IOException;
- method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void clearPrepareForUnattendedUpdate(@NonNull android.content.Context) throws java.io.IOException;
+ method @RequiresPermission(anyOf={android.Manifest.permission.RECOVERY, android.Manifest.permission.REBOOT}) public static void clearPrepareForUnattendedUpdate(@NonNull android.content.Context) throws java.io.IOException;
method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void installPackage(android.content.Context, java.io.File, boolean) throws java.io.IOException;
- method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void prepareForUnattendedUpdate(@NonNull android.content.Context, @NonNull String, @Nullable android.content.IntentSender) throws java.io.IOException;
+ method @RequiresPermission(anyOf={android.Manifest.permission.RECOVERY, android.Manifest.permission.REBOOT}) public static boolean isPreparedForUnattendedUpdate(@NonNull android.content.Context) throws java.io.IOException;
+ method @RequiresPermission(anyOf={android.Manifest.permission.RECOVERY, android.Manifest.permission.REBOOT}) public static void prepareForUnattendedUpdate(@NonNull android.content.Context, @NonNull String, @Nullable android.content.IntentSender) throws java.io.IOException;
method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void processPackage(android.content.Context, java.io.File, android.os.RecoverySystem.ProgressListener, android.os.Handler) throws java.io.IOException;
method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void processPackage(android.content.Context, java.io.File, android.os.RecoverySystem.ProgressListener) throws java.io.IOException;
- method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void rebootAndApply(@NonNull android.content.Context, @NonNull String, @NonNull String) throws java.io.IOException;
+ method @Deprecated @RequiresPermission(android.Manifest.permission.RECOVERY) public static void rebootAndApply(@NonNull android.content.Context, @NonNull String, @NonNull String) throws java.io.IOException;
+ method @RequiresPermission(anyOf={android.Manifest.permission.RECOVERY, android.Manifest.permission.REBOOT}) public static void rebootAndApply(@NonNull android.content.Context, @NonNull String, boolean) throws java.io.IOException;
method @RequiresPermission(allOf={android.Manifest.permission.RECOVERY, android.Manifest.permission.REBOOT}) public static void rebootWipeAb(android.content.Context, java.io.File, String) throws java.io.IOException;
method @RequiresPermission(android.Manifest.permission.RECOVERY) public static void scheduleUpdateOnBoot(android.content.Context, java.io.File) throws java.io.IOException;
method public static boolean verifyPackageCompatibility(java.io.File) throws java.io.IOException;
@@ -9777,6 +9722,7 @@
ctor public ExternalStorageService();
method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent);
method public abstract void onEndSession(@NonNull String) throws java.io.IOException;
+ method public void onFreeCacheRequested(@NonNull java.util.UUID, long);
method public abstract void onStartSession(@NonNull String, int, @NonNull android.os.ParcelFileDescriptor, @NonNull java.io.File, @NonNull java.io.File) throws java.io.IOException;
method public abstract void onVolumeStateChanged(@NonNull android.os.storage.StorageVolume) throws java.io.IOException;
field public static final int FLAG_SESSION_ATTRIBUTE_INDEXABLE = 2; // 0x2
@@ -9814,6 +9760,38 @@
}
+package android.service.timezone {
+
+ public abstract class TimeZoneProviderService extends android.app.Service {
+ ctor public TimeZoneProviderService();
+ method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent);
+ method public abstract void onStartUpdates(long);
+ method public abstract void onStopUpdates();
+ method public final void reportPermanentFailure(@NonNull Throwable);
+ method public final void reportSuggestion(@NonNull android.service.timezone.TimeZoneProviderSuggestion);
+ method public final void reportUncertain();
+ field public static final String BIND_PERMISSION = "android.permission.INSTALL_LOCATION_TIME_ZONE_PROVIDER";
+ field public static final String PRIMARY_LOCATION_TIME_ZONE_PROVIDER_SERVICE_INTERFACE = "android.service.timezone.PrimaryLocationTimeZoneProviderService";
+ field public static final String SECONDARY_LOCATION_TIME_ZONE_PROVIDER_SERVICE_INTERFACE = "android.service.timezone.SecondaryLocationTimeZoneProviderService";
+ }
+
+ public final class TimeZoneProviderSuggestion implements android.os.Parcelable {
+ method public int describeContents();
+ method public long getElapsedRealtimeMillis();
+ method @NonNull public java.util.List<java.lang.String> getTimeZoneIds();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.service.timezone.TimeZoneProviderSuggestion> CREATOR;
+ }
+
+ public static final class TimeZoneProviderSuggestion.Builder {
+ ctor public TimeZoneProviderSuggestion.Builder();
+ method @NonNull public android.service.timezone.TimeZoneProviderSuggestion build();
+ method @NonNull public android.service.timezone.TimeZoneProviderSuggestion.Builder setElapsedRealtimeMillis(long);
+ method @NonNull public android.service.timezone.TimeZoneProviderSuggestion.Builder setTimeZoneIds(@NonNull java.util.List<java.lang.String>);
+ }
+
+}
+
package android.service.trust {
public class TrustAgentService extends android.app.Service {
@@ -11006,6 +10984,7 @@
method public boolean disableCellBroadcastRange(int, int, int);
method public boolean enableCellBroadcastRange(int, int, int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getPremiumSmsConsent(@NonNull String);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_CELL_BROADCASTS) public void resetAllCellBroadcastRanges();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void sendMultipartTextMessageWithoutPersisting(String, String, java.util.List<java.lang.String>, java.util.List<android.app.PendingIntent>, java.util.List<android.app.PendingIntent>);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setPremiumSmsConsent(@NonNull String, int);
field public static final int PREMIUM_SMS_CONSENT_ALWAYS_ALLOW = 3; // 0x3
@@ -11486,6 +11465,7 @@
method public int getPduSessionId();
method public int getProtocolType();
method public long getRetryDurationMillis();
+ method @Nullable public android.telephony.data.SliceInfo getSliceInfo();
method @Deprecated public int getSuggestedRetryTime();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.DataCallResponse> CREATOR;
@@ -11520,6 +11500,7 @@
method @NonNull public android.telephony.data.DataCallResponse.Builder setPduSessionId(int);
method @NonNull public android.telephony.data.DataCallResponse.Builder setProtocolType(int);
method @NonNull public android.telephony.data.DataCallResponse.Builder setRetryDurationMillis(long);
+ method @NonNull public android.telephony.data.DataCallResponse.Builder setSliceInfo(@Nullable android.telephony.data.SliceInfo);
method @Deprecated @NonNull public android.telephony.data.DataCallResponse.Builder setSuggestedRetryTime(int);
}
@@ -11592,7 +11573,7 @@
method public void setDataProfile(@NonNull java.util.List<android.telephony.data.DataProfile>, boolean, @NonNull android.telephony.data.DataServiceCallback);
method public void setInitialAttachApn(@NonNull android.telephony.data.DataProfile, boolean, @NonNull android.telephony.data.DataServiceCallback);
method public void setupDataCall(int, @NonNull android.telephony.data.DataProfile, boolean, boolean, int, @Nullable android.net.LinkProperties, @NonNull android.telephony.data.DataServiceCallback);
- method public void setupDataCall(int, @NonNull android.telephony.data.DataProfile, boolean, boolean, int, @Nullable android.net.LinkProperties, @IntRange(from=0, to=15) int, @NonNull android.telephony.data.DataServiceCallback);
+ method public void setupDataCall(int, @NonNull android.telephony.data.DataProfile, boolean, boolean, int, @Nullable android.net.LinkProperties, @IntRange(from=0, to=15) int, @Nullable android.telephony.data.SliceInfo, @NonNull android.telephony.data.DataServiceCallback);
method public void startHandover(int, @NonNull android.telephony.data.DataServiceCallback);
}
@@ -11627,6 +11608,32 @@
method public final void updateQualifiedNetworkTypes(int, @NonNull java.util.List<java.lang.Integer>);
}
+ public final class SliceInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method @IntRange(from=android.telephony.data.SliceInfo.MIN_SLICE_DIFFERENTIATOR, to=android.telephony.data.SliceInfo.MAX_SLICE_DIFFERENTIATOR) public int getMappedHplmnSliceDifferentiator();
+ method public int getMappedHplmnSliceServiceType();
+ method @IntRange(from=android.telephony.data.SliceInfo.MIN_SLICE_DIFFERENTIATOR, to=android.telephony.data.SliceInfo.MAX_SLICE_DIFFERENTIATOR) public int getSliceDifferentiator();
+ method public int getSliceServiceType();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.data.SliceInfo> CREATOR;
+ field public static final int MAX_SLICE_DIFFERENTIATOR = 16777214; // 0xfffffe
+ field public static final int MIN_SLICE_DIFFERENTIATOR = -1; // 0xffffffff
+ field public static final int SLICE_DIFFERENTIATOR_NO_SLICE = -1; // 0xffffffff
+ field public static final int SLICE_SERVICE_TYPE_EMBB = 1; // 0x1
+ field public static final int SLICE_SERVICE_TYPE_MIOT = 3; // 0x3
+ field public static final int SLICE_SERVICE_TYPE_NONE = 0; // 0x0
+ field public static final int SLICE_SERVICE_TYPE_URLLC = 2; // 0x2
+ }
+
+ public static final class SliceInfo.Builder {
+ ctor public SliceInfo.Builder();
+ method @NonNull public android.telephony.data.SliceInfo build();
+ method @NonNull public android.telephony.data.SliceInfo.Builder setMappedHplmnSliceDifferentiator(@IntRange(from=android.telephony.data.SliceInfo.MIN_SLICE_DIFFERENTIATOR, to=android.telephony.data.SliceInfo.MAX_SLICE_DIFFERENTIATOR) int);
+ method @NonNull public android.telephony.data.SliceInfo.Builder setMappedHplmnSliceServiceType(int);
+ method @NonNull public android.telephony.data.SliceInfo.Builder setSliceDifferentiator(@IntRange(from=android.telephony.data.SliceInfo.MIN_SLICE_DIFFERENTIATOR, to=android.telephony.data.SliceInfo.MAX_SLICE_DIFFERENTIATOR) int);
+ method @NonNull public android.telephony.data.SliceInfo.Builder setSliceServiceType(int);
+ }
+
}
package android.telephony.euicc {
@@ -12457,18 +12464,29 @@
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getProvisioningStatusForCapability(int, int);
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public String getProvisioningStringValue(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getRcsProvisioningStatusForCapability(int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isRcsVolteSingleRegistrationCapable() throws android.telephony.ims.ImsException;
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void notifyRcsAutoConfigurationReceived(@NonNull byte[], boolean);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.Callback) throws android.telephony.ims.ImsException;
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerRcsProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.RcsProvisioningCallback) throws android.telephony.ims.ImsException;
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningIntValue(int, int);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setProvisioningStatusForCapability(int, int, boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, @NonNull String);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRcsClientConfiguration(@NonNull android.telephony.ims.RcsClientConfiguration) throws android.telephony.ims.ImsException;
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setRcsProvisioningStatusForCapability(int, boolean);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void triggerRcsReconfiguration();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterRcsProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.RcsProvisioningCallback);
+ field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE = "android.telephony.ims.action.RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE";
+ field public static final String EXTRA_STATUS = "android.telephony.ims.extra.STATUS";
+ field public static final String EXTRA_SUBSCRIPTION_ID = "android.telephony.ims.extra.SUBSCRIPTION_ID";
field public static final int KEY_VOICE_OVER_WIFI_ENTITLEMENT_ID = 67; // 0x43
field public static final int KEY_VOICE_OVER_WIFI_MODE_OVERRIDE = 27; // 0x1b
field public static final int KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE = 26; // 0x1a
field public static final int PROVISIONING_VALUE_DISABLED = 0; // 0x0
field public static final int PROVISIONING_VALUE_ENABLED = 1; // 0x1
+ field public static final int STATUS_CAPABLE = 0; // 0x0
+ field public static final int STATUS_CARRIER_NOT_CAPABLE = 2; // 0x2
+ field public static final int STATUS_DEVICE_NOT_CAPABLE = 1; // 0x1
field public static final String STRING_QUERY_RESULT_ERROR_GENERIC = "STRING_QUERY_RESULT_ERROR_GENERIC";
field public static final String STRING_QUERY_RESULT_ERROR_NOT_READY = "STRING_QUERY_RESULT_ERROR_NOT_READY";
}
@@ -12479,6 +12497,27 @@
method public void onProvisioningStringChanged(int, @NonNull String);
}
+ public static class ProvisioningManager.RcsProvisioningCallback {
+ ctor public ProvisioningManager.RcsProvisioningCallback();
+ method public void onAutoConfigurationErrorReceived(int, @NonNull String);
+ method public void onConfigurationChanged(@NonNull byte[]);
+ method public void onConfigurationReset();
+ method public void onRemoved();
+ }
+
+ public final class RcsClientConfiguration implements android.os.Parcelable {
+ ctor public RcsClientConfiguration(@NonNull String, @NonNull String, @NonNull String, @NonNull String);
+ method public int describeContents();
+ method @NonNull public String getClientVendor();
+ method @NonNull public String getClientVersion();
+ method @NonNull public String getRcsProfile();
+ method @NonNull public String getRcsVersion();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.RcsClientConfiguration> CREATOR;
+ field public static final String RCS_PROFILE_1_0 = "UP_1.0";
+ field public static final String RCS_PROFILE_2_3 = "UP_2.3";
+ }
+
public class RcsUceAdapter {
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUceSettingEnabled(boolean) throws android.telephony.ims.ImsException;
}
@@ -12571,6 +12610,7 @@
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void createSipDelegate(@NonNull android.telephony.ims.DelegateRequest, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.stub.DelegateConnectionStateCallback, @NonNull android.telephony.ims.stub.DelegateConnectionMessageCallback) throws android.telephony.ims.ImsException;
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void destroySipDelegate(@NonNull android.telephony.ims.SipDelegateConnection, int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isSupported() throws android.telephony.ims.ImsException;
+ method public void triggerFullNetworkRegistration(@NonNull android.telephony.ims.SipDelegateConnection, @IntRange(from=100, to=699) int, @Nullable String);
field public static final int DENIED_REASON_INVALID = 4; // 0x4
field public static final int DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE = 1; // 0x1
field public static final int DENIED_REASON_NOT_ALLOWED = 2; // 0x2
@@ -12766,11 +12806,15 @@
ctor public ImsConfigImplBase();
method public int getConfigInt(int);
method public String getConfigString(int);
+ method public final void notifyAutoConfigurationErrorReceived(int, @NonNull String);
method public final void notifyProvisionedValueChanged(int, int);
method public final void notifyProvisionedValueChanged(int, String);
method public void notifyRcsAutoConfigurationReceived(@NonNull byte[], boolean);
+ method public void notifyRcsAutoConfigurationRemoved();
method public int setConfig(int, int);
method public int setConfig(int, String);
+ method public void setRcsClientConfiguration(@NonNull android.telephony.ims.RcsClientConfiguration);
+ method public void triggerAutoConfiguration();
field public static final int CONFIG_RESULT_FAILED = 1; // 0x1
field public static final int CONFIG_RESULT_SUCCESS = 0; // 0x0
field public static final int CONFIG_RESULT_UNKNOWN = -1; // 0xffffffff
@@ -12815,6 +12859,9 @@
method public final void onRegistering(int);
method public final void onSubscriberAssociatedUriChanged(android.net.Uri[]);
method public final void onTechnologyChangeFailed(int, android.telephony.ims.ImsReasonInfo);
+ method public void triggerFullNetworkRegistration(@IntRange(from=100, to=699) int, @Nullable String);
+ method public void triggerSipDelegateDeregistration();
+ method public void updateSipDelegateRegistration();
field public static final int REGISTRATION_TECH_IWLAN = 1; // 0x1
field public static final int REGISTRATION_TECH_LTE = 0; // 0x0
field public static final int REGISTRATION_TECH_NONE = -1; // 0xffffffff
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 1998563..5b86e8d 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -141,7 +141,6 @@
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public boolean moveTopActivityToPinnedRootTask(int, @NonNull android.graphics.Rect);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public void removeRootTasksInWindowingModes(@NonNull int[]);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public void removeRootTasksWithActivityTypes(@NonNull int[]);
- method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public void requestPictureInPictureMode(@NonNull android.os.IBinder);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public void resizePrimarySplitScreen(@NonNull android.graphics.Rect, @NonNull android.graphics.Rect);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public void resizeTask(int, android.graphics.Rect);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public boolean setTaskWindowingMode(int, int, boolean) throws java.lang.SecurityException;
@@ -382,11 +381,14 @@
field public static final String ACTION_DATA_SHARING_RESTRICTION_APPLIED = "android.app.action.DATA_SHARING_RESTRICTION_APPLIED";
field public static final int OPERATION_CREATE_AND_MANAGE_USER = 5; // 0x5
field public static final int OPERATION_LOCK_NOW = 1; // 0x1
+ field public static final int OPERATION_LOGOUT_USER = 9; // 0x9
field public static final int OPERATION_REBOOT = 7; // 0x7
field public static final int OPERATION_REMOVE_USER = 6; // 0x6
+ field public static final int OPERATION_SET_USER_RESTRICTION = 10; // 0xa
field public static final int OPERATION_START_USER_IN_BACKGROUND = 3; // 0x3
field public static final int OPERATION_STOP_USER = 4; // 0x4
field public static final int OPERATION_SWITCH_USER = 2; // 0x2
+ field public static final int OPERATION_WIPE_DATA = 8; // 0x8
}
public static final class SecurityLog.SecurityEvent implements android.os.Parcelable {
@@ -986,6 +988,7 @@
}
public class AudioManager {
+ method @Nullable public static android.media.AudioDeviceInfo getDeviceInfoFromType(int);
method public boolean hasRegisteredDynamicPolicy();
}
@@ -2017,6 +2020,10 @@
field public static final int CALLBACK_ANIMATION = 1; // 0x1
}
+ public final class ContentInfo {
+ method @NonNull public android.util.Pair<android.view.ContentInfo,android.view.ContentInfo> partition(@NonNull java.util.function.Predicate<android.content.ClipData.Item>);
+ }
+
public final class Display {
method @NonNull public android.graphics.ColorSpace[] getSupportedWideColorGamut();
method public int getType();
@@ -2454,6 +2461,13 @@
field public static final int FEATURE_WINDOW_TOKENS = 2; // 0x2
}
+ public final class StartingWindowInfo implements android.os.Parcelable {
+ ctor public StartingWindowInfo();
+ method public int describeContents();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.window.StartingWindowInfo> CREATOR;
+ }
+
public final class TaskAppearedInfo implements android.os.Parcelable {
ctor public TaskAppearedInfo(@NonNull android.app.ActivityManager.RunningTaskInfo, @NonNull android.view.SurfaceControl);
method public int describeContents();
@@ -2465,7 +2479,7 @@
public class TaskOrganizer extends android.window.WindowOrganizer {
ctor public TaskOrganizer();
- method @BinderThread public void addStartingWindow(@NonNull android.app.ActivityManager.RunningTaskInfo, @NonNull android.os.IBinder);
+ method @BinderThread public void addStartingWindow(@NonNull android.window.StartingWindowInfo, @NonNull android.os.IBinder);
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public void createRootTask(int, int, @Nullable android.os.IBinder);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public boolean deleteRootTask(@NonNull android.window.WindowContainerToken);
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public java.util.List<android.app.ActivityManager.RunningTaskInfo> getChildTasks(@NonNull android.window.WindowContainerToken, @NonNull int[]);
@@ -2476,7 +2490,7 @@
method @BinderThread public void onTaskInfoChanged(@NonNull android.app.ActivityManager.RunningTaskInfo);
method @BinderThread public void onTaskVanished(@NonNull android.app.ActivityManager.RunningTaskInfo);
method @CallSuper @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public java.util.List<android.window.TaskAppearedInfo> registerOrganizer();
- method @BinderThread public void removeStartingWindow(@NonNull android.app.ActivityManager.RunningTaskInfo);
+ method @BinderThread public void removeStartingWindow(int);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public void setInterceptBackPressedOnTaskRoot(@NonNull android.window.WindowContainerToken, boolean);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public void setLaunchRoot(int, @NonNull android.window.WindowContainerToken);
method @CallSuper @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) public void unregisterOrganizer();
diff --git a/core/java/android/accounts/AbstractAccountAuthenticator.java b/core/java/android/accounts/AbstractAccountAuthenticator.java
index 6470a04..7b57442 100644
--- a/core/java/android/accounts/AbstractAccountAuthenticator.java
+++ b/core/java/android/accounts/AbstractAccountAuthenticator.java
@@ -93,7 +93,8 @@
* {@link AccountAuthenticatorResponse#onError} when it is complete.
* <li> If the authenticator cannot synchronously process the request and return a result then it
* may choose to return null and then use the AccountManagerResponse to send the result
- * when it has completed the request.
+ * when it has completed the request. This asynchronous option is not available for the
+ * {@link #addAccount} method, which must complete synchronously.
* </ul>
* <p>
* The following descriptions of each of the abstract authenticator methods will not describe the
@@ -101,7 +102,7 @@
* parameters and the expected result.
* <p>
* When writing an activity to satisfy these requests one must pass in the AccountManagerResponse
- * and return the result via that response when the activity finishes (or whenever else the
+ * and return the result via that response when the activity finishes (or whenever else the
* activity author deems it is the correct time to respond).
*/
public abstract class AbstractAccountAuthenticator {
diff --git a/core/java/android/app/ActivityManager.aidl b/core/java/android/app/ActivityManager.aidl
index 45a0e87..341393c 100644
--- a/core/java/android/app/ActivityManager.aidl
+++ b/core/java/android/app/ActivityManager.aidl
@@ -24,6 +24,4 @@
parcelable ActivityManager.RunningServiceInfo;
parcelable ActivityManager.RunningTaskInfo;
/** @hide */
-parcelable ActivityManager.TaskThumbnail;
-/** @hide */
-parcelable ActivityManager.TaskSnapshot;
\ No newline at end of file
+parcelable ActivityManager.TaskThumbnail;
\ No newline at end of file
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index a5d88ef..1227cc2 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -2114,351 +2114,6 @@
return ActivityTaskManager.getInstance().getTasks(maxNum);
}
- /**
- * Represents a task snapshot.
- * @hide
- */
- public static class TaskSnapshot implements Parcelable {
- // Identifier of this snapshot
- private final long mId;
- // Top activity in task when snapshot was taken
- private final ComponentName mTopActivityComponent;
- private final HardwareBuffer mSnapshot;
- /** Indicates whether task was in landscape or portrait */
- @Configuration.Orientation
- private final int mOrientation;
- /** See {@link android.view.Surface.Rotation} */
- @Surface.Rotation
- private int mRotation;
- /** The size of the snapshot before scaling */
- private final Point mTaskSize;
- private final Rect mContentInsets;
- // Whether this snapshot is a down-sampled version of the high resolution snapshot, used
- // mainly for loading snapshots quickly from disk when user is flinging fast
- private final boolean mIsLowResolution;
- // Whether or not the snapshot is a real snapshot or an app-theme generated snapshot due to
- // the task having a secure window or having previews disabled
- private final boolean mIsRealSnapshot;
- private final int mWindowingMode;
- private final @Appearance int mAppearance;
- private final boolean mIsTranslucent;
- // Must be one of the named color spaces, otherwise, always use SRGB color space.
- private final ColorSpace mColorSpace;
-
- public TaskSnapshot(long id,
- @NonNull ComponentName topActivityComponent, HardwareBuffer snapshot,
- @NonNull ColorSpace colorSpace, int orientation, int rotation, Point taskSize,
- Rect contentInsets, boolean isLowResolution, boolean isRealSnapshot,
- int windowingMode, @Appearance int appearance, boolean isTranslucent) {
- mId = id;
- mTopActivityComponent = topActivityComponent;
- mSnapshot = snapshot;
- mColorSpace = colorSpace.getId() < 0
- ? ColorSpace.get(ColorSpace.Named.SRGB) : colorSpace;
- mOrientation = orientation;
- mRotation = rotation;
- mTaskSize = new Point(taskSize);
- mContentInsets = new Rect(contentInsets);
- mIsLowResolution = isLowResolution;
- mIsRealSnapshot = isRealSnapshot;
- mWindowingMode = windowingMode;
- mAppearance = appearance;
- mIsTranslucent = isTranslucent;
- }
-
- private TaskSnapshot(Parcel source) {
- mId = source.readLong();
- mTopActivityComponent = ComponentName.readFromParcel(source);
- mSnapshot = source.readParcelable(null /* classLoader */);
- int colorSpaceId = source.readInt();
- mColorSpace = colorSpaceId >= 0 && colorSpaceId < ColorSpace.Named.values().length
- ? ColorSpace.get(ColorSpace.Named.values()[colorSpaceId])
- : ColorSpace.get(ColorSpace.Named.SRGB);
- mOrientation = source.readInt();
- mRotation = source.readInt();
- mTaskSize = source.readParcelable(null /* classLoader */);
- mContentInsets = source.readParcelable(null /* classLoader */);
- mIsLowResolution = source.readBoolean();
- mIsRealSnapshot = source.readBoolean();
- mWindowingMode = source.readInt();
- mAppearance = source.readInt();
- mIsTranslucent = source.readBoolean();
- }
-
- /**
- * @return Identifier of this snapshot.
- */
- public long getId() {
- return mId;
- }
-
- /**
- * @return The top activity component for the task at the point this snapshot was taken.
- */
- public ComponentName getTopActivityComponent() {
- return mTopActivityComponent;
- }
-
- /**
- * @return The graphic buffer representing the screenshot.
- *
- * Note: Prefer {@link #getHardwareBuffer}, which returns the internal object. This version
- * creates a new object.
- */
- @UnsupportedAppUsage
- public GraphicBuffer getSnapshot() {
- return GraphicBuffer.createFromHardwareBuffer(mSnapshot);
- }
-
- /**
- * @return The hardware buffer representing the screenshot.
- */
- public HardwareBuffer getHardwareBuffer() {
- return mSnapshot;
- }
-
- /**
- * @return The color space of hardware buffer representing the screenshot.
- */
- public ColorSpace getColorSpace() {
- return mColorSpace;
- }
-
- /**
- * @return The screen orientation the screenshot was taken in.
- */
- @UnsupportedAppUsage
- public int getOrientation() {
- return mOrientation;
- }
-
- /**
- * @return The screen rotation the screenshot was taken in.
- */
- public int getRotation() {
- return mRotation;
- }
-
- /**
- * @return The size of the task at the point this snapshot was taken.
- */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public Point getTaskSize() {
- return mTaskSize;
- }
-
- /**
- * @return The system/content insets on the snapshot. These can be clipped off in order to
- * remove any areas behind system bars in the snapshot.
- */
- @UnsupportedAppUsage
- public Rect getContentInsets() {
- return mContentInsets;
- }
-
- /**
- * @return Whether this snapshot is a down-sampled version of the full resolution.
- */
- @UnsupportedAppUsage
- public boolean isLowResolution() {
- return mIsLowResolution;
- }
-
- /**
- * @return Whether or not the snapshot is a real snapshot or an app-theme generated snapshot
- * due to the task having a secure window or having previews disabled.
- */
- @UnsupportedAppUsage
- public boolean isRealSnapshot() {
- return mIsRealSnapshot;
- }
-
- /**
- * @return Whether or not the snapshot is of a translucent app window (non-fullscreen or has
- * a non-opaque pixel format).
- */
- public boolean isTranslucent() {
- return mIsTranslucent;
- }
-
- /**
- * @return The windowing mode of the task when this snapshot was taken.
- */
- public int getWindowingMode() {
- return mWindowingMode;
- }
-
- /**
- * @return The {@link Appearance} flags for the top most visible fullscreen window at the
- * time that the snapshot was taken.
- */
- public @Appearance int getAppearance() {
- return mAppearance;
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeLong(mId);
- ComponentName.writeToParcel(mTopActivityComponent, dest);
- dest.writeParcelable(mSnapshot != null && !mSnapshot.isClosed() ? mSnapshot : null,
- 0);
- dest.writeInt(mColorSpace.getId());
- dest.writeInt(mOrientation);
- dest.writeInt(mRotation);
- dest.writeParcelable(mTaskSize, 0);
- dest.writeParcelable(mContentInsets, 0);
- dest.writeBoolean(mIsLowResolution);
- dest.writeBoolean(mIsRealSnapshot);
- dest.writeInt(mWindowingMode);
- dest.writeInt(mAppearance);
- dest.writeBoolean(mIsTranslucent);
- }
-
- @Override
- public String toString() {
- final int width = mSnapshot != null ? mSnapshot.getWidth() : 0;
- final int height = mSnapshot != null ? mSnapshot.getHeight() : 0;
- return "TaskSnapshot{"
- + " mId=" + mId
- + " mTopActivityComponent=" + mTopActivityComponent.flattenToShortString()
- + " mSnapshot=" + mSnapshot + " (" + width + "x" + height + ")"
- + " mColorSpace=" + mColorSpace.toString()
- + " mOrientation=" + mOrientation
- + " mRotation=" + mRotation
- + " mTaskSize=" + mTaskSize.toString()
- + " mContentInsets=" + mContentInsets.toShortString()
- + " mIsLowResolution=" + mIsLowResolution
- + " mIsRealSnapshot=" + mIsRealSnapshot
- + " mWindowingMode=" + mWindowingMode
- + " mAppearance=" + mAppearance
- + " mIsTranslucent=" + mIsTranslucent;
- }
-
- public static final @android.annotation.NonNull Creator<TaskSnapshot> CREATOR = new Creator<TaskSnapshot>() {
- public TaskSnapshot createFromParcel(Parcel source) {
- return new TaskSnapshot(source);
- }
- public TaskSnapshot[] newArray(int size) {
- return new TaskSnapshot[size];
- }
- };
-
- /** Builder for a {@link TaskSnapshot} object */
- public static final class Builder {
- private long mId;
- private ComponentName mTopActivity;
- private HardwareBuffer mSnapshot;
- private ColorSpace mColorSpace;
- private int mOrientation;
- private int mRotation;
- private Point mTaskSize;
- private Rect mContentInsets;
- private boolean mIsRealSnapshot;
- private int mWindowingMode;
- private @Appearance int mAppearance;
- private boolean mIsTranslucent;
- private int mPixelFormat;
-
- public Builder setId(long id) {
- mId = id;
- return this;
- }
-
- public Builder setTopActivityComponent(ComponentName name) {
- mTopActivity = name;
- return this;
- }
-
- public Builder setSnapshot(HardwareBuffer buffer) {
- mSnapshot = buffer;
- return this;
- }
-
- public Builder setColorSpace(ColorSpace colorSpace) {
- mColorSpace = colorSpace;
- return this;
- }
-
- public Builder setOrientation(int orientation) {
- mOrientation = orientation;
- return this;
- }
-
- public Builder setRotation(int rotation) {
- mRotation = rotation;
- return this;
- }
-
- /**
- * Sets the original size of the task
- */
- public Builder setTaskSize(Point size) {
- mTaskSize = size;
- return this;
- }
-
- public Builder setContentInsets(Rect contentInsets) {
- mContentInsets = contentInsets;
- return this;
- }
-
- public Builder setIsRealSnapshot(boolean realSnapshot) {
- mIsRealSnapshot = realSnapshot;
- return this;
- }
-
- public Builder setWindowingMode(int windowingMode) {
- mWindowingMode = windowingMode;
- return this;
- }
-
- public Builder setAppearance(@Appearance int appearance) {
- mAppearance = appearance;
- return this;
- }
-
- public Builder setIsTranslucent(boolean isTranslucent) {
- mIsTranslucent = isTranslucent;
- return this;
- }
-
- public int getPixelFormat() {
- return mPixelFormat;
- }
-
- public Builder setPixelFormat(int pixelFormat) {
- mPixelFormat = pixelFormat;
- return this;
- }
-
- public TaskSnapshot build() {
- return new TaskSnapshot(
- mId,
- mTopActivity,
- mSnapshot,
- mColorSpace,
- mOrientation,
- mRotation,
- mTaskSize,
- mContentInsets,
- // When building a TaskSnapshot with the Builder class, isLowResolution
- // is always false. Low-res snapshots are only created when loading from
- // disk.
- false /* isLowResolution */,
- mIsRealSnapshot,
- mWindowingMode,
- mAppearance,
- mIsTranslucent);
-
- }
- }
- }
-
/** @hide */
@IntDef(flag = true, prefix = { "MOVE_TASK_" }, value = {
MOVE_TASK_WITH_HOME,
diff --git a/core/java/android/app/ActivityTaskManager.java b/core/java/android/app/ActivityTaskManager.java
index 03c1a01..2060252 100644
--- a/core/java/android/app/ActivityTaskManager.java
+++ b/core/java/android/app/ActivityTaskManager.java
@@ -419,20 +419,6 @@
}
/**
- * Requests that an activity should enter picture-in-picture mode if possible.
- * @hide
- */
- @TestApi
- @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
- public void requestPictureInPictureMode(@NonNull IBinder token) {
- try {
- getService().requestPictureInPictureMode(token);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
* @return whether the UI mode of the given config supports error dialogs (ANR, crash, etc).
* @hide
*/
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 6d564a3..28834f1 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -90,6 +90,7 @@
import android.hardware.display.DisplayManagerGlobal;
import android.inputmethodservice.InputMethodService;
import android.media.MediaFrameworkInitializer;
+import android.media.MediaFrameworkPlatformInitializer;
import android.media.MediaServiceManager;
import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
@@ -7701,6 +7702,7 @@
public static void initializeMainlineModules() {
TelephonyFrameworkInitializer.setTelephonyServiceManager(new TelephonyServiceManager());
StatsFrameworkInitializer.setStatsServiceManager(new StatsServiceManager());
+ MediaFrameworkPlatformInitializer.setMediaServiceManager(new MediaServiceManager());
MediaFrameworkInitializer.setMediaServiceManager(new MediaServiceManager());
}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 124cf71..700d8ff 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2468,8 +2468,9 @@
return context;
}
+ @NonNull
@Override
- public @NonNull WindowContext createWindowContext(int type, Bundle options) {
+ public WindowContext createWindowContext(int type, @NonNull Bundle options) {
if (getDisplay() == null) {
throw new UnsupportedOperationException("WindowContext can only be created from "
+ "other visual contexts, such as Activity or one created with "
@@ -2478,13 +2479,26 @@
return new WindowContext(this, type, options);
}
- ContextImpl createBaseWindowContext(IBinder token) {
+ @NonNull
+ @Override
+ public WindowContext createWindowContext(@NonNull Display display, int type,
+ @NonNull Bundle options) {
+ if (display == null) {
+ throw new IllegalArgumentException("Display must not be null");
+ }
+ return new WindowContext(this, display, type, options);
+ }
+
+ ContextImpl createBaseWindowContext(IBinder token, Display display) {
ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mAttributionTag,
mSplitName, token, mUser, mFlags, mClassLoader, null);
// Window contexts receive configurations directly from the server and as such do not
// need to override their display in ResourcesManager.
context.mForceDisplayOverrideInResources = false;
context.mContextType = CONTEXT_TYPE_WINDOW_CONTEXT;
+ if (display != null) {
+ context.mDisplay = display;
+ }
return context;
}
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index c564d28..94b2118 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -543,14 +543,6 @@
/** Cancels the window transitions for the given task. */
@UnsupportedAppUsage
void cancelTaskWindowTransition(int taskId);
- /**
- * @param taskId the id of the task to retrieve the sAutoapshots for
- * @param isLowResolution if set, if the snapshot needs to be loaded from disk, this will load
- * a reduced resolution of it, which is much faster
- * @return a graphic buffer representing a screenshot of a task
- */
- @UnsupportedAppUsage
- ActivityManager.TaskSnapshot getTaskSnapshot(int taskId, boolean isLowResolution);
void scheduleApplicationInfoChanged(in List<String> packageNames, int userId);
void setPersistentVrThread(int tid);
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index fabce45..523c155 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -191,7 +191,7 @@
*/
IBinder requestStartActivityPermissionToken(in IBinder delegatorToken);
- void releaseSomeActivities(in IApplicationThread app);
+ oneway void releaseSomeActivities(in IApplicationThread app);
Bitmap getTaskDescriptionIcon(in String filename, int userId);
void registerTaskStackListener(in ITaskStackListener listener);
void unregisterTaskStackListener(in ITaskStackListener listener);
@@ -258,7 +258,6 @@
void suppressResizeConfigChanges(boolean suppress);
boolean moveTopActivityToPinnedRootTask(int rootTaskId, in Rect bounds);
- void requestPictureInPictureMode(in IBinder token);
/**
* Resizes the docked stack, and all other stacks as the result of the dock stack bounds change.
@@ -308,7 +307,7 @@
* a reduced resolution of it, which is much faster
* @return a graphic buffer representing a screenshot of a task
*/
- ActivityManager.TaskSnapshot getTaskSnapshot(int taskId, boolean isLowResolution);
+ android.window.TaskSnapshot getTaskSnapshot(int taskId, boolean isLowResolution);
/**
* It should only be called from home activity to remove its outdated snapshot. The home
diff --git a/core/java/android/app/ITaskStackListener.aidl b/core/java/android/app/ITaskStackListener.aidl
index dc7782a..301d188 100644
--- a/core/java/android/app/ITaskStackListener.aidl
+++ b/core/java/android/app/ITaskStackListener.aidl
@@ -18,6 +18,7 @@
import android.app.ActivityManager;
import android.content.ComponentName;
+import android.window.TaskSnapshot;
/** @hide */
oneway interface ITaskStackListener {
@@ -141,7 +142,7 @@
/**
* Called when a task snapshot got updated.
*/
- void onTaskSnapshotChanged(int taskId, in ActivityManager.TaskSnapshot snapshot);
+ void onTaskSnapshotChanged(int taskId, in TaskSnapshot snapshot);
/**
* Called when the resumed activity is in size compatibility mode and its override configuration
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 99785e1..50853a3 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -729,6 +729,23 @@
}
}
+ private StrictMode.VmPolicy allowVmViolations() {
+ if (mActivityThread == null) {
+ // When LoadedApk is used without an ActivityThread (usually in a
+ // zygote context), don't call into StrictMode, as it initializes
+ // the binder subsystem, which we don't want.
+ return null;
+ }
+
+ return StrictMode.allowVmViolations();
+ }
+
+ private void setVmPolicy(StrictMode.VmPolicy policy) {
+ if (mActivityThread != null && policy != null) {
+ StrictMode.setVmPolicy(policy);
+ }
+ }
+
private void createOrUpdateClassLoaderLocked(List<String> addedPaths) {
if (mPackageName.equals("android")) {
// Note: This branch is taken for system server and we don't need to setup
@@ -984,13 +1001,20 @@
// Temporarily disable logging of disk reads on the Looper thread as this is necessary -
// and the loader will access the directory anyway if we don't check it.
- StrictMode.ThreadPolicy oldPolicy = allowThreadDiskReads();
+ StrictMode.ThreadPolicy oldThreadPolicy = allowThreadDiskReads();
+
+ // Also disable logging of access to /data/user before CE storage is unlocked. The check
+ // below will return false (because the directory name we pass will not match the
+ // encrypted one), but that's correct.
+ StrictMode.VmPolicy oldVmPolicy = allowVmViolations();
+
try {
// We are constructing a classloader for a different package. It is likely,
// but not certain, that we can't acccess its app data dir - so check.
return new File(mDataDir).canExecute();
} finally {
- setThreadPolicy(oldPolicy);
+ setThreadPolicy(oldThreadPolicy);
+ setVmPolicy(oldVmPolicy);
}
}
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 4afbfbf..48d2dfe 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -104,8 +104,8 @@
import android.location.LocationManager;
import android.media.AudioManager;
import android.media.MediaFrameworkInitializer;
+import android.media.MediaFrameworkPlatformInitializer;
import android.media.MediaRouter;
-import android.media.MediaTranscodeManager;
import android.media.midi.IMidiManager;
import android.media.midi.MidiManager;
import android.media.musicrecognition.IMusicRecognitionManager;
@@ -312,15 +312,6 @@
return new AudioManager(ctx);
}});
- registerService(Context.MEDIA_TRANSCODING_SERVICE, MediaTranscodeManager.class,
- new CachedServiceFetcher<MediaTranscodeManager>() {
- @Override
- public MediaTranscodeManager createService(ContextImpl ctx)
- throws ServiceNotFoundException {
- return new MediaTranscodeManager(ctx);
- }
- });
-
registerService(Context.MEDIA_ROUTER_SERVICE, MediaRouter.class,
new CachedServiceFetcher<MediaRouter>() {
@Override
@@ -1401,6 +1392,7 @@
WifiFrameworkInitializer.registerServiceWrappers();
StatsFrameworkInitializer.registerServiceWrappers();
RollbackManagerFrameworkInitializer.initialize();
+ MediaFrameworkPlatformInitializer.registerServiceWrappers();
MediaFrameworkInitializer.registerServiceWrappers();
} finally {
// If any of the above code throws, we're in a pretty bad shape and the process
diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java
index 2da5e00..61c4d39 100644
--- a/core/java/android/app/TaskInfo.java
+++ b/core/java/android/app/TaskInfo.java
@@ -32,6 +32,7 @@
import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log;
+import android.window.TaskSnapshot;
import android.window.WindowContainerToken;
import java.util.ArrayList;
@@ -230,9 +231,9 @@
* @return
* @hide
*/
- public ActivityManager.TaskSnapshot getTaskSnapshot(boolean isLowResolution) {
+ public TaskSnapshot getTaskSnapshot(boolean isLowResolution) {
try {
- return ActivityManager.getService().getTaskSnapshot(taskId, isLowResolution);
+ return ActivityTaskManager.getService().getTaskSnapshot(taskId, isLowResolution);
} catch (RemoteException e) {
Log.e(TAG, "Failed to get task snapshot, taskId=" + taskId, e);
return null;
diff --git a/core/java/android/app/TaskStackListener.java b/core/java/android/app/TaskStackListener.java
index 70ad9af..c311d71 100644
--- a/core/java/android/app/TaskStackListener.java
+++ b/core/java/android/app/TaskStackListener.java
@@ -17,7 +17,7 @@
package android.app;
import android.app.ActivityManager.RunningTaskInfo;
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.os.Binder;
diff --git a/core/java/android/app/WindowContext.java b/core/java/android/app/WindowContext.java
index 5f72bac..14ed414 100644
--- a/core/java/android/app/WindowContext.java
+++ b/core/java/android/app/WindowContext.java
@@ -26,6 +26,7 @@
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
+import android.view.Display;
import android.view.IWindowManager;
import android.view.WindowManagerGlobal;
import android.view.WindowManagerImpl;
@@ -59,13 +60,27 @@
* @hide
*/
public WindowContext(@NonNull Context base, int type, @Nullable Bundle options) {
+ this(base, null /* display */, type, options);
+ }
+
+ /**
+ * Default constructor. Will generate a {@link WindowTokenClient} and attach this context to
+ * the token.
+ *
+ * @param base Base {@link Context} for this new instance.
+ * @param display the {@link Display} to override.
+ * @param type Window type to be used with this context.
+ * @hide
+ */
+ public WindowContext(@NonNull Context base, @Nullable Display display, int type,
+ @Nullable Bundle options) {
// Correct base context will be built once the token is resolved, so passing 'null' here.
super(null /* base */);
mWms = WindowManagerGlobal.getWindowManagerService();
mToken = new WindowTokenClient();
- final ContextImpl contextImpl = createBaseWindowContext(base, mToken);
+ final ContextImpl contextImpl = createBaseWindowContext(base, mToken, display);
attachBaseContext(contextImpl);
contextImpl.setOuterContext(this);
@@ -93,9 +108,10 @@
Reference.reachabilityFence(this);
}
- private static ContextImpl createBaseWindowContext(Context outer, IBinder token) {
+ private static ContextImpl createBaseWindowContext(Context outer, IBinder token,
+ Display display) {
final ContextImpl contextImpl = ContextImpl.getImpl(outer);
- return contextImpl.createBaseWindowContext(token);
+ return contextImpl.createBaseWindowContext(token, display);
}
@Override
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 2a79c72..a154396 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -54,7 +54,6 @@
import android.content.pm.ParceledListSlice;
import android.content.pm.UserInfo;
import android.graphics.Bitmap;
-import android.net.NetworkUtils;
import android.net.PrivateDnsConnectivityChecker;
import android.net.ProxyInfo;
import android.net.Uri;
@@ -92,6 +91,7 @@
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.net.NetworkUtilsInternal;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.Preconditions;
import com.android.org.conscrypt.TrustedCertificateStore;
@@ -2615,6 +2615,15 @@
/** @hide */
@TestApi
public static final int OPERATION_REBOOT = 7;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_WIPE_DATA = 8;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_LOGOUT_USER = 9;
+ /** @hide */
+ @TestApi
+ public static final int OPERATION_SET_USER_RESTRICTION = 10;
private static final String PREFIX_OPERATION = "OPERATION_";
@@ -2626,7 +2635,10 @@
OPERATION_STOP_USER,
OPERATION_CREATE_AND_MANAGE_USER,
OPERATION_REMOVE_USER,
- OPERATION_REBOOT
+ OPERATION_REBOOT,
+ OPERATION_WIPE_DATA,
+ OPERATION_LOGOUT_USER,
+ OPERATION_SET_USER_RESTRICTION
})
@Retention(RetentionPolicy.SOURCE)
public static @interface DevicePolicyOperation {
@@ -11973,7 +11985,7 @@
return PRIVATE_DNS_SET_ERROR_FAILURE_SETTING;
}
- if (NetworkUtils.isWeaklyValidatedHostname(privateDnsHost)) {
+ if (NetworkUtilsInternal.isWeaklyValidatedHostname(privateDnsHost)) {
if (!PrivateDnsConnectivityChecker.canConnectToPrivateDnsServer(privateDnsHost)) {
return PRIVATE_DNS_SET_ERROR_HOST_NOT_SERVING;
}
@@ -12677,21 +12689,4 @@
}
}
}
-
- // 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/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index b046014..ce2fd4f 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -231,16 +231,22 @@
* Returns the profile owner component for the given user, or {@code null} if there is not one.
*/
@Nullable
- public abstract ComponentName getProfileOwnerAsUser(@UserIdInt int userId);
-
- /**
- * Returns the user id of the device owner, or {@link UserHandle#USER_NULL} if there is not one.
- */
- @UserIdInt
- public abstract int getDeviceOwnerUserId();
+ public abstract ComponentName getProfileOwnerAsUser(int userHandle);
/**
* Returns whether the given package is a device owner or a profile owner in the calling user.
*/
public abstract boolean isDeviceOrProfileOwnerInCallingUser(String packageName);
+
+ /**
+ * Returns whether this class supports being deferred the responsibility for resetting the given
+ * op.
+ */
+ public abstract boolean supportsResetOp(int op);
+
+ /**
+ * Resets the given op across the profile group of the given user for the given package. Assumes
+ * {@link #supportsResetOp(int)} is true.
+ */
+ public abstract void resetOp(int op, String packageName, @UserIdInt int userId);
}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index a81b506..bcc90f7 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -488,6 +488,4 @@
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/people/PeopleSpaceTile.java b/core/java/android/app/people/PeopleSpaceTile.java
index f60e42f..95739f3 100644
--- a/core/java/android/app/people/PeopleSpaceTile.java
+++ b/core/java/android/app/people/PeopleSpaceTile.java
@@ -17,6 +17,7 @@
package android.app.people;
import android.annotation.NonNull;
+import android.app.Person;
import android.content.Intent;
import android.content.pm.LauncherApps;
import android.content.pm.ShortcutInfo;
@@ -44,6 +45,7 @@
private int mUid;
private Uri mContactUri;
private String mPackageName;
+ private String mStatusText;
private long mLastInteractionTimestamp;
private boolean mIsImportantConversation;
private boolean mIsHiddenConversation;
@@ -61,6 +63,7 @@
mContactUri = b.mContactUri;
mUid = b.mUid;
mPackageName = b.mPackageName;
+ mStatusText = b.mStatusText;
mLastInteractionTimestamp = b.mLastInteractionTimestamp;
mIsImportantConversation = b.mIsImportantConversation;
mIsHiddenConversation = b.mIsHiddenConversation;
@@ -95,6 +98,10 @@
return mPackageName;
}
+ public String getStatusText() {
+ return mStatusText;
+ }
+
/** Returns the timestamp of the last interaction. */
public long getLastInteractionTimestamp() {
return mLastInteractionTimestamp;
@@ -148,6 +155,7 @@
builder.setContactUri(mContactUri);
builder.setUid(mUid);
builder.setPackageName(mPackageName);
+ builder.setStatusText(mStatusText);
builder.setLastInteractionTimestamp(mLastInteractionTimestamp);
builder.setIsImportantConversation(mIsImportantConversation);
builder.setIsHiddenConversation(mIsHiddenConversation);
@@ -165,6 +173,7 @@
private Uri mContactUri;
private int mUid;
private String mPackageName;
+ private String mStatusText;
private long mLastInteractionTimestamp;
private boolean mIsImportantConversation;
private boolean mIsHiddenConversation;
@@ -188,6 +197,16 @@
mUserIcon = convertDrawableToIcon(launcherApps.getShortcutIconDrawable(info, 0));
mUid = info.getUserId();
mPackageName = info.getPackage();
+ mContactUri = getContactUri(info);
+ }
+
+ private Uri getContactUri(ShortcutInfo info) {
+ if (info.getPersons() == null || info.getPersons().length != 1) {
+ return null;
+ }
+ // TODO(b/175584929): Update to use the Uri from PeopleService directly
+ Person person = info.getPersons()[0];
+ return person.getUri() == null ? null : Uri.parse(person.getUri());
}
/** Sets the ID for the tile. */
@@ -226,6 +245,12 @@
return this;
}
+ /** Sets the status text. */
+ public Builder setStatusText(String statusText) {
+ mStatusText = statusText;
+ return this;
+ }
+
/** Sets the last interaction timestamp. */
public Builder setLastInteractionTimestamp(long lastInteractionTimestamp) {
mLastInteractionTimestamp = lastInteractionTimestamp;
@@ -279,8 +304,10 @@
mId = in.readString();
mUserName = in.readCharSequence();
mUserIcon = in.readParcelable(Icon.class.getClassLoader());
+ mContactUri = in.readParcelable(Uri.class.getClassLoader());
mUid = in.readInt();
mPackageName = in.readString();
+ mStatusText = in.readString();
mLastInteractionTimestamp = in.readLong();
mIsImportantConversation = in.readBoolean();
mIsHiddenConversation = in.readBoolean();
@@ -300,8 +327,10 @@
dest.writeString(mId);
dest.writeCharSequence(mUserName);
dest.writeParcelable(mUserIcon, flags);
+ dest.writeParcelable(mContactUri, flags);
dest.writeInt(mUid);
dest.writeString(mPackageName);
+ dest.writeString(mStatusText);
dest.writeLong(mLastInteractionTimestamp);
dest.writeBoolean(mIsImportantConversation);
dest.writeBoolean(mIsHiddenConversation);
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 1713a0c..406fe8d 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -2967,6 +2967,16 @@
}
});
}
+ synchronized (mBluetoothConnectionCallbackExecutorMap) {
+ if (!mBluetoothConnectionCallbackExecutorMap.isEmpty()) {
+ try {
+ mService.registerBluetoothConnectionCallback(mConnectionCallback);
+ } catch (RemoteException e) {
+ Log.e(TAG, "onBluetoothServiceUp: Failed to register bluetooth"
+ + "connection callback", e);
+ }
+ }
+ }
}
public void onBluetoothServiceDown() {
@@ -3616,25 +3626,25 @@
return false;
}
- // If the callback map is empty, we register the service-to-app callback
- if (mBluetoothConnectionCallbackExecutorMap.isEmpty()) {
- try {
- mServiceLock.readLock().lock();
- if (mService != null) {
- if (!mService.registerBluetoothConnectionCallback(mConnectionCallback)) {
- return false;
- }
- }
- } catch (RemoteException e) {
- Log.e(TAG, "", e);
- mBluetoothConnectionCallbackExecutorMap.remove(callback);
- } finally {
- mServiceLock.readLock().unlock();
- }
- }
-
- // Adds the passed in callback to our map of callbacks to executors
synchronized (mBluetoothConnectionCallbackExecutorMap) {
+ // If the callback map is empty, we register the service-to-app callback
+ if (mBluetoothConnectionCallbackExecutorMap.isEmpty()) {
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null) {
+ if (!mService.registerBluetoothConnectionCallback(mConnectionCallback)) {
+ return false;
+ }
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ mBluetoothConnectionCallbackExecutorMap.remove(callback);
+ } finally {
+ mServiceLock.readLock().unlock();
+ }
+ }
+
+ // Adds the passed in callback to our map of callbacks to executors
if (mBluetoothConnectionCallbackExecutorMap.containsKey(callback)) {
throw new IllegalArgumentException("This callback has already been registered");
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 62ba2b2..abe7fda 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4564,6 +4564,7 @@
* @hide
* @see #getSystemService(String)
*/
+ @SystemApi
public static final String MUSIC_RECOGNITION_SERVICE = "music_recognition";
/**
@@ -5988,22 +5989,22 @@
* Creating a window context is an expensive operation. Misuse of this API may lead to a huge
* performance drop. The best practice is to use the same window context when possible.
* An approach is to create one window context with specific window type and display and
- * use it everywhere it's needed..
+ * use it everywhere it's needed.
* </p>
*
* @param type Window type in {@link WindowManager.LayoutParams}
- * @param options Bundle used to pass window-related options.
- * @return A {@link Context} that can be used to create windows.
- * @throws UnsupportedOperationException if this is called on a non-UI context, such as
- * {@link android.app.Application Application} or {@link android.app.Service Service}.
+ * @param options A bundle used to pass window-related options
+ * @return A {@link Context} that can be used to create
+ * non-{@link android.app.Activity activity} windows.
*
* @see #getSystemService(String)
* @see #getSystemService(Class)
* @see #WINDOW_SERVICE
* @see #LAYOUT_INFLATER_SERVICE
* @see #WALLPAPER_SERVICE
- * @throws UnsupportedOperationException if this {@link Context} does not attach to a display or
- * the current number of window contexts without adding any view by
+ * @throws UnsupportedOperationException if this {@link Context} does not attach to a display,
+ * such as {@link android.app.Application Application} or {@link android.app.Service Service},
+ * or the current number of window contexts without adding any view by
* {@link WindowManager#addView} <b>exceeds five</b>.
*/
@UiContext
@@ -6013,6 +6014,32 @@
}
/**
+ * A special version of {@link #createWindowContext(int, Bundle)} which also takes
+ * {@link Display}. The only difference between this API and
+ * {@link #createWindowContext(int, Bundle)} is that this API can create window context from
+ * any context even if the context which is not associated to a {@link Display} instance.
+ *
+ * @param display The {@link Display} to associate with
+ * @param type Window type in {@link WindowManager.LayoutParams}
+ * @param options A bundle used to pass window-related options.
+ * @return A {@link Context} that can be used to create
+ * non-{@link android.app.Activity activity} windows.
+ * @throws IllegalArgumentException if the {@link Display} is {@code null}.
+ *
+ * @see #getSystemService(String)
+ * @see #getSystemService(Class)
+ * @see #WINDOW_SERVICE
+ * @see #LAYOUT_INFLATER_SERVICE
+ * @see #WALLPAPER_SERVICE
+ */
+ @UiContext
+ @NonNull
+ public Context createWindowContext(@NonNull Display display, @WindowType int type,
+ @Nullable Bundle options) {
+ throw new RuntimeException("Not implemented. Must override in a subclass.");
+ }
+
+ /**
* Return a new Context object for the current Context but attribute to a different tag.
* In complex apps attribution tagging can be used to distinguish between separate logical
* parts.
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 56da3cb..e450c08 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -988,6 +988,13 @@
}
@Override
+ @NonNull
+ public Context createWindowContext(@NonNull Display display, @WindowType int type,
+ @Nullable Bundle options) {
+ return mBase.createWindowContext(display, type, options);
+ }
+
+ @Override
public @NonNull Context createAttributionContext(@Nullable String attributionTag) {
return mBase.createAttributionContext(attributionTag);
}
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 81d9b11..e32068f 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -2101,7 +2101,7 @@
}
/** @hide */
- @SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+ @SystemApi
public boolean isOem() {
return (privateFlags & ApplicationInfo.PRIVATE_FLAG_OEM) != 0;
}
@@ -2149,13 +2149,13 @@
}
/** @hide */
- @SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+ @SystemApi
public boolean isVendor() {
return (privateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0;
}
/** @hide */
- @SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+ @SystemApi
public boolean isProduct() {
return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0;
}
diff --git a/core/java/android/content/pm/CrossProfileAppsInternal.java b/core/java/android/content/pm/CrossProfileAppsInternal.java
index 16a749f..255aeac 100644
--- a/core/java/android/content/pm/CrossProfileAppsInternal.java
+++ b/core/java/android/content/pm/CrossProfileAppsInternal.java
@@ -17,6 +17,7 @@
package android.content.pm;
import android.annotation.UserIdInt;
+import android.app.AppOpsManager.Mode;
import android.os.UserHandle;
import java.util.List;
@@ -62,4 +63,14 @@
*/
public abstract List<UserHandle> getTargetUserProfiles(
String packageName, @UserIdInt int userId);
+
+ /**
+ * Sets the app-op for {@link android.Manifest.permission#INTERACT_ACROSS_PROFILES} that is
+ * configurable by users in Settings. This configures it for the profile group of the given
+ * user.
+ *
+ * @see CrossProfileApps#setInteractAcrossProfilesAppOp(String, int)
+ */
+ public abstract void setInteractAcrossProfilesAppOp(
+ String packageName, @Mode int newMode, @UserIdInt int userId);
}
diff --git a/core/java/android/content/pm/LimitedLengthInputStream.java b/core/java/android/content/pm/LimitedLengthInputStream.java
index 19b681e..05089f6 100644
--- a/core/java/android/content/pm/LimitedLengthInputStream.java
+++ b/core/java/android/content/pm/LimitedLengthInputStream.java
@@ -1,6 +1,6 @@
package android.content.pm;
-import libcore.util.ArrayUtils;
+import com.android.internal.util.ArrayUtils;
import java.io.FilterInputStream;
import java.io.IOException;
diff --git a/core/java/android/content/res/ApkAssets.java b/core/java/android/content/res/ApkAssets.java
index f5e1719..2d381eb 100644
--- a/core/java/android/content/res/ApkAssets.java
+++ b/core/java/android/content/res/ApkAssets.java
@@ -25,6 +25,8 @@
import com.android.internal.annotations.GuardedBy;
+import libcore.util.NativeAllocationRegistry;
+
import java.io.FileDescriptor;
import java.io.IOException;
import java.lang.annotation.Retention;
@@ -101,11 +103,11 @@
public @interface FormatType {}
@GuardedBy("this")
- private long mNativePtr; // final, except cleared in finalizer.
+ private final long mNativePtr;
@Nullable
@GuardedBy("this")
- private final StringBlock mStringBlock; // null or closed if mNativePtr = 0.
+ private final StringBlock mStringBlock;
@PropertyFlags
private final int mFlags;
@@ -113,6 +115,19 @@
@Nullable
private final AssetsProvider mAssets;
+ @GuardedBy("this")
+ @Nullable
+ private final Runnable mRunNativeCleanup;
+
+ // Use a Holder to allow static initialization of ApkAssets in the boot image, and
+ // possibly to avoid some initialization ordering issues.
+ private static class NoImagePreloadHolder {
+ // TODO(175425996): Make size estimate more accurate
+ public static final NativeAllocationRegistry REGISTRY =
+ NativeAllocationRegistry.createMalloced(ApkAssets.class.getClassLoader(),
+ nativeGetFinalizer());
+ }
+
/**
* Creates a new ApkAssets instance from the given path on disk.
*
@@ -287,6 +302,8 @@
mFlags = flags;
mNativePtr = nativeLoad(format, path, flags, assets);
mStringBlock = new StringBlock(nativeGetStringBlock(mNativePtr), true /*useSparse*/);
+ mRunNativeCleanup = NoImagePreloadHolder.REGISTRY.registerNativeAllocation(
+ this, mNativePtr);
mAssets = assets;
}
@@ -298,6 +315,8 @@
mFlags = flags;
mNativePtr = nativeLoadFd(format, fd, friendlyName, flags, assets);
mStringBlock = new StringBlock(nativeGetStringBlock(mNativePtr), true /*useSparse*/);
+ mRunNativeCleanup = NoImagePreloadHolder.REGISTRY.registerNativeAllocation(
+ this, mNativePtr);
mAssets = assets;
}
@@ -309,6 +328,8 @@
mFlags = flags;
mNativePtr = nativeLoadFdOffsets(format, fd, friendlyName, offset, length, flags, assets);
mStringBlock = new StringBlock(nativeGetStringBlock(mNativePtr), true /*useSparse*/);
+ mRunNativeCleanup = NoImagePreloadHolder.REGISTRY.registerNativeAllocation(
+ this, mNativePtr);
mAssets = assets;
}
@@ -316,6 +337,7 @@
mFlags = flags;
mNativePtr = nativeLoadEmpty(flags, assets);
mStringBlock = null;
+ mRunNativeCleanup = null;
mAssets = assets;
}
@@ -403,22 +425,16 @@
return "ApkAssets{path=" + getAssetPath() + "}";
}
- @Override
- protected void finalize() throws Throwable {
- close();
- }
-
/**
* Closes this class and the contained {@link #mStringBlock}.
*/
public void close() {
synchronized (this) {
- if (mNativePtr != 0) {
- if (mStringBlock != null) {
- mStringBlock.close();
- }
- nativeDestroy(mNativePtr);
- mNativePtr = 0;
+ if (mStringBlock != null) {
+ mStringBlock.close();
+ }
+ if (mRunNativeCleanup != null) {
+ mRunNativeCleanup.run();
}
}
}
@@ -433,7 +449,6 @@
private static native long nativeLoadFdOffsets(@FormatType int format,
@NonNull FileDescriptor fd, @NonNull String friendlyName, long offset, long length,
@PropertyFlags int flags, @Nullable AssetsProvider asset) throws IOException;
- private static native void nativeDestroy(long ptr);
private static native @NonNull String nativeGetAssetPath(long ptr);
private static native long nativeGetStringBlock(long ptr);
private static native boolean nativeIsUpToDate(long ptr);
@@ -441,4 +456,5 @@
private static native @Nullable OverlayableInfo nativeGetOverlayableInfo(long ptr,
String overlayableName) throws IOException;
private static native boolean nativeDefinesOverlayable(long ptr) throws IOException;
+ private static native final long nativeGetFinalizer();
}
diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java
index 78cea15..cbcdb37 100644
--- a/core/java/android/content/res/ResourcesImpl.java
+++ b/core/java/android/content/res/ResourcesImpl.java
@@ -534,7 +534,24 @@
remainder = languageTag.substring(separator);
}
- return Locale.adjustLanguageCode(language) + remainder;
+ // No need to convert to lower cases because the language in the return value of
+ // Locale.toLanguageTag has been lower-cased.
+ final String adjustedLanguage;
+ switch(language) {
+ case "id":
+ adjustedLanguage = "in";
+ break;
+ case "yi":
+ adjustedLanguage = "ji";
+ break;
+ case "he":
+ adjustedLanguage = "iw";
+ break;
+ default:
+ adjustedLanguage = language;
+ break;
+ }
+ return adjustedLanguage + remainder;
}
/**
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index e913986..f7c4c2c 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -19,6 +19,7 @@
import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
+import android.hardware.input.InputSensorInfo;
import android.os.Build;
/**
@@ -923,6 +924,30 @@
}
/**
+ * Construct a sensor object from SensorInfo of an input device.
+ * This is only used for constructing an input device sensor object.
+ * @hide
+ */
+ public Sensor(InputSensorInfo sensorInfo) {
+ this.mName = sensorInfo.getName();
+ this.mVendor = sensorInfo.getVendor();
+ this.mVersion = sensorInfo.getVersion();
+ this.mHandle = sensorInfo.getHandle();
+ this.mType = sensorInfo.getType();
+ this.mMaxRange = sensorInfo.getMaxRange();
+ this.mResolution = sensorInfo.getResolution();
+ this.mPower = sensorInfo.getPower();
+ this.mMinDelay = sensorInfo.getMinDelay();
+ this.mFifoReservedEventCount = sensorInfo.getFifoReservedEventCount();
+ this.mFifoMaxEventCount = sensorInfo.getFifoMaxEventCount();
+ this.mStringType = sensorInfo.getStringType();
+ this.mRequiredPermission = sensorInfo.getRequiredPermission();
+ this.mMaxDelay = sensorInfo.getMaxDelay();
+ this.mFlags = sensorInfo.getFlags();
+ this.mId = sensorInfo.getId();
+ }
+
+ /**
* @return name string of the sensor.
*/
public String getName() {
diff --git a/core/java/android/hardware/SensorEvent.java b/core/java/android/hardware/SensorEvent.java
index 236fab0..232f234 100644
--- a/core/java/android/hardware/SensorEvent.java
+++ b/core/java/android/hardware/SensorEvent.java
@@ -16,6 +16,7 @@
package android.hardware;
+import android.annotation.NonNull;
import android.compat.annotation.UnsupportedAppUsage;
/**
@@ -667,4 +668,16 @@
SensorEvent(int valueSize) {
values = new float[valueSize];
}
+
+ /**
+ * Construct a sensor event object by sensor object, accuracy, timestamp and values.
+ * This is only used for constructing an input device sensor event object.
+ * @hide
+ */
+ public SensorEvent(@NonNull Sensor sensor, int accuracy, long timestamp, float[] values) {
+ this.sensor = sensor;
+ this.accuracy = accuracy;
+ this.timestamp = timestamp;
+ this.values = values;
+ }
}
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index 3a73de6..43f04cd 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -848,6 +848,20 @@
}
/**
+ * Determines whether the HDMI CEC stack should handle KEYCODE_TV_POWER.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.HDMI_CEC)
+ public boolean shouldHandleTvPowerKey() {
+ try {
+ return mService.shouldHandleTvPowerKey();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Controls whether volume control commands via HDMI CEC are enabled.
*
* <p>When disabled:
diff --git a/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java b/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java
index 202e090..3b61911f 100644
--- a/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java
+++ b/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java
@@ -72,6 +72,11 @@
}
@Override
+ public boolean shouldHandleTvPowerKey() {
+ return HdmiControlServiceWrapper.this.shouldHandleTvPowerKey();
+ }
+
+ @Override
public void queryDisplayStatus(IHdmiControlCallback callback) {
HdmiControlServiceWrapper.this.queryDisplayStatus(callback);
}
@@ -368,6 +373,11 @@
public void toggleAndFollowTvPower() {}
/** @hide */
+ public boolean shouldHandleTvPowerKey() {
+ return true;
+ }
+
+ /** @hide */
public void queryDisplayStatus(IHdmiControlCallback callback) {}
/** @hide */
diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
index 6d0c688..65bd856 100644
--- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
@@ -43,6 +43,7 @@
HdmiDeviceInfo getActiveSource();
void oneTouchPlay(IHdmiControlCallback callback);
void toggleAndFollowTvPower();
+ boolean shouldHandleTvPowerKey();
void queryDisplayStatus(IHdmiControlCallback callback);
void addHdmiControlStatusChangeListener(IHdmiControlStatusChangeListener listener);
void removeHdmiControlStatusChangeListener(IHdmiControlStatusChangeListener listener);
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index 57c0398..b39df4d 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -23,6 +23,8 @@
import android.hardware.input.ITabletModeChangedListener;
import android.hardware.input.TouchCalibration;
import android.os.CombinedVibrationEffect;
+import android.hardware.input.IInputSensorEventListener;
+import android.hardware.input.InputSensorInfo;
import android.os.IBinder;
import android.os.VibrationEffect;
import android.view.InputDevice;
@@ -94,7 +96,7 @@
void setPointerIconType(int typeId);
void setCustomPointerIcon(in PointerIcon icon);
- void requestPointerCapture(IBinder windowToken, boolean enabled);
+ oneway void requestPointerCapture(IBinder inputChannelToken, boolean enabled);
/** Create an input monitor for gestures. */
InputMonitor monitorGestureInput(String name, int displayId);
@@ -105,4 +107,17 @@
// Remove the runtime association between the input port and the display port. Any existing
// static association for the cleared input port will be restored.
void removePortAssociation(in String inputPort);
+
+ InputSensorInfo[] getSensorList(int deviceId);
+
+ boolean registerSensorListener(IInputSensorEventListener listener);
+
+ void unregisterSensorListener(IInputSensorEventListener listener);
+
+ boolean enableSensor(int deviceId, int sensorType, int samplingPeriodUs,
+ int maxBatchReportLatencyUs);
+
+ void disableSensor(int deviceId, int sensorType);
+
+ boolean flushSensor(int deviceId, int sensorType);
}
diff --git a/core/java/android/hardware/input/IInputSensorEventListener.aidl b/core/java/android/hardware/input/IInputSensorEventListener.aidl
new file mode 100644
index 0000000..508f590
--- /dev/null
+++ b/core/java/android/hardware/input/IInputSensorEventListener.aidl
@@ -0,0 +1,27 @@
+/*
+ * 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.hardware.input;
+
+/** @hide */
+interface IInputSensorEventListener {
+ /* Called when there is a new sensor event. */
+ oneway void onInputSensorChanged(int deviceId, int sensorId, int accuracy, long timestamp,
+ in float[] values);
+
+ /* Called when the accuracy of the registered sensor has changed. */
+ oneway void onInputSensorAccuracyChanged(int deviceId, int sensorId, int accuracy);
+}
diff --git a/core/java/android/hardware/input/InputDeviceSensorManager.java b/core/java/android/hardware/input/InputDeviceSensorManager.java
new file mode 100644
index 0000000..56c2cdd
--- /dev/null
+++ b/core/java/android/hardware/input/InputDeviceSensorManager.java
@@ -0,0 +1,661 @@
+/*
+ * 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.hardware.input;
+
+import android.annotation.NonNull;
+import android.hardware.HardwareBuffer;
+import android.hardware.Sensor;
+import android.hardware.SensorAdditionalInfo;
+import android.hardware.SensorDirectChannel;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.hardware.TriggerEventListener;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.MemoryFile;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.Slog;
+import android.view.InputDevice;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.os.SomeArgs;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Sensor manager implementation that communicates with the input device
+ * sensors.
+ * @hide
+ */
+public class InputDeviceSensorManager implements InputManager.InputDeviceListener {
+ private static final String TAG = "InputDeviceSensorManager";
+ private static final boolean DEBUG = false;
+
+ private static final int MSG_SENSOR_ACCURACY_CHANGED = 1;
+ private static final int MSG_SENSOR_CHANGED = 2;
+
+ private InputManager mInputManager;
+
+ // sensor map from device id to sensor list
+ @GuardedBy("mInputSensorLock")
+ private final Map<Integer, List<Sensor>> mSensors = new HashMap<>();
+
+ private final Object mInputSensorLock = new Object();
+ private InputSensorEventListener mInputServiceSensorListener;
+ @GuardedBy("mInputSensorLock")
+ private final ArrayList<InputSensorEventListenerDelegate> mInputSensorEventListeners =
+ new ArrayList<InputSensorEventListenerDelegate>();
+ private HandlerThread mSensorThread = null;
+ private Handler mSensorHandler = null;
+
+ public InputDeviceSensorManager(InputManager inputManager) {
+ mInputManager = inputManager;
+
+ mSensorThread = new HandlerThread("SensorThread");
+ mSensorThread.start();
+ mSensorHandler = new Handler(mSensorThread.getLooper());
+
+ // Register the input device listener
+ mInputManager.registerInputDeviceListener(this, mSensorHandler);
+ // Initialize the sensor list
+ initializeSensors();
+ }
+
+ /*
+ * Get SensorManager object for specific input device
+ *
+ * @param deviceId Input device ID
+ * @return SensorManager object for input device
+ */
+ SensorManager getSensorManager(int deviceId) {
+ return new InputSensorManager(deviceId);
+ }
+
+ /*
+ * Update input device sensor info for specified input device ID.
+ */
+ private void updateInputDeviceSensorInfoLocked(int deviceId) {
+ final InputDevice inputDevice = InputDevice.getDevice(deviceId);
+ if (inputDevice.hasSensor()) {
+ final InputSensorInfo[] sensorInfos =
+ mInputManager.getSensorList(deviceId);
+ populateSensorsForInputDeviceLocked(deviceId, sensorInfos);
+ }
+ }
+
+ @Override
+ public void onInputDeviceAdded(int deviceId) {
+ synchronized (mInputSensorLock) {
+ if (!mSensors.containsKey(deviceId)) {
+ updateInputDeviceSensorInfoLocked(deviceId);
+ } else {
+ Slog.e(TAG, "Received 'device added' notification for device " + deviceId
+ + ", but it is already in the list");
+ }
+ }
+ }
+
+ @Override
+ public void onInputDeviceRemoved(int deviceId) {
+ synchronized (mInputSensorLock) {
+ mSensors.remove(deviceId);
+ }
+ }
+
+ @Override
+ public void onInputDeviceChanged(int deviceId) {
+ synchronized (mInputSensorLock) {
+ if (mSensors.containsKey(deviceId)) {
+ mSensors.remove(deviceId);
+ }
+ updateInputDeviceSensorInfoLocked(deviceId);
+ }
+ }
+
+ private static boolean sensorEquals(@NonNull Sensor lhs, @NonNull Sensor rhs) {
+ if (lhs.getType() == rhs.getType() && lhs.getId() == rhs.getId()) {
+ return true;
+ }
+ return false;
+ }
+
+ private void populateSensorsForInputDeviceLocked(int deviceId, InputSensorInfo[] sensorInfos) {
+ List<Sensor> sensors = new ArrayList<Sensor>();
+ for (int i = 0; i < sensorInfos.length; i++) {
+ Sensor sensor = new Sensor(sensorInfos[i]);
+ if (DEBUG) {
+ Slog.d(TAG, "Device " + deviceId + " sensor " + sensor.getStringType() + " added");
+ }
+ sensors.add(sensor);
+ }
+ mSensors.put(deviceId, sensors);
+ }
+
+ private void initializeSensors() {
+ synchronized (mInputSensorLock) {
+ mSensors.clear();
+ int[] deviceIds = mInputManager.getInputDeviceIds();
+ for (int i = 0; i < deviceIds.length; i++) {
+ final int deviceId = deviceIds[i];
+ updateInputDeviceSensorInfoLocked(deviceId);
+ }
+ }
+ }
+
+ /**
+ * Get a sensor object for input device, with specific sensor type.
+ * @param deviceId The input devicd ID
+ * @param sensorType The sensor type
+ * @return The sensor object if exists or null
+ */
+ @GuardedBy("mInputSensorLock")
+ private Sensor getInputDeviceSensorLocked(int deviceId, int sensorType) {
+ List<Sensor> sensors = mSensors.get(deviceId);
+ for (Sensor sensor : sensors) {
+ if (sensor.getType() == sensorType) {
+ return sensor;
+ }
+ }
+ return null;
+ }
+
+ @GuardedBy("mInputSensorLock")
+ private int findSensorEventListenerLocked(SensorEventListener listener) {
+ for (int i = 0; i < mInputSensorEventListeners.size(); i++) {
+ if (mInputSensorEventListeners.get(i).getListener() == listener) {
+ return i;
+ }
+ }
+ return Integer.MIN_VALUE;
+ }
+
+ private void onInputSensorChanged(int deviceId, int sensorType, int accuracy, long timestamp,
+ float[] values) {
+ if (DEBUG) {
+ Slog.d(TAG, "Sensor changed: deviceId =" + deviceId
+ + " timestamp=" + timestamp + " sensorType=" + sensorType);
+ }
+ synchronized (mInputSensorLock) {
+ SensorEvent event = createSensorEvent(
+ InputDevice.getDevice(deviceId), sensorType, accuracy, timestamp, values);
+ if (event == null) {
+ Slog.wtf(TAG, "Failed to create SensorEvent.");
+ return;
+ }
+ for (int i = 0; i < mInputSensorEventListeners.size(); i++) {
+ InputSensorEventListenerDelegate listener =
+ mInputSensorEventListeners.get(i);
+ if (listener.hasSensorRegistered(deviceId, sensorType)) {
+ listener.sendSensorChanged(event);
+ }
+ }
+ }
+ }
+
+ private void onInputSensorAccuracyChanged(int deviceId, int sensorType, int accuracy) {
+ if (DEBUG) {
+ Slog.d(TAG, "Sensor accuracy changed: "
+ + "accuracy=" + accuracy + ", sensorType=" + sensorType);
+ }
+ synchronized (mInputSensorLock) {
+ for (int i = 0; i < mInputSensorEventListeners.size(); i++) {
+ InputSensorEventListenerDelegate listener =
+ mInputSensorEventListeners.get(i);
+ if (listener.hasSensorRegistered(deviceId, sensorType)) {
+ listener.sendSensorAccuracyChanged(deviceId, sensorType, accuracy);
+ }
+ }
+ }
+ }
+
+ private final class InputSensorEventListener extends IInputSensorEventListener.Stub {
+ @Override
+ public void onInputSensorChanged(int deviceId, int sensorType, int accuracy, long timestamp,
+ float[] values) throws RemoteException {
+ InputDeviceSensorManager.this.onInputSensorChanged(
+ deviceId, sensorType, accuracy, timestamp, values);
+ }
+
+ @Override
+ public void onInputSensorAccuracyChanged(int deviceId, int sensorType, int accuracy)
+ throws RemoteException {
+ InputDeviceSensorManager.this.onInputSensorAccuracyChanged(deviceId, sensorType,
+ accuracy);
+ }
+
+ }
+
+ private static final class InputSensorEventListenerDelegate extends Handler {
+ private final SensorEventListener mListener;
+ private final int mDelayUs;
+ private final int mMaxBatchReportLatencyUs;
+ private List<Sensor> mSensors = new ArrayList<Sensor>();
+
+ InputSensorEventListenerDelegate(SensorEventListener listener, Sensor sensor,
+ int delayUs, int maxBatchReportLatencyUs, Handler handler) {
+ super(handler != null ? handler.getLooper() : Looper.myLooper());
+ mListener = listener;
+ mSensors.add(sensor);
+ mDelayUs = delayUs;
+ mMaxBatchReportLatencyUs = maxBatchReportLatencyUs;
+ }
+
+ public List<Sensor> getSensors() {
+ return mSensors;
+ }
+
+ public boolean isEmpty() {
+ return mSensors.isEmpty();
+ }
+
+ /**
+ * Remove sensor from sensor list for listener
+ */
+ public void removeSensor(Sensor sensor) {
+ // If sensor is not specified the listener will be unregistered for all sensors
+ // and the sensor list is cleared.
+ if (sensor == null) {
+ mSensors.clear();
+ }
+ for (Sensor s : mSensors) {
+ if (sensorEquals(s, sensor)) {
+ mSensors.remove(sensor);
+ }
+ }
+ }
+
+ /**
+ * Add a sensor to listener's sensor list
+ */
+ public void addSensor(@NonNull Sensor sensor) {
+ for (Sensor s : mSensors) {
+ if (sensorEquals(s, sensor)) {
+ Slog.w(TAG, "Adding sensor " + sensor + " already exist!");
+ return;
+ }
+ }
+ mSensors.add(sensor);
+ }
+
+ /**
+ * Check if the listener has been registered to the sensor
+ * @param deviceId The input device ID of the sensor
+ * @param sensorType The sensor type of the sensor
+ * @return true if specified sensor is registered for the listener.
+ */
+ public boolean hasSensorRegistered(int deviceId, int sensorType) {
+ for (Sensor sensor : mSensors) {
+ if (sensor.getType() == sensorType && sensor.getId() == deviceId) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Get listener handle for the delegate
+ */
+ public SensorEventListener getListener() {
+ return mListener;
+ }
+
+ /**
+ * Send sensor changed message
+ */
+ public void sendSensorChanged(SensorEvent event) {
+ SomeArgs args = SomeArgs.obtain();
+ obtainMessage(MSG_SENSOR_CHANGED, event).sendToTarget();
+ }
+
+ /**
+ * Send sensor accuracy changed message
+ */
+ public void sendSensorAccuracyChanged(int deviceId, int sensorType, int accuracy) {
+ SomeArgs args = SomeArgs.obtain();
+ obtainMessage(MSG_SENSOR_ACCURACY_CHANGED, deviceId, sensorType, accuracy)
+ .sendToTarget();
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_SENSOR_ACCURACY_CHANGED: {
+ final int deviceId = msg.arg1;
+ final int sensorType = msg.arg2;
+ final int accuracy = (int) msg.obj;
+ for (Sensor sensor : mSensors) {
+ if (sensor.getId() == deviceId && sensor.getType() == sensorType) {
+ mListener.onAccuracyChanged(sensor, accuracy);
+ }
+ }
+ break;
+ }
+ case MSG_SENSOR_CHANGED: {
+ SensorEvent event = (SensorEvent) msg.obj;
+ mListener.onSensorChanged(event);
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Create SensorEvent object for input device, with specified device ID, sensor Type,
+ * sensor event timestamp, accuracy, and sensor values.
+ */
+ private SensorEvent createSensorEvent(InputDevice inputDevice, int sensorType, int accuracy,
+ long timestamp, float[] values) {
+ synchronized (mInputSensorLock) {
+ Sensor sensor = getInputDeviceSensorLocked(inputDevice.getId(), sensorType);
+ if (sensor == null) {
+ Slog.wtf(TAG, "Can't get sensor type " + sensorType + " for input device "
+ + inputDevice);
+ }
+ SensorEvent event = new SensorEvent(sensor, accuracy, timestamp, values);
+ if (event == null) {
+ Slog.wtf(TAG, "Failed to create SensorEvent.");
+ }
+ return event;
+ }
+ }
+
+ /**
+ * Return the default sensor object for input device, for specific sensor type.
+ */
+ private Sensor getSensorForInputDevice(int deviceId, int type) {
+ synchronized (mInputSensorLock) {
+ for (Map.Entry<Integer, List<Sensor>> entry : mSensors.entrySet()) {
+ for (Sensor sensor : entry.getValue()) {
+ if (sensor.getId() == deviceId && sensor.getType() == type) {
+ if (DEBUG) {
+ Slog.d(TAG, "Device " + deviceId + " sensor " + sensor.getStringType());
+ }
+ return sensor;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Return list of sensors that belong to an input device, specified by input device ID.
+ */
+ private List<Sensor> getFullSensorListForDevice(int deviceId) {
+ List<Sensor> sensors = new ArrayList<Sensor>();
+ synchronized (mInputSensorLock) {
+ for (Map.Entry<Integer, List<Sensor>> entry : mSensors.entrySet()) {
+ for (Sensor sensor : entry.getValue()) {
+ if (sensor.getId() == deviceId) {
+ if (DEBUG) {
+ Slog.d(TAG, "Device " + deviceId + " sensor " + sensor.getStringType());
+ }
+ sensors.add(sensor);
+ }
+ }
+ }
+ }
+ return sensors;
+ }
+
+ private boolean registerListenerInternal(SensorEventListener listener, Sensor sensor,
+ int delayUs, int maxBatchReportLatencyUs, Handler handler) {
+ if (DEBUG) {
+ Slog.d(TAG, "registerListenerImpl listener=" + listener + " sensor=" + sensor
+ + " delayUs=" + delayUs
+ + " maxBatchReportLatencyUs=" + maxBatchReportLatencyUs);
+ }
+ if (listener == null) {
+ Slog.e(TAG, "listener is null");
+ return false;
+ }
+
+ if (sensor == null) {
+ Slog.e(TAG, "sensor is null");
+ return false;
+ }
+
+ // Trigger Sensors should use the requestTriggerSensor call.
+ if (sensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
+ Slog.e(TAG, "Trigger Sensors should use the requestTriggerSensor.");
+ return false;
+ }
+ if (maxBatchReportLatencyUs < 0 || delayUs < 0) {
+ Slog.e(TAG, "maxBatchReportLatencyUs and delayUs should be non-negative");
+ return false;
+ }
+
+ if (getSensorForInputDevice(sensor.getId(), sensor.getType()) != null) {
+ synchronized (mInputSensorLock) {
+ final int deviceId = sensor.getId();
+ InputDevice inputDevice = InputDevice.getDevice(deviceId);
+ if (!inputDevice.hasSensor()) {
+ Slog.e(TAG, "The device doesn't have the sensor:" + sensor);
+ return false;
+ }
+ if (!mInputManager.enableSensor(deviceId, sensor.getType(), delayUs,
+ maxBatchReportLatencyUs)) {
+ Slog.e(TAG, "Can't enable the sensor:" + sensor);
+ return false;
+ }
+ }
+ }
+
+ synchronized (mInputSensorLock) {
+ // Register the InputManagerService sensor listener if not yet.
+ if (mInputServiceSensorListener == null) {
+ mInputServiceSensorListener = new InputSensorEventListener();
+ if (!mInputManager.registerSensorListener(mInputServiceSensorListener)) {
+ Slog.e(TAG, "Failed registering the sensor listener");
+ return false;
+ }
+ }
+
+ int idx = findSensorEventListenerLocked(listener);
+ if (idx < 0) {
+ InputSensorEventListenerDelegate d =
+ new InputSensorEventListenerDelegate(listener, sensor, delayUs,
+ maxBatchReportLatencyUs,
+ handler == null ? mSensorHandler : handler);
+ mInputSensorEventListeners.add(d);
+ } else {
+ // The listener is already registered, see if it wants to listen to more sensors.
+ mInputSensorEventListeners.get(idx).addSensor(sensor);
+ }
+ }
+
+ return true;
+ }
+
+ private void unregisterListenerInternal(SensorEventListener listener, Sensor sensor) {
+ if (DEBUG) {
+ Slog.d(TAG, "unregisterListenerImpl listener=" + listener + " sensor=" + sensor);
+ }
+ if (listener == null) { // it's OK for the sensor to be null
+ throw new IllegalArgumentException("listener must not be null");
+ }
+ synchronized (mInputSensorLock) {
+ int idx = findSensorEventListenerLocked(listener);
+ // Track the sensor types and the device Id the listener has registered.
+ final List<Sensor> sensorsRegistered;
+ if (idx >= 0) {
+ InputSensorEventListenerDelegate delegate =
+ mInputSensorEventListeners.get(idx);
+ sensorsRegistered = new ArrayList<Sensor>(delegate.getSensors());
+ // Get the sensor types the listener is listening to
+ delegate.removeSensor(sensor);
+ if (delegate.isEmpty()) {
+ // If no sensors to listen, remove the listener delegate
+ mInputSensorEventListeners.remove(idx);
+ }
+ } else {
+ Slog.e(TAG, "Listener is not registered");
+ return;
+ }
+ // If no delegation remains, unregister the listener to input service
+ if (mInputServiceSensorListener != null && mInputSensorEventListeners.size() == 0) {
+ mInputManager.unregisterSensorListener(mInputServiceSensorListener);
+ mInputServiceSensorListener = null;
+ }
+ // For each sensor type check if it is still in use by other listeners.
+ for (Sensor s : sensorsRegistered) {
+ final int deviceId = s.getId();
+ final int sensorType = s.getType();
+ // See if we can disable the sensor
+ boolean enableSensor = false;
+ for (int i = 0; i < mInputSensorEventListeners.size(); i++) {
+ InputSensorEventListenerDelegate delegate =
+ mInputSensorEventListeners.get(i);
+ if (delegate.hasSensorRegistered(deviceId, sensorType)) {
+ enableSensor = true;
+ Slog.w(TAG, "device " + deviceId + " still uses sensor " + sensorType);
+ break;
+ }
+ }
+ // Sensor is not listened, disable it.
+ if (!enableSensor) {
+ if (DEBUG) {
+ Slog.d(TAG, "device " + deviceId + " sensor " + sensorType + " disabled");
+ }
+ mInputManager.disableSensor(deviceId, sensorType);
+ }
+ }
+ }
+ }
+
+ private boolean flush(SensorEventListener listener) {
+ synchronized (mInputSensorLock) {
+ int idx = findSensorEventListenerLocked(listener);
+ if (idx < 0) {
+ return false;
+ }
+ for (Sensor sensor : mInputSensorEventListeners.get(idx).getSensors()) {
+ final int deviceId = sensor.getId();
+ if (!mInputManager.flushSensor(deviceId, sensor.getType())) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ /**
+ * Sensor Manager class associated with specific input device
+ */
+ public class InputSensorManager extends SensorManager {
+ // Input device ID that the sensors belong to
+ final int mId;
+
+ InputSensorManager(int deviceId) {
+ mId = deviceId;
+ }
+
+ @Override
+ public Sensor getDefaultSensor(int type) {
+ return getSensorForInputDevice(mId, type);
+ }
+
+ @Override
+ protected List<Sensor> getFullSensorList() {
+ return getFullSensorListForDevice(mId);
+ }
+
+ @Override
+ protected List<Sensor> getFullDynamicSensorList() {
+ return new ArrayList<>();
+ }
+
+ @Override
+ protected boolean registerListenerImpl(SensorEventListener listener, Sensor sensor,
+ int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags) {
+ return registerListenerInternal(listener, sensor, delayUs,
+ maxBatchReportLatencyUs, handler);
+ }
+
+ @Override
+ protected void unregisterListenerImpl(SensorEventListener listener, Sensor sensor) {
+ unregisterListenerInternal(listener, sensor);
+ }
+
+ @Override
+ protected boolean flushImpl(SensorEventListener listener) {
+ return flush(listener);
+ }
+
+ @Override
+ protected SensorDirectChannel createDirectChannelImpl(MemoryFile memoryFile,
+ HardwareBuffer hardwareBuffer) {
+ return null;
+ }
+
+ @Override
+ protected void destroyDirectChannelImpl(SensorDirectChannel channel) {
+
+ }
+
+ @Override
+ protected int configureDirectChannelImpl(SensorDirectChannel channel, Sensor s, int rate) {
+ return 0;
+ }
+
+ @Override
+ protected void registerDynamicSensorCallbackImpl(DynamicSensorCallback callback,
+ Handler handler) {
+
+ }
+
+ @Override
+ protected void unregisterDynamicSensorCallbackImpl(
+ DynamicSensorCallback callback) {
+
+ }
+
+ @Override
+ protected boolean requestTriggerSensorImpl(TriggerEventListener listener, Sensor sensor) {
+ return true;
+ }
+
+ @Override
+ protected boolean cancelTriggerSensorImpl(TriggerEventListener listener, Sensor sensor,
+ boolean disable) {
+ return true;
+ }
+
+ @Override
+ protected boolean initDataInjectionImpl(boolean enable) {
+ return false;
+ }
+
+ @Override
+ protected boolean injectSensorDataImpl(Sensor sensor, float[] values, int accuracy,
+ long timestamp) {
+ return false;
+ }
+
+ @Override
+ protected boolean setOperationParameterImpl(SensorAdditionalInfo parameter) {
+ return false;
+ }
+ }
+
+}
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 40c7e9a..300d99b 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -28,6 +28,7 @@
import android.compat.annotation.ChangeId;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
+import android.hardware.SensorManager;
import android.os.BlockUntrustedTouchesMode;
import android.os.Build;
import android.os.CombinedVibrationEffect;
@@ -100,6 +101,7 @@
private TabletModeChangedListener mTabletModeChangedListener;
private List<OnTabletModeChangedListenerDelegate> mOnTabletModeChangedListeners;
+ private InputDeviceSensorManager mInputDeviceSensorManager;
/**
* Broadcast Action: Query available keyboard layouts.
* <p>
@@ -291,6 +293,18 @@
}
/**
+ * Clear the instance of the input manager.
+ *
+ * @hide
+ */
+ @VisibleForTesting
+ public static void clearInstance() {
+ synchronized (InputManager.class) {
+ sInstance = null;
+ }
+ }
+
+ /**
* Gets an instance of the input manager.
*
* @return The input manager instance.
@@ -1152,6 +1166,86 @@
}
/**
+ * Get sensors information as list.
+ *
+ * @hide
+ */
+ public InputSensorInfo[] getSensorList(int deviceId) {
+ try {
+ return mIm.getSensorList(deviceId);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Enable input device sensor
+ *
+ * @hide
+ */
+ public boolean enableSensor(int deviceId, int sensorType, int samplingPeriodUs,
+ int maxBatchReportLatencyUs) {
+ try {
+ return mIm.enableSensor(deviceId, sensorType, samplingPeriodUs,
+ maxBatchReportLatencyUs);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Enable input device sensor
+ *
+ * @hide
+ */
+ public void disableSensor(int deviceId, int sensorType) {
+ try {
+ mIm.disableSensor(deviceId, sensorType);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Flush input device sensor
+ *
+ * @hide
+ */
+ public boolean flushSensor(int deviceId, int sensorType) {
+ try {
+ return mIm.flushSensor(deviceId, sensorType);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Register input device sensor listener
+ *
+ * @hide
+ */
+ public boolean registerSensorListener(IInputSensorEventListener listener) {
+ try {
+ return mIm.registerSensorListener(listener);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Unregister input device sensor listener
+ *
+ * @hide
+ */
+ public void unregisterSensorListener(IInputSensorEventListener listener) {
+ try {
+ mIm.unregisterSensorListener(listener);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Add a runtime association between the input port and the display port. This overrides any
* static associations.
* @param inputPort The port of the input device.
@@ -1289,7 +1383,7 @@
}
/**
- * Gets a vibrator service associated with an input device, assuming it has one.
+ * Gets a vibrator service associated with an input device, always create a new instance.
* @return The vibrator, never null.
* @hide
*/
@@ -1365,6 +1459,19 @@
}
/**
+ * Gets a sensor manager service associated with an input device, always create a new instance.
+ * @return The sensor manager, never null.
+ * @hide
+ */
+ @NonNull
+ public SensorManager getInputDeviceSensorManager(int deviceId) {
+ if (mInputDeviceSensorManager == null) {
+ mInputDeviceSensorManager = new InputDeviceSensorManager(this);
+ }
+ return mInputDeviceSensorManager.getSensorManager(deviceId);
+ }
+
+ /**
* Listens for changes in input devices.
*/
public interface InputDeviceListener {
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java b/core/java/android/hardware/input/InputSensorInfo.aidl
similarity index 62%
copy from media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java
copy to core/java/android/hardware/input/InputSensorInfo.aidl
index 52f2787..d9a604a 100644
--- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java
+++ b/core/java/android/hardware/input/InputSensorInfo.aidl
@@ -14,19 +14,6 @@
* limitations under the License.
*/
-package com.android.mediatranscodingtest;
+package android.hardware.input;
-/**
- *
- * This class has the names of the all the activity name and variables in the
- * instrumentation test.
- *
- */
-public class MediaConstants {
- /*
- * Source test files.
- */
- public static final String[] SOURCE_HEVC_VIDEO_ONLY_TEST_FILES = {
- "/sdcard/media_api/video/VideoOnlyHEVC.mp4",
- };
-}
+parcelable InputSensorInfo;
diff --git a/core/java/android/hardware/input/InputSensorInfo.java b/core/java/android/hardware/input/InputSensorInfo.java
new file mode 100644
index 0000000..99b1879
--- /dev/null
+++ b/core/java/android/hardware/input/InputSensorInfo.java
@@ -0,0 +1,330 @@
+/*
+ * 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.hardware.input;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+/**
+ * This class represents a motion sensor for input devices.
+ *
+ * @hide
+ */
+@DataClass(
+ genToString = true,
+ genHiddenConstructor = true,
+ genHiddenConstDefs = true)
+public class InputSensorInfo implements Parcelable {
+
+ private @NonNull String mName;
+ private @NonNull String mVendor;
+ private int mVersion;
+ private int mHandle;
+ private int mType;
+ private float mMaxRange;
+ private float mResolution;
+ private float mPower;
+ private int mMinDelay;
+ private int mFifoReservedEventCount;
+ private int mFifoMaxEventCount;
+ private @NonNull String mStringType;
+ private @NonNull String mRequiredPermission;
+ private int mMaxDelay;
+ private int mFlags;
+ private int mId;
+
+
+
+ // Code below generated by codegen v1.0.20.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/hardware/input/InputSensorInfo.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ /**
+ * Creates a new InputSensorInfo.
+ *
+ * @hide
+ */
+ @DataClass.Generated.Member
+ public InputSensorInfo(
+ @NonNull String name,
+ @NonNull String vendor,
+ int version,
+ int handle,
+ int type,
+ float maxRange,
+ float resolution,
+ float power,
+ int minDelay,
+ int fifoReservedEventCount,
+ int fifoMaxEventCount,
+ @NonNull String stringType,
+ @NonNull String requiredPermission,
+ int maxDelay,
+ int flags,
+ int id) {
+ this.mName = name;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mName);
+ this.mVendor = vendor;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mVendor);
+ this.mVersion = version;
+ this.mHandle = handle;
+ this.mType = type;
+ this.mMaxRange = maxRange;
+ this.mResolution = resolution;
+ this.mPower = power;
+ this.mMinDelay = minDelay;
+ this.mFifoReservedEventCount = fifoReservedEventCount;
+ this.mFifoMaxEventCount = fifoMaxEventCount;
+ this.mStringType = stringType;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mStringType);
+ this.mRequiredPermission = requiredPermission;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mRequiredPermission);
+ this.mMaxDelay = maxDelay;
+ this.mFlags = flags;
+ this.mId = id;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull String getName() {
+ return mName;
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull String getVendor() {
+ return mVendor;
+ }
+
+ @DataClass.Generated.Member
+ public int getVersion() {
+ return mVersion;
+ }
+
+ @DataClass.Generated.Member
+ public int getHandle() {
+ return mHandle;
+ }
+
+ @DataClass.Generated.Member
+ public int getType() {
+ return mType;
+ }
+
+ @DataClass.Generated.Member
+ public float getMaxRange() {
+ return mMaxRange;
+ }
+
+ @DataClass.Generated.Member
+ public float getResolution() {
+ return mResolution;
+ }
+
+ @DataClass.Generated.Member
+ public float getPower() {
+ return mPower;
+ }
+
+ @DataClass.Generated.Member
+ public int getMinDelay() {
+ return mMinDelay;
+ }
+
+ @DataClass.Generated.Member
+ public int getFifoReservedEventCount() {
+ return mFifoReservedEventCount;
+ }
+
+ @DataClass.Generated.Member
+ public int getFifoMaxEventCount() {
+ return mFifoMaxEventCount;
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull String getStringType() {
+ return mStringType;
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull String getRequiredPermission() {
+ return mRequiredPermission;
+ }
+
+ @DataClass.Generated.Member
+ public int getMaxDelay() {
+ return mMaxDelay;
+ }
+
+ @DataClass.Generated.Member
+ public int getFlags() {
+ return mFlags;
+ }
+
+ @DataClass.Generated.Member
+ public int getId() {
+ return mId;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public String toString() {
+ // You can override field toString logic by defining methods like:
+ // String fieldNameToString() { ... }
+
+ return "InputSensorInfo { " +
+ "name = " + mName + ", " +
+ "vendor = " + mVendor + ", " +
+ "version = " + mVersion + ", " +
+ "handle = " + mHandle + ", " +
+ "type = " + mType + ", " +
+ "maxRange = " + mMaxRange + ", " +
+ "resolution = " + mResolution + ", " +
+ "power = " + mPower + ", " +
+ "minDelay = " + mMinDelay + ", " +
+ "fifoReservedEventCount = " + mFifoReservedEventCount + ", " +
+ "fifoMaxEventCount = " + mFifoMaxEventCount + ", " +
+ "stringType = " + mStringType + ", " +
+ "requiredPermission = " + mRequiredPermission + ", " +
+ "maxDelay = " + mMaxDelay + ", " +
+ "flags = " + mFlags + ", " +
+ "id = " + mId +
+ " }";
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ dest.writeString(mName);
+ dest.writeString(mVendor);
+ dest.writeInt(mVersion);
+ dest.writeInt(mHandle);
+ dest.writeInt(mType);
+ dest.writeFloat(mMaxRange);
+ dest.writeFloat(mResolution);
+ dest.writeFloat(mPower);
+ dest.writeInt(mMinDelay);
+ dest.writeInt(mFifoReservedEventCount);
+ dest.writeInt(mFifoMaxEventCount);
+ dest.writeString(mStringType);
+ dest.writeString(mRequiredPermission);
+ dest.writeInt(mMaxDelay);
+ dest.writeInt(mFlags);
+ dest.writeInt(mId);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ protected InputSensorInfo(@NonNull Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ String name = in.readString();
+ String vendor = in.readString();
+ int version = in.readInt();
+ int handle = in.readInt();
+ int type = in.readInt();
+ float maxRange = in.readFloat();
+ float resolution = in.readFloat();
+ float power = in.readFloat();
+ int minDelay = in.readInt();
+ int fifoReservedEventCount = in.readInt();
+ int fifoMaxEventCount = in.readInt();
+ String stringType = in.readString();
+ String requiredPermission = in.readString();
+ int maxDelay = in.readInt();
+ int flags = in.readInt();
+ int id = in.readInt();
+
+ this.mName = name;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mName);
+ this.mVendor = vendor;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mVendor);
+ this.mVersion = version;
+ this.mHandle = handle;
+ this.mType = type;
+ this.mMaxRange = maxRange;
+ this.mResolution = resolution;
+ this.mPower = power;
+ this.mMinDelay = minDelay;
+ this.mFifoReservedEventCount = fifoReservedEventCount;
+ this.mFifoMaxEventCount = fifoMaxEventCount;
+ this.mStringType = stringType;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mStringType);
+ this.mRequiredPermission = requiredPermission;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mRequiredPermission);
+ this.mMaxDelay = maxDelay;
+ this.mFlags = flags;
+ this.mId = id;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<InputSensorInfo> CREATOR
+ = new Parcelable.Creator<InputSensorInfo>() {
+ @Override
+ public InputSensorInfo[] newArray(int size) {
+ return new InputSensorInfo[size];
+ }
+
+ @Override
+ public InputSensorInfo createFromParcel(@NonNull Parcel in) {
+ return new InputSensorInfo(in);
+ }
+ };
+
+ @DataClass.Generated(
+ time = 1605294854951L,
+ codegenVersion = "1.0.20",
+ sourceFile = "frameworks/base/core/java/android/hardware/input/InputSensorInfo.java",
+ inputSignatures = "private @android.annotation.NonNull java.lang.String mName\nprivate @android.annotation.NonNull java.lang.String mVendor\nprivate int mVersion\nprivate int mHandle\nprivate int mType\nprivate float mMaxRange\nprivate float mResolution\nprivate float mPower\nprivate int mMinDelay\nprivate int mFifoReservedEventCount\nprivate int mFifoMaxEventCount\nprivate @android.annotation.NonNull java.lang.String mStringType\nprivate @android.annotation.NonNull java.lang.String mRequiredPermission\nprivate int mMaxDelay\nprivate int mFlags\nprivate int mId\nclass InputSensorInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstructor=true, genHiddenConstDefs=true)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 6831eca..df9a7c2 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -1700,8 +1700,12 @@
if (config.orientation != Configuration.ORIENTATION_LANDSCAPE) {
return false;
}
- if (mInputEditorInfo != null
- && (mInputEditorInfo.imeOptions & EditorInfo.IME_FLAG_NO_FULLSCREEN) != 0) {
+ if ((mInputEditorInfo != null
+ && (mInputEditorInfo.imeOptions & EditorInfo.IME_FLAG_NO_FULLSCREEN) != 0)
+ // If app window has portrait orientation, regardless of what display orientation
+ // is, IME shouldn't use fullscreen-mode.
+ || (mInputEditorInfo.internalImeOptions
+ & EditorInfo.IME_FLAG_APP_WINDOW_PORTRAIT) != 0) {
return false;
}
return true;
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index fb01283..95a2f2e 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -31,6 +31,7 @@
import android.net.ProxyInfo;
import android.os.Bundle;
import android.os.IBinder;
+import android.os.INetworkActivityListener;
import android.os.Messenger;
import android.os.ParcelFileDescriptor;
import android.os.PersistableBundle;
@@ -233,4 +234,10 @@
in PersistableBundle extras);
void systemReady();
+
+ void registerNetworkActivityListener(in INetworkActivityListener l);
+
+ void unregisterNetworkActivityListener(in INetworkActivityListener l);
+
+ boolean isDefaultNetworkActive();
}
diff --git a/core/java/android/net/NetworkStatsHistory.java b/core/java/android/net/NetworkStatsHistory.java
index fba7561..bf25602 100644
--- a/core/java/android/net/NetworkStatsHistory.java
+++ b/core/java/android/net/NetworkStatsHistory.java
@@ -26,9 +26,9 @@
import static android.net.NetworkStatsHistory.Entry.UNKNOWN;
import static android.net.NetworkStatsHistory.ParcelUtils.readLongArray;
import static android.net.NetworkStatsHistory.ParcelUtils.writeLongArray;
-import static android.net.NetworkUtils.multiplySafeByRational;
import static android.text.format.DateUtils.SECOND_IN_MILLIS;
+import static com.android.internal.net.NetworkUtilsInternal.multiplySafeByRational;
import static com.android.internal.util.ArrayUtils.total;
import android.compat.annotation.UnsupportedAppUsage;
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index d84ee2a..b5962c5 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -16,14 +16,9 @@
package android.net;
-import static android.system.OsConstants.AF_INET;
-import static android.system.OsConstants.AF_INET6;
-
-import android.annotation.NonNull;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.system.ErrnoException;
-import android.system.Os;
import android.util.Log;
import android.util.Pair;
@@ -155,14 +150,6 @@
public static native Network getDnsNetwork() throws ErrnoException;
/**
- * Allow/Disallow creating AF_INET/AF_INET6 sockets and DNS lookups for current process.
- *
- * @param allowNetworking whether to allow or disallow creating AF_INET/AF_INET6 sockets
- * and DNS lookups.
- */
- public static native void setAllowNetworkingForProcess(boolean allowNetworking);
-
- /**
* Get the tcp repair window associated with the {@code fd}.
*
* @param fd the tcp socket's {@link FileDescriptor}.
@@ -437,60 +424,4 @@
return routedIPCount;
}
- private static final int[] ADDRESS_FAMILIES = new int[] {AF_INET, AF_INET6};
-
- /**
- * Returns true if the hostname is weakly validated.
- * @param hostname Name of host to validate.
- * @return True if it's a valid-ish hostname.
- *
- * @hide
- */
- public static boolean isWeaklyValidatedHostname(@NonNull String hostname) {
- // TODO(b/34953048): Use a validation method that permits more accurate,
- // but still inexpensive, checking of likely valid DNS hostnames.
- final String weakHostnameRegex = "^[a-zA-Z0-9_.-]+$";
- if (!hostname.matches(weakHostnameRegex)) {
- return false;
- }
-
- for (int address_family : ADDRESS_FAMILIES) {
- if (Os.inet_pton(address_family, hostname) != null) {
- return false;
- }
- }
-
- return true;
- }
-
- /**
- * Safely multiple a value by a rational.
- * <p>
- * Internally it uses integer-based math whenever possible, but switches
- * over to double-based math if values would overflow.
- * @hide
- */
- public static long multiplySafeByRational(long value, long num, long den) {
- if (den == 0) {
- throw new ArithmeticException("Invalid Denominator");
- }
- long x = value;
- long y = num;
-
- // Logic shamelessly borrowed from Math.multiplyExact()
- long r = x * y;
- long ax = Math.abs(x);
- long ay = Math.abs(y);
- if (((ax | ay) >>> 31 != 0)) {
- // Some bits greater than 2^31 that might cause overflow
- // Check the result using the divide operator
- // and check for the special case of Long.MIN_VALUE * -1
- if (((y != 0) && (r / y != x)) ||
- (x == Long.MIN_VALUE && y == -1)) {
- // Use double math to avoid overflowing
- return (long) (((double) num / den) * value);
- }
- }
- return r / den;
- }
}
diff --git a/core/java/android/net/vcn/VcnConfig.java b/core/java/android/net/vcn/VcnConfig.java
index 148acf1..d4a3fa7 100644
--- a/core/java/android/net/vcn/VcnConfig.java
+++ b/core/java/android/net/vcn/VcnConfig.java
@@ -15,30 +15,104 @@
*/
package android.net.vcn;
+import static com.android.internal.annotations.VisibleForTesting.Visibility;
+
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.PersistableBundle;
+import android.util.ArraySet;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
+import com.android.server.vcn.util.PersistableBundleUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Objects;
+import java.util.Set;
/**
* This class represents a configuration for a Virtual Carrier Network.
*
+ * <p>Each {@link VcnGatewayConnectionConfig} instance added represents a connection that will be
+ * brought up on demand based on active {@link NetworkRequest}(s).
+ *
+ * @see VcnManager for more information on the Virtual Carrier Network feature
* @hide
*/
public final class VcnConfig implements Parcelable {
@NonNull private static final String TAG = VcnConfig.class.getSimpleName();
- private VcnConfig() {
+ private static final String GATEWAY_CONNECTION_CONFIGS_KEY = "mGatewayConnectionConfigs";
+ @NonNull private final Set<VcnGatewayConnectionConfig> mGatewayConnectionConfigs;
+
+ private VcnConfig(@NonNull Set<VcnGatewayConnectionConfig> tunnelConfigs) {
+ mGatewayConnectionConfigs = Collections.unmodifiableSet(tunnelConfigs);
+
validate();
}
- // TODO: Implement getters, validators, etc
/**
- * Validates this configuration.
+ * Deserializes a VcnConfig from a PersistableBundle.
*
* @hide
*/
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ public VcnConfig(@NonNull PersistableBundle in) {
+ final PersistableBundle gatewayConnectionConfigsBundle =
+ in.getPersistableBundle(GATEWAY_CONNECTION_CONFIGS_KEY);
+ mGatewayConnectionConfigs =
+ new ArraySet<>(
+ PersistableBundleUtils.toList(
+ gatewayConnectionConfigsBundle, VcnGatewayConnectionConfig::new));
+
+ validate();
+ }
+
private void validate() {
- // TODO: implement validation logic
+ Preconditions.checkCollectionNotEmpty(
+ mGatewayConnectionConfigs, "gatewayConnectionConfigs");
+ }
+
+ /** Retrieves the set of configured tunnels. */
+ @NonNull
+ public Set<VcnGatewayConnectionConfig> getGatewayConnectionConfigs() {
+ return Collections.unmodifiableSet(mGatewayConnectionConfigs);
+ }
+
+ /**
+ * Serializes this object to a PersistableBundle.
+ *
+ * @hide
+ */
+ @NonNull
+ public PersistableBundle toPersistableBundle() {
+ final PersistableBundle result = new PersistableBundle();
+
+ final PersistableBundle gatewayConnectionConfigsBundle =
+ PersistableBundleUtils.fromList(
+ new ArrayList<>(mGatewayConnectionConfigs),
+ VcnGatewayConnectionConfig::toPersistableBundle);
+ result.putPersistableBundle(GATEWAY_CONNECTION_CONFIGS_KEY, gatewayConnectionConfigsBundle);
+
+ return result;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mGatewayConnectionConfigs);
+ }
+
+ @Override
+ public boolean equals(@Nullable Object other) {
+ if (!(other instanceof VcnConfig)) {
+ return false;
+ }
+
+ final VcnConfig rhs = (VcnConfig) other;
+ return mGatewayConnectionConfigs.equals(rhs.mGatewayConnectionConfigs);
}
// Parcelable methods
@@ -49,15 +123,16 @@
}
@Override
- public void writeToParcel(Parcel out, int flags) {}
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeParcelable(toPersistableBundle(), flags);
+ }
@NonNull
public static final Parcelable.Creator<VcnConfig> CREATOR =
new Parcelable.Creator<VcnConfig>() {
@NonNull
public VcnConfig createFromParcel(Parcel in) {
- // TODO: Ensure all methods are pulled from the parcels
- return new VcnConfig();
+ return new VcnConfig((PersistableBundle) in.readParcelable(null));
}
@NonNull
@@ -68,7 +143,23 @@
/** This class is used to incrementally build {@link VcnConfig} objects. */
public static class Builder {
- // TODO: Implement this builder
+ @NonNull
+ private final Set<VcnGatewayConnectionConfig> mGatewayConnectionConfigs = new ArraySet<>();
+
+ /**
+ * Adds a configuration for an individual gateway connection.
+ *
+ * @param gatewayConnectionConfig the configuration for an individual gateway connection
+ * @return this {@link Builder} instance, for chaining
+ */
+ @NonNull
+ public Builder addGatewayConnectionConfig(
+ @NonNull VcnGatewayConnectionConfig gatewayConnectionConfig) {
+ Objects.requireNonNull(gatewayConnectionConfig, "gatewayConnectionConfig was null");
+
+ mGatewayConnectionConfigs.add(gatewayConnectionConfig);
+ return this;
+ }
/**
* Builds and validates the VcnConfig.
@@ -77,7 +168,7 @@
*/
@NonNull
public VcnConfig build() {
- return new VcnConfig();
+ return new VcnConfig(mGatewayConnectionConfigs);
}
}
}
diff --git a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
index 8160edc..039360a 100644
--- a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
+++ b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
@@ -15,7 +15,27 @@
*/
package android.net.vcn;
+import static android.net.NetworkCapabilities.NetCapability;
+
+import static com.android.internal.annotations.VisibleForTesting.Visibility;
+
+import android.annotation.IntRange;
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.NetworkCapabilities;
+import android.os.PersistableBundle;
+import android.util.ArraySet;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
+import com.android.server.vcn.util.PersistableBundleUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
/**
* This class represents a configuration for a connection to a Virtual Carrier Network gateway.
@@ -49,38 +69,399 @@
* <li>{@link android.net.NetworkCapabilities.NET_CAPABILITY_MCX}
* </ul>
*
+ * <p>The meteredness and roaming of the VCN {@link Network} will be determined by that of the
+ * underlying Network(s).
+ *
* @hide
*/
public final class VcnGatewayConnectionConfig {
- private VcnGatewayConnectionConfig() {
+ // TODO: Use MIN_MTU_V6 once it is public, @hide
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ static final int MIN_MTU_V6 = 1280;
+
+ private static final Set<Integer> ALLOWED_CAPABILITIES;
+
+ static {
+ Set<Integer> allowedCaps = new ArraySet<>();
+ allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_MMS);
+ allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_SUPL);
+ allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_DUN);
+ allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_FOTA);
+ allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_IMS);
+ allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_CBS);
+ allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_IA);
+ allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_RCS);
+ allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_XCAP);
+ allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_EIMS);
+ allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_MCX);
+
+ ALLOWED_CAPABILITIES = Collections.unmodifiableSet(allowedCaps);
+ }
+
+ private static final int DEFAULT_MAX_MTU = 1500;
+
+ /**
+ * The maximum number of retry intervals that may be specified.
+ *
+ * <p>Limited to ensure an upper bound on config sizes.
+ */
+ private static final int MAX_RETRY_INTERVAL_COUNT = 10;
+
+ /**
+ * The minimum allowable repeating retry interval
+ *
+ * <p>To ensure the device is not constantly being woken up, this retry interval MUST be greater
+ * than this value.
+ *
+ * @see {@link Builder#setRetryInterval()}
+ */
+ private static final long MINIMUM_REPEATING_RETRY_INTERVAL_MS = TimeUnit.MINUTES.toMillis(15);
+
+ private static final long[] DEFAULT_RETRY_INTERVALS_MS =
+ new long[] {
+ TimeUnit.SECONDS.toMillis(1),
+ TimeUnit.SECONDS.toMillis(2),
+ TimeUnit.SECONDS.toMillis(5),
+ TimeUnit.SECONDS.toMillis(30),
+ TimeUnit.MINUTES.toMillis(1),
+ TimeUnit.MINUTES.toMillis(5),
+ TimeUnit.MINUTES.toMillis(15)
+ };
+
+ private static final String EXPOSED_CAPABILITIES_KEY = "mExposedCapabilities";
+ @NonNull private final Set<Integer> mExposedCapabilities;
+
+ private static final String UNDERLYING_CAPABILITIES_KEY = "mUnderlyingCapabilities";
+ @NonNull private final Set<Integer> mUnderlyingCapabilities;
+
+ // TODO: Add Ike/ChildSessionParams as a subclass - maybe VcnIkeGatewayConnectionConfig
+
+ private static final String MAX_MTU_KEY = "mMaxMtu";
+ private final int mMaxMtu;
+
+ private static final String RETRY_INTERVAL_MS_KEY = "mRetryIntervalsMs";
+ @NonNull private final long[] mRetryIntervalsMs;
+
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ public VcnGatewayConnectionConfig(
+ @NonNull Set<Integer> exposedCapabilities,
+ @NonNull Set<Integer> underlyingCapabilities,
+ @NonNull long[] retryIntervalsMs,
+ @IntRange(from = MIN_MTU_V6) int maxMtu) {
+ mExposedCapabilities = exposedCapabilities;
+ mUnderlyingCapabilities = underlyingCapabilities;
+ mRetryIntervalsMs = retryIntervalsMs;
+ mMaxMtu = maxMtu;
+
validate();
}
- // TODO: Implement getters, validators, etc
+ /** @hide */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ public VcnGatewayConnectionConfig(@NonNull PersistableBundle in) {
+ final PersistableBundle exposedCapsBundle =
+ in.getPersistableBundle(EXPOSED_CAPABILITIES_KEY);
+ final PersistableBundle underlyingCapsBundle =
+ in.getPersistableBundle(UNDERLYING_CAPABILITIES_KEY);
+
+ mExposedCapabilities = new ArraySet<>(PersistableBundleUtils.toList(
+ exposedCapsBundle, PersistableBundleUtils.INTEGER_DESERIALIZER));
+ mUnderlyingCapabilities = new ArraySet<>(PersistableBundleUtils.toList(
+ underlyingCapsBundle, PersistableBundleUtils.INTEGER_DESERIALIZER));
+ mRetryIntervalsMs = in.getLongArray(RETRY_INTERVAL_MS_KEY);
+ mMaxMtu = in.getInt(MAX_MTU_KEY);
+
+ validate();
+ }
+
+ private void validate() {
+ Preconditions.checkArgument(
+ mExposedCapabilities != null && !mExposedCapabilities.isEmpty(),
+ "exposedCapsBundle was null or empty");
+ for (Integer cap : getAllExposedCapabilities()) {
+ checkValidCapability(cap);
+ }
+
+ Preconditions.checkArgument(
+ mUnderlyingCapabilities != null && !mUnderlyingCapabilities.isEmpty(),
+ "underlyingCapabilities was null or empty");
+ for (Integer cap : getAllUnderlyingCapabilities()) {
+ checkValidCapability(cap);
+ }
+
+ Objects.requireNonNull(mRetryIntervalsMs, "retryIntervalsMs was null");
+ validateRetryInterval(mRetryIntervalsMs);
+
+ Preconditions.checkArgument(
+ mMaxMtu >= MIN_MTU_V6, "maxMtu must be at least IPv6 min MTU (1280)");
+ }
+
+ private static void checkValidCapability(int capability) {
+ Preconditions.checkArgument(
+ ALLOWED_CAPABILITIES.contains(capability),
+ "NetworkCapability " + capability + "out of range");
+ }
+
+ private static void validateRetryInterval(@Nullable long[] retryIntervalsMs) {
+ Preconditions.checkArgument(
+ retryIntervalsMs != null
+ && retryIntervalsMs.length > 0
+ && retryIntervalsMs.length <= MAX_RETRY_INTERVAL_COUNT,
+ "retryIntervalsMs was null, empty or exceed max interval count");
+
+ final long repeatingInterval = retryIntervalsMs[retryIntervalsMs.length - 1];
+ if (repeatingInterval < MINIMUM_REPEATING_RETRY_INTERVAL_MS) {
+ throw new IllegalArgumentException(
+ "Repeating retry interval was too short, must be a minimum of 15 minutes: "
+ + repeatingInterval);
+ }
+ }
/**
- * Validates this configuration
+ * Returns all exposed capabilities.
*
* @hide
*/
- private void validate() {
- // TODO: implement validation logic
+ @NonNull
+ public Set<Integer> getAllExposedCapabilities() {
+ return Collections.unmodifiableSet(mExposedCapabilities);
}
- // Parcelable methods
+ /**
+ * Checks if this config is configured to support/expose a specific capability.
+ *
+ * @param capability the capability to check for
+ */
+ public boolean hasExposedCapability(@NetCapability int capability) {
+ checkValidCapability(capability);
- /** This class is used to incrementally build {@link VcnGatewayConnectionConfig} objects */
+ return mExposedCapabilities.contains(capability);
+ }
+
+ /**
+ * Returns all capabilities required of underlying networks.
+ *
+ * @hide
+ */
+ @NonNull
+ public Set<Integer> getAllUnderlyingCapabilities() {
+ return Collections.unmodifiableSet(mUnderlyingCapabilities);
+ }
+
+ /**
+ * Checks if this config requires an underlying network to have the specified capability.
+ *
+ * @param capability the capability to check for
+ */
+ public boolean requiresUnderlyingCapability(@NetCapability int capability) {
+ checkValidCapability(capability);
+
+ return mUnderlyingCapabilities.contains(capability);
+ }
+
+ /** Retrieves the configured retry intervals. */
+ @NonNull
+ public long[] getRetryIntervalsMs() {
+ return Arrays.copyOf(mRetryIntervalsMs, mRetryIntervalsMs.length);
+ }
+
+ /** Retrieves the maximum MTU allowed for this Gateway Connection. */
+ @IntRange(from = MIN_MTU_V6)
+ public int getMaxMtu() {
+ return mMaxMtu;
+ }
+
+ /**
+ * Converts this config to a PersistableBundle.
+ *
+ * @hide
+ */
+ @NonNull
+ @VisibleForTesting(visibility = Visibility.PROTECTED)
+ public PersistableBundle toPersistableBundle() {
+ final PersistableBundle result = new PersistableBundle();
+
+ final PersistableBundle exposedCapsBundle =
+ PersistableBundleUtils.fromList(
+ new ArrayList<>(mExposedCapabilities),
+ PersistableBundleUtils.INTEGER_SERIALIZER);
+ final PersistableBundle underlyingCapsBundle =
+ PersistableBundleUtils.fromList(
+ new ArrayList<>(mUnderlyingCapabilities),
+ PersistableBundleUtils.INTEGER_SERIALIZER);
+
+ result.putPersistableBundle(EXPOSED_CAPABILITIES_KEY, exposedCapsBundle);
+ result.putPersistableBundle(UNDERLYING_CAPABILITIES_KEY, underlyingCapsBundle);
+ result.putLongArray(RETRY_INTERVAL_MS_KEY, mRetryIntervalsMs);
+ result.putInt(MAX_MTU_KEY, mMaxMtu);
+
+ return result;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(
+ mExposedCapabilities,
+ mUnderlyingCapabilities,
+ Arrays.hashCode(mRetryIntervalsMs),
+ mMaxMtu);
+ }
+
+ @Override
+ public boolean equals(@Nullable Object other) {
+ if (!(other instanceof VcnGatewayConnectionConfig)) {
+ return false;
+ }
+
+ final VcnGatewayConnectionConfig rhs = (VcnGatewayConnectionConfig) other;
+ return mExposedCapabilities.equals(rhs.mExposedCapabilities)
+ && mUnderlyingCapabilities.equals(rhs.mUnderlyingCapabilities)
+ && Arrays.equals(mRetryIntervalsMs, rhs.mRetryIntervalsMs)
+ && mMaxMtu == rhs.mMaxMtu;
+ }
+
+ /** This class is used to incrementally build {@link VcnGatewayConnectionConfig} objects. */
public static class Builder {
- // TODO: Implement this builder
+ @NonNull private final Set<Integer> mExposedCapabilities = new ArraySet();
+ @NonNull private final Set<Integer> mUnderlyingCapabilities = new ArraySet();
+ @NonNull private long[] mRetryIntervalsMs = DEFAULT_RETRY_INTERVALS_MS;
+ private int mMaxMtu = DEFAULT_MAX_MTU;
+
+ // TODO: (b/175829816) Consider VCN-exposed capabilities that may be transport dependent.
+ // Consider the case where the VCN might only expose MMS on WiFi, but defer to MMS
+ // when on Cell.
/**
- * Builds and validates the VcnGatewayConnectionConfig
+ * Add a capability that this VCN Gateway Connection will support.
+ *
+ * @param exposedCapability the app-facing capability to be exposed by this VCN Gateway
+ * Connection (i.e., the capabilities that this VCN Gateway Connection will support).
+ * @return this {@link Builder} instance, for chaining
+ * @see VcnGatewayConnectionConfig for a list of capabilities may be exposed by a Gateway
+ * Connection
+ */
+ public Builder addExposedCapability(@NetCapability int exposedCapability) {
+ checkValidCapability(exposedCapability);
+
+ mExposedCapabilities.add(exposedCapability);
+ return this;
+ }
+
+ /**
+ * Remove a capability that this VCN Gateway Connection will support.
+ *
+ * @param exposedCapability the app-facing capability to not be exposed by this VCN Gateway
+ * Connection (i.e., the capabilities that this VCN Gateway Connection will support)
+ * @return this {@link Builder} instance, for chaining
+ * @see VcnGatewayConnectionConfig for a list of capabilities may be exposed by a Gateway
+ * Connection
+ */
+ public Builder removeExposedCapability(@NetCapability int exposedCapability) {
+ checkValidCapability(exposedCapability);
+
+ mExposedCapabilities.remove(exposedCapability);
+ return this;
+ }
+
+ /**
+ * Require a capability for Networks underlying this VCN Gateway Connection.
+ *
+ * @param underlyingCapability the capability that a network MUST have in order to be an
+ * underlying network for this VCN Gateway Connection.
+ * @return this {@link Builder} instance, for chaining
+ * @see VcnGatewayConnectionConfig for a list of capabilities may be required of underlying
+ * networks
+ */
+ public Builder addRequiredUnderlyingCapability(@NetCapability int underlyingCapability) {
+ checkValidCapability(underlyingCapability);
+
+ mUnderlyingCapabilities.add(underlyingCapability);
+ return this;
+ }
+
+ /**
+ * Remove a requirement of a capability for Networks underlying this VCN Gateway Connection.
+ *
+ * <p>Calling this method will allow Networks that do NOT have this capability to be
+ * selected as an underlying network for this VCN Gateway Connection. However, underlying
+ * networks MAY still have the removed capability.
+ *
+ * @param underlyingCapability the capability that a network DOES NOT need to have in order
+ * to be an underlying network for this VCN Gateway Connection.
+ * @return this {@link Builder} instance, for chaining
+ * @see VcnGatewayConnectionConfig for a list of capabilities may be required of underlying
+ * networks
+ */
+ public Builder removeRequiredUnderlyingCapability(@NetCapability int underlyingCapability) {
+ checkValidCapability(underlyingCapability);
+
+ mUnderlyingCapabilities.remove(underlyingCapability);
+ return this;
+ }
+
+ /**
+ * Set the retry interval between VCN establishment attempts upon successive failures.
+ *
+ * <p>The last retry interval will be repeated until safe mode is entered, or a connection
+ * is successfully established, at which point the retry timers will be reset. For power
+ * reasons, the last (repeated) retry interval MUST be at least 15 minutes.
+ *
+ * <p>Retry intervals MAY be subject to system power saving modes. That is to say that if
+ * the system enters a power saving mode, the retry may not occur until the device leaves
+ * the specified power saving mode. Intervals are sequential, and intervals will NOT be
+ * skipped if system power saving results in delaying retries (even if it exceed multiple
+ * retry intervals).
+ *
+ * <p>Each Gateway Connection will retry according to the retry intervals configured, but if
+ * safe mode is enabled, all Gateway Connection(s) will be disabled.
+ *
+ * @param retryIntervalsMs an array of between 1 and 10 millisecond intervals after which
+ * the VCN will attempt to retry a session initiation. The last (repeating) retry
+ * interval must be at least 15 minutes. Defaults to: {@code [1s, 2s, 5s, 30s, 1m, 5m,
+ * 15m]}
+ * @return this {@link Builder} instance, for chaining
+ * @see VcnManager for additional discussion on fail-safe mode
+ */
+ @NonNull
+ public Builder setRetryInterval(@NonNull long[] retryIntervalsMs) {
+ validateRetryInterval(retryIntervalsMs);
+
+ mRetryIntervalsMs = retryIntervalsMs;
+ return this;
+ }
+
+ /**
+ * Sets the maximum MTU allowed for this VCN Gateway Connection.
+ *
+ * <p>This MTU is applied to the VCN Gateway Connection exposed Networks, and represents the
+ * MTU of the virtualized network.
+ *
+ * <p>The system may reduce the MTU below the maximum specified based on signals such as the
+ * MTU of the underlying networks (and adjusted for Gateway Connection overhead).
+ *
+ * @param maxMtu the maximum MTU allowed for this Gateway Connection. Must be greater than
+ * the IPv6 minimum MTU of 1280. Defaults to 1500.
+ * @return this {@link Builder} instance, for chaining
+ */
+ @NonNull
+ public Builder setMaxMtu(@IntRange(from = MIN_MTU_V6) int maxMtu) {
+ Preconditions.checkArgument(
+ maxMtu >= MIN_MTU_V6, "maxMtu must be at least IPv6 min MTU (1280)");
+
+ mMaxMtu = maxMtu;
+ return this;
+ }
+
+ /**
+ * Builds and validates the VcnGatewayConnectionConfig.
*
* @return an immutable VcnGatewayConnectionConfig instance
*/
@NonNull
public VcnGatewayConnectionConfig build() {
- return new VcnGatewayConnectionConfig();
+ return new VcnGatewayConnectionConfig(
+ mExposedCapabilities, mUnderlyingCapabilities, mRetryIntervalsMs, mMaxMtu);
}
}
}
diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java
index 6769b9e..19c183f 100644
--- a/core/java/android/net/vcn/VcnManager.java
+++ b/core/java/android/net/vcn/VcnManager.java
@@ -23,10 +23,37 @@
import android.content.Context;
import android.os.ParcelUuid;
import android.os.RemoteException;
+import android.os.ServiceSpecificException;
+
+import java.io.IOException;
/**
* VcnManager publishes APIs for applications to configure and manage Virtual Carrier Networks.
*
+ * <p>A VCN creates a virtualization layer to allow MVNOs to aggregate heterogeneous physical
+ * networks, unifying them as a single carrier network. This enables infrastructure flexibility on
+ * the part of MVNOs without impacting user connectivity, abstracting the physical network
+ * technologies as an implementation detail of their public network.
+ *
+ * <p>Each VCN virtualizes an Carrier's network by building tunnels to a carrier's core network over
+ * carrier-managed physical links and supports a IP mobility layer to ensure seamless transitions
+ * between the underlying networks. Each VCN is configured based on a Subscription Group (see {@link
+ * android.telephony.SubscriptionManager}) and aggregates all networks that are brought up based on
+ * a profile or suggestion in the specified Subscription Group.
+ *
+ * <p>The VCN can be configured to expose one or more {@link android.net.Network}(s), each with
+ * different capabilities, allowing for APN virtualization.
+ *
+ * <p>If a tunnel fails to connect, or otherwise encounters a fatal error, the VCN will attempt to
+ * reestablish the connection. If the tunnel still has not reconnected after a system-determined
+ * timeout, the VCN Safe Mode (see below) will be entered.
+ *
+ * <p>The VCN Safe Mode ensures that users (and carriers) have a fallback to restore system
+ * connectivity to update profiles, diagnose issues, contact support, or perform other remediation
+ * tasks. In Safe Mode, the system will allow underlying cellular networks to be used as default.
+ * Additionally, during Safe Mode, the VCN will continue to retry the connections, and will
+ * automatically exit Safe Mode if all active tunnels connect successfully.
+ *
* @hide
*/
@SystemService(Context.VCN_MANAGEMENT_SERVICE)
@@ -63,15 +90,20 @@
* @param config the configuration parameters for the VCN
* @throws SecurityException if the caller does not have carrier privileges, or is not running
* as the primary user
+ * @throws IOException if the configuration failed to be persisted. A caller encountering this
+ * exception should attempt to retry (possibly after a delay).
* @hide
*/
@RequiresPermission("carrier privileges") // TODO (b/72967236): Define a system-wide constant
- public void setVcnConfig(@NonNull ParcelUuid subscriptionGroup, @NonNull VcnConfig config) {
+ public void setVcnConfig(@NonNull ParcelUuid subscriptionGroup, @NonNull VcnConfig config)
+ throws IOException {
requireNonNull(subscriptionGroup, "subscriptionGroup was null");
requireNonNull(config, "config was null");
try {
mService.setVcnConfig(subscriptionGroup, config);
+ } catch (ServiceSpecificException e) {
+ throw new IOException(e);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -88,14 +120,18 @@
* @param subscriptionGroup the subscription group that the configuration should be applied to
* @throws SecurityException if the caller does not have carrier privileges, or is not running
* as the primary user
+ * @throws IOException if the configuration failed to be cleared. A caller encountering this
+ * exception should attempt to retry (possibly after a delay).
* @hide
*/
@RequiresPermission("carrier privileges") // TODO (b/72967236): Define a system-wide constant
- public void clearVcnConfig(@NonNull ParcelUuid subscriptionGroup) {
+ public void clearVcnConfig(@NonNull ParcelUuid subscriptionGroup) throws IOException {
requireNonNull(subscriptionGroup, "subscriptionGroup was null");
try {
mService.clearVcnConfig(subscriptionGroup);
+ } catch (ServiceSpecificException e) {
+ throw new IOException(e);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index e3f996b..0af322e 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -98,6 +98,11 @@
final boolean mRequiresDeviceUnlock;
/**
+ * Whether this service should only be started when the device is screen on.
+ */
+ final boolean mRequiresDeviceScreenOn;
+
+ /**
* The id of the service banner specified in XML.
*/
final int mBannerResourceId;
@@ -120,6 +125,18 @@
ArrayList<AidGroup> staticAidGroups, ArrayList<AidGroup> dynamicAidGroups,
boolean requiresUnlock, int bannerResource, int uid,
String settingsActivityName, String offHost, String staticOffHost) {
+ this(info, onHost, description, staticAidGroups, dynamicAidGroups,
+ requiresUnlock, onHost ? true : false, bannerResource, uid,
+ settingsActivityName, offHost, staticOffHost);
+ }
+
+ /**
+ * @hide
+ */
+ public ApduServiceInfo(ResolveInfo info, boolean onHost, String description,
+ ArrayList<AidGroup> staticAidGroups, ArrayList<AidGroup> dynamicAidGroups,
+ boolean requiresUnlock, boolean requiresScreenOn, int bannerResource, int uid,
+ String settingsActivityName, String offHost, String staticOffHost) {
this.mService = info;
this.mDescription = description;
this.mStaticAidGroups = new HashMap<String, AidGroup>();
@@ -128,6 +145,7 @@
this.mStaticOffHostName = staticOffHost;
this.mOnHost = onHost;
this.mRequiresDeviceUnlock = requiresUnlock;
+ this.mRequiresDeviceScreenOn = requiresScreenOn;
for (AidGroup aidGroup : staticAidGroups) {
this.mStaticAidGroups.put(aidGroup.category, aidGroup);
}
@@ -184,6 +202,9 @@
mRequiresDeviceUnlock = sa.getBoolean(
com.android.internal.R.styleable.HostApduService_requireDeviceUnlock,
false);
+ mRequiresDeviceScreenOn = sa.getBoolean(
+ com.android.internal.R.styleable.HostApduService_requireDeviceScreenOn,
+ true);
mBannerResourceId = sa.getResourceId(
com.android.internal.R.styleable.HostApduService_apduServiceBanner, -1);
mSettingsActivityName = sa.getString(
@@ -197,7 +218,12 @@
mService = info;
mDescription = sa.getString(
com.android.internal.R.styleable.OffHostApduService_description);
- mRequiresDeviceUnlock = false;
+ mRequiresDeviceUnlock = sa.getBoolean(
+ com.android.internal.R.styleable.OffHostApduService_requireDeviceUnlock,
+ false);
+ mRequiresDeviceScreenOn = sa.getBoolean(
+ com.android.internal.R.styleable.OffHostApduService_requireDeviceScreenOn,
+ false);
mBannerResourceId = sa.getResourceId(
com.android.internal.R.styleable.OffHostApduService_apduServiceBanner, -1);
mSettingsActivityName = sa.getString(
@@ -420,6 +446,13 @@
return mRequiresDeviceUnlock;
}
+ /**
+ * Returns whether this service should only be started when the device is screen on.
+ */
+ public boolean requiresScreenOn() {
+ return mRequiresDeviceScreenOn;
+ }
+
@UnsupportedAppUsage
public String getDescription() {
return mDescription;
@@ -543,6 +576,7 @@
dest.writeTypedList(new ArrayList<AidGroup>(mDynamicAidGroups.values()));
}
dest.writeInt(mRequiresDeviceUnlock ? 1 : 0);
+ dest.writeInt(mRequiresDeviceScreenOn ? 1 : 0);
dest.writeInt(mBannerResourceId);
dest.writeInt(mUid);
dest.writeString(mSettingsActivityName);
@@ -569,11 +603,12 @@
source.readTypedList(dynamicAidGroups, AidGroup.CREATOR);
}
boolean requiresUnlock = source.readInt() != 0;
+ boolean requiresScreenOn = source.readInt() != 0;
int bannerResource = source.readInt();
int uid = source.readInt();
String settingsActivityName = source.readString();
return new ApduServiceInfo(info, onHost, description, staticAidGroups,
- dynamicAidGroups, requiresUnlock, bannerResource, uid,
+ dynamicAidGroups, requiresUnlock, requiresScreenOn, bannerResource, uid,
settingsActivityName, offHostName, staticOffHostName);
}
@@ -608,6 +643,8 @@
}
}
pw.println(" Settings Activity: " + mSettingsActivityName);
+ pw.println(" Requires Device Unlock: " + mRequiresDeviceUnlock);
+ pw.println(" Requires Device ScreenOn: " + mRequiresDeviceScreenOn);
}
/**
diff --git a/core/java/android/os/BatteryConsumer.java b/core/java/android/os/BatteryConsumer.java
index 3956ef9..bf8ac6e 100644
--- a/core/java/android/os/BatteryConsumer.java
+++ b/core/java/android/os/BatteryConsumer.java
@@ -36,7 +36,9 @@
* @hide
*/
@IntDef(prefix = {"POWER_COMPONENT_"}, value = {
+ POWER_COMPONENT_USAGE,
POWER_COMPONENT_CPU,
+ POWER_COMPONENT_BLUETOOTH,
})
@Retention(RetentionPolicy.SOURCE)
public static @interface PowerComponent {
@@ -44,21 +46,35 @@
public static final int POWER_COMPONENT_USAGE = 0;
public static final int POWER_COMPONENT_CPU = 1;
+ public static final int POWER_COMPONENT_BLUETOOTH = 2;
- public static final int POWER_COMPONENT_COUNT = 2;
+ public static final int POWER_COMPONENT_COUNT = 3;
public static final int FIRST_CUSTOM_POWER_COMPONENT_ID = 1000;
public static final int LAST_CUSTOM_POWER_COMPONENT_ID = 9999;
/**
+ * Modeled power components are used for testing only. They are returned if the
+ * {@link BatteryUsageStatsQuery#FLAG_BATTERY_USAGE_STATS_INCLUDE_MODELED} is set.
+ * The modeled power components are retrieved with {@link #getConsumedPowerForCustomComponent}.
+ * The ID of a modeled power component is calculated as
+ * (FIRST_MODELED_POWER_COMPONENT_ID + powerComponentId), e.g.
+ * FIRST_MODELED_POWER_COMPONENT_ID + POWER_COMPONENT_CPU.
+ */
+ public static final int FIRST_MODELED_POWER_COMPONENT_ID = 10000;
+ public static final int LAST_MODELED_POWER_COMPONENT_ID = 19999;
+
+ /**
* Time usage component, describing the particular part of the system
* that was used for the corresponding amount of time.
*
* @hide
*/
@IntDef(prefix = {"TIME_COMPONENT_"}, value = {
+ TIME_COMPONENT_USAGE,
TIME_COMPONENT_CPU,
TIME_COMPONENT_CPU_FOREGROUND,
+ TIME_COMPONENT_BLUETOOTH,
})
@Retention(RetentionPolicy.SOURCE)
public static @interface TimeComponent {
@@ -67,8 +83,9 @@
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_BLUETOOTH = 3;
- public static final int TIME_COMPONENT_COUNT = 3;
+ public static final int TIME_COMPONENT_COUNT = 4;
public static final int FIRST_CUSTOM_TIME_COMPONENT_ID = 1000;
public static final int LAST_CUSTOM_TIME_COMPONENT_ID = 9999;
@@ -137,9 +154,10 @@
protected abstract static class BaseBuilder<T extends BaseBuilder<?>> {
final PowerComponents.Builder mPowerComponentsBuilder;
- public BaseBuilder(int customPowerComponentCount, int customTimeComponentCount) {
+ public BaseBuilder(int customPowerComponentCount, int customTimeComponentCount,
+ boolean includeModeledComponents) {
mPowerComponentsBuilder = new PowerComponents.Builder(customPowerComponentCount,
- customTimeComponentCount);
+ customTimeComponentCount, includeModeledComponents);
}
/**
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 9c2ae4e..a89de01 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -27,6 +27,7 @@
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ApplicationInfo;
+import android.location.GnssSignalQuality;
import android.os.BatteryStatsManager.WifiState;
import android.os.BatteryStatsManager.WifiSupplState;
import android.server.ServerProtoEnums;
@@ -47,7 +48,6 @@
import android.view.Display;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.location.gnssmetrics.GnssMetrics;
import com.android.internal.os.BatterySipper;
import com.android.internal.os.BatteryStatsHelper;
@@ -5087,8 +5087,9 @@
final String[] gpsSignalQualityDescription = new String[]{
"poor (less than 20 dBHz): ",
"good (greater than 20 dBHz): "};
- final int numGpsSignalQualityBins = Math.min(GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS,
- gpsSignalQualityDescription.length);
+ final int numGpsSignalQualityBins = Math.min(
+ GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS,
+ gpsSignalQualityDescription.length);
for (int i=0; i<numGpsSignalQualityBins; i++) {
final long time = getGpsSignalQualityTime(i, rawRealtime, which);
sb.append("\n ");
diff --git a/core/java/android/os/BatteryStatsManager.java b/core/java/android/os/BatteryStatsManager.java
index d9e01cd..f344208 100644
--- a/core/java/android/os/BatteryStatsManager.java
+++ b/core/java/android/os/BatteryStatsManager.java
@@ -85,7 +85,7 @@
public static final int NUM_WIFI_STATES = WIFI_STATE_SOFT_AP + 1;
/** @hide */
- @IntDef(flag = true, prefix = { "WIFI_STATE_" }, value = {
+ @IntDef(prefix = { "WIFI_STATE_" }, value = {
WIFI_STATE_OFF,
WIFI_STATE_OFF_SCANNING,
WIFI_STATE_ON_NO_NETWORKS,
@@ -135,7 +135,7 @@
public static final int NUM_WIFI_SUPPL_STATES = WIFI_SUPPL_STATE_UNINITIALIZED + 1;
/** @hide */
- @IntDef(flag = true, prefix = { "WIFI_SUPPL_STATE_" }, value = {
+ @IntDef(prefix = { "WIFI_SUPPL_STATE_" }, value = {
WIFI_SUPPL_STATE_INVALID,
WIFI_SUPPL_STATE_DISCONNECTED,
WIFI_SUPPL_STATE_INTERFACE_DISABLED,
@@ -160,6 +160,7 @@
mBatteryStats = batteryStats;
}
+
/**
* Returns BatteryUsageStats, which contains power attribution data on a per-subsystem
* and per-UID basis.
@@ -169,8 +170,20 @@
@RequiresPermission(android.Manifest.permission.BATTERY_STATS)
@NonNull
public BatteryUsageStats getBatteryUsageStats() {
+ return getBatteryUsageStats(BatteryUsageStatsQuery.DEFAULT);
+ }
+
+ /**
+ * Returns BatteryUsageStats, which contains power attribution data on a per-subsystem
+ * and per-UID basis.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.BATTERY_STATS)
+ @NonNull
+ public BatteryUsageStats getBatteryUsageStats(BatteryUsageStatsQuery query) {
try {
- return mBatteryStats.getBatteryUsageStats();
+ return mBatteryStats.getBatteryUsageStats(query);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/os/BatteryUsageStats.java b/core/java/android/os/BatteryUsageStats.java
index af8e8de..a6df87d 100644
--- a/core/java/android/os/BatteryUsageStats.java
+++ b/core/java/android/os/BatteryUsageStats.java
@@ -114,6 +114,7 @@
public static final class Builder {
private final int mCustomPowerComponentCount;
private final int mCustomTimeComponentCount;
+ private final boolean mIncludeModeledComponents;
private double mConsumedPower;
private int mDischargePercentage;
private final SparseArray<UidBatteryConsumer.Builder> mUidBatteryConsumerBuilders =
@@ -121,9 +122,11 @@
private final SparseArray<SystemBatteryConsumer.Builder> mSystemBatteryConsumerBuilders =
new SparseArray<>();
- public Builder(int customPowerComponentCount, int customTimeComponentCount) {
+ public Builder(int customPowerComponentCount, int customTimeComponentCount,
+ boolean includeModeledComponents) {
mCustomPowerComponentCount = customPowerComponentCount;
mCustomTimeComponentCount = customTimeComponentCount;
+ mIncludeModeledComponents = includeModeledComponents;
}
/**
@@ -166,7 +169,7 @@
UidBatteryConsumer.Builder builder = mUidBatteryConsumerBuilders.get(uid);
if (builder == null) {
builder = new UidBatteryConsumer.Builder(mCustomPowerComponentCount,
- mCustomTimeComponentCount, batteryStatsUid);
+ mCustomTimeComponentCount, mIncludeModeledComponents, batteryStatsUid);
mUidBatteryConsumerBuilders.put(uid, builder);
}
return builder;
@@ -182,7 +185,7 @@
SystemBatteryConsumer.Builder builder = mSystemBatteryConsumerBuilders.get(drainType);
if (builder == null) {
builder = new SystemBatteryConsumer.Builder(mCustomPowerComponentCount,
- mCustomTimeComponentCount, drainType);
+ mCustomTimeComponentCount, mIncludeModeledComponents, drainType);
mSystemBatteryConsumerBuilders.put(drainType, builder);
}
return builder;
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java b/core/java/android/os/BatteryUsageStatsQuery.aidl
similarity index 62%
copy from media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java
copy to core/java/android/os/BatteryUsageStatsQuery.aidl
index 52f2787..207396c 100644
--- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java
+++ b/core/java/android/os/BatteryUsageStatsQuery.aidl
@@ -14,19 +14,6 @@
* limitations under the License.
*/
-package com.android.mediatranscodingtest;
+package android.os;
-/**
- *
- * This class has the names of the all the activity name and variables in the
- * instrumentation test.
- *
- */
-public class MediaConstants {
- /*
- * Source test files.
- */
- public static final String[] SOURCE_HEVC_VIDEO_ONLY_TEST_FILES = {
- "/sdcard/media_api/video/VideoOnlyHEVC.mp4",
- };
-}
+parcelable BatteryUsageStatsQuery;
diff --git a/core/java/android/os/BatteryUsageStatsQuery.java b/core/java/android/os/BatteryUsageStatsQuery.java
new file mode 100644
index 0000000..9a00679
--- /dev/null
+++ b/core/java/android/os/BatteryUsageStatsQuery.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Query parameters for the {@link BatteryStatsManager#getBatteryUsageStats()} call.
+ *
+ * @hide
+ */
+public final class BatteryUsageStatsQuery implements Parcelable {
+
+ @NonNull
+ public static final BatteryUsageStatsQuery DEFAULT =
+ new BatteryUsageStatsQuery.Builder().build();
+
+ /**
+ * Flags for the {@link BatteryStatsManager#getBatteryUsageStats()} method.
+ * @hide
+ */
+ @IntDef(flag = true, prefix = { "FLAG_BATTERY_USAGE_STATS_" }, value = {
+ FLAG_BATTERY_USAGE_STATS_INCLUDE_MODELED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface BatteryUsageStatsFlags {}
+
+ /**
+ * Indicates that modeled battery usage stats should be returned along with
+ * measured ones.
+ *
+ * @hide
+ */
+ public static final int FLAG_BATTERY_USAGE_STATS_INCLUDE_MODELED = 1;
+
+ private final int mFlags;
+
+ private BatteryUsageStatsQuery(@NonNull Builder builder) {
+ mFlags = builder.mFlags;
+ }
+
+ @BatteryUsageStatsFlags
+ public int getFlags() {
+ return mFlags;
+ }
+
+ private BatteryUsageStatsQuery(Parcel in) {
+ mFlags = in.readInt();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mFlags);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @NonNull
+ public static final Creator<BatteryUsageStatsQuery> CREATOR =
+ new Creator<BatteryUsageStatsQuery>() {
+ @Override
+ public BatteryUsageStatsQuery createFromParcel(Parcel in) {
+ return new BatteryUsageStatsQuery(in);
+ }
+
+ @Override
+ public BatteryUsageStatsQuery[] newArray(int size) {
+ return new BatteryUsageStatsQuery[size];
+ }
+ };
+
+ /**
+ * Builder for BatteryUsageStatsQuery.
+ */
+ public static final class Builder {
+ private int mFlags;
+
+ /**
+ * Builds a read-only BatteryUsageStatsQuery object.
+ */
+ public BatteryUsageStatsQuery build() {
+ return new BatteryUsageStatsQuery(this);
+ }
+
+ /**
+ * Sets flags to modify the behavior of {@link BatteryStatsManager#getBatteryUsageStats}.
+ */
+ public Builder setFlags(@BatteryUsageStatsFlags int flags) {
+ mFlags = flags;
+ return this;
+ }
+
+ /**
+ * Requests to include modeled battery usage stats along with measured ones.
+ * Should only be used for testing and debugging.
+ */
+ public Builder includeModeled() {
+ mFlags |= BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_MODELED;
+ return this;
+ }
+ }
+}
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index e2e1bbe..9584bc7 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -2582,6 +2582,13 @@
public static native long getIonMappedSizeKb();
/**
+ * Return memory size in kilobytes used by GPU.
+ *
+ * @hide
+ */
+ public static native long getGpuTotalUsageKb();
+
+ /**
* Return whether virtually-mapped kernel stacks are enabled (CONFIG_VMAP_STACK).
* Note: caller needs config_gz read sepolicy permission
*
diff --git a/core/java/android/os/FileBridge.java b/core/java/android/os/FileBridge.java
index ab5637c..7b84575 100644
--- a/core/java/android/os/FileBridge.java
+++ b/core/java/android/os/FileBridge.java
@@ -22,11 +22,12 @@
import android.system.Os;
import android.util.Log;
+import com.android.internal.util.ArrayUtils;
+
import libcore.io.IoBridge;
import libcore.io.IoUtils;
import libcore.io.Memory;
import libcore.io.Streams;
-import libcore.util.ArrayUtils;
import java.io.FileDescriptor;
import java.io.IOException;
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 92fe98c..c014ef6 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -83,6 +83,7 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
+import java.util.Locale;
import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
@@ -115,6 +116,9 @@
private FileUtils() {
}
+ private static final String CAMERA_DIR_LOWER_CASE = "/storage/emulated/" + UserHandle.myUserId()
+ + "/dcim/camera";
+
/** Regular expression for safe filenames: no spaces or metacharacters.
*
* Use a preload holder so that FileUtils can be compile-time initialized.
@@ -1432,18 +1436,27 @@
}
}
+ // TODO(b/170488060): Consider better approach
/** {@hide} */
+ @VisibleForTesting
public static FileDescriptor convertToModernFd(FileDescriptor fd) {
try {
Context context = AppGlobals.getInitialApplication();
+ File realFile = ParcelFileDescriptor.getFile(fd);
+ String fileName = realFile.getName();
+ boolean isCameraVideo = !fileName.startsWith(".") && fileName.endsWith(".mp4")
+ && contains(CAMERA_DIR_LOWER_CASE, realFile.getAbsolutePath().toLowerCase(
+ Locale.ROOT));
+
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
+ || UserHandle.getAppId(Process.myUid()) == getMediaProviderAppId(context)
+ || !isCameraVideo) {
+ // 1. If transcode is enabled we optimize by default, unless explicitly disabled.
+ // 2. Never convert modern fd for MediaProvider, because this requires
// MediaStore#scanFile and can cause infinite loops when MediaProvider scans
+ // 3. Only convert published mp4 videos in the DCIM/Camera dir
return null;
}
- File realFile = ParcelFileDescriptor.getFile(fd);
Log.i(TAG, "Changing to modern format dataSource for: " + realFile);
ContentResolver resolver = context.getContentResolver();
diff --git a/core/java/android/os/IRecoverySystem.aidl b/core/java/android/os/IRecoverySystem.aidl
index 2561e1e..2052883 100644
--- a/core/java/android/os/IRecoverySystem.aidl
+++ b/core/java/android/os/IRecoverySystem.aidl
@@ -27,7 +27,9 @@
boolean setupBcb(in String command);
boolean clearBcb();
void rebootRecoveryWithCommand(in String command);
- boolean requestLskf(in String updateToken, in IntentSender sender);
- boolean clearLskf();
- boolean rebootWithLskf(in String updateToken, in String reason);
+ boolean requestLskf(in String packageName, in IntentSender sender);
+ boolean clearLskf(in String packageName);
+ boolean isLskfCaptured(in String packageName);
+ boolean rebootWithLskfAssumeSlotSwitch(in String packageName, in String reason);
+ boolean rebootWithLskf(in String packageName, in String reason, in boolean slotSwitch);
}
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 5242750..fc65090 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -34,11 +34,11 @@
import android.util.SparseIntArray;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.ArrayUtils;
import dalvik.annotation.optimization.CriticalNative;
import dalvik.annotation.optimization.FastNative;
-import libcore.util.ArrayUtils;
import libcore.util.SneakyThrow;
import java.io.ByteArrayInputStream;
diff --git a/core/java/android/os/PowerComponents.java b/core/java/android/os/PowerComponents.java
index c18fff6..18dca68 100644
--- a/core/java/android/os/PowerComponents.java
+++ b/core/java/android/os/PowerComponents.java
@@ -13,10 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package android.os;
-
import android.annotation.NonNull;
/**
@@ -26,19 +24,31 @@
* @hide
*/
class PowerComponents {
+ private static final int CUSTOM_POWER_COMPONENT_OFFSET = BatteryConsumer.POWER_COMPONENT_COUNT
+ - BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID;
+ public static final int CUSTOM_TIME_COMPONENT_OFFSET = BatteryConsumer.TIME_COMPONENT_COUNT
+ - BatteryConsumer.FIRST_CUSTOM_TIME_COMPONENT_ID;
private final double mTotalPowerConsumed;
private final double[] mPowerComponents;
private final long[] mTimeComponents;
+ private final int mCustomPowerComponentCount;
+ private final int mModeledPowerComponentOffset;
PowerComponents(@NonNull Builder builder) {
mTotalPowerConsumed = builder.mTotalPowerConsumed;
+ mCustomPowerComponentCount = builder.mCustomPowerComponentCount;
+ mModeledPowerComponentOffset = builder.mModeledPowerComponentOffset;
mPowerComponents = builder.mPowerComponents;
mTimeComponents = builder.mTimeComponents;
}
PowerComponents(@NonNull Parcel source) {
mTotalPowerConsumed = source.readDouble();
+ mCustomPowerComponentCount = source.readInt();
+ mModeledPowerComponentOffset =
+ BatteryConsumer.POWER_COMPONENT_COUNT + mCustomPowerComponentCount
+ - BatteryConsumer.FIRST_MODELED_POWER_COMPONENT_ID;
mPowerComponents = source.createDoubleArray();
mTimeComponents = source.createLongArray();
}
@@ -46,6 +56,7 @@
/** Writes contents to Parcel */
void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeDouble(mTotalPowerConsumed);
+ dest.writeInt(mCustomPowerComponentCount);
dest.writeDoubleArray(mPowerComponents);
dest.writeLongArray(mTimeComponents);
}
@@ -64,7 +75,7 @@
* {@link BatteryConsumer#POWER_COMPONENT_CPU}.
* @return Amount of consumed power in mAh.
*/
- public double getConsumedPower(@UidBatteryConsumer.PowerComponent int componentId) {
+ public double getConsumedPower(@BatteryConsumer.PowerComponent int componentId) {
if (componentId >= BatteryConsumer.POWER_COMPONENT_COUNT) {
throw new IllegalArgumentException(
"Unsupported power component ID: " + componentId);
@@ -83,15 +94,23 @@
* @return Amount of consumed power in mAh.
*/
public double getConsumedPowerForCustomComponent(int componentId) {
- if (componentId < BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID) {
- throw new IllegalArgumentException(
- "Unsupported custom power component ID: " + componentId);
- }
- try {
- return mPowerComponents[
- BatteryConsumer.POWER_COMPONENT_COUNT + componentId
- - BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID];
- } catch (ArrayIndexOutOfBoundsException e) {
+ if (componentId >= BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID
+ && componentId < BatteryConsumer.LAST_CUSTOM_POWER_COMPONENT_ID) {
+ try {
+ return mPowerComponents[CUSTOM_POWER_COMPONENT_OFFSET + componentId];
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new IllegalArgumentException(
+ "Unsupported custom power component ID: " + componentId);
+ }
+ } else if (componentId >= BatteryConsumer.FIRST_MODELED_POWER_COMPONENT_ID
+ && componentId < BatteryConsumer.LAST_MODELED_POWER_COMPONENT_ID) {
+ try {
+ return mPowerComponents[mModeledPowerComponentOffset + componentId];
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new IllegalArgumentException(
+ "Unsupported modeled power component ID: " + componentId);
+ }
+ } else {
throw new IllegalArgumentException(
"Unsupported custom power component ID: " + componentId);
}
@@ -101,11 +120,11 @@
* Returns 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}.
+ * {@link BatteryConsumer#TIME_COMPONENT_CPU}.
* @return Amount of time in milliseconds.
*/
- public long getUsageDurationMillis(@UidBatteryConsumer.TimeComponent int componentId) {
- if (componentId >= UidBatteryConsumer.TIME_COMPONENT_COUNT) {
+ public long getUsageDurationMillis(@BatteryConsumer.TimeComponent int componentId) {
+ if (componentId >= BatteryConsumer.TIME_COMPONENT_COUNT) {
throw new IllegalArgumentException(
"Unsupported time component ID: " + componentId);
}
@@ -123,14 +142,12 @@
* @return Amount of time in milliseconds.
*/
public long getUsageDurationForCustomComponentMillis(int componentId) {
- if (componentId < UidBatteryConsumer.FIRST_CUSTOM_TIME_COMPONENT_ID) {
+ if (componentId < BatteryConsumer.FIRST_CUSTOM_TIME_COMPONENT_ID) {
throw new IllegalArgumentException(
"Unsupported custom time component ID: " + componentId);
}
try {
- return mTimeComponents[
- UidBatteryConsumer.TIME_COMPONENT_COUNT + componentId
- - UidBatteryConsumer.FIRST_CUSTOM_TIME_COMPONENT_ID];
+ return mTimeComponents[CUSTOM_TIME_COMPONENT_OFFSET + componentId];
} catch (ArrayIndexOutOfBoundsException e) {
throw new IllegalArgumentException(
"Unsupported custom time component ID: " + componentId);
@@ -143,13 +160,24 @@
static final class Builder {
private double mTotalPowerConsumed;
private final double[] mPowerComponents;
+ private final int mCustomPowerComponentCount;
private final long[] mTimeComponents;
+ private final int mModeledPowerComponentOffset;
- Builder(int customPowerComponentCount, int customTimeComponentCount) {
- mPowerComponents = new double[UidBatteryConsumer.POWER_COMPONENT_COUNT
- + customPowerComponentCount];
- mTimeComponents = new long[UidBatteryConsumer.TIME_COMPONENT_COUNT
- + customTimeComponentCount];
+ Builder(int customPowerComponentCount, int customTimeComponentCount,
+ boolean includeModeledPowerComponents) {
+ mCustomPowerComponentCount = customPowerComponentCount;
+ int powerComponentCount =
+ BatteryConsumer.POWER_COMPONENT_COUNT + customPowerComponentCount;
+ if (includeModeledPowerComponents) {
+ powerComponentCount += BatteryConsumer.POWER_COMPONENT_COUNT;
+ }
+ mPowerComponents = new double[powerComponentCount];
+ mModeledPowerComponentOffset =
+ BatteryConsumer.POWER_COMPONENT_COUNT + mCustomPowerComponentCount
+ - BatteryConsumer.FIRST_MODELED_POWER_COMPONENT_ID;
+ mTimeComponents =
+ new long[BatteryConsumer.TIME_COMPONENT_COUNT + customTimeComponentCount];
}
/**
@@ -169,7 +197,7 @@
* @param componentPower Amount of consumed power in mAh.
*/
@NonNull
- public Builder setConsumedPower(@UidBatteryConsumer.PowerComponent int componentId,
+ public Builder setConsumedPower(@BatteryConsumer.PowerComponent int componentId,
double componentPower) {
if (componentId >= BatteryConsumer.POWER_COMPONENT_COUNT) {
throw new IllegalArgumentException(
@@ -192,14 +220,23 @@
*/
@NonNull
public Builder setConsumedPowerForCustomComponent(int componentId, double componentPower) {
- if (componentId < BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID) {
- throw new IllegalArgumentException(
- "Unsupported custom power component ID: " + componentId);
- }
- try {
- mPowerComponents[BatteryConsumer.POWER_COMPONENT_COUNT + componentId
- - BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID] = componentPower;
- } catch (ArrayIndexOutOfBoundsException e) {
+ if (componentId >= BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID
+ && componentId < BatteryConsumer.LAST_CUSTOM_POWER_COMPONENT_ID) {
+ try {
+ mPowerComponents[CUSTOM_POWER_COMPONENT_OFFSET + componentId] = componentPower;
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new IllegalArgumentException(
+ "Unsupported custom power component ID: " + componentId);
+ }
+ } else if (componentId >= BatteryConsumer.FIRST_MODELED_POWER_COMPONENT_ID
+ && componentId < BatteryConsumer.LAST_MODELED_POWER_COMPONENT_ID) {
+ try {
+ mPowerComponents[mModeledPowerComponentOffset + componentId] = componentPower;
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new IllegalArgumentException(
+ "Unsupported modeled power component ID: " + componentId);
+ }
+ } else {
throw new IllegalArgumentException(
"Unsupported custom power component ID: " + componentId);
}
@@ -210,13 +247,13 @@
* 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}.
+ * {@link BatteryConsumer#TIME_COMPONENT_CPU}.
* @param componentUsageDurationMillis Amount of time in milliseconds.
*/
@NonNull
- public Builder setUsageDurationMillis(@UidBatteryConsumer.TimeComponent int componentId,
+ public Builder setUsageDurationMillis(@BatteryConsumer.TimeComponent int componentId,
long componentUsageDurationMillis) {
- if (componentId >= UidBatteryConsumer.TIME_COMPONENT_COUNT) {
+ if (componentId >= BatteryConsumer.TIME_COMPONENT_COUNT) {
throw new IllegalArgumentException(
"Unsupported time component ID: " + componentId);
}
@@ -238,13 +275,12 @@
@NonNull
public Builder setUsageDurationForCustomComponentMillis(int componentId,
long componentUsageDurationMillis) {
- if (componentId < UidBatteryConsumer.FIRST_CUSTOM_TIME_COMPONENT_ID) {
+ if (componentId < BatteryConsumer.FIRST_CUSTOM_TIME_COMPONENT_ID) {
throw new IllegalArgumentException(
"Unsupported custom time component ID: " + componentId);
}
try {
- mTimeComponents[UidBatteryConsumer.TIME_COMPONENT_COUNT + componentId
- - UidBatteryConsumer.FIRST_CUSTOM_TIME_COMPONENT_ID] =
+ mTimeComponents[CUSTOM_TIME_COMPONENT_OFFSET + componentId] =
componentUsageDurationMillis;
} catch (ArrayIndexOutOfBoundsException e) {
throw new IllegalArgumentException(
@@ -253,6 +289,15 @@
return this;
}
+ public void addPowerAndDuration(Builder other) {
+ for (int i = 0; i < mPowerComponents.length; i++) {
+ mPowerComponents[i] += other.mPowerComponents[i];
+ }
+ for (int i = 0; i < mTimeComponents.length; i++) {
+ mTimeComponents[i] += other.mTimeComponents[i];
+ }
+ }
+
/**
* Creates a read-only object out of the Builder values.
*/
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 72cd8ba..93c1690 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -631,31 +631,35 @@
/**
* Prepare to apply an unattended update by asking the user for their Lock Screen Knowledge
* Factor (LSKF). If supplied, the {@code intentSender} will be called when the system is setup
- * and ready to apply the OTA.
- * <p>
- * When the system is already prepared for update and this API is called again with the same
- * {@code updateToken}, it will not call the intent sender nor request the user enter their Lock
- * Screen Knowledge Factor.
- * <p>
- * When this API is called again with a different {@code updateToken}, the prepared-for-update
- * status is reset and process repeats as though it's the initial call to this method as
- * described in the first paragraph.
+ * and ready to apply the OTA. This API is expected to handle requests from multiple clients
+ * simultaneously, e.g. from ota and mainline.
+ *
+ * <p> The behavior of multi-client Resume on Reboot works as follows
+ * <li> Each client should call this function to prepare for Resume on Reboot before calling
+ * {@link #rebootAndApply(Context, String, boolean)} </li>
+ * <li> One client cannot clear the Resume on Reboot preparation of another client. </li>
+ * <li> If multiple clients have prepared for Resume on Reboot, the subsequent reboot will be
+ * first come, first served. </li>
*
* @param context the Context to use.
- * @param updateToken token used to indicate which update was prepared
+ * @param updateToken this parameter is deprecated and won't be used. Callers can supply with
+ * an empty string. See details in
+ * <a href="http://go/multi-client-ror">http://go/multi-client-ror</a>
+ * TODO(xunchang) update the link of document with the public doc.
* @param intentSender the intent to call when the update is prepared; may be {@code null}
* @throws IOException if there were any errors setting up unattended update
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.RECOVERY)
+ @RequiresPermission(anyOf = {android.Manifest.permission.RECOVERY,
+ android.Manifest.permission.REBOOT})
public static void prepareForUnattendedUpdate(@NonNull Context context,
@NonNull String updateToken, @Nullable IntentSender intentSender) throws IOException {
if (updateToken == null) {
throw new NullPointerException("updateToken == null");
}
RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE);
- if (!rs.requestLskf(updateToken, intentSender)) {
+ if (!rs.requestLskf(context.getPackageName(), intentSender)) {
throw new IOException("preparation for update failed");
}
}
@@ -664,32 +668,38 @@
* Request that any previously requested Lock Screen Knowledge Factor (LSKF) is cleared and
* the preparation for unattended update is reset.
*
+ * <p> Note that the API won't clear the underlying Resume on Reboot preparation state if
+ * another client has requested. So the reboot call from the other client can still succeed.
+ *
* @param context the Context to use.
* @throws IOException if there were any errors clearing the unattended update state
* @hide
*/
@SystemApi
- @RequiresPermission(android.Manifest.permission.RECOVERY)
+ @RequiresPermission(anyOf = {android.Manifest.permission.RECOVERY,
+ android.Manifest.permission.REBOOT})
public static void clearPrepareForUnattendedUpdate(@NonNull Context context)
throws IOException {
RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE);
- if (!rs.clearLskf()) {
+ if (!rs.clearLskf(context.getPackageName())) {
throw new IOException("could not reset unattended update state");
}
}
/**
- * Request that the device reboot and apply the update that has been prepared. The
- * {@code updateToken} must match what was given for {@link #prepareForUnattendedUpdate} or
- * this will return {@code false}.
+ * Request that the device reboot and apply the update that has been prepared. This API is
+ * deprecated, and is expected to be used by OTA only on devices running Android 11.
*
* @param context the Context to use.
- * @param updateToken the token used to call {@link #prepareForUnattendedUpdate} before
+ * @param updateToken this parameter is deprecated and won't be used. See details in
+ * <a href="http://go/multi-client-ror">http://go/multi-client-ror</a>
+ * TODO(xunchang) update the link of document with the public doc.
* @param reason the reboot reason to give to the {@link PowerManager}
* @throws IOException if the reboot couldn't proceed because the device wasn't ready for an
* unattended reboot or if the {@code updateToken} did not match the previously
* given token
* @hide
+ * @deprecated Use {@link #rebootAndApply(Context, String, boolean)} instead
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.RECOVERY)
@@ -699,7 +709,47 @@
throw new NullPointerException("updateToken == null");
}
RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE);
- if (!rs.rebootWithLskf(updateToken, reason)) {
+ // OTA is the sole user, who expects a slot switch.
+ if (!rs.rebootWithLskfAssumeSlotSwitch(context.getPackageName(), reason)) {
+ throw new IOException("system not prepared to apply update");
+ }
+ }
+
+ /**
+ * Query if Resume on Reboot has been prepared for a given caller.
+ *
+ * @param context the Context to use.
+ * @throws IOException if there were any errors connecting to the service or querying the state.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(anyOf = {android.Manifest.permission.RECOVERY,
+ android.Manifest.permission.REBOOT})
+ public static boolean isPreparedForUnattendedUpdate(@NonNull Context context)
+ throws IOException {
+ RecoverySystem rs = context.getSystemService(RecoverySystem.class);
+ return rs.isLskfCaptured(context.getPackageName());
+ }
+
+ /**
+ * Request that the device reboot and apply the update that has been prepared.
+ * {@link #prepareForUnattendedUpdate} must be called before for the given client,
+ * otherwise the function call will fail.
+ *
+ * @param context the Context to use.
+ * @param reason the reboot reason to give to the {@link PowerManager}
+ * @param slotSwitch true if the caller expects the slot to be switched on A/B devices.
+ * @throws IOException if the reboot couldn't proceed because the device wasn't ready for an
+ * unattended reboot.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(anyOf = {android.Manifest.permission.RECOVERY,
+ android.Manifest.permission.REBOOT})
+ public static void rebootAndApply(@NonNull Context context,
+ @NonNull String reason, boolean slotSwitch) throws IOException {
+ RecoverySystem rs = context.getSystemService(RecoverySystem.class);
+ if (!rs.rebootWithLskf(context.getPackageName(), reason, slotSwitch)) {
throw new IOException("system not prepared to apply update");
}
}
@@ -1291,16 +1341,15 @@
/**
* Begins the process of asking the user for the Lock Screen Knowledge Factor.
*
- * @param updateToken token that will be used in calls to {@link #rebootAndApply} to ensure
- * that the preparation was for the correct update
+ * @param packageName the package name of the caller who requests Resume on Reboot
* @return true if the request was correct
* @throws IOException if the recovery system service could not be contacted
*/
- private boolean requestLskf(String updateToken, IntentSender sender) throws IOException {
+ private boolean requestLskf(String packageName, IntentSender sender) throws IOException {
try {
- return mService.requestLskf(updateToken, sender);
+ return mService.requestLskf(packageName, sender);
} catch (RemoteException e) {
- throw new IOException("could request update");
+ throw new IOException("could request LSKF capture");
}
}
@@ -1310,22 +1359,52 @@
* @return true if the setup for OTA was cleared
* @throws IOException if the recovery system service could not be contacted
*/
- private boolean clearLskf() throws IOException {
+ private boolean clearLskf(String packageName) throws IOException {
try {
- return mService.clearLskf();
+ return mService.clearLskf(packageName);
} catch (RemoteException e) {
throw new IOException("could not clear LSKF");
}
}
/**
+ * Queries if the Resume on Reboot has been prepared for a given caller.
+ *
+ * @param packageName the identifier of the caller who requests Resume on Reboot
+ * @return true if Resume on Reboot is prepared.
+ * @throws IOException if the recovery system service could not be contacted
+ */
+ private boolean isLskfCaptured(String packageName) throws IOException {
+ try {
+ return mService.isLskfCaptured(packageName);
+ } catch (RemoteException e) {
+ throw new IOException("could not get LSKF capture state");
+ }
+ }
+
+ /**
* Calls the recovery system service to reboot and apply update.
*
- * @param updateToken the update token for which the update was prepared
*/
- private boolean rebootWithLskf(String updateToken, String reason) throws IOException {
+ private boolean rebootWithLskf(String packageName, String reason, boolean slotSwitch)
+ throws IOException {
try {
- return mService.rebootWithLskf(updateToken, reason);
+ return mService.rebootWithLskf(packageName, reason, slotSwitch);
+ } catch (RemoteException e) {
+ throw new IOException("could not reboot for update");
+ }
+ }
+
+
+ /**
+ * Calls the recovery system service to reboot and apply update. This is the legacy API and
+ * expects a slot switch for A/B devices.
+ *
+ */
+ private boolean rebootWithLskfAssumeSlotSwitch(String packageName, String reason)
+ throws IOException {
+ try {
+ return mService.rebootWithLskfAssumeSlotSwitch(packageName, reason);
} catch (RemoteException e) {
throw new IOException("could not reboot for update");
}
diff --git a/core/java/android/os/SystemBatteryConsumer.java b/core/java/android/os/SystemBatteryConsumer.java
index 570a2dc..08e358f 100644
--- a/core/java/android/os/SystemBatteryConsumer.java
+++ b/core/java/android/os/SystemBatteryConsumer.java
@@ -21,6 +21,8 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
/**
@@ -118,18 +120,44 @@
public static final class Builder extends BaseBuilder<Builder> {
@DrainType
private final int mDrainType;
+ private List<UidBatteryConsumer.Builder> mUidBatteryConsumers;
Builder(int customPowerComponentCount, int customTimeComponentCount,
- @DrainType int drainType) {
- super(customPowerComponentCount, customTimeComponentCount);
+ boolean includeModeledComponents, @DrainType int drainType) {
+ super(customPowerComponentCount, customTimeComponentCount, includeModeledComponents);
mDrainType = drainType;
}
/**
+ * Add a UidBatteryConsumer to this SystemBatteryConsumer. For example,
+ * the UidBatteryConsumer with the UID == {@link Process#BLUETOOTH_UID} should
+ * be added to the SystemBatteryConsumer with the drain type == {@link
+ * #DRAIN_TYPE_BLUETOOTH}.
+ * <p>
+ * Calculated power and duration components of the added battery consumers
+ * are aggregated at the time the SystemBatteryConsumer is built by the {@link #build()}
+ * method.
+ * </p>
+ */
+ public void addUidBatteryConsumer(UidBatteryConsumer.Builder uidBatteryConsumerBuilder) {
+ if (mUidBatteryConsumers == null) {
+ mUidBatteryConsumers = new ArrayList<>();
+ }
+ mUidBatteryConsumers.add(uidBatteryConsumerBuilder);
+ }
+
+ /**
* Creates a read-only object out of the Builder values.
*/
@NonNull
public SystemBatteryConsumer build() {
+ if (mUidBatteryConsumers != null) {
+ for (int i = mUidBatteryConsumers.size() - 1; i >= 0; i--) {
+ UidBatteryConsumer.Builder uidBatteryConsumer = mUidBatteryConsumers.get(i);
+ mPowerComponentsBuilder.addPowerAndDuration(
+ uidBatteryConsumer.mPowerComponentsBuilder);
+ }
+ }
return new SystemBatteryConsumer(this);
}
}
diff --git a/core/java/android/os/UidBatteryConsumer.java b/core/java/android/os/UidBatteryConsumer.java
index 06cf4a6..3161766 100644
--- a/core/java/android/os/UidBatteryConsumer.java
+++ b/core/java/android/os/UidBatteryConsumer.java
@@ -29,11 +29,21 @@
private final int mUid;
@Nullable
private final String mPackageWithHighestDrain;
+ private boolean mSystemComponent;
public int getUid() {
return mUid;
}
+ /**
+ * Returns true if this battery consumer is considered to be a part of the operating
+ * system itself. For example, the UidBatteryConsumer with the UID {@link Process#BLUETOOTH_UID}
+ * is a system component.
+ */
+ public boolean isSystemComponent() {
+ return mSystemComponent;
+ }
+
@Nullable
public String getPackageWithHighestDrain() {
return mPackageWithHighestDrain;
@@ -42,6 +52,7 @@
private UidBatteryConsumer(@NonNull Builder builder) {
super(builder.mPowerComponentsBuilder.build());
mUid = builder.mUid;
+ mSystemComponent = builder.mSystemComponent;
mPackageWithHighestDrain = builder.mPackageWithHighestDrain;
}
@@ -84,10 +95,11 @@
private final BatteryStats.Uid mBatteryStatsUid;
private final int mUid;
private String mPackageWithHighestDrain;
+ private boolean mSystemComponent;
public Builder(int customPowerComponentCount, int customTimeComponentCount,
- BatteryStats.Uid batteryStatsUid) {
- super(customPowerComponentCount, customTimeComponentCount);
+ boolean includeModeledComponents, BatteryStats.Uid batteryStatsUid) {
+ super(customPowerComponentCount, customTimeComponentCount, includeModeledComponents);
mBatteryStatsUid = batteryStatsUid;
mUid = batteryStatsUid.getUid();
}
@@ -117,5 +129,14 @@
mPackageWithHighestDrain = packageName;
return this;
}
+
+ /**
+ * Marks the UidBatteryConsumer as part of the system. For example,
+ * the UidBatteryConsumer with the UID {@link Process#BLUETOOTH_UID} is considered
+ * as a system component.
+ */
+ public void setSystemComponent(boolean systemComponent) {
+ mSystemComponent = systemComponent;
+ }
}
}
diff --git a/core/java/android/os/connectivity/GpsBatteryStats.java b/core/java/android/os/connectivity/GpsBatteryStats.java
index ef03caa..5e21bd3 100644
--- a/core/java/android/os/connectivity/GpsBatteryStats.java
+++ b/core/java/android/os/connectivity/GpsBatteryStats.java
@@ -15,11 +15,10 @@
*/
package android.os.connectivity;
+import android.location.GnssSignalQuality;
import android.os.Parcel;
import android.os.Parcelable;
-import com.android.internal.location.gnssmetrics.GnssMetrics;
-
import java.util.Arrays;
/**
@@ -85,7 +84,7 @@
public void setTimeInGpsSignalQualityLevel(long[] t) {
mTimeInGpsSignalQualityLevel = Arrays.copyOfRange(t, 0,
- Math.min(t.length, GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS));
+ Math.min(t.length, GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS));
return;
}
@@ -102,7 +101,7 @@
private void initialize() {
mLoggingDurationMs = 0;
mEnergyConsumedMaMs = 0;
- mTimeInGpsSignalQualityLevel = new long[GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS];
+ mTimeInGpsSignalQualityLevel = new long[GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS];
return;
}
}
\ No newline at end of file
diff --git a/core/java/android/os/incremental/OWNERS b/core/java/android/os/incremental/OWNERS
new file mode 100644
index 0000000..3795493
--- /dev/null
+++ b/core/java/android/os/incremental/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 554432
+alexbuy@google.com
+schfan@google.com
+toddke@google.com
+zyy@google.com
diff --git a/core/java/android/os/storage/StorageManagerInternal.java b/core/java/android/os/storage/StorageManagerInternal.java
index 55ba15a..b12bb2e 100644
--- a/core/java/android/os/storage/StorageManagerInternal.java
+++ b/core/java/android/os/storage/StorageManagerInternal.java
@@ -101,4 +101,15 @@
* Return true if uid is external storage service.
*/
public abstract boolean isExternalStorageService(int uid);
+
+ /**
+ * Frees cache held by ExternalStorageService.
+ *
+ * <p> Blocks until the service frees the cache or fails in doing so.
+ *
+ * @param volumeUuid uuid of the {@link StorageVolume} from which cache needs to be freed,
+ * null value indicates private internal volume.
+ * @param bytes number of bytes which need to be freed
+ */
+ public abstract void freeCache(@Nullable String volumeUuid, long bytes);
}
diff --git a/core/java/android/permission/IPermissionManager.aidl b/core/java/android/permission/IPermissionManager.aidl
index 4ad17ef..441908d 100644
--- a/core/java/android/permission/IPermissionManager.aidl
+++ b/core/java/android/permission/IPermissionManager.aidl
@@ -56,13 +56,13 @@
void removeOnPermissionsChangeListener(in IOnPermissionsChangeListener listener);
- List<String> getWhitelistedRestrictedPermissions(String packageName,
+ List<String> getAllowlistedRestrictedPermissions(String packageName,
int flags, int userId);
- boolean addWhitelistedRestrictedPermission(String packageName, String permName,
+ boolean addAllowlistedRestrictedPermission(String packageName, String permissionName,
int flags, int userId);
- boolean removeWhitelistedRestrictedPermission(String packageName, String permName,
+ boolean removeAllowlistedRestrictedPermission(String packageName, String permissionName,
int flags, int userId);
void grantRuntimePermission(String packageName, String permName, int userId);
@@ -87,7 +87,7 @@
List<String> getAutoRevokeExemptionGrantedPackages(int userId);
- boolean setAutoRevokeWhitelisted(String packageName, boolean whitelisted, int userId);
+ boolean setAutoRevokeExempted(String packageName, boolean exempted, int userId);
- boolean isAutoRevokeWhitelisted(String packageName, int userId);
+ boolean isAutoRevokeExempted(String packageName, int userId);
}
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index d31e012..87f3764 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -510,7 +510,7 @@
public Set<String> getAllowlistedRestrictedPermissions(@NonNull String packageName,
@PackageManager.PermissionWhitelistFlags int allowlistFlag) {
try {
- final List<String> allowlist = mPermissionManager.getWhitelistedRestrictedPermissions(
+ final List<String> allowlist = mPermissionManager.getAllowlistedRestrictedPermissions(
packageName, allowlistFlag, mContext.getUserId());
if (allowlist == null) {
return Collections.emptySet();
@@ -578,7 +578,7 @@
@NonNull String permissionName,
@PackageManager.PermissionWhitelistFlags int allowlistFlags) {
try {
- return mPermissionManager.addWhitelistedRestrictedPermission(packageName,
+ return mPermissionManager.addAllowlistedRestrictedPermission(packageName,
permissionName, allowlistFlags, mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -642,7 +642,7 @@
@NonNull String permissionName,
@PackageManager.PermissionWhitelistFlags int allowlistFlags) {
try {
- return mPermissionManager.removeWhitelistedRestrictedPermission(packageName,
+ return mPermissionManager.removeAllowlistedRestrictedPermission(packageName,
permissionName, allowlistFlags, mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -668,7 +668,7 @@
conditional = true)
public boolean isAutoRevokeExempted(@NonNull String packageName) {
try {
- return mPermissionManager.isAutoRevokeWhitelisted(packageName, mContext.getUserId());
+ return mPermissionManager.isAutoRevokeExempted(packageName, mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -697,7 +697,7 @@
conditional = true)
public boolean setAutoRevokeExempted(@NonNull String packageName, boolean exempted) {
try {
- return mPermissionManager.setAutoRevokeWhitelisted(packageName, exempted,
+ return mPermissionManager.setAutoRevokeExempted(packageName, exempted,
mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index b2b8db1..376d942 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -4313,13 +4313,23 @@
* <P>
* Type: INTEGER (A bitmask of CARRIER_PRESENCE_* fields)
* </P>
+ *
+ * @deprecated The contacts database will only show presence
+ * information on devices where
+ * {@link android.telephony.CarrierConfigManager#KEY_USE_RCS_PRESENCE_BOOL} is true,
+ * otherwise use {@link android.telephony.ims.RcsUceAdapter}.
*/
+ @Deprecated
public static final String CARRIER_PRESENCE = "carrier_presence";
/**
* Indicates that the entry is Video Telephony (VT) capable on the
* current carrier. An allowed bitmask of {@link #CARRIER_PRESENCE}.
+ *
+ * @deprecated Same as {@link DataColumns#CARRIER_PRESENCE}.
+ *
*/
+ @Deprecated
public static final int CARRIER_PRESENCE_VT_CAPABLE = 0x01;
/**
diff --git a/core/java/android/provider/OWNERS b/core/java/android/provider/OWNERS
index 792ff20..b02102b 100644
--- a/core/java/android/provider/OWNERS
+++ b/core/java/android/provider/OWNERS
@@ -1,9 +1,17 @@
-per-file DeviceConfig.java = svetoslavganov@google.com
-per-file DeviceConfig.java = hackbod@google.com
-per-file DeviceConfig.java = schfan@google.com
+per-file *BlockedNumber* = file:/telephony/OWNERS
+per-file *Telephony* = file:/telephony/OWNERS
-per-file CallLog.java = file:/telephony/OWNERS
-per-file DocumentsContract.java = file:/core/java/android/os/storage/OWNERS
-per-file DocumentsProvider.java = file:/core/java/android/os/storage/OWNERS
-per-file MediaStore.java = file:/core/java/android/os/storage/OWNERS
-per-file Telephony.java = file:/telephony/OWNERS
+per-file *CallLog* = file:platform/packages/providers/ContactsProvider:/OWNERS
+per-file *Contacts* = file:platform/packages/providers/ContactsProvider:/OWNERS
+per-file *Voicemail* = file:platform/packages/providers/ContactsProvider:/OWNERS
+
+per-file *Calendar* = file:platform/packages/providers/CalendarProvider:/OWNERS
+
+per-file *Downloads* = file:platform/packages/providers/DownloadProvider:/OWNERS
+
+per-file *DeviceConfig* = file:/packages/SettingsProvider/OWNERS
+
+per-file *Documents* = file:/core/java/android/os/storage/OWNERS
+per-file *Documents* = file:platform/packages/apps/DocumentsUI:/OWNERS
+
+per-file *Slices* = file:/core/java/android/app/slice/OWNERS
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 83cab0a..d4c86e8 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -5280,5 +5280,13 @@
* @hide
*/
public static final String COLUMN_ALLOWED_NETWORK_TYPES = "allowed_network_types";
+
+ /**
+ * TelephonyProvider column name for RCS configuration.
+ * <p>TYPE: BLOB
+ *
+ * @hide
+ */
+ public static final String COLUMN_RCS_CONFIG = "rcs_config";
}
}
diff --git a/core/java/android/security/OWNERS b/core/java/android/security/OWNERS
index 3f8d75e..7140ff1 100644
--- a/core/java/android/security/OWNERS
+++ b/core/java/android/security/OWNERS
@@ -7,3 +7,5 @@
per-file NetworkSecurityPolicy.java = klyubin@google.com
per-file FrameworkNetworkSecurityPolicy.java = cbrubaker@google.com
per-file FrameworkNetworkSecurityPolicy.java = klyubin@google.com
+per-file Confirmation*.java = jdanis@google.com
+per-file Confirmation*.java = swillden@google.com
diff --git a/core/java/android/service/attestation/OWNERS b/core/java/android/service/attestation/OWNERS
new file mode 100644
index 0000000..b9e7b99
--- /dev/null
+++ b/core/java/android/service/attestation/OWNERS
@@ -0,0 +1,2 @@
+chaviw@google.com
+ogunwale@google.com
diff --git a/core/java/android/service/storage/ExternalStorageService.java b/core/java/android/service/storage/ExternalStorageService.java
index 3b4d84a..0123c36 100644
--- a/core/java/android/service/storage/ExternalStorageService.java
+++ b/core/java/android/service/storage/ExternalStorageService.java
@@ -16,6 +16,7 @@
package android.service.storage;
+import android.annotation.BytesLong;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SdkConstant;
@@ -29,6 +30,7 @@
import android.os.ParcelableException;
import android.os.RemoteCallback;
import android.os.RemoteException;
+import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
import com.android.internal.os.BackgroundThread;
@@ -37,6 +39,7 @@
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.UUID;
/**
* A service to handle filesystem I/O from other apps.
@@ -147,6 +150,18 @@
*/
public abstract void onVolumeStateChanged(@NonNull StorageVolume vol) throws IOException;
+ /**
+ * Called when any cache held by the ExternalStorageService needs to be freed.
+ *
+ * <p> Blocks until the service frees the cache or fails in doing so.
+ *
+ * @param volumeUuid uuid of the {@link StorageVolume} from which cache needs to be freed
+ * @param bytes number of bytes which need to be freed
+ */
+ public void onFreeCacheRequested(@NonNull UUID volumeUuid, @BytesLong long bytes) {
+ throw new UnsupportedOperationException("onFreeCacheRequested not implemented");
+ }
+
@Override
@NonNull
public final IBinder onBind(@NonNull Intent intent) {
@@ -183,6 +198,19 @@
}
@Override
+ public void freeCache(String sessionId, String volumeUuid, long bytes,
+ RemoteCallback callback) {
+ mHandler.post(() -> {
+ try {
+ onFreeCacheRequested(StorageManager.convert(volumeUuid), bytes);
+ sendResult(sessionId, null /* throwable */, callback);
+ } catch (Throwable t) {
+ sendResult(sessionId, t, callback);
+ }
+ });
+ }
+
+ @Override
public void endSession(String sessionId, RemoteCallback callback) throws RemoteException {
mHandler.post(() -> {
try {
diff --git a/core/java/android/service/storage/IExternalStorageService.aidl b/core/java/android/service/storage/IExternalStorageService.aidl
index 30fefd3..d06671b 100644
--- a/core/java/android/service/storage/IExternalStorageService.aidl
+++ b/core/java/android/service/storage/IExternalStorageService.aidl
@@ -30,4 +30,6 @@
void endSession(@utf8InCpp String sessionId, in RemoteCallback callback);
void notifyVolumeStateChanged(@utf8InCpp String sessionId, in StorageVolume vol,
in RemoteCallback callback);
+ void freeCache(@utf8InCpp String sessionId, in String volumeUuid, long bytes,
+ in RemoteCallback callback);
}
\ No newline at end of file
diff --git a/core/java/android/service/storage/OWNERS b/core/java/android/service/storage/OWNERS
new file mode 100644
index 0000000..6f9dbea
--- /dev/null
+++ b/core/java/android/service/storage/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/os/storage/OWNERS
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java b/core/java/android/service/timezone/ITimeZoneProvider.aidl
similarity index 63%
rename from media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java
rename to core/java/android/service/timezone/ITimeZoneProvider.aidl
index 52f2787..62fa157 100644
--- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java
+++ b/core/java/android/service/timezone/ITimeZoneProvider.aidl
@@ -14,19 +14,15 @@
* limitations under the License.
*/
-package com.android.mediatranscodingtest;
+package android.service.timezone;
+
+import android.service.timezone.ITimeZoneProviderManager;
/**
- *
- * This class has the names of the all the activity name and variables in the
- * instrumentation test.
- *
+ * @hide
*/
-public class MediaConstants {
- /*
- * Source test files.
- */
- public static final String[] SOURCE_HEVC_VIDEO_ONLY_TEST_FILES = {
- "/sdcard/media_api/video/VideoOnlyHEVC.mp4",
- };
+oneway interface ITimeZoneProvider {
+ void setTimeZoneProviderManager(in @nullable ITimeZoneProviderManager manager);
+ void startUpdates(in long initializationTimeoutMillis);
+ void stopUpdates();
}
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java b/core/java/android/service/timezone/ITimeZoneProviderManager.aidl
similarity index 63%
copy from media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java
copy to core/java/android/service/timezone/ITimeZoneProviderManager.aidl
index 52f2787..bf4fe0a 100644
--- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java
+++ b/core/java/android/service/timezone/ITimeZoneProviderManager.aidl
@@ -14,19 +14,15 @@
* limitations under the License.
*/
-package com.android.mediatranscodingtest;
+package android.service.timezone;
+
+import android.service.timezone.TimeZoneProviderSuggestion;
/**
- *
- * This class has the names of the all the activity name and variables in the
- * instrumentation test.
- *
+ * @hide
*/
-public class MediaConstants {
- /*
- * Source test files.
- */
- public static final String[] SOURCE_HEVC_VIDEO_ONLY_TEST_FILES = {
- "/sdcard/media_api/video/VideoOnlyHEVC.mp4",
- };
+oneway interface ITimeZoneProviderManager {
+ void onTimeZoneProviderSuggestion(in TimeZoneProviderSuggestion timeZoneProviderSuggestion);
+ void onTimeZoneProviderUncertain();
+ void onTimeZoneProviderPermanentFailure(in String failureReason);
}
diff --git a/core/java/android/service/timezone/TimeZoneProviderService.java b/core/java/android/service/timezone/TimeZoneProviderService.java
new file mode 100644
index 0000000..9533a8f
--- /dev/null
+++ b/core/java/android/service/timezone/TimeZoneProviderService.java
@@ -0,0 +1,225 @@
+/*
+ * 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.service.timezone;
+
+import android.annotation.DurationMillisLong;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
+import android.app.Service;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.internal.os.BackgroundThread;
+
+import java.util.Objects;
+
+/**
+ * A service to generate time zone callbacks to the platform. Developers must extend this class.
+ *
+ * <p>Provider implementations are started via a call to {@link #onStartUpdates(long)} and stopped
+ * via a call to {@link #onStopUpdates()}.
+ *
+ * <p>Once started, providers are expected to detect the time zone if possible, and report the
+ * result via {@link #reportSuggestion(TimeZoneProviderSuggestion)} or {@link
+ * #reportUncertain()}. Providers may also report that they have permanently failed
+ * by calling {@link #reportPermanentFailure(Throwable)}. See the javadocs for each
+ * method for details.
+ *
+ * <p>After starting, providers are expected to issue their first callback within the timeout
+ * duration specified in {@link #onStartUpdates(long)}, or they will be implicitly considered to be
+ * uncertain.
+ *
+ * <p>Once stopped or failed, providers are required to stop generating callbacks.
+ *
+ * <p>Provider discovery:
+ *
+ * <p>You must declare the service in your manifest file with the
+ * {@link android.Manifest.permission#INSTALL_LOCATION_TIME_ZONE_PROVIDER} permission,
+ * and include an intent filter with the necessary action indicating what type of provider it is.
+ *
+ * <p>Device configuration can influence how {@link TimeZoneProviderService}s are discovered.
+ * In one mode, there can be multiple {@link TimeZoneProviderService}s configured with the same
+ * action, and the one with the highest "serviceVersion" metadata will be used.
+ *
+ * <p>{@link TimeZoneProviderService}s may be deployed into processes that run once-per-user
+ * or once-per-device (i.e. they service multiple users). The "serviceIsMultiuser" metadata must
+ * be set accordingly.
+ *
+ * <p>Provider types:
+ *
+ * <p>Android currently supports up to two location-derived time zone providers. These are called
+ * the "primary" and "secondary" location time zone provider, configured using {@link
+ * #PRIMARY_LOCATION_TIME_ZONE_PROVIDER_SERVICE_INTERFACE} and {@link
+ * #SECONDARY_LOCATION_TIME_ZONE_PROVIDER_SERVICE_INTERFACE} respectively. The primary location time
+ * zone provider is started first and will be used until becomes uncertain or fails, at which point
+ * the secondary provider will be started.
+ *
+ * For example:
+ * <pre>
+ * <service android:name=".FooTimeZoneProviderService"
+ * android:exported="true"
+ * android:permission="android.permission.INSTALL_LOCATION_TIME_ZONE_PROVIDER">
+ * <intent-filter>
+ * <action
+ * android:name="android.service.timezone.SecondaryLocationTimeZoneProviderService"
+ * />
+ * </intent-filter>
+ * <meta-data android:name="serviceVersion" android:value="1" />
+ * <meta-data android:name="serviceIsMultiuser" android:value="true" />
+ * </service>
+ * </pre>
+ *
+ *
+ * <p>Threading:
+ *
+ * <p>Calls to {@code report} methods can be made on on any thread and will be passed asynchronously
+ * to the system server. Calls to {@link #onStartUpdates(long)} and {@link #onStopUpdates()} will
+ * occur on a single thread.
+ *
+ * @hide
+ */
+@SystemApi
+public abstract class TimeZoneProviderService extends Service {
+
+ private static final String TAG = "TimeZoneProviderService";
+
+ private final Handler mHandler = BackgroundThread.getHandler();
+
+ /**
+ * The Intent action that the primary location-derived time zone provider service must respond
+ * to. Add it to the intent filter of the service in its manifest.
+ */
+ @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+ public static final String PRIMARY_LOCATION_TIME_ZONE_PROVIDER_SERVICE_INTERFACE =
+ "android.service.timezone.PrimaryLocationTimeZoneProviderService";
+
+ /**
+ * The Intent action that the secondary location-based time zone provider service must respond
+ * to. Add it to the intent filter of the service in its manifest.
+ */
+ @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+ public static final String SECONDARY_LOCATION_TIME_ZONE_PROVIDER_SERVICE_INTERFACE =
+ "android.service.timezone.SecondaryLocationTimeZoneProviderService";
+
+ /**
+ * The permission that a service must require to ensure that only Android system can bind to it.
+ * If this permission is not enforced in the AndroidManifest of the service, the system will
+ * skip that service.
+ */
+ public static final String BIND_PERMISSION =
+ "android.permission.INSTALL_LOCATION_TIME_ZONE_PROVIDER";
+
+ private final TimeZoneProviderServiceWrapper mWrapper = new TimeZoneProviderServiceWrapper();
+
+ /** Set by {@link #mHandler} thread. */
+ @Nullable
+ private ITimeZoneProviderManager mManager;
+
+ @Override
+ @NonNull
+ public final IBinder onBind(@NonNull Intent intent) {
+ return mWrapper;
+ }
+
+ /**
+ * Indicates a successful time zone detection. See {@link TimeZoneProviderSuggestion} for
+ * details.
+ */
+ public final void reportSuggestion(@NonNull TimeZoneProviderSuggestion suggestion) {
+ Objects.requireNonNull(suggestion);
+
+ mHandler.post(() -> {
+ ITimeZoneProviderManager manager = mManager;
+ if (manager != null) {
+ try {
+ manager.onTimeZoneProviderSuggestion(suggestion);
+ } catch (RemoteException | RuntimeException e) {
+ Log.w(TAG, e);
+ }
+ }
+ });
+ }
+
+ /**
+ * Indicates the time zone is not known because of an expected runtime state or error, e.g. when
+ * the provider is unable to detect location, or there was a problem when resolving the location
+ * to a time zone.
+ */
+ public final void reportUncertain() {
+ mHandler.post(() -> {
+ ITimeZoneProviderManager manager = mManager;
+ if (manager != null) {
+ try {
+ manager.onTimeZoneProviderUncertain();
+ } catch (RemoteException | RuntimeException e) {
+ Log.w(TAG, e);
+ }
+ }
+ });
+ }
+
+ /**
+ * Indicates there was a permanent failure. This is not generally expected, and probably means a
+ * required backend service has been turned down, or the client is unreasonably old.
+ */
+ public final void reportPermanentFailure(@NonNull Throwable cause) {
+ Objects.requireNonNull(cause);
+
+ mHandler.post(() -> {
+ ITimeZoneProviderManager manager = mManager;
+ if (manager != null) {
+ try {
+ manager.onTimeZoneProviderPermanentFailure(cause.getMessage());
+ } catch (RemoteException | RuntimeException e) {
+ Log.w(TAG, e);
+ }
+ }
+ });
+ }
+
+ /**
+ * Starts the provider sending updates.
+ */
+ public abstract void onStartUpdates(@DurationMillisLong long initializationTimeoutMillis);
+
+ /**
+ * Stops the provider sending updates.
+ */
+ public abstract void onStopUpdates();
+
+ private class TimeZoneProviderServiceWrapper extends ITimeZoneProvider.Stub {
+
+ @Override
+ public void setTimeZoneProviderManager(ITimeZoneProviderManager manager) {
+ Objects.requireNonNull(manager);
+ mHandler.post(() -> TimeZoneProviderService.this.mManager = manager);
+ }
+
+ public void startUpdates(@DurationMillisLong long initializationTimeoutMillis) {
+ mHandler.post(() -> onStartUpdates(initializationTimeoutMillis));
+ }
+
+ public void stopUpdates() {
+ mHandler.post(TimeZoneProviderService.this::onStopUpdates);
+ }
+ }
+}
diff --git a/core/java/android/service/timezone/TimeZoneProviderSuggestion.aidl b/core/java/android/service/timezone/TimeZoneProviderSuggestion.aidl
new file mode 100644
index 0000000..d0cb73b
--- /dev/null
+++ b/core/java/android/service/timezone/TimeZoneProviderSuggestion.aidl
@@ -0,0 +1,22 @@
+/*
+ * 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.service.timezone;
+
+/**
+ * @hide
+ */
+parcelable TimeZoneProviderSuggestion;
diff --git a/core/java/android/service/timezone/TimeZoneProviderSuggestion.java b/core/java/android/service/timezone/TimeZoneProviderSuggestion.java
new file mode 100644
index 0000000..cf299a7
--- /dev/null
+++ b/core/java/android/service/timezone/TimeZoneProviderSuggestion.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.timezone;
+
+import android.annotation.ElapsedRealtimeLong;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.SystemClock;
+
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A suggestion from a {@link TimeZoneProviderService} containing zero or more time zones.
+ *
+ * @hide
+ */
+@SystemApi
+public final class TimeZoneProviderSuggestion implements Parcelable {
+
+ @NonNull
+ private final List<String> mTimeZoneIds;
+
+ @ElapsedRealtimeLong
+ private final long mElapsedRealtimeMillis;
+
+ private TimeZoneProviderSuggestion(@NonNull List<String> timeZoneIds,
+ @ElapsedRealtimeLong long elapsedRealtimeMillis) {
+ mTimeZoneIds = immutableList(timeZoneIds);
+ mElapsedRealtimeMillis = elapsedRealtimeMillis;
+ }
+
+ /**
+ * Returns the time of the suggestion in elapsed real-time since system boot. Where possible,
+ * the time should be based on the time of the data used when determining time zone. For
+ * example, if it was based on a {@link android.location.Location} then it should be the time
+ * associated with that location.
+ *
+ * <p>This value is compared to {@link
+ * android.os.SystemClock#elapsedRealtime()}, to calculate the age of a fix and to compare
+ * {@link TimeZoneProviderSuggestion} instances.
+ *
+ * @return elapsed real-time of fix, in milliseconds
+ */
+ @ElapsedRealtimeLong
+ public long getElapsedRealtimeMillis() {
+ return mElapsedRealtimeMillis;
+ }
+
+ /**
+ * Returns the zero or more time zone IDs for this suggestion.
+ *
+ * <p>Time zone IDs are TZDB IDs like "America/Los_Angeles" that would be accepted by {@link
+ * java.util.TimeZone#getTimeZone(String)}.
+ *
+ * <p>Most often a suggestion will contain a single time zone ID but other possibilities are
+ * valid. A suggestion with zero time zone IDs means the provider is certain there are no time
+ * zones for the current location, e.g. for oceans, boundaries or disputed areas. A suggestion
+ * with multiple IDs can occur on boundaries or disputed areas. The ordering should be in order
+ * of likelihood if possible, but the time zone detection service may choose from any of the
+ * zones suggested if it has other supporting information available.
+ */
+ @NonNull
+ public List<String> getTimeZoneIds() {
+ return mTimeZoneIds;
+ }
+
+ @Override
+ public String toString() {
+ return "TimeZoneProviderSuggestion{"
+ + "mTimeZoneIds=" + mTimeZoneIds
+ + ", mElapsedRealtimeMillis=" + mElapsedRealtimeMillis
+ + "(" + Duration.ofMillis(mElapsedRealtimeMillis) + ")"
+ + '}';
+ }
+
+ public static final @NonNull Creator<TimeZoneProviderSuggestion> CREATOR =
+ new Creator<TimeZoneProviderSuggestion>() {
+ @Override
+ public TimeZoneProviderSuggestion createFromParcel(Parcel in) {
+ @SuppressWarnings("unchecked")
+ ArrayList<String> timeZoneIds =
+ (ArrayList<String>) in.readArrayList(null /* classLoader */);
+ long elapsedRealtimeMillis = in.readLong();
+ return new TimeZoneProviderSuggestion(timeZoneIds, elapsedRealtimeMillis);
+ }
+
+ @Override
+ public TimeZoneProviderSuggestion[] newArray(int size) {
+ return new TimeZoneProviderSuggestion[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel parcel, int flags) {
+ parcel.writeList(mTimeZoneIds);
+ parcel.writeLong(mElapsedRealtimeMillis);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ TimeZoneProviderSuggestion that = (TimeZoneProviderSuggestion) o;
+ return mElapsedRealtimeMillis == that.mElapsedRealtimeMillis
+ && mTimeZoneIds.equals(that.mTimeZoneIds);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mTimeZoneIds, mElapsedRealtimeMillis);
+ }
+
+ /** A builder for {@link TimeZoneProviderSuggestion}. */
+ public static final class Builder {
+
+ private @NonNull List<String> mTimeZoneIds = Collections.emptyList();
+ @ElapsedRealtimeLong
+ private long mElapsedRealtimeMillis = SystemClock.elapsedRealtime();
+
+ /**
+ * Sets the time zone IDs of this suggestion.
+ */
+ @NonNull
+ public Builder setTimeZoneIds(@NonNull List<String> timeZoneIds) {
+ mTimeZoneIds = Objects.requireNonNull(timeZoneIds);
+ return this;
+ }
+
+ /**
+ * Sets the time of this suggestion, in elapsed real-time since system boot.
+ */
+ @NonNull
+ public Builder setElapsedRealtimeMillis(@ElapsedRealtimeLong long time) {
+ mElapsedRealtimeMillis = time;
+ return this;
+ }
+
+ /**
+ * Builds a {@link TimeZoneProviderSuggestion} instance.
+ */
+ @NonNull
+ public TimeZoneProviderSuggestion build() {
+ return new TimeZoneProviderSuggestion(mTimeZoneIds, mElapsedRealtimeMillis);
+ }
+ }
+
+ @NonNull
+ private static List<String> immutableList(@NonNull List<String> list) {
+ Objects.requireNonNull(list);
+ if (list.isEmpty()) {
+ return Collections.emptyList();
+ } else {
+ return Collections.unmodifiableList(new ArrayList<>(list));
+ }
+ }
+}
diff --git a/core/java/android/text/style/SuggestionSpan.java b/core/java/android/text/style/SuggestionSpan.java
index 1f15d46..4a48832 100644
--- a/core/java/android/text/style/SuggestionSpan.java
+++ b/core/java/android/text/style/SuggestionSpan.java
@@ -402,6 +402,10 @@
}
} else if (autoCorrection) {
tp.setUnderlineText(mAutoCorrectionUnderlineColor, mAutoCorrectionUnderlineThickness);
+ } else if (misspelled) {
+ tp.setUnderlineText(mMisspelledUnderlineColor, mMisspelledUnderlineThickness);
+ } else if (grammarError) {
+ tp.setUnderlineText(mGrammarErrorUnderlineColor, mGrammarErrorUnderlineThickness);
}
}
@@ -425,6 +429,10 @@
}
} else if (autoCorrection) {
return mAutoCorrectionUnderlineColor;
+ } else if (misspelled) {
+ return mMisspelledUnderlineColor;
+ } else if (grammarError) {
+ return mGrammarErrorUnderlineColor;
}
return 0;
}
diff --git a/core/java/android/util/Xml.java b/core/java/android/util/Xml.java
index c8193b3..38decf9 100644
--- a/core/java/android/util/Xml.java
+++ b/core/java/android/util/Xml.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.os.SystemProperties;
import android.system.ErrnoException;
import android.system.Os;
@@ -64,8 +65,11 @@
/**
* Feature flag: when set, {@link #resolveSerializer(OutputStream)} will
* emit binary XML by default.
+ *
+ * @hide
*/
- private static final boolean ENABLE_BINARY_DEFAULT = false;
+ public static final boolean ENABLE_BINARY_DEFAULT = SystemProperties
+ .getBoolean("persist.sys.binary_xml", true);
/**
* Parses the given xml string and fires events on the given SAX handler.
@@ -172,7 +176,7 @@
if (!in.markSupported()) {
in = new BufferedInputStream(in);
}
- in.mark(4);
+ in.mark(8);
in.read(magic);
in.reset();
}
diff --git a/core/java/android/util/imetracing/ImeTracingClientImpl.java b/core/java/android/util/imetracing/ImeTracingClientImpl.java
index 6cc652d..2c27639 100644
--- a/core/java/android/util/imetracing/ImeTracingClientImpl.java
+++ b/core/java/android/util/imetracing/ImeTracingClientImpl.java
@@ -25,6 +25,9 @@
import android.util.proto.ProtoOutputStream;
import android.view.inputmethod.InputMethodManager;
+import com.android.internal.inputmethod.Completable;
+import com.android.internal.inputmethod.ResultCallbacks;
+
import java.io.PrintWriter;
/**
@@ -32,7 +35,9 @@
*/
class ImeTracingClientImpl extends ImeTracing {
ImeTracingClientImpl() throws ServiceNotFoundException, RemoteException {
- sEnabled = mService.isImeTraceEnabled();
+ final Completable.Boolean value = Completable.createBoolean();
+ mService.isImeTraceEnabled(ResultCallbacks.of(value));
+ sEnabled = Completable.getResult(value);
}
@Override
diff --git a/core/java/android/uwb/RangingManager.java b/core/java/android/uwb/RangingManager.java
new file mode 100644
index 0000000..a9bf4ab
--- /dev/null
+++ b/core/java/android/uwb/RangingManager.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.uwb;
+
+import android.annotation.NonNull;
+import android.os.PersistableBundle;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.Hashtable;
+import java.util.concurrent.Executor;
+
+/**
+ * @hide
+ */
+public class RangingManager extends android.uwb.IUwbRangingCallbacks.Stub {
+ private static final String TAG = "Uwb.RangingManager";
+
+ private final IUwbAdapter mAdapter;
+ private final Hashtable<SessionHandle, RangingSession> mRangingSessionTable = new Hashtable<>();
+
+ public RangingManager(IUwbAdapter adapter) {
+ mAdapter = adapter;
+ }
+
+ /**
+ * Open a new ranging session
+ *
+ * @param params the parameters that define the ranging session
+ * @param executor {@link Executor} to run callbacks
+ * @param callbacks {@link RangingSession.Callback} to associate with the {@link RangingSession}
+ * that is being opened.
+ * @return a new {@link RangingSession}
+ */
+ public RangingSession openSession(@NonNull PersistableBundle params, @NonNull Executor executor,
+ @NonNull RangingSession.Callback callbacks) {
+ SessionHandle sessionHandle;
+ try {
+ sessionHandle = mAdapter.startRanging(this, params);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+
+ synchronized (this) {
+ if (hasSession(sessionHandle)) {
+ Log.w(TAG, "Newly created session unexpectedly reuses an active SessionHandle");
+ executor.execute(() -> callbacks.onClosed(
+ RangingSession.Callback.CLOSE_REASON_LOCAL_GENERIC_ERROR,
+ new PersistableBundle()));
+ }
+
+ RangingSession session =
+ new RangingSession(executor, callbacks, mAdapter, sessionHandle);
+ mRangingSessionTable.put(sessionHandle, session);
+ return session;
+ }
+ }
+
+ private boolean hasSession(SessionHandle sessionHandle) {
+ return mRangingSessionTable.containsKey(sessionHandle);
+ }
+
+ @Override
+ public void onRangingStarted(SessionHandle sessionHandle, PersistableBundle parameters) {
+ synchronized (this) {
+ if (!hasSession(sessionHandle)) {
+ Log.w(TAG,
+ "onRangingStarted - received unexpected SessionHandle: " + sessionHandle);
+ return;
+ }
+
+ RangingSession session = mRangingSessionTable.get(sessionHandle);
+ session.onRangingStarted(parameters);
+ }
+ }
+
+ @Override
+ public void onRangingStartFailed(SessionHandle sessionHandle, int reason,
+ PersistableBundle params) {
+ synchronized (this) {
+ if (!hasSession(sessionHandle)) {
+ Log.w(TAG, "onRangingStartFailed - received unexpected SessionHandle: "
+ + sessionHandle);
+ return;
+ }
+
+ RangingSession session = mRangingSessionTable.get(sessionHandle);
+ session.onRangingClosed(convertStartFailureToCloseReason(reason), params);
+ mRangingSessionTable.remove(sessionHandle);
+ }
+ }
+
+ @Override
+ public void onRangingClosed(SessionHandle sessionHandle, int reason, PersistableBundle params) {
+ synchronized (this) {
+ if (!hasSession(sessionHandle)) {
+ Log.w(TAG, "onRangingClosed - received unexpected SessionHandle: " + sessionHandle);
+ return;
+ }
+
+ RangingSession session = mRangingSessionTable.get(sessionHandle);
+ session.onRangingClosed(convertToCloseReason(reason), params);
+ mRangingSessionTable.remove(sessionHandle);
+ }
+ }
+
+ @Override
+ public void onRangingResult(SessionHandle sessionHandle, RangingReport result) {
+ synchronized (this) {
+ if (!hasSession(sessionHandle)) {
+ Log.w(TAG, "onRangingResult - received unexpected SessionHandle: " + sessionHandle);
+ return;
+ }
+
+ RangingSession session = mRangingSessionTable.get(sessionHandle);
+ session.onRangingResult(result);
+ }
+ }
+
+ @RangingSession.Callback.CloseReason
+ private static int convertToCloseReason(@CloseReason int reason) {
+ switch (reason) {
+ case CloseReason.LOCAL_API:
+ return RangingSession.Callback.CLOSE_REASON_LOCAL_CLOSE_API;
+
+ case CloseReason.MAX_SESSIONS_REACHED:
+ return RangingSession.Callback.CLOSE_REASON_LOCAL_MAX_SESSIONS_REACHED;
+
+ case CloseReason.SYSTEM_POLICY:
+ return RangingSession.Callback.CLOSE_REASON_LOCAL_SYSTEM_POLICY;
+
+ case CloseReason.REMOTE_REQUEST:
+ return RangingSession.Callback.CLOSE_REASON_REMOTE_REQUEST;
+
+ case CloseReason.PROTOCOL_SPECIFIC:
+ return RangingSession.Callback.CLOSE_REASON_PROTOCOL_SPECIFIC;
+
+ case CloseReason.UNKNOWN:
+ default:
+ return RangingSession.Callback.CLOSE_REASON_UNKNOWN;
+ }
+ }
+
+ @RangingSession.Callback.CloseReason
+ private static int convertStartFailureToCloseReason(@StartFailureReason int reason) {
+ switch (reason) {
+ case StartFailureReason.BAD_PARAMETERS:
+ return RangingSession.Callback.CLOSE_REASON_LOCAL_BAD_PARAMETERS;
+
+ case StartFailureReason.MAX_SESSIONS_REACHED:
+ return RangingSession.Callback.CLOSE_REASON_LOCAL_MAX_SESSIONS_REACHED;
+
+ case StartFailureReason.SYSTEM_POLICY:
+ return RangingSession.Callback.CLOSE_REASON_LOCAL_SYSTEM_POLICY;
+
+ case StartFailureReason.PROTOCOL_SPECIFIC:
+ return RangingSession.Callback.CLOSE_REASON_PROTOCOL_SPECIFIC;
+
+ case StartFailureReason.UNKNOWN:
+ default:
+ return RangingSession.Callback.CLOSE_REASON_UNKNOWN;
+ }
+ }
+}
diff --git a/core/java/android/uwb/RangingSession.java b/core/java/android/uwb/RangingSession.java
index e1af9b1..b0dbd85 100644
--- a/core/java/android/uwb/RangingSession.java
+++ b/core/java/android/uwb/RangingSession.java
@@ -18,7 +18,10 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.os.Binder;
import android.os.PersistableBundle;
+import android.os.RemoteException;
+import android.util.Log;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -34,12 +37,26 @@
* {@link UwbManager#openRangingSession(PersistableBundle, Executor, Callback)} to request to open a
* session. Once the session is opened, a {@link RangingSession} object is provided through
* {@link RangingSession.Callback#onOpenSuccess(RangingSession, PersistableBundle)}. If opening a
- * session fails, the failure is reported through {@link RangingSession.Callback#onClosed(int)} with
- * the failure reason.
+ * session fails, the failure is reported through
+ * {@link RangingSession.Callback#onClosed(int, PersistableBundle)} with the failure reason.
*
* @hide
*/
public final class RangingSession implements AutoCloseable {
+ private static final String TAG = "Uwb.RangingSession";
+ private final SessionHandle mSessionHandle;
+ private final IUwbAdapter mAdapter;
+ private final Executor mExecutor;
+ private final Callback mCallback;
+
+ private enum State {
+ INIT,
+ OPEN,
+ CLOSED,
+ }
+
+ private State mState;
+
/**
* Interface for receiving {@link RangingSession} events
*/
@@ -116,13 +133,20 @@
int CLOSE_REASON_REMOTE_REQUEST = 7;
/**
+ * Indicates that the session was closed for a protocol specific reason. The associated
+ * {@link PersistableBundle} should be consulted for additional information.
+ */
+ int CLOSE_REASON_PROTOCOL_SPECIFIC = 8;
+
+ /**
* Invoked when session is either closed spontaneously, or per user request via
* {@link RangingSession#close()} or {@link AutoCloseable#close()}, or when session failed
* to open.
*
* @param reason reason for the session closure
+ * @param parameters protocol specific parameters related to the close reason
*/
- void onClosed(@CloseReason int reason);
+ void onClosed(@CloseReason int reason, @NonNull PersistableBundle parameters);
/**
* Called once per ranging interval even when a ranging measurement fails
@@ -133,20 +157,97 @@
}
/**
+ * @hide
+ */
+ public RangingSession(Executor executor, Callback callback, IUwbAdapter adapter,
+ SessionHandle sessionHandle) {
+ mState = State.INIT;
+ mExecutor = executor;
+ mCallback = callback;
+ mAdapter = adapter;
+ mSessionHandle = sessionHandle;
+ }
+
+ /**
+ * @hide
+ */
+ public boolean isOpen() {
+ return mState == State.OPEN;
+ }
+
+ /**
* Close the ranging session
* <p>If this session is currently open, it will close and stop the session.
* <p>If the session is in the process of being opened, it will attempt to stop the session from
* being opened.
- * <p>If the session is already closed, the registered {@link Callback#onClosed(int)} callback
- * will still be invoked.
+ * <p>If the session is already closed, the registered
+ * {@link Callback#onClosed(int, PersistableBundle)} callback will still be invoked.
*
- * <p>{@link Callback#onClosed(int)} will be invoked using the same callback
+ * <p>{@link Callback#onClosed(int, PersistableBundle)} will be invoked using the same callback
* object given to {@link UwbManager#openRangingSession(PersistableBundle, Executor, Callback)}
* when the {@link RangingSession} was opened. The callback will be invoked after each call to
* {@link #close()}, even if the {@link RangingSession} is already closed.
*/
@Override
public void close() {
- throw new UnsupportedOperationException();
+ if (mState == State.CLOSED) {
+ mExecutor.execute(() -> mCallback.onClosed(
+ Callback.CLOSE_REASON_LOCAL_CLOSE_API, new PersistableBundle()));
+ return;
+ }
+
+ try {
+ mAdapter.closeRanging(mSessionHandle);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void onRangingStarted(@NonNull PersistableBundle parameters) {
+ if (mState == State.CLOSED) {
+ Log.w(TAG, "onRangingStarted invoked for a closed session");
+ return;
+ }
+
+ mState = State.OPEN;
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mCallback.onOpenSuccess(this, parameters));
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void onRangingClosed(@Callback.CloseReason int reason, PersistableBundle parameters) {
+ mState = State.CLOSED;
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mCallback.onClosed(reason, parameters));
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void onRangingResult(@NonNull RangingReport report) {
+ if (!isOpen()) {
+ Log.w(TAG, "onRangingResult invoked for non-open session");
+ return;
+ }
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mCallback.onReportReceived(report));
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
}
diff --git a/core/java/android/uwb/UwbManager.java b/core/java/android/uwb/UwbManager.java
index bb2be02..f4d8018 100644
--- a/core/java/android/uwb/UwbManager.java
+++ b/core/java/android/uwb/UwbManager.java
@@ -49,7 +49,8 @@
private IUwbAdapter mUwbAdapter;
private static final String SERVICE_NAME = "uwb";
- private AdapterStateListener mAdapterStateListener;
+ private final AdapterStateListener mAdapterStateListener;
+ private final RangingManager mRangingManager;
/**
* Interface for receiving UWB adapter state changes
@@ -119,6 +120,7 @@
private UwbManager(IUwbAdapter adapter) {
mUwbAdapter = adapter;
mAdapterStateListener = new AdapterStateListener(adapter);
+ mRangingManager = new RangingManager(adapter);
}
/**
@@ -395,6 +397,6 @@
public AutoCloseable openRangingSession(@NonNull PersistableBundle parameters,
@NonNull @CallbackExecutor Executor executor,
@NonNull RangingSession.Callback callbacks) {
- throw new UnsupportedOperationException();
+ return mRangingManager.openSession(parameters, executor, callbacks);
}
}
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 9473845..2e90619 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -113,6 +113,8 @@
private AddNodeInfosForViewId mAddNodeInfosForViewId;
+ private List<Message> mPendingFindNodeByIdMessages;
+
@GuardedBy("mLock")
private int mNumActiveRequestPreparers;
@GuardedBy("mLock")
@@ -128,6 +130,7 @@
mViewRootImpl = viewRootImpl;
mPrefetcher = new AccessibilityNodePrefetcher();
mA11yManager = mViewRootImpl.mContext.getSystemService(AccessibilityManager.class);
+ mPendingFindNodeByIdMessages = new ArrayList<>();
}
private void scheduleMessage(Message message, int interrogatingPid, long interrogatingTid,
@@ -177,6 +180,7 @@
args.arg4 = arguments;
message.obj = args;
+ mPendingFindNodeByIdMessages.add(message);
scheduleMessage(message, interrogatingPid, interrogatingTid, CONSIDER_REQUEST_PREPARERS);
}
@@ -315,6 +319,8 @@
}
private void findAccessibilityNodeInfoByAccessibilityIdUiThread(Message message) {
+ mPendingFindNodeByIdMessages.remove(message);
+
final int flags = message.arg1;
SomeArgs args = (SomeArgs) message.obj;
@@ -329,22 +335,58 @@
args.recycle();
- List<AccessibilityNodeInfo> infos = mTempAccessibilityNodeInfoList;
- infos.clear();
+ View rootView = null;
+ AccessibilityNodeInfo rootNode = null;
try {
if (mViewRootImpl.mView == null || mViewRootImpl.mAttachInfo == null) {
return;
}
mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = flags;
- final View root = findViewByAccessibilityId(accessibilityViewId);
- if (root != null && isShown(root)) {
- mPrefetcher.prefetchAccessibilityNodeInfos(
- root, virtualDescendantId, flags, infos, arguments);
+ rootView = findViewByAccessibilityId(accessibilityViewId);
+ if (rootView != null && isShown(rootView)) {
+ rootNode = populateAccessibilityNodeInfoForView(
+ rootView, arguments, virtualDescendantId);
}
} finally {
- updateInfosForViewportAndReturnFindNodeResult(
- infos, callback, interactionId, spec, interactiveRegion);
+ updateInfoForViewportAndReturnFindNodeResult(
+ rootNode == null ? null : AccessibilityNodeInfo.obtain(rootNode),
+ callback, interactionId, spec, interactiveRegion);
}
+ List<AccessibilityNodeInfo> infos = mTempAccessibilityNodeInfoList;
+ infos.clear();
+ mPrefetcher.prefetchAccessibilityNodeInfos(
+ rootView, rootNode == null ? null : AccessibilityNodeInfo.obtain(rootNode),
+ virtualDescendantId, flags, infos);
+ mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
+ updateInfosForViewPort(infos, spec, interactiveRegion);
+ returnPrefetchResult(interactionId, infos, callback);
+ returnPendingFindAccessibilityNodeInfosInPrefetch(infos);
+ }
+
+ private AccessibilityNodeInfo populateAccessibilityNodeInfoForView(
+ View view, Bundle arguments, int virtualViewId) {
+ AccessibilityNodeProvider provider = view.getAccessibilityNodeProvider();
+ // Determine if we'll be populating extra data
+ final String extraDataRequested = (arguments == null) ? null
+ : arguments.getString(EXTRA_DATA_REQUESTED_KEY);
+ AccessibilityNodeInfo root = null;
+ if (provider == null) {
+ root = view.createAccessibilityNodeInfo();
+ if (root != null) {
+ if (extraDataRequested != null) {
+ view.addExtraDataToAccessibilityNodeInfo(root, extraDataRequested, arguments);
+ }
+ }
+ } else {
+ root = provider.createAccessibilityNodeInfo(virtualViewId);
+ if (root != null) {
+ if (extraDataRequested != null) {
+ provider.addExtraDataToAccessibilityNodeInfo(
+ virtualViewId, root, extraDataRequested, arguments);
+ }
+ }
+ }
+ return root;
}
public void findAccessibilityNodeInfosByViewIdClientThread(long accessibilityNodeId,
@@ -402,6 +444,7 @@
mAddNodeInfosForViewId.reset();
}
} finally {
+ mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
updateInfosForViewportAndReturnFindNodeResult(
infos, callback, interactionId, spec, interactiveRegion);
}
@@ -484,6 +527,7 @@
}
}
} finally {
+ mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
updateInfosForViewportAndReturnFindNodeResult(
infos, callback, interactionId, spec, interactiveRegion);
}
@@ -575,6 +619,7 @@
}
}
} finally {
+ mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
updateInfoForViewportAndReturnFindNodeResult(
focused, callback, interactionId, spec, interactiveRegion);
}
@@ -629,6 +674,7 @@
}
}
} finally {
+ mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
updateInfoForViewportAndReturnFindNodeResult(
next, callback, interactionId, spec, interactiveRegion);
}
@@ -785,33 +831,6 @@
}
}
- private void applyAppScaleAndMagnificationSpecIfNeeded(List<AccessibilityNodeInfo> infos,
- MagnificationSpec spec) {
- if (infos == null) {
- return;
- }
- final float applicationScale = mViewRootImpl.mAttachInfo.mApplicationScale;
- if (shouldApplyAppScaleAndMagnificationSpec(applicationScale, spec)) {
- final int infoCount = infos.size();
- for (int i = 0; i < infoCount; i++) {
- AccessibilityNodeInfo info = infos.get(i);
- applyAppScaleAndMagnificationSpecIfNeeded(info, spec);
- }
- }
- }
-
- private void adjustIsVisibleToUserIfNeeded(List<AccessibilityNodeInfo> infos,
- Region interactiveRegion) {
- if (interactiveRegion == null || infos == null) {
- return;
- }
- final int infoCount = infos.size();
- for (int i = 0; i < infoCount; i++) {
- AccessibilityNodeInfo info = infos.get(i);
- adjustIsVisibleToUserIfNeeded(info, interactiveRegion);
- }
- }
-
private void adjustIsVisibleToUserIfNeeded(AccessibilityNodeInfo info,
Region interactiveRegion) {
if (interactiveRegion == null || info == null) {
@@ -832,17 +851,6 @@
return false;
}
- private void adjustBoundsInScreenIfNeeded(List<AccessibilityNodeInfo> infos) {
- if (infos == null || shouldBypassAdjustBoundsInScreen()) {
- return;
- }
- final int infoCount = infos.size();
- for (int i = 0; i < infoCount; i++) {
- final AccessibilityNodeInfo info = infos.get(i);
- adjustBoundsInScreenIfNeeded(info);
- }
- }
-
private void adjustBoundsInScreenIfNeeded(AccessibilityNodeInfo info) {
if (info == null || shouldBypassAdjustBoundsInScreen()) {
return;
@@ -890,17 +898,6 @@
return screenMatrix == null || screenMatrix.isIdentity();
}
- private void associateLeashedParentIfNeeded(List<AccessibilityNodeInfo> infos) {
- if (infos == null || shouldBypassAssociateLeashedParent()) {
- return;
- }
- final int infoCount = infos.size();
- for (int i = 0; i < infoCount; i++) {
- final AccessibilityNodeInfo info = infos.get(i);
- associateLeashedParentIfNeeded(info);
- }
- }
-
private void associateLeashedParentIfNeeded(AccessibilityNodeInfo info) {
if (info == null || shouldBypassAssociateLeashedParent()) {
return;
@@ -974,18 +971,46 @@
return (appScale != 1.0f || (spec != null && !spec.isNop()));
}
+ private void updateInfosForViewPort(List<AccessibilityNodeInfo> infos, MagnificationSpec spec,
+ Region interactiveRegion) {
+ for (int i = 0; i < infos.size(); i++) {
+ updateInfoForViewPort(infos.get(i), spec, interactiveRegion);
+ }
+ }
+
+ private void updateInfoForViewPort(AccessibilityNodeInfo info, MagnificationSpec spec,
+ Region interactiveRegion) {
+ associateLeashedParentIfNeeded(info);
+ applyScreenMatrixIfNeeded(info);
+ adjustBoundsInScreenIfNeeded(info);
+ // To avoid applyAppScaleAndMagnificationSpecIfNeeded changing the bounds of node,
+ // then impact the visibility result, we need to adjust visibility before apply scale.
+ adjustIsVisibleToUserIfNeeded(info, interactiveRegion);
+ applyAppScaleAndMagnificationSpecIfNeeded(info, spec);
+ }
+
private void updateInfosForViewportAndReturnFindNodeResult(List<AccessibilityNodeInfo> infos,
IAccessibilityInteractionConnectionCallback callback, int interactionId,
MagnificationSpec spec, Region interactiveRegion) {
+ if (infos != null) {
+ updateInfosForViewPort(infos, spec, interactiveRegion);
+ }
+ returnFindNodesResult(infos, callback, interactionId);
+ }
+
+ private void returnFindNodeResult(AccessibilityNodeInfo info,
+ IAccessibilityInteractionConnectionCallback callback,
+ int interactionId) {
try {
- mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
- associateLeashedParentIfNeeded(infos);
- applyScreenMatrixIfNeeded(infos);
- adjustBoundsInScreenIfNeeded(infos);
- // To avoid applyAppScaleAndMagnificationSpecIfNeeded changing the bounds of node,
- // then impact the visibility result, we need to adjust visibility before apply scale.
- adjustIsVisibleToUserIfNeeded(infos, interactiveRegion);
- applyAppScaleAndMagnificationSpecIfNeeded(infos, spec);
+ callback.setFindAccessibilityNodeInfoResult(info, interactionId);
+ } catch (RemoteException re) {
+ /* ignore - the other side will time out */
+ }
+ }
+
+ private void returnFindNodesResult(List<AccessibilityNodeInfo> infos,
+ IAccessibilityInteractionConnectionCallback callback, int interactionId) {
+ try {
callback.setFindAccessibilityNodeInfosResult(infos, interactionId);
if (infos != null) {
infos.clear();
@@ -995,22 +1020,49 @@
}
}
+ private void returnPendingFindAccessibilityNodeInfosInPrefetch(
+ List<AccessibilityNodeInfo> infos) {
+ for (Message pendingMessage : mPendingFindNodeByIdMessages) {
+ SomeArgs args = (SomeArgs) pendingMessage.obj;
+ final int accessibilityViewId = args.argi1;
+ final int virtualDescendantId = args.argi2;
+ final int interactionId = args.argi3;
+ final IAccessibilityInteractionConnectionCallback callback =
+ (IAccessibilityInteractionConnectionCallback) args.arg1;
+ final long nodeId =
+ AccessibilityNodeInfo.makeNodeId(accessibilityViewId, virtualDescendantId);
+ for (int i = 0; i < infos.size(); i++) {
+ AccessibilityNodeInfo info = infos.get(i);
+ if (info.getSourceNodeId() == nodeId) {
+ returnFindNodeResult(
+ AccessibilityNodeInfo.obtain(info), callback, interactionId);
+ mHandler.removeMessages(
+ PrivateHandler.MSG_FIND_ACCESSIBILITY_NODE_INFO_BY_ACCESSIBILITY_ID,
+ pendingMessage.obj);
+ args.recycle();
+ break;
+ }
+ }
+ }
+ mPendingFindNodeByIdMessages.clear();
+ }
+
+ private void returnPrefetchResult(int interactionId, List<AccessibilityNodeInfo> infos,
+ IAccessibilityInteractionConnectionCallback callback) {
+ if (infos.size() > 0) {
+ try {
+ callback.setPrefetchAccessibilityNodeInfoResult(infos, interactionId);
+ } catch (RemoteException re) {
+ /* ignore - other side isn't too bothered if this doesn't arrive */
+ }
+ }
+ }
+
private void updateInfoForViewportAndReturnFindNodeResult(AccessibilityNodeInfo info,
IAccessibilityInteractionConnectionCallback callback, int interactionId,
MagnificationSpec spec, Region interactiveRegion) {
- try {
- mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
- associateLeashedParentIfNeeded(info);
- applyScreenMatrixIfNeeded(info);
- adjustBoundsInScreenIfNeeded(info);
- // To avoid applyAppScaleAndMagnificationSpecIfNeeded changing the bounds of node,
- // then impact the visibility result, we need to adjust visibility before apply scale.
- adjustIsVisibleToUserIfNeeded(info, interactiveRegion);
- applyAppScaleAndMagnificationSpecIfNeeded(info, spec);
- callback.setFindAccessibilityNodeInfoResult(info, interactionId);
- } catch (RemoteException re) {
- /* ignore - the other side will time out */
- }
+ updateInfoForViewPort(info, spec, interactiveRegion);
+ returnFindNodeResult(info, callback, interactionId);
}
private boolean handleClickableSpanActionUiThread(
@@ -1053,20 +1105,11 @@
private final ArrayList<View> mTempViewList = new ArrayList<View>();
- public void prefetchAccessibilityNodeInfos(View view, int virtualViewId, int fetchFlags,
- List<AccessibilityNodeInfo> outInfos, Bundle arguments) {
- AccessibilityNodeProvider provider = view.getAccessibilityNodeProvider();
- // Determine if we'll be populating extra data
- final String extraDataRequested = (arguments == null) ? null
- : arguments.getString(EXTRA_DATA_REQUESTED_KEY);
- if (provider == null) {
- AccessibilityNodeInfo root = view.createAccessibilityNodeInfo();
- if (root != null) {
- if (extraDataRequested != null) {
- view.addExtraDataToAccessibilityNodeInfo(
- root, extraDataRequested, arguments);
- }
- outInfos.add(root);
+ public void prefetchAccessibilityNodeInfos(View view, AccessibilityNodeInfo root,
+ int virtualViewId, int fetchFlags, List<AccessibilityNodeInfo> outInfos) {
+ if (root != null) {
+ AccessibilityNodeProvider provider = view.getAccessibilityNodeProvider();
+ if (provider == null) {
if ((fetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_PREDECESSORS) != 0) {
prefetchPredecessorsOfRealNode(view, outInfos);
}
@@ -1076,16 +1119,7 @@
if ((fetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS) != 0) {
prefetchDescendantsOfRealNode(view, outInfos);
}
- }
- } else {
- final AccessibilityNodeInfo root =
- provider.createAccessibilityNodeInfo(virtualViewId);
- if (root != null) {
- if (extraDataRequested != null) {
- provider.addExtraDataToAccessibilityNodeInfo(
- virtualViewId, root, extraDataRequested, arguments);
- }
- outInfos.add(root);
+ } else {
if ((fetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_PREDECESSORS) != 0) {
prefetchPredecessorsOfVirtualNode(root, view, provider, outInfos);
}
@@ -1096,13 +1130,19 @@
prefetchDescendantsOfVirtualNode(root, provider, outInfos);
}
}
- }
- if (ENFORCE_NODE_TREE_CONSISTENT) {
- enforceNodeTreeConsistent(outInfos);
+ if (ENFORCE_NODE_TREE_CONSISTENT) {
+ enforceNodeTreeConsistent(root, outInfos);
+ }
}
}
- private void enforceNodeTreeConsistent(List<AccessibilityNodeInfo> nodes) {
+ private boolean shouldStopPrefetching(List prefetchededInfos) {
+ return mHandler.hasUserInteractiveMessagesWaiting()
+ || prefetchededInfos.size() >= MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE;
+ }
+
+ private void enforceNodeTreeConsistent(
+ AccessibilityNodeInfo root, List<AccessibilityNodeInfo> nodes) {
LongSparseArray<AccessibilityNodeInfo> nodeMap =
new LongSparseArray<AccessibilityNodeInfo>();
final int nodeCount = nodes.size();
@@ -1113,7 +1153,6 @@
// If the nodes are a tree it does not matter from
// which node we start to search for the root.
- AccessibilityNodeInfo root = nodeMap.valueAt(0);
AccessibilityNodeInfo parent = root;
while (parent != null) {
root = parent;
@@ -1180,9 +1219,11 @@
private void prefetchPredecessorsOfRealNode(View view,
List<AccessibilityNodeInfo> outInfos) {
+ if (shouldStopPrefetching(outInfos)) {
+ return;
+ }
ViewParent parent = view.getParentForAccessibility();
- while (parent instanceof View
- && outInfos.size() < MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
+ while (parent instanceof View && !shouldStopPrefetching(outInfos)) {
View parentView = (View) parent;
AccessibilityNodeInfo info = parentView.createAccessibilityNodeInfo();
if (info != null) {
@@ -1194,6 +1235,9 @@
private void prefetchSiblingsOfRealNode(View current,
List<AccessibilityNodeInfo> outInfos) {
+ if (shouldStopPrefetching(outInfos)) {
+ return;
+ }
ViewParent parent = current.getParentForAccessibility();
if (parent instanceof ViewGroup) {
ViewGroup parentGroup = (ViewGroup) parent;
@@ -1203,7 +1247,7 @@
parentGroup.addChildrenForAccessibility(children);
final int childCount = children.size();
for (int i = 0; i < childCount; i++) {
- if (outInfos.size() >= MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
+ if (shouldStopPrefetching(outInfos)) {
return;
}
View child = children.get(i);
@@ -1231,7 +1275,7 @@
private void prefetchDescendantsOfRealNode(View root,
List<AccessibilityNodeInfo> outInfos) {
- if (!(root instanceof ViewGroup)) {
+ if (shouldStopPrefetching(outInfos) || !(root instanceof ViewGroup)) {
return;
}
HashMap<View, AccessibilityNodeInfo> addedChildren =
@@ -1242,7 +1286,7 @@
root.addChildrenForAccessibility(children);
final int childCount = children.size();
for (int i = 0; i < childCount; i++) {
- if (outInfos.size() >= MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
+ if (shouldStopPrefetching(outInfos)) {
return;
}
View child = children.get(i);
@@ -1267,7 +1311,7 @@
} finally {
children.clear();
}
- if (outInfos.size() < MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
+ if (!shouldStopPrefetching(outInfos)) {
for (Map.Entry<View, AccessibilityNodeInfo> entry : addedChildren.entrySet()) {
View addedChild = entry.getKey();
AccessibilityNodeInfo virtualRoot = entry.getValue();
@@ -1289,7 +1333,7 @@
long parentNodeId = root.getParentNodeId();
int accessibilityViewId = AccessibilityNodeInfo.getAccessibilityViewId(parentNodeId);
while (accessibilityViewId != AccessibilityNodeInfo.UNDEFINED_ITEM_ID) {
- if (outInfos.size() >= MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
+ if (shouldStopPrefetching(outInfos)) {
return;
}
final int virtualDescendantId =
@@ -1334,7 +1378,7 @@
if (parent != null) {
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
- if (outInfos.size() >= MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
+ if (shouldStopPrefetching(outInfos)) {
return;
}
final long childNodeId = parent.getChildId(i);
@@ -1359,7 +1403,7 @@
final int initialOutInfosSize = outInfos.size();
final int childCount = root.getChildCount();
for (int i = 0; i < childCount; i++) {
- if (outInfos.size() >= MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
+ if (shouldStopPrefetching(outInfos)) {
return;
}
final long childNodeId = root.getChildId(i);
@@ -1369,7 +1413,7 @@
outInfos.add(child);
}
}
- if (outInfos.size() < MAX_ACCESSIBILITY_NODE_INFO_BATCH_SIZE) {
+ if (!shouldStopPrefetching(outInfos)) {
final int addedChildCount = outInfos.size() - initialOutInfosSize;
for (int i = 0; i < addedChildCount; i++) {
AccessibilityNodeInfo child = outInfos.get(initialOutInfosSize + i);
@@ -1478,6 +1522,10 @@
boolean hasAccessibilityCallback(Message message) {
return message.what < FIRST_NO_ACCESSIBILITY_CALLBACK_MSG ? true : false;
}
+
+ boolean hasUserInteractiveMessagesWaiting() {
+ return hasMessagesOrCallbacks();
+ }
}
private final class AddNodeInfosForViewId implements Predicate<View> {
diff --git a/core/java/android/view/ContentInfo.java b/core/java/android/view/ContentInfo.java
index fcf699f..bc66ea1 100644
--- a/core/java/android/view/ContentInfo.java
+++ b/core/java/android/view/ContentInfo.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.TestApi;
import android.content.ClipData;
import android.content.ClipDescription;
import android.net.Uri;
@@ -222,7 +223,10 @@
* content that matched the predicate, or null if none of the items matched. The pair's
* second object will have the content that didn't match the predicate, or null if all of
* the items matched.
+ *
+ * @hide
*/
+ @TestApi
@NonNull
public Pair<ContentInfo, ContentInfo> partition(
@NonNull Predicate<ClipData.Item> itemPredicate) {
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 0201605..0ac0305 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -325,6 +325,7 @@
&& rotation == other.rotation
&& modeId == other.modeId
&& defaultModeId == other.defaultModeId
+ && Arrays.equals(supportedModes, other.supportedModes)
&& colorMode == other.colorMode
&& Arrays.equals(supportedColorModes, other.supportedColorModes)
&& Objects.equals(hdrCapabilities, other.hdrCapabilities)
diff --git a/core/java/android/view/IRecentsAnimationController.aidl b/core/java/android/view/IRecentsAnimationController.aidl
index cac91a9..afbd249 100644
--- a/core/java/android/view/IRecentsAnimationController.aidl
+++ b/core/java/android/view/IRecentsAnimationController.aidl
@@ -20,6 +20,7 @@
import android.view.IRemoteAnimationFinishedCallback;
import android.graphics.GraphicBuffer;
import android.graphics.Rect;
+import android.window.TaskSnapshot;
/**
* Passed to the {@link IRecentsAnimationRunner} in order for the runner to control to let the
@@ -34,8 +35,7 @@
* Takes a screenshot of the task associated with the given {@param taskId}. Only valid for the
* current set of task ids provided to the handler.
*/
- @UnsupportedAppUsage
- ActivityManager.TaskSnapshot screenshotTask(int taskId);
+ TaskSnapshot screenshotTask(int taskId);
/**
* Sets the final bounds on a Task. This is used by Launcher to notify the system that
diff --git a/core/java/android/view/IRecentsAnimationRunner.aidl b/core/java/android/view/IRecentsAnimationRunner.aidl
index f054b86..8111755 100644
--- a/core/java/android/view/IRecentsAnimationRunner.aidl
+++ b/core/java/android/view/IRecentsAnimationRunner.aidl
@@ -20,6 +20,7 @@
import android.graphics.Rect;
import android.view.RemoteAnimationTarget;
import android.view.IRecentsAnimationController;
+import android.window.TaskSnapshot;
/**
* Interface that is used to callback from window manager to the process that runs a recents
@@ -42,8 +43,7 @@
*
* @see {@link RecentsAnimationController#cleanupScreenshot}
*/
- @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
- void onAnimationCanceled(in @nullable ActivityManager.TaskSnapshot taskSnapshot) = 1;
+ void onAnimationCanceled(in @nullable TaskSnapshot taskSnapshot) = 1;
/**
* Called when the system is ready for the handler to start animating all the visible tasks.
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index e685b30..fb012eb 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -130,11 +130,6 @@
void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId);
/**
- * Tell the window that it is either gaining or losing pointer capture.
- */
- void dispatchPointerCaptureChanged(boolean hasCapture);
-
- /**
* Called when Scroll Capture support is requested for a window.
*
* @param callbacks to receive responses
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index df96dc3..f4b90e1 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -22,6 +22,7 @@
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
+import android.hardware.SensorManager;
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.InputManager;
import android.os.Build;
@@ -71,13 +72,18 @@
private final boolean mHasVibrator;
private final boolean mHasMicrophone;
private final boolean mHasButtonUnderPad;
+ private final boolean mHasSensor;
private final ArrayList<MotionRange> mMotionRanges = new ArrayList<MotionRange>();
+ @GuardedBy("mMotionRanges")
private Vibrator mVibrator; // guarded by mMotionRanges during initialization
@GuardedBy("mMotionRanges")
private VibratorManager mVibratorManager;
+ @GuardedBy("mMotionRanges")
+ private SensorManager mSensorManager;
+
/**
* A mask for input source classes.
*
@@ -442,7 +448,7 @@
public InputDevice(int id, int generation, int controllerNumber, String name, int vendorId,
int productId, String descriptor, boolean isExternal, int sources, int keyboardType,
KeyCharacterMap keyCharacterMap, boolean hasVibrator, boolean hasMicrophone,
- boolean hasButtonUnderPad) {
+ boolean hasButtonUnderPad, boolean hasSensor) {
mId = id;
mGeneration = generation;
mControllerNumber = controllerNumber;
@@ -457,10 +463,12 @@
mHasVibrator = hasVibrator;
mHasMicrophone = hasMicrophone;
mHasButtonUnderPad = hasButtonUnderPad;
+ mHasSensor = hasSensor;
mIdentifier = new InputDeviceIdentifier(descriptor, vendorId, productId);
}
private InputDevice(Parcel in) {
+ mKeyCharacterMap = KeyCharacterMap.CREATOR.createFromParcel(in);
mId = in.readInt();
mGeneration = in.readInt();
mControllerNumber = in.readInt();
@@ -471,10 +479,10 @@
mIsExternal = in.readInt() != 0;
mSources = in.readInt();
mKeyboardType = in.readInt();
- mKeyCharacterMap = KeyCharacterMap.CREATOR.createFromParcel(in);
mHasVibrator = in.readInt() != 0;
mHasMicrophone = in.readInt() != 0;
mHasButtonUnderPad = in.readInt() != 0;
+ mHasSensor = in.readInt() != 0;
mIdentifier = new InputDeviceIdentifier(mDescriptor, mVendorId, mProductId);
int numRanges = in.readInt();
@@ -822,6 +830,26 @@
}
/**
+ * Gets the sensor manager service associated with the input device.
+ * Even if the device does not have a sensor, the result is never null.
+ * Use {@link SensorManager#getSensorList} to get a full list of all supported sensors.
+ *
+ * Note that the sensors associated with the device may be different from
+ * the system sensors, as typically they are builtin sensors physically attached to
+ * input devices.
+ *
+ * @return The sensor manager service associated with the device, never null.
+ */
+ public @NonNull SensorManager getSensorManager() {
+ synchronized (mMotionRanges) {
+ if (mSensorManager == null) {
+ mSensorManager = InputManager.getInstance().getInputDeviceSensorManager(mId);
+ }
+ }
+ return mSensorManager;
+ }
+
+ /**
* Returns true if input device is enabled.
* @return Whether the input device is enabled.
*/
@@ -869,6 +897,15 @@
}
/**
+ * Reports whether the device has a sensor.
+ * @return Whether the device has a sensor.
+ * @hide
+ */
+ public boolean hasSensor() {
+ return mHasSensor;
+ }
+
+ /**
* Sets the current pointer type.
* @param pointerType the type of the pointer icon.
* @hide
@@ -999,6 +1036,7 @@
@Override
public void writeToParcel(Parcel out, int flags) {
+ mKeyCharacterMap.writeToParcel(out, flags);
out.writeInt(mId);
out.writeInt(mGeneration);
out.writeInt(mControllerNumber);
@@ -1009,10 +1047,10 @@
out.writeInt(mIsExternal ? 1 : 0);
out.writeInt(mSources);
out.writeInt(mKeyboardType);
- mKeyCharacterMap.writeToParcel(out, flags);
out.writeInt(mHasVibrator ? 1 : 0);
out.writeInt(mHasMicrophone ? 1 : 0);
out.writeInt(mHasButtonUnderPad ? 1 : 0);
+ out.writeInt(mHasSensor ? 1 : 0);
final int numRanges = mMotionRanges.size();
out.writeInt(numRanges);
@@ -1057,6 +1095,8 @@
description.append(" Has Vibrator: ").append(mHasVibrator).append("\n");
+ description.append(" Has Sensor: ").append(mHasSensor).append("\n");
+
description.append(" Has mic: ").append(mHasMicrophone).append("\n");
description.append(" Sources: 0x").append(Integer.toHexString(mSources)).append(" (");
diff --git a/core/java/android/view/OWNERS b/core/java/android/view/OWNERS
index 72fa4c3..bae6ee8 100644
--- a/core/java/android/view/OWNERS
+++ b/core/java/android/view/OWNERS
@@ -47,11 +47,13 @@
per-file View.java = file:/graphics/java/android/graphics/OWNERS
per-file View.java = file:/services/core/java/com/android/server/input/OWNERS
per-file View.java = file:/services/core/java/com/android/server/wm/OWNERS
+per-file View.java = file:/core/java/android/view/inputmethod/OWNERS
per-file ViewRootImpl.java = file:/services/accessibility/OWNERS
per-file ViewRootImpl.java = file:/core/java/android/service/autofill/OWNERS
per-file ViewRootImpl.java = file:/graphics/java/android/graphics/OWNERS
per-file ViewRootImpl.java = file:/services/core/java/com/android/server/input/OWNERS
per-file ViewRootImpl.java = file:/services/core/java/com/android/server/wm/OWNERS
+per-file ViewRootImpl.java = file:/core/java/android/view/inputmethod/OWNERS
# WindowManager
per-file DisplayCutout.aidl = file:/services/core/java/com/android/server/wm/OWNERS
diff --git a/core/java/android/view/OnReceiveContentListener.java b/core/java/android/view/OnReceiveContentListener.java
index 419f964..3d9968c 100644
--- a/core/java/android/view/OnReceiveContentListener.java
+++ b/core/java/android/view/OnReceiveContentListener.java
@@ -36,7 +36,7 @@
* @Override
* public ContentInfo onReceiveContent(View view, ContentInfo payload) {
* Pair<ContentInfo, ContentInfo> split =
- * payload.partition(item -> item.getUri() != null);
+ * ContentInfoCompat.partition(payload, item -> item.getUri() != null);
* ContentInfo uriContent = split.first;
* ContentInfo remaining = split.second;
* if (uriContent != null) {
@@ -72,8 +72,7 @@
* handling. For example, an implementation may provide handling for content URIs (to provide
* support for inserting images, etc) and delegate the processing of text to the platform to
* preserve the common behavior for inserting text. See the class javadoc for a sample
- * implementation and see {@link ContentInfo#partition} for a convenient way to split the
- * passed-in content.
+ * implementation.
*
* <p>If implementing handling for text: if the view has a selection, the selection should
* be overwritten by the passed-in content; if there's no selection, the passed-in content
diff --git a/core/java/android/view/ScrollCaptureTargetResolver.java b/core/java/android/view/ScrollCaptureTargetResolver.java
index 5106534..e4316bb 100644
--- a/core/java/android/view/ScrollCaptureTargetResolver.java
+++ b/core/java/android/view/ScrollCaptureTargetResolver.java
@@ -182,9 +182,8 @@
}
mResult = chooseTarget(mResult, target);
boolean finish = mPendingBoundsRequests == 0
- || SystemClock.elapsedRealtime() >= mDeadlineMillis;
+ || SystemClock.uptimeMillis() >= mDeadlineMillis;
if (finish) {
- System.err.println("We think we're done, or timed out");
mPendingBoundsRequests = 0;
mWhenComplete.accept(mResult);
synchronized (mLock) {
@@ -233,7 +232,7 @@
for (ScrollCaptureTarget target : mTargets) {
queryTarget(target);
}
- mDeadlineMillis = SystemClock.elapsedRealtime() + mTimeLimitMillis;
+ mDeadlineMillis = SystemClock.uptimeMillis() + mTimeLimitMillis;
mHandler.postAtTime(mTimeoutRunnable, mDeadlineMillis);
}
@@ -275,7 +274,7 @@
mHandler.removeCallbacks(mTimeoutRunnable);
boolean doneOrTimedOut = mPendingBoundsRequests == 0
- || SystemClock.elapsedRealtime() >= mDeadlineMillis;
+ || SystemClock.uptimeMillis() >= mDeadlineMillis;
final View containingView = target.getContainingView();
if (!nullOrEmpty(scrollBounds) && containingView.isAggregatedVisible()) {
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 23de215..f642d75 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -232,6 +232,7 @@
long nativeSurfaceControl);
private static native void nativeRemoveJankDataListener(long nativeListener);
private static native long nativeCreateJankDataListenerWrapper(OnJankDataListener listener);
+ private static native int nativeGetGPUContextPriority();
@Nullable
@GuardedBy("mLock")
@@ -2438,7 +2439,15 @@
nativeRemoveJankDataListener(listener.mNativePtr.get());
}
- /**
+ /**
+ * Return GPU Context priority that is set in SurfaceFlinger's Render Engine.
+ * @hide
+ */
+ public static int getGPUContextPriority() {
+ return nativeGetGPUContextPriority();
+ }
+
+ /**
* An atomic set of changes to a set of SurfaceControl.
*/
public static class Transaction implements Closeable, Parcelable {
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 15adc5a..b5185ae 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -232,6 +232,7 @@
private final Matrix mTmpMatrix = new Matrix();
SurfaceControlViewHost.SurfacePackage mSurfacePackage;
+ private final boolean mUseBlastSync = false;
/**
* Returns {@code true} if buffers should be submitted via blast
@@ -239,7 +240,7 @@
private static boolean useBlastAdapter(Context context) {
ContentResolver contentResolver = context.getContentResolver();
return Settings.Global.getInt(contentResolver,
- Settings.Global.DEVELOPMENT_USE_BLAST_ADAPTER_SV, 0 /* default */) == 1;
+ Settings.Global.DEVELOPMENT_USE_BLAST_ADAPTER_SV, 1 /* default */) == 1;
}
private final boolean mUseBlastAdapter;
@@ -1922,6 +1923,6 @@
}
private boolean useBLASTSync(ViewRootImpl viewRoot) {
- return viewRoot.useBLAST() && mUseBlastAdapter;
+ return viewRoot.useBLAST() && mUseBlastAdapter && mUseBlastSync;
}
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 37c18b5..52ce5e7 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -4667,7 +4667,12 @@
if (mPointerCapture == enabled) {
return;
}
- InputManager.getInstance().requestPointerCapture(mAttachInfo.mWindowToken, enabled);
+ final IBinder inputToken = getInputToken();
+ if (inputToken == null) {
+ Log.e(mTag, "No input channel to request Pointer Capture.");
+ return;
+ }
+ InputManager.getInstance().requestPointerCapture(inputToken, enabled);
}
private void handlePointerCaptureChanged(boolean hasCapture) {
@@ -8381,6 +8386,11 @@
}
@Override
+ public void onPointerCaptureEvent(boolean pointerCaptureEnabled) {
+ dispatchPointerCaptureChanged(pointerCaptureEnabled);
+ }
+
+ @Override
public void dispose() {
unscheduleConsumeBatchedInput();
super.dispose();
@@ -8655,7 +8665,7 @@
MSG_REQUEST_KEYBOARD_SHORTCUTS, deviceId, 0, receiver).sendToTarget();
}
- public void dispatchPointerCaptureChanged(boolean on) {
+ private void dispatchPointerCaptureChanged(boolean on) {
final int what = MSG_POINTER_CAPTURE_CHANGED;
mHandler.removeMessages(what);
Message msg = mHandler.obtainMessage(what);
@@ -9428,14 +9438,6 @@
}
@Override
- public void dispatchPointerCaptureChanged(boolean hasCapture) {
- final ViewRootImpl viewAncestor = mViewAncestor.get();
- if (viewAncestor != null) {
- viewAncestor.dispatchPointerCaptureChanged(hasCapture);
- }
- }
-
- @Override
public void requestScrollCapture(IScrollCaptureCallbacks callbacks) {
final ViewRootImpl viewAncestor = mViewAncestor.get();
if (viewAncestor != null) {
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index f63749b..aff0b35 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -23,7 +23,9 @@
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
+import android.os.Handler;
import android.os.IBinder;
+import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
@@ -123,6 +125,12 @@
private Message mSameThreadMessage;
+ private int mInteractionIdWaitingForPrefetchResult;
+ private int mConnectionIdWaitingForPrefetchResult;
+ private String[] mPackageNamesForNextPrefetchResult;
+ private final Handler mMainHandler;
+ private Runnable mPrefetchResultRunnable;
+
/**
* @return The client for the current thread.
*/
@@ -197,6 +205,7 @@
private AccessibilityInteractionClient() {
/* reducing constructor visibility */
+ mMainHandler = new Handler(Looper.getMainLooper());
}
/**
@@ -451,16 +460,16 @@
Binder.restoreCallingIdentity(identityToken);
}
if (packageNames != null) {
- List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear(
- interactionId);
- finalizeAndCacheAccessibilityNodeInfos(infos, connectionId,
- bypassCache, packageNames);
- if (infos != null && !infos.isEmpty()) {
- for (int i = 1; i < infos.size(); i++) {
- infos.get(i).recycle();
- }
- return infos.get(0);
+ AccessibilityNodeInfo info =
+ getFindAccessibilityNodeInfoResultAndClear(interactionId);
+ if ((prefetchFlags & AccessibilityNodeInfo.FLAG_PREFETCH_MASK) != 0
+ && info != null) {
+ setInteractionWaitingForPrefetchResult(interactionId, connectionId,
+ packageNames);
}
+ finalizeAndCacheAccessibilityNodeInfo(info, connectionId,
+ bypassCache, packageNames);
+ return info;
}
} else {
if (DEBUG) {
@@ -474,6 +483,15 @@
return null;
}
+ private void setInteractionWaitingForPrefetchResult(int interactionId, int connectionId,
+ String[] packageNames) {
+ synchronized (mInstanceLock) {
+ mInteractionIdWaitingForPrefetchResult = interactionId;
+ mConnectionIdWaitingForPrefetchResult = connectionId;
+ mPackageNamesForNextPrefetchResult = packageNames;
+ }
+ }
+
private static String idToString(int accessibilityWindowId, long accessibilityNodeId) {
return accessibilityWindowId + "/"
+ AccessibilityNodeInfo.idToString(accessibilityNodeId);
@@ -829,6 +847,26 @@
}
/**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setPrefetchAccessibilityNodeInfoResult(List<AccessibilityNodeInfo> infos,
+ int interactionId) {
+ synchronized (mInstanceLock) {
+ if (mPrefetchResultRunnable != null) {
+ mMainHandler.removeCallbacks(mPrefetchResultRunnable);
+ mPrefetchResultRunnable = null;
+ }
+ if (!infos.isEmpty() && mInteractionIdWaitingForPrefetchResult == interactionId) {
+ mPrefetchResultRunnable = () -> finalizeAndCacheAccessibilityNodeInfos(
+ infos, mConnectionIdWaitingForPrefetchResult, false,
+ mPackageNamesForNextPrefetchResult);
+ mMainHandler.post(mPrefetchResultRunnable);
+ }
+ }
+ }
+
+ /**
* Gets the result of a request to perform an accessibility action.
*
* @param interactionId The interaction id to match the result with the request.
diff --git a/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl b/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl
index 049bb31..231e75a 100644
--- a/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl
@@ -47,6 +47,15 @@
int interactionId);
/**
+ * Sets the result of a prefetch request that returns {@link AccessibilityNodeInfo}s.
+ *
+ * @param root The {@link AccessibilityNodeInfo} for which the prefetching is based off of.
+ * @param infos The result {@link AccessibilityNodeInfo}s.
+ */
+ void setPrefetchAccessibilityNodeInfoResult(
+ in List<AccessibilityNodeInfo> infos, int interactionId);
+
+ /**
* Sets the result of a request to perform an accessibility action.
*
* @param Whether the action was performed.
diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java
index 7dbf693..1cf25a7 100644
--- a/core/java/android/view/inputmethod/EditorInfo.java
+++ b/core/java/android/view/inputmethod/EditorInfo.java
@@ -28,6 +28,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.content.res.Configuration;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.os.LocaleList;
@@ -293,6 +294,13 @@
public static final int IME_FLAG_FORCE_ASCII = 0x80000000;
/**
+ * Flag of {@link #internalImeOptions}: flag is set when app window containing this
+ * {@link EditorInfo} is using {@link Configuration#ORIENTATION_PORTRAIT} mode.
+ * @hide
+ */
+ public static final int IME_FLAG_APP_WINDOW_PORTRAIT = 0x80000000;
+
+ /**
* Generic unspecified type for {@link #imeOptions}.
*/
public static final int IME_NULL = 0x00000000;
@@ -312,6 +320,7 @@
* 1 1 IME_ACTION_NEXT
* 11 IME_ACTION_DONE
* 111 IME_ACTION_PREVIOUS
+ * 1 IME_FLAG_APP_WINDOW_PORTRAIT
* 1 IME_FLAG_NO_PERSONALIZED_LEARNING
* 1 IME_FLAG_NO_FULLSCREEN
* 1 IME_FLAG_NAVIGATE_PREVIOUS
@@ -343,6 +352,20 @@
public String privateImeOptions = null;
/**
+ * Masks for {@link internalImeOptions}
+ *
+ * <pre>
+ * 1 IME_FLAG_APP_WINDOW_PORTRAIT
+ * |-------|-------|-------|-------|</pre>
+ */
+
+ /**
+ * Same as {@link android.R.attr#imeOptions} but for framework's internal-use only.
+ * @hide
+ */
+ public int internalImeOptions = IME_NULL;
+
+ /**
* In some cases an IME may be able to display an arbitrary label for
* a command the user can perform, which you can specify here. This is
* typically used as the label for the action to use in-line as a replacement
diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java
index 14b5d7c..8c81143 100644
--- a/core/java/android/view/inputmethod/InputConnection.java
+++ b/core/java/android/view/inputmethod/InputConnection.java
@@ -858,6 +858,20 @@
boolean reportFullscreenMode(boolean enabled);
/**
+ * Have the editor perform spell checking around the current selection.
+ *
+ * <p>The editor can ignore this method call if it does not support spell checking.
+ *
+ * @return For editor authors, the return value will always be ignored. For IME authors, this
+ * method returns true if the spell check request was sent (whether or not the
+ * associated editor supports spell checking), false if the input connection is no
+ * longer valid.
+ */
+ default boolean performSpellCheck() {
+ return false;
+ }
+
+ /**
* API to send private commands from an input method to its
* connected editor. This can be used to provide domain-specific
* features that are only known between certain input methods and
diff --git a/core/java/android/view/inputmethod/InputConnectionWrapper.java b/core/java/android/view/inputmethod/InputConnectionWrapper.java
index 77956d1..ca85348 100644
--- a/core/java/android/view/inputmethod/InputConnectionWrapper.java
+++ b/core/java/android/view/inputmethod/InputConnectionWrapper.java
@@ -287,6 +287,15 @@
* @throws NullPointerException if the target is {@code null}.
*/
@Override
+ public boolean performSpellCheck() {
+ return mTarget.performSpellCheck();
+ }
+
+ /**
+ * {@inheritDoc}
+ * @throws NullPointerException if the target is {@code null}.
+ */
+ @Override
public boolean performPrivateCommand(String action, Bundle data) {
return mTarget.performPrivateCommand(action, data);
}
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index eaf72dc..c7c00cb 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1430,8 +1430,13 @@
public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(InputMethodInfo imi,
boolean allowsImplicitlySelectedSubtypes) {
try {
- return mService.getEnabledInputMethodSubtypeList(
- imi == null ? null : imi.getId(), allowsImplicitlySelectedSubtypes);
+ final Completable.InputMethodSubtypeList value =
+ Completable.createInputMethodSubtypeList();
+ mService.getEnabledInputMethodSubtypeList(
+ imi == null ? null : imi.getId(),
+ allowsImplicitlySelectedSubtypes,
+ ResultCallbacks.of(value));
+ return Completable.getResult(value);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1747,8 +1752,14 @@
try {
Log.d(TAG, "showSoftInput() view=" + view + " flags=" + flags);
- return mService.showSoftInput(
- mClient, view.getWindowToken(), flags, resultReceiver);
+ final Completable.Boolean value = Completable.createBoolean();
+ mService.showSoftInput(
+ mClient,
+ view.getWindowToken(),
+ flags,
+ resultReceiver,
+ ResultCallbacks.of(value));
+ return Completable.getResult(value);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1775,8 +1786,14 @@
Log.w(TAG, "No current root view, ignoring showSoftInputUnchecked()");
return;
}
+ final Completable.Boolean value = Completable.createBoolean();
mService.showSoftInput(
- mClient, mCurRootView.getView().getWindowToken(), flags, resultReceiver);
+ mClient,
+ mCurRootView.getView().getWindowToken(),
+ flags,
+ resultReceiver,
+ ResultCallbacks.of(value));
+ Completable.getResult(value); // ignore the result
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1849,7 +1866,10 @@
}
try {
- return mService.hideSoftInput(mClient, windowToken, flags, resultReceiver);
+ final Completable.Boolean value = Completable.createBoolean();
+ mService.hideSoftInput(
+ mClient, windowToken, flags, resultReceiver, ResultCallbacks.of(value));
+ return Completable.getResult(value);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2184,8 +2204,14 @@
return;
}
try {
+ final Completable.Boolean value = Completable.createBoolean();
mService.hideSoftInput(
- mClient, mCurRootView.getView().getWindowToken(), HIDE_NOT_ALWAYS, null);
+ mClient,
+ mCurRootView.getView().getWindowToken(),
+ HIDE_NOT_ALWAYS,
+ null,
+ ResultCallbacks.of(value));
+ Completable.getResult(value); // ignore the result
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2920,7 +2946,9 @@
@TestApi
public boolean isInputMethodPickerShown() {
try {
- return mService.isInputMethodPickerShownForTest();
+ final Completable.Boolean value = Completable.createBoolean();
+ mService.isInputMethodPickerShownForTest(ResultCallbacks.of(value));
+ return Completable.getResult(value);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2947,7 +2975,9 @@
*/
public InputMethodSubtype getCurrentInputMethodSubtype() {
try {
- return mService.getCurrentInputMethodSubtype();
+ final Completable.InputMethodSubtype value = Completable.createInputMethodSubtype();
+ mService.getCurrentInputMethodSubtype(ResultCallbacks.of(value));
+ return Completable.getResult(value);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2996,7 +3026,11 @@
}
final List<InputMethodSubtype> enabledSubtypes;
try {
- enabledSubtypes = mService.getEnabledInputMethodSubtypeList(imeId, true);
+ final Completable.InputMethodSubtypeList value =
+ Completable.createInputMethodSubtypeList();
+ mService.getEnabledInputMethodSubtypeList(
+ imeId, true, ResultCallbacks.of(value));
+ enabledSubtypes = Completable.getResult(value);
} catch (RemoteException e) {
return false;
}
@@ -3191,7 +3225,9 @@
public InputMethodSubtype getLastInputMethodSubtype() {
try {
- return mService.getLastInputMethodSubtype();
+ final Completable.InputMethodSubtype value = Completable.createInputMethodSubtype();
+ mService.getLastInputMethodSubtype(ResultCallbacks.of(value));
+ return Completable.getResult(value);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/view/textservice/SuggestionsInfo.java b/core/java/android/view/textservice/SuggestionsInfo.java
index ca529f6..1301c49 100644
--- a/core/java/android/view/textservice/SuggestionsInfo.java
+++ b/core/java/android/view/textservice/SuggestionsInfo.java
@@ -53,6 +53,16 @@
*/
public static final int RESULT_ATTR_LOOKS_LIKE_GRAMMAR_ERROR = 0x0008;
+ /**
+ * Flag of the attributes of the suggestions that can be obtained by
+ * {@link #getSuggestionsAttributes}: this tells that the text service has an alternative way to
+ * show UI for the list of correction suggestions to the user. When this flag is set, the
+ * receiver of the result suggestions should mark the erroneous part of the text with a text
+ * signifier (for example, underline), but should not show any UI for the list of correction
+ * suggestions to the user (for example, in a popup window).
+ */
+ public static final int RESULT_ATTR_DONT_SHOW_UI_FOR_SUGGESTIONS = 0x0010;
+
private final int mSuggestionsAttributes;
private final String[] mSuggestions;
private final boolean mSuggestionsAvailable;
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index 0611bea..b06fa1a 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -215,6 +215,27 @@
spellCheck();
}
+ void onPerformSpellCheck() {
+ final int selectionStart = mTextView.getSelectionStart();
+ final int selectionEnd = mTextView.getSelectionEnd();
+ final int selectionRangeStart;
+ final int selectionRangeEnd;
+ if (selectionStart < selectionEnd) {
+ selectionRangeStart = selectionStart;
+ selectionRangeEnd = selectionEnd;
+ } else {
+ selectionRangeStart = selectionEnd;
+ selectionRangeEnd = selectionStart;
+ }
+ // Expand the range so that it (hopefully) includes the current sentence.
+ final int start = Math.max(0, selectionRangeStart - MIN_SENTENCE_LENGTH);
+ final int end = Math.min(mTextView.length(), selectionRangeEnd + MIN_SENTENCE_LENGTH);
+ if (DBG) {
+ Log.d(TAG, "performSpellCheckAroundSelection: " + start + ", " + end);
+ }
+ spellCheck(start, end);
+ }
+
public void spellCheck(int start, int end) {
if (DBG) {
Log.d(TAG, "Start spell-checking: " + start + ", " + end);
@@ -456,6 +477,8 @@
mTextView.postDelayed(mSpellRunnable, SPELL_PAUSE_DURATION);
}
+ // When calling this method, RESULT_ATTR_LOOKS_LIKE_TYPO or RESULT_ATTR_LOOKS_LIKE_GRAMMAR_ERROR
+ // (or both) should be set in suggestionsInfo.
private void createMisspelledSuggestionSpan(Editable editable, SuggestionsInfo suggestionsInfo,
SpellCheckSpan spellCheckSpan, int offset, int length) {
final int spellCheckSpanStart = editable.getSpanStart(spellCheckSpan);
@@ -485,7 +508,10 @@
}
final int suggestionsAttrs = suggestionsInfo.getSuggestionsAttributes();
- int flags = SuggestionSpan.FLAG_EASY_CORRECT;
+ int flags = 0;
+ if ((suggestionsAttrs & SuggestionsInfo.RESULT_ATTR_DONT_SHOW_UI_FOR_SUGGESTIONS) == 0) {
+ flags |= SuggestionSpan.FLAG_EASY_CORRECT;
+ }
if ((suggestionsAttrs & SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO) != 0) {
flags |= SuggestionSpan.FLAG_MISSPELLED;
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 02a9300..977a0e8 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -17,6 +17,7 @@
package android.widget;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.view.ContentInfo.FLAG_CONVERT_TO_PLAIN_TEXT;
import static android.view.ContentInfo.SOURCE_AUTOFILL;
import static android.view.ContentInfo.SOURCE_CLIPBOARD;
@@ -8738,6 +8739,9 @@
outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_ENTER_ACTION;
}
}
+ if (getResources().getConfiguration().orientation == ORIENTATION_PORTRAIT) {
+ outAttrs.internalImeOptions |= EditorInfo.IME_FLAG_APP_WINDOW_PORTRAIT;
+ }
if (isMultilineInputType(outAttrs.inputType)) {
// Multi-line text editors should always show an enter key.
outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_ENTER_ACTION;
@@ -8913,6 +8917,13 @@
// intentionally empty
}
+ /** @hide */
+ public void onPerformSpellCheck() {
+ if (mEditor != null && mEditor.mSpellChecker != null) {
+ mEditor.mSpellChecker.onPerformSpellCheck();
+ }
+ }
+
/**
* Called by the framework in response to a private command from the
* current method, provided by it calling
@@ -13736,8 +13747,12 @@
* custom behavior should configure a listener via {@link #setOnReceiveContentListener}.
*
* <p>For non-editable TextViews the default behavior is a no-op (returns the passed-in
- * content without acting on it). For editable TextViews the default behavior coerces all
- * content to text and inserts into the view.
+ * content without acting on it).
+ *
+ * <p>For editable TextViews the default behavior is to insert text into the view, coercing
+ * non-text content to text as needed. The MIME types "text/plain" and "text/html" have
+ * well-defined behavior for this, while other MIME types have reasonable fallback behavior
+ * (see {@link ClipData.Item#coerceToStyledText}).
*
* @param payload The content to insert and related metadata.
*
diff --git a/core/java/android/window/DisplayAreaOrganizer.java b/core/java/android/window/DisplayAreaOrganizer.java
index 8a1d4a0..1254647 100644
--- a/core/java/android/window/DisplayAreaOrganizer.java
+++ b/core/java/android/window/DisplayAreaOrganizer.java
@@ -164,15 +164,19 @@
}
/**
- * Creates a persistent task display area. It will be added to be the top most task display area
- * in the root.
+ * Creates a persistent {@link com.android.server.wm.TaskDisplayArea}.
*
* The new created TDA is organized by the organizer, and will be deleted on calling
* {@link #deleteTaskDisplayArea(WindowContainerToken)} or {@link #unregisterOrganizer()}.
*
- * @param displayId the display to create the new task display area in.
- * @param rootFeatureId the root display area to create the new task display area in. Caller can
- * use {@link #FEATURE_ROOT} as the root of the logical display.
+ * @param displayId the display to create the new TDA in.
+ * @param parentFeatureId the parent to create the new TDA in. If it is a
+ * {@link com.android.server.wm.RootDisplayArea}, the new TDA will be
+ * placed as the topmost TDA. If it is another TDA, the new TDA will be
+ * placed as the topmost child.
+ * Caller can use {@link #FEATURE_ROOT} as the root of the logical
+ * display, or {@link #FEATURE_DEFAULT_TASK_CONTAINER} as the default
+ * TDA.
* @param name the name for the new task display area.
* @return the new created task display area.
* @throws IllegalArgumentException if failed to create a new task display area.
@@ -181,11 +185,11 @@
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
@CallSuper
@NonNull
- public DisplayAreaAppearedInfo createTaskDisplayArea(int displayId, int rootFeatureId,
+ public DisplayAreaAppearedInfo createTaskDisplayArea(int displayId, int parentFeatureId,
@NonNull String name) {
try {
return getController().createTaskDisplayArea(
- mInterface, displayId, rootFeatureId, name);
+ mInterface, displayId, parentFeatureId, name);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/window/IDisplayAreaOrganizerController.aidl b/core/java/android/window/IDisplayAreaOrganizerController.aidl
index 26fa434..6c097bb 100644
--- a/core/java/android/window/IDisplayAreaOrganizerController.aidl
+++ b/core/java/android/window/IDisplayAreaOrganizerController.aidl
@@ -40,21 +40,25 @@
void unregisterOrganizer(in IDisplayAreaOrganizer organizer);
/**
- * Creates a persistent task display area. It will be added to be the top most task display area
- * in the root.
+ * Creates a persistent {@link com.android.server.wm.TaskDisplayArea}.
*
* The new created TDA is organized by the organizer, and will be deleted on calling
* {@link #deleteTaskDisplayArea(WindowContainerToken)} or {@link #unregisterOrganizer()}.
*
- * @param displayId the display to create the new task display area in.
- * @param rootFeatureId the root display area to create the new task display area in. Caller can
- * use {@link #FEATURE_ROOT} as the root of the logical display.
+ * @param displayId the display to create the new TDA in.
+ * @param parentFeatureId the parent to create the new TDA in. If it is a
+ * {@link com.android.server.wm.RootDisplayArea}, the new TDA will be
+ * placed as the topmost TDA. If it is another TDA, the new TDA will be
+ * placed as the topmost child.
+ * Caller can use {@link #FEATURE_ROOT} as the root of the logical
+ * display, or {@link #FEATURE_DEFAULT_TASK_CONTAINER} as the default
+ * TDA.
* @param name the name for the new task display area.
* @return the new created task display area.
* @throws IllegalArgumentException if failed to create a new task display area.
*/
DisplayAreaAppearedInfo createTaskDisplayArea(in IDisplayAreaOrganizer organizer, int displayId,
- int rootFeatureId, in String name);
+ int parentFeatureId, in String name);
/**
* Deletes a persistent task display area. It can only be one that created by an organizer.
diff --git a/core/java/android/window/ITaskOrganizer.aidl b/core/java/android/window/ITaskOrganizer.aidl
index b503184..88b2257 100644
--- a/core/java/android/window/ITaskOrganizer.aidl
+++ b/core/java/android/window/ITaskOrganizer.aidl
@@ -18,6 +18,7 @@
import android.view.SurfaceControl;
import android.app.ActivityManager;
+import android.window.StartingWindowInfo;
import android.window.WindowContainerToken;
/**
@@ -30,15 +31,15 @@
* application is starting. The client is responsible to add/remove the starting window if it
* has create a starting window for the Task.
*
- * @param taskInfo The information about the Task that's available
+ * @param info The information about the Task that's available
* @param appToken Token of the application being started.
*/
- void addStartingWindow(in ActivityManager.RunningTaskInfo taskInfo, IBinder appToken);
+ void addStartingWindow(in StartingWindowInfo info, IBinder appToken);
/**
* Called when the Task want to remove the starting window.
*/
- void removeStartingWindow(in ActivityManager.RunningTaskInfo taskInfo);
+ void removeStartingWindow(int taskId);
/**
* A callback when the Task is available for the registered organizer. The client is responsible
diff --git a/core/java/android/window/StartingWindowInfo.aidl b/core/java/android/window/StartingWindowInfo.aidl
new file mode 100644
index 0000000..69b18f0
--- /dev/null
+++ b/core/java/android/window/StartingWindowInfo.aidl
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.window;
+
+/** @hide */
+parcelable StartingWindowInfo;
\ No newline at end of file
diff --git a/core/java/android/window/StartingWindowInfo.java b/core/java/android/window/StartingWindowInfo.java
new file mode 100644
index 0000000..2282cc5
--- /dev/null
+++ b/core/java/android/window/StartingWindowInfo.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.window;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.TestApi;
+import android.app.ActivityManager;
+import android.app.TaskInfo;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.view.InsetsState;
+import android.view.WindowManager;
+
+/**
+ * Information you can retrieve about a starting window of a particular task that is currently
+ * start in the system.
+ * @hide
+ */
+@TestApi
+public final class StartingWindowInfo implements Parcelable {
+ /**
+ * The {@link TaskInfo} from this task.
+ * @hide
+ */
+ @NonNull
+ public ActivityManager.RunningTaskInfo taskInfo;
+
+ /**
+ * InsetsState of TopFullscreenOpaqueWindow
+ * @hide
+ */
+ @Nullable
+ public InsetsState topOpaqueWindowInsetsState;
+
+ /**
+ * LayoutParams of TopFullscreenOpaqueWindow
+ * @hide
+ */
+ @Nullable
+ public WindowManager.LayoutParams topOpaqueWindowLayoutParams;
+
+ /**
+ * LayoutParams of MainWindow
+ * @hide
+ */
+ @Nullable
+ public WindowManager.LayoutParams mainWindowLayoutParams;
+
+ /**
+ * @hide
+ */
+ @IntDef(flag = true, prefix = "TYPE_PARAMETER_", value = {
+ TYPE_PARAMETER_NEW_TASK,
+ TYPE_PARAMETER_TASK_SWITCH,
+ TYPE_PARAMETER_PROCESS_RUNNING,
+ TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT,
+ TYPE_PARAMETER_ACTIVITY_CREATED
+ })
+ public @interface StartingTypeParams {}
+
+ /**
+ * The parameters of the starting window...
+ * @hide
+ */
+ public static final int TYPE_PARAMETER_NEW_TASK = 0x00000001;
+ /** @hide */
+ public static final int TYPE_PARAMETER_TASK_SWITCH = 0x00000002;
+ /** @hide */
+ public static final int TYPE_PARAMETER_PROCESS_RUNNING = 0x00000004;
+ /** @hide */
+ public static final int TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT = 0x00000008;
+ /** @hide */
+ public static final int TYPE_PARAMETER_ACTIVITY_CREATED = 0x00000010;
+
+ /**
+ * The parameters which effect the starting window type.
+ * @see android.window.StartingWindowInfo.StartingTypeParams
+ * @hide
+ */
+ public int startingWindowTypeParameter;
+
+ public StartingWindowInfo() {
+
+ }
+
+ private StartingWindowInfo(@NonNull Parcel source) {
+ readFromParcel(source);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeTypedObject(taskInfo, flags);
+ dest.writeInt(startingWindowTypeParameter);
+ dest.writeTypedObject(topOpaqueWindowInsetsState, flags);
+ dest.writeTypedObject(topOpaqueWindowLayoutParams, flags);
+ dest.writeTypedObject(mainWindowLayoutParams, flags);
+ }
+
+ void readFromParcel(@NonNull Parcel source) {
+ taskInfo = source.readTypedObject(ActivityManager.RunningTaskInfo.CREATOR);
+ startingWindowTypeParameter = source.readInt();
+ topOpaqueWindowInsetsState = source.readTypedObject(InsetsState.CREATOR);
+ topOpaqueWindowLayoutParams = source.readTypedObject(
+ WindowManager.LayoutParams.CREATOR);
+ mainWindowLayoutParams = source.readTypedObject(WindowManager.LayoutParams.CREATOR);
+ }
+
+ @Override
+ public String toString() {
+ return "StartingWindowInfo{taskId=" + taskInfo.taskId
+ + " displayId=" + taskInfo.displayId
+ + " topActivityType=" + taskInfo.topActivityType
+ + " preferredStartingWindowType="
+ + Integer.toHexString(startingWindowTypeParameter)
+ + " insetsState=" + topOpaqueWindowInsetsState
+ + " topWindowLayoutParams=" + topOpaqueWindowLayoutParams
+ + " mainWindowLayoutParams=" + mainWindowLayoutParams;
+ }
+
+ public static final @android.annotation.NonNull Creator<StartingWindowInfo> CREATOR =
+ new Creator<StartingWindowInfo>() {
+ public StartingWindowInfo createFromParcel(@NonNull Parcel source) {
+ return new StartingWindowInfo(source);
+ }
+ public StartingWindowInfo[] newArray(int size) {
+ return new StartingWindowInfo[size];
+ }
+ };
+}
diff --git a/core/java/android/window/TaskOrganizer.java b/core/java/android/window/TaskOrganizer.java
index 12c4b5b..73b2fe1 100644
--- a/core/java/android/window/TaskOrganizer.java
+++ b/core/java/android/window/TaskOrganizer.java
@@ -89,19 +89,19 @@
* application is starting. The client is responsible to add/remove the starting window if it
* has create a starting window for the Task.
*
- * @param taskInfo The information about the Task that's available
+ * @param info The information about the Task that's available
* @param appToken Token of the application being started.
* context to for resources
*/
@BinderThread
- public void addStartingWindow(@NonNull ActivityManager.RunningTaskInfo taskInfo,
+ public void addStartingWindow(@NonNull StartingWindowInfo info,
@NonNull IBinder appToken) {}
/**
* Called when the Task want to remove the starting window.
*/
@BinderThread
- public void removeStartingWindow(@NonNull ActivityManager.RunningTaskInfo taskInfo) {}
+ public void removeStartingWindow(int taskId) {}
/**
* Called when a task with the registered windowing mode can be controlled by this task
@@ -221,13 +221,15 @@
private final ITaskOrganizer mInterface = new ITaskOrganizer.Stub() {
@Override
- public void addStartingWindow(ActivityManager.RunningTaskInfo taskInfo, IBinder appToken) {
- mExecutor.execute(() -> TaskOrganizer.this.addStartingWindow(taskInfo, appToken));
+
+ public void addStartingWindow(StartingWindowInfo windowInfo,
+ IBinder appToken) {
+ mExecutor.execute(() -> TaskOrganizer.this.addStartingWindow(windowInfo, appToken));
}
@Override
- public void removeStartingWindow(ActivityManager.RunningTaskInfo taskInfo) {
- mExecutor.execute(() -> TaskOrganizer.this.removeStartingWindow(taskInfo));
+ public void removeStartingWindow(int taskId) {
+ mExecutor.execute(() -> TaskOrganizer.this.removeStartingWindow(taskId));
}
@Override
diff --git a/core/java/android/window/TaskSnapshot.aidl b/core/java/android/window/TaskSnapshot.aidl
new file mode 100644
index 0000000..4f0eb7f
--- /dev/null
+++ b/core/java/android/window/TaskSnapshot.aidl
@@ -0,0 +1,4 @@
+package android.window;
+
+/** @hide */
+parcelable TaskSnapshot;
\ No newline at end of file
diff --git a/core/java/android/window/TaskSnapshot.java b/core/java/android/window/TaskSnapshot.java
new file mode 100644
index 0000000..9834aad
--- /dev/null
+++ b/core/java/android/window/TaskSnapshot.java
@@ -0,0 +1,385 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.window;
+
+import android.annotation.NonNull;
+import android.compat.annotation.UnsupportedAppUsage;
+import android.content.ComponentName;
+import android.content.res.Configuration;
+import android.graphics.ColorSpace;
+import android.graphics.GraphicBuffer;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.hardware.HardwareBuffer;
+import android.os.Build;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.view.Surface;
+import android.view.WindowInsetsController;
+
+/**
+ * Represents a task snapshot.
+ * @hide
+ */
+public class TaskSnapshot implements Parcelable {
+ // Identifier of this snapshot
+ private final long mId;
+ // Top activity in task when snapshot was taken
+ private final ComponentName mTopActivityComponent;
+ private final HardwareBuffer mSnapshot;
+ /** Indicates whether task was in landscape or portrait */
+ @Configuration.Orientation
+ private final int mOrientation;
+ /** See {@link android.view.Surface.Rotation} */
+ @Surface.Rotation
+ private int mRotation;
+ /** The size of the snapshot before scaling */
+ private final Point mTaskSize;
+ private final Rect mContentInsets;
+ // Whether this snapshot is a down-sampled version of the high resolution snapshot, used
+ // mainly for loading snapshots quickly from disk when user is flinging fast
+ private final boolean mIsLowResolution;
+ // Whether or not the snapshot is a real snapshot or an app-theme generated snapshot due to
+ // the task having a secure window or having previews disabled
+ private final boolean mIsRealSnapshot;
+ private final int mWindowingMode;
+ private final @WindowInsetsController.Appearance
+ int mAppearance;
+ private final boolean mIsTranslucent;
+ // Must be one of the named color spaces, otherwise, always use SRGB color space.
+ private final ColorSpace mColorSpace;
+
+ public TaskSnapshot(long id,
+ @NonNull ComponentName topActivityComponent, HardwareBuffer snapshot,
+ @NonNull ColorSpace colorSpace, int orientation, int rotation, Point taskSize,
+ Rect contentInsets, boolean isLowResolution, boolean isRealSnapshot,
+ int windowingMode, @WindowInsetsController.Appearance int appearance,
+ boolean isTranslucent) {
+ mId = id;
+ mTopActivityComponent = topActivityComponent;
+ mSnapshot = snapshot;
+ mColorSpace = colorSpace.getId() < 0
+ ? ColorSpace.get(ColorSpace.Named.SRGB) : colorSpace;
+ mOrientation = orientation;
+ mRotation = rotation;
+ mTaskSize = new Point(taskSize);
+ mContentInsets = new Rect(contentInsets);
+ mIsLowResolution = isLowResolution;
+ mIsRealSnapshot = isRealSnapshot;
+ mWindowingMode = windowingMode;
+ mAppearance = appearance;
+ mIsTranslucent = isTranslucent;
+ }
+
+ private TaskSnapshot(Parcel source) {
+ mId = source.readLong();
+ mTopActivityComponent = ComponentName.readFromParcel(source);
+ mSnapshot = source.readParcelable(null /* classLoader */);
+ int colorSpaceId = source.readInt();
+ mColorSpace = colorSpaceId >= 0 && colorSpaceId < ColorSpace.Named.values().length
+ ? ColorSpace.get(ColorSpace.Named.values()[colorSpaceId])
+ : ColorSpace.get(ColorSpace.Named.SRGB);
+ mOrientation = source.readInt();
+ mRotation = source.readInt();
+ mTaskSize = source.readParcelable(null /* classLoader */);
+ mContentInsets = source.readParcelable(null /* classLoader */);
+ mIsLowResolution = source.readBoolean();
+ mIsRealSnapshot = source.readBoolean();
+ mWindowingMode = source.readInt();
+ mAppearance = source.readInt();
+ mIsTranslucent = source.readBoolean();
+ }
+
+ /**
+ * @return Identifier of this snapshot.
+ */
+ public long getId() {
+ return mId;
+ }
+
+ /**
+ * @return The top activity component for the task at the point this snapshot was taken.
+ */
+ public ComponentName getTopActivityComponent() {
+ return mTopActivityComponent;
+ }
+
+ /**
+ * @return The graphic buffer representing the screenshot.
+ *
+ * Note: Prefer {@link #getHardwareBuffer}, which returns the internal object. This version
+ * creates a new object.
+ */
+ @UnsupportedAppUsage
+ public GraphicBuffer getSnapshot() {
+ return GraphicBuffer.createFromHardwareBuffer(mSnapshot);
+ }
+
+ /**
+ * @return The hardware buffer representing the screenshot.
+ */
+ public HardwareBuffer getHardwareBuffer() {
+ return mSnapshot;
+ }
+
+ /**
+ * @return The color space of hardware buffer representing the screenshot.
+ */
+ public ColorSpace getColorSpace() {
+ return mColorSpace;
+ }
+
+ /**
+ * @return The screen orientation the screenshot was taken in.
+ */
+ @UnsupportedAppUsage
+ public int getOrientation() {
+ return mOrientation;
+ }
+
+ /**
+ * @return The screen rotation the screenshot was taken in.
+ */
+ public int getRotation() {
+ return mRotation;
+ }
+
+ /**
+ * @return The size of the task at the point this snapshot was taken.
+ */
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ public Point getTaskSize() {
+ return mTaskSize;
+ }
+
+ /**
+ * @return The system/content insets on the snapshot. These can be clipped off in order to
+ * remove any areas behind system bars in the snapshot.
+ */
+ @UnsupportedAppUsage
+ public Rect getContentInsets() {
+ return mContentInsets;
+ }
+
+ /**
+ * @return Whether this snapshot is a down-sampled version of the full resolution.
+ */
+ @UnsupportedAppUsage
+ public boolean isLowResolution() {
+ return mIsLowResolution;
+ }
+
+ /**
+ * @return Whether or not the snapshot is a real snapshot or an app-theme generated snapshot
+ * due to the task having a secure window or having previews disabled.
+ */
+ @UnsupportedAppUsage
+ public boolean isRealSnapshot() {
+ return mIsRealSnapshot;
+ }
+
+ /**
+ * @return Whether or not the snapshot is of a translucent app window (non-fullscreen or has
+ * a non-opaque pixel format).
+ */
+ public boolean isTranslucent() {
+ return mIsTranslucent;
+ }
+
+ /**
+ * @return The windowing mode of the task when this snapshot was taken.
+ */
+ public int getWindowingMode() {
+ return mWindowingMode;
+ }
+
+ /**
+ * @return The {@link WindowInsetsController.Appearance} flags for the top most visible
+ * fullscreen window at the time that the snapshot was taken.
+ */
+ public @WindowInsetsController.Appearance
+ int getAppearance() {
+ return mAppearance;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeLong(mId);
+ ComponentName.writeToParcel(mTopActivityComponent, dest);
+ dest.writeParcelable(mSnapshot != null && !mSnapshot.isClosed() ? mSnapshot : null,
+ 0);
+ dest.writeInt(mColorSpace.getId());
+ dest.writeInt(mOrientation);
+ dest.writeInt(mRotation);
+ dest.writeParcelable(mTaskSize, 0);
+ dest.writeParcelable(mContentInsets, 0);
+ dest.writeBoolean(mIsLowResolution);
+ dest.writeBoolean(mIsRealSnapshot);
+ dest.writeInt(mWindowingMode);
+ dest.writeInt(mAppearance);
+ dest.writeBoolean(mIsTranslucent);
+ }
+
+ @Override
+ public String toString() {
+ final int width = mSnapshot != null ? mSnapshot.getWidth() : 0;
+ final int height = mSnapshot != null ? mSnapshot.getHeight() : 0;
+ return "TaskSnapshot{"
+ + " mId=" + mId
+ + " mTopActivityComponent=" + mTopActivityComponent.flattenToShortString()
+ + " mSnapshot=" + mSnapshot + " (" + width + "x" + height + ")"
+ + " mColorSpace=" + mColorSpace.toString()
+ + " mOrientation=" + mOrientation
+ + " mRotation=" + mRotation
+ + " mTaskSize=" + mTaskSize.toString()
+ + " mContentInsets=" + mContentInsets.toShortString()
+ + " mIsLowResolution=" + mIsLowResolution
+ + " mIsRealSnapshot=" + mIsRealSnapshot
+ + " mWindowingMode=" + mWindowingMode
+ + " mAppearance=" + mAppearance
+ + " mIsTranslucent=" + mIsTranslucent;
+ }
+
+ public static final @NonNull Creator<TaskSnapshot> CREATOR = new Creator<TaskSnapshot>() {
+ public TaskSnapshot createFromParcel(Parcel source) {
+ return new TaskSnapshot(source);
+ }
+ public TaskSnapshot[] newArray(int size) {
+ return new TaskSnapshot[size];
+ }
+ };
+
+ /** Builder for a {@link TaskSnapshot} object */
+ public static final class Builder {
+ private long mId;
+ private ComponentName mTopActivity;
+ private HardwareBuffer mSnapshot;
+ private ColorSpace mColorSpace;
+ private int mOrientation;
+ private int mRotation;
+ private Point mTaskSize;
+ private Rect mContentInsets;
+ private boolean mIsRealSnapshot;
+ private int mWindowingMode;
+ private @WindowInsetsController.Appearance
+ int mAppearance;
+ private boolean mIsTranslucent;
+ private int mPixelFormat;
+
+ public Builder setId(long id) {
+ mId = id;
+ return this;
+ }
+
+ public Builder setTopActivityComponent(
+ ComponentName name) {
+ mTopActivity = name;
+ return this;
+ }
+
+ public Builder setSnapshot(HardwareBuffer buffer) {
+ mSnapshot = buffer;
+ return this;
+ }
+
+ public Builder setColorSpace(ColorSpace colorSpace) {
+ mColorSpace = colorSpace;
+ return this;
+ }
+
+ public Builder setOrientation(int orientation) {
+ mOrientation = orientation;
+ return this;
+ }
+
+ public Builder setRotation(int rotation) {
+ mRotation = rotation;
+ return this;
+ }
+
+ /**
+ * Sets the original size of the task
+ */
+ public Builder setTaskSize(Point size) {
+ mTaskSize = size;
+ return this;
+ }
+
+ public Builder setContentInsets(Rect contentInsets) {
+ mContentInsets = contentInsets;
+ return this;
+ }
+
+ public Builder setIsRealSnapshot(
+ boolean realSnapshot) {
+ mIsRealSnapshot = realSnapshot;
+ return this;
+ }
+
+ public Builder setWindowingMode(int windowingMode) {
+ mWindowingMode = windowingMode;
+ return this;
+ }
+
+ public Builder setAppearance(
+ @WindowInsetsController.Appearance int appearance) {
+ mAppearance = appearance;
+ return this;
+ }
+
+ public Builder setIsTranslucent(
+ boolean isTranslucent) {
+ mIsTranslucent = isTranslucent;
+ return this;
+ }
+
+ public int getPixelFormat() {
+ return mPixelFormat;
+ }
+
+ public Builder setPixelFormat(int pixelFormat) {
+ mPixelFormat = pixelFormat;
+ return this;
+ }
+
+ public TaskSnapshot build() {
+ return new TaskSnapshot(
+ mId,
+ mTopActivity,
+ mSnapshot,
+ mColorSpace,
+ mOrientation,
+ mRotation,
+ mTaskSize,
+ mContentInsets,
+ // When building a TaskSnapshot with the Builder class, isLowResolution
+ // is always false. Low-res snapshots are only created when loading from
+ // disk.
+ false /* isLowResolution */,
+ mIsRealSnapshot,
+ mWindowingMode,
+ mAppearance,
+ mIsTranslucent);
+
+ }
+ }
+}
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index ea458a1..e064137 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -28,6 +28,7 @@
import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityManager;
+import android.app.SharedElementCallback;
import android.app.prediction.AppPredictionContext;
import android.app.prediction.AppPredictionManager;
import android.app.prediction.AppPredictor;
@@ -176,6 +177,13 @@
public static final String EXTRA_PRIVATE_RETAIN_IN_ON_STOP
= "com.android.internal.app.ChooserActivity.EXTRA_PRIVATE_RETAIN_IN_ON_STOP";
+ /**
+ * Transition name for the first image preview.
+ * To be used for shared element transition into this activity.
+ * @hide
+ */
+ public static final String FIRST_IMAGE_PREVIEW_TRANSITION_NAME = "chooser_preview_image_1";
+
private static final String PREF_NUM_SHEET_EXPANSIONS = "pref_num_sheet_expansions";
private static final String CHIP_LABEL_METADATA_KEY = "android.service.chooser.chip_label";
@@ -307,6 +315,8 @@
@VisibleForTesting
protected ChooserMultiProfilePagerAdapter mChooserMultiProfilePagerAdapter;
+ private boolean mRemoveSharedElements = false;
+
private class ContentPreviewCoordinator {
private static final int IMAGE_FADE_IN_MILLIS = 150;
private static final int IMAGE_LOAD_TIMEOUT = 1;
@@ -370,10 +380,29 @@
if (task.mExtraCount > 0) {
imageView.setExtraImageCount(task.mExtraCount);
}
+
+ setupPreDrawForSharedElementTransition(imageView);
}
}
};
+ private void setupPreDrawForSharedElementTransition(View v) {
+ v.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ v.getViewTreeObserver().removeOnPreDrawListener(this);
+
+ if (!mRemoveSharedElements && isActivityTransitionRunning()) {
+ // Disable the window animations as it interferes with the
+ // transition animation.
+ getWindow().setWindowAnimations(0);
+ }
+ startPostponedEnterTransition();
+ return true;
+ }
+ });
+ }
+
ContentPreviewCoordinator(View parentView, boolean hideParentOnFail) {
super();
@@ -413,6 +442,8 @@
}
mHideParentOnFail = false;
}
+ mRemoveSharedElements = true;
+ startPostponedEnterTransition();
}
private void collapseParentView() {
@@ -794,6 +825,19 @@
);
mDirectShareShortcutInfoCache = new HashMap<>();
mChooserTargetComponentNameCache = new HashMap<>();
+
+ setEnterSharedElementCallback(new SharedElementCallback() {
+ @Override
+ public void onMapSharedElements(List<String> names, Map<String, View> sharedElements) {
+ if (mRemoveSharedElements) {
+ names.remove(FIRST_IMAGE_PREVIEW_TRANSITION_NAME);
+ sharedElements.remove(FIRST_IMAGE_PREVIEW_TRANSITION_NAME);
+ }
+ super.onMapSharedElements(names, sharedElements);
+ mRemoveSharedElements = false;
+ }
+ });
+ postponeEnterTransition();
}
@Override
@@ -1337,6 +1381,8 @@
String action = targetIntent.getAction();
if (Intent.ACTION_SEND.equals(action)) {
Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM);
+ imagePreview.findViewById(R.id.content_preview_image_1_large)
+ .setTransitionName(ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME);
mPreviewCoord.loadUriIntoView(R.id.content_preview_image_1_large, uri, 0);
} else {
ContentResolver resolver = getContentResolver();
@@ -1356,6 +1402,8 @@
return contentPreviewLayout;
}
+ imagePreview.findViewById(R.id.content_preview_image_1_large)
+ .setTransitionName(ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME);
mPreviewCoord.loadUriIntoView(R.id.content_preview_image_1_large, imageUris.get(0), 0);
if (imageUris.size() == 2) {
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 0b047a2..7a30ee2 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -20,6 +20,7 @@
import android.bluetooth.BluetoothActivityEnergyInfo;
import android.os.BatteryUsageStats;
+import android.os.BatteryUsageStatsQuery;
import android.os.ParcelFileDescriptor;
import android.os.WorkSource;
import android.os.connectivity.CellularBatteryStats;
@@ -51,7 +52,7 @@
// Remaining methods are only used in Java.
- BatteryUsageStats getBatteryUsageStats();
+ BatteryUsageStats getBatteryUsageStats(in BatteryUsageStatsQuery query);
@UnsupportedAppUsage
byte[] getStatistics();
diff --git a/core/java/com/android/internal/inputmethod/CallbackUtils.java b/core/java/com/android/internal/inputmethod/CallbackUtils.java
index a315e5a..f72d0e6 100644
--- a/core/java/com/android/internal/inputmethod/CallbackUtils.java
+++ b/core/java/com/android/internal/inputmethod/CallbackUtils.java
@@ -19,9 +19,12 @@
import android.annotation.AnyThread;
import android.annotation.NonNull;
import android.os.RemoteException;
+import android.view.inputmethod.InputMethodSubtype;
import com.android.internal.view.InputBindResult;
+import java.util.List;
+import java.util.function.BooleanSupplier;
import java.util.function.Supplier;
/**
@@ -62,4 +65,84 @@
callback.onResult(result);
} catch (RemoteException ignored) { }
}
+
+ /**
+ * A utility method using given {@link IBooleanResultCallback} to callback the result.
+ *
+ * @param callback {@link IBooleanResultCallback} to be called back.
+ * @param resultSupplier the supplier from which the result is provided.
+ */
+ public static void onResult(@NonNull IBooleanResultCallback callback,
+ @NonNull BooleanSupplier resultSupplier) {
+ boolean result = false;
+ Throwable exception = null;
+
+ try {
+ result = resultSupplier.getAsBoolean();
+ } catch (Throwable throwable) {
+ exception = throwable;
+ }
+
+ try {
+ if (exception != null) {
+ callback.onError(ThrowableHolder.of(exception));
+ return;
+ }
+ callback.onResult(result);
+ } catch (RemoteException ignored) { }
+ }
+
+ /**
+ * A utility method using given {@link IInputMethodSubtypeResultCallback} to callback the
+ * result.
+ *
+ * @param callback {@link IInputMethodSubtypeResultCallback} to be called back.
+ * @param resultSupplier the supplier from which the result is provided.
+ */
+ public static void onResult(@NonNull IInputMethodSubtypeResultCallback callback,
+ @NonNull Supplier<InputMethodSubtype> resultSupplier) {
+ InputMethodSubtype result = null;
+ Throwable exception = null;
+
+ try {
+ result = resultSupplier.get();
+ } catch (Throwable throwable) {
+ exception = throwable;
+ }
+
+ try {
+ if (exception != null) {
+ callback.onError(ThrowableHolder.of(exception));
+ return;
+ }
+ callback.onResult(result);
+ } catch (RemoteException ignored) { }
+ }
+
+ /**
+ * A utility method using given {@link IInputMethodSubtypeListResultCallback} to callback the
+ * result.
+ *
+ * @param callback {@link IInputMethodSubtypeListResultCallback} to be called back.
+ * @param resultSupplier the supplier from which the result is provided.
+ */
+ public static void onResult(@NonNull IInputMethodSubtypeListResultCallback callback,
+ @NonNull Supplier<List<InputMethodSubtype>> resultSupplier) {
+ List<InputMethodSubtype> result = null;
+ Throwable exception = null;
+
+ try {
+ result = resultSupplier.get();
+ } catch (Throwable throwable) {
+ exception = throwable;
+ }
+
+ try {
+ if (exception != null) {
+ callback.onError(ThrowableHolder.of(exception));
+ return;
+ }
+ callback.onResult(result);
+ } catch (RemoteException ignored) { }
+ }
}
diff --git a/core/java/com/android/internal/inputmethod/Completable.java b/core/java/com/android/internal/inputmethod/Completable.java
index bd8c23e..8196536 100644
--- a/core/java/com/android/internal/inputmethod/Completable.java
+++ b/core/java/com/android/internal/inputmethod/Completable.java
@@ -23,10 +23,12 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.util.Log;
+import android.view.inputmethod.InputMethodSubtype;
import com.android.internal.annotations.GuardedBy;
import java.lang.annotation.Retention;
+import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -373,6 +375,20 @@
}
/**
+ * @return an instance of {@link Completable.InputMethodSubtype}.
+ */
+ public static Completable.InputMethodSubtype createInputMethodSubtype() {
+ return new Completable.InputMethodSubtype();
+ }
+
+ /**
+ * @return an instance of {@link Completable.InputMethodSubtypeList}.
+ */
+ public static Completable.InputMethodSubtypeList createInputMethodSubtypeList() {
+ return new Completable.InputMethodSubtypeList();
+ }
+
+ /**
* Completable object of {@link java.lang.Boolean}.
*/
public static final class Boolean extends Values<java.lang.Boolean> { }
@@ -401,6 +417,18 @@
extends Values<com.android.internal.view.InputBindResult> { }
/**
+ * Completable object of {@link android.view.inputmethod.InputMethodSubtype}.
+ */
+ public static final class InputMethodSubtype
+ extends Values<android.view.inputmethod.InputMethodSubtype> { }
+
+ /**
+ * Completable object of {@link List<android.view.inputmethod.InputMethodSubtype>}.
+ */
+ public static final class InputMethodSubtypeList
+ extends Values<List<android.view.inputmethod.InputMethodSubtype>> { }
+
+ /**
* Await the result by the {@link Completable.Values}.
*
* @return the result once {@link ValueBase#onComplete()}
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java b/core/java/com/android/internal/inputmethod/IBooleanResultCallback.aidl
similarity index 62%
copy from media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java
copy to core/java/com/android/internal/inputmethod/IBooleanResultCallback.aidl
index 52f2787..6daeb3f 100644
--- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java
+++ b/core/java/com/android/internal/inputmethod/IBooleanResultCallback.aidl
@@ -14,19 +14,11 @@
* limitations under the License.
*/
-package com.android.mediatranscodingtest;
+package com.android.internal.inputmethod;
-/**
- *
- * This class has the names of the all the activity name and variables in the
- * instrumentation test.
- *
- */
-public class MediaConstants {
- /*
- * Source test files.
- */
- public static final String[] SOURCE_HEVC_VIDEO_ONLY_TEST_FILES = {
- "/sdcard/media_api/video/VideoOnlyHEVC.mp4",
- };
-}
+import com.android.internal.inputmethod.ThrowableHolder;
+
+oneway interface IBooleanResultCallback {
+ void onResult(boolean result);
+ void onError(in ThrowableHolder exception);
+}
\ No newline at end of file
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java b/core/java/com/android/internal/inputmethod/IInputMethodSubtypeListResultCallback.aidl
similarity index 62%
copy from media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java
copy to core/java/com/android/internal/inputmethod/IInputMethodSubtypeListResultCallback.aidl
index 52f2787..619c87e 100644
--- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java
+++ b/core/java/com/android/internal/inputmethod/IInputMethodSubtypeListResultCallback.aidl
@@ -14,19 +14,12 @@
* limitations under the License.
*/
-package com.android.mediatranscodingtest;
+package com.android.internal.inputmethod;
-/**
- *
- * This class has the names of the all the activity name and variables in the
- * instrumentation test.
- *
- */
-public class MediaConstants {
- /*
- * Source test files.
- */
- public static final String[] SOURCE_HEVC_VIDEO_ONLY_TEST_FILES = {
- "/sdcard/media_api/video/VideoOnlyHEVC.mp4",
- };
-}
+import android.view.inputmethod.InputMethodSubtype;
+import com.android.internal.inputmethod.ThrowableHolder;
+
+oneway interface IInputMethodSubtypeListResultCallback {
+ void onResult(in List<InputMethodSubtype> result);
+ void onError(in ThrowableHolder exception);
+}
\ No newline at end of file
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java b/core/java/com/android/internal/inputmethod/IInputMethodSubtypeResultCallback.aidl
similarity index 62%
copy from media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java
copy to core/java/com/android/internal/inputmethod/IInputMethodSubtypeResultCallback.aidl
index 52f2787..66c0902 100644
--- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java
+++ b/core/java/com/android/internal/inputmethod/IInputMethodSubtypeResultCallback.aidl
@@ -14,19 +14,12 @@
* limitations under the License.
*/
-package com.android.mediatranscodingtest;
+package com.android.internal.inputmethod;
-/**
- *
- * This class has the names of the all the activity name and variables in the
- * instrumentation test.
- *
- */
-public class MediaConstants {
- /*
- * Source test files.
- */
- public static final String[] SOURCE_HEVC_VIDEO_ONLY_TEST_FILES = {
- "/sdcard/media_api/video/VideoOnlyHEVC.mp4",
- };
-}
+import android.view.inputmethod.InputMethodSubtype;
+import com.android.internal.inputmethod.ThrowableHolder;
+
+oneway interface IInputMethodSubtypeResultCallback {
+ void onResult(in InputMethodSubtype result);
+ void onError(in ThrowableHolder exception);
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/inputmethod/ResultCallbacks.java b/core/java/com/android/internal/inputmethod/ResultCallbacks.java
index 1929b6f..8d95f29 100644
--- a/core/java/com/android/internal/inputmethod/ResultCallbacks.java
+++ b/core/java/com/android/internal/inputmethod/ResultCallbacks.java
@@ -20,10 +20,12 @@
import android.annotation.BinderThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.view.inputmethod.InputMethodSubtype;
import com.android.internal.view.InputBindResult;
import java.lang.ref.WeakReference;
+import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
/**
@@ -193,4 +195,113 @@
}
};
}
+
+ /**
+ * Creates {@link IBooleanResultCallback.Stub} that is to set {@link Completable.Boolean} when
+ * receiving the result.
+ *
+ * @param value {@link Completable.Boolean} to be set when receiving the result.
+ * @return {@link IBooleanResultCallback.Stub} that can be passed as a binder IPC parameter.
+ */
+ @AnyThread
+ public static IBooleanResultCallback.Stub of(@NonNull Completable.Boolean value) {
+ final AtomicReference<WeakReference<Completable.Boolean>>
+ atomicRef = new AtomicReference<>(new WeakReference<>(value));
+
+ return new IBooleanResultCallback.Stub() {
+ @BinderThread
+ @Override
+ public void onResult(boolean result) {
+ final Completable.Boolean value = unwrap(atomicRef);
+ if (value == null) {
+ return;
+ }
+ value.onComplete(result);
+ }
+
+ @BinderThread
+ @Override
+ public void onError(ThrowableHolder throwableHolder) {
+ final Completable.Boolean value = unwrap(atomicRef);
+ if (value == null) {
+ return;
+ }
+ value.onError(throwableHolder);
+ }
+ };
+ }
+
+ /**
+ * Creates {@link IInputMethodSubtypeResultCallback.Stub} that is to set
+ * {@link Completable.InputMethodSubtype} when receiving the result.
+ *
+ * @param value {@link Completable.InputMethodSubtype} to be set when receiving the result.
+ * @return {@link IInputMethodSubtypeResultCallback.Stub} that can be passed as a binder
+ * IPC parameter.
+ */
+ @AnyThread
+ public static IInputMethodSubtypeResultCallback.Stub of(
+ @NonNull Completable.InputMethodSubtype value) {
+ final AtomicReference<WeakReference<Completable.InputMethodSubtype>>
+ atomicRef = new AtomicReference<>(new WeakReference<>(value));
+
+ return new IInputMethodSubtypeResultCallback.Stub() {
+ @BinderThread
+ @Override
+ public void onResult(InputMethodSubtype result) {
+ final Completable.InputMethodSubtype value = unwrap(atomicRef);
+ if (value == null) {
+ return;
+ }
+ value.onComplete(result);
+ }
+
+ @BinderThread
+ @Override
+ public void onError(ThrowableHolder throwableHolder) {
+ final Completable.InputMethodSubtype value = unwrap(atomicRef);
+ if (value == null) {
+ return;
+ }
+ value.onError(throwableHolder);
+ }
+ };
+ }
+
+ /**
+ * Creates {@link IInputMethodSubtypeListResultCallback.Stub} that is to set
+ * {@link Completable.InputMethodSubtypeList} when receiving the result.
+ *
+ * @param value {@link Completable.InputMethodSubtypeList} to be set when receiving the result.
+ * @return {@link IInputMethodSubtypeListResultCallback.Stub} that can be passed as a binder
+ * IPC parameter.
+ */
+ @AnyThread
+ public static IInputMethodSubtypeListResultCallback.Stub of(
+ @NonNull Completable.InputMethodSubtypeList value) {
+ final AtomicReference<WeakReference<Completable.InputMethodSubtypeList>>
+ atomicRef = new AtomicReference<>(new WeakReference<>(value));
+
+ return new IInputMethodSubtypeListResultCallback.Stub() {
+ @BinderThread
+ @Override
+ public void onResult(List<InputMethodSubtype> result) {
+ final Completable.InputMethodSubtypeList value = unwrap(atomicRef);
+ if (value == null) {
+ return;
+ }
+ value.onComplete(result);
+ }
+
+ @BinderThread
+ @Override
+ public void onError(ThrowableHolder throwableHolder) {
+ final Completable.InputMethodSubtypeList value = unwrap(atomicRef);
+ if (value == null) {
+ return;
+ }
+ value.onError(throwableHolder);
+ }
+ };
+ }
}
diff --git a/core/java/com/android/internal/net/NetworkUtilsInternal.java b/core/java/com/android/internal/net/NetworkUtilsInternal.java
new file mode 100644
index 0000000..571d7e7
--- /dev/null
+++ b/core/java/com/android/internal/net/NetworkUtilsInternal.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.net;
+
+import static android.system.OsConstants.AF_INET;
+import static android.system.OsConstants.AF_INET6;
+
+import android.annotation.NonNull;
+import android.system.Os;
+
+/** @hide */
+public class NetworkUtilsInternal {
+
+ private static final int[] ADDRESS_FAMILIES = new int[] {AF_INET, AF_INET6};
+
+ /**
+ * Allow/Disallow creating AF_INET/AF_INET6 sockets and DNS lookups for current process.
+ *
+ * @param allowNetworking whether to allow or disallow creating AF_INET/AF_INET6 sockets
+ * and DNS lookups.
+ */
+ public static native void setAllowNetworkingForProcess(boolean allowNetworking);
+
+ /**
+ * Returns true if the hostname is weakly validated.
+ * @param hostname Name of host to validate.
+ * @return True if it's a valid-ish hostname.
+ *
+ * @hide
+ */
+ public static boolean isWeaklyValidatedHostname(@NonNull String hostname) {
+ // TODO(b/34953048): Use a validation method that permits more accurate,
+ // but still inexpensive, checking of likely valid DNS hostnames.
+ final String weakHostnameRegex = "^[a-zA-Z0-9_.-]+$";
+ if (!hostname.matches(weakHostnameRegex)) {
+ return false;
+ }
+
+ for (int address_family : ADDRESS_FAMILIES) {
+ if (Os.inet_pton(address_family, hostname) != null) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Safely multiple a value by a rational.
+ * <p>
+ * Internally it uses integer-based math whenever possible, but switches
+ * over to double-based math if values would overflow.
+ * @hide
+ */
+ public static long multiplySafeByRational(long value, long num, long den) {
+ if (den == 0) {
+ throw new ArithmeticException("Invalid Denominator");
+ }
+ long x = value;
+ long y = num;
+
+ // Logic shamelessly borrowed from Math.multiplyExact()
+ long r = x * y;
+ long ax = Math.abs(x);
+ long ay = Math.abs(y);
+ if (((ax | ay) >>> 31 != 0)) {
+ // Some bits greater than 2^31 that might cause overflow
+ // Check the result using the divide operator
+ // and check for the special case of Long.MIN_VALUE * -1
+ if (((y != 0) && (r / y != x))
+ || (x == Long.MIN_VALUE && y == -1)) {
+ // Use double math to avoid overflowing
+ return (long) (((double) num / den) * value);
+ }
+ }
+ return r / den;
+ }
+}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 4476e7e..0fa0df6 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -19,6 +19,7 @@
import static android.os.BatteryStatsManager.NUM_WIFI_STATES;
import static android.os.BatteryStatsManager.NUM_WIFI_SUPPL_STATES;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
@@ -32,6 +33,7 @@
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.hardware.usb.UsbManager;
+import android.location.GnssSignalQuality;
import android.net.ConnectivityManager;
import android.net.INetworkStatsService;
import android.net.NetworkStats;
@@ -97,13 +99,13 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.location.gnssmetrics.GnssMetrics;
import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidActiveTimeReader;
import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidClusterTimeReader;
import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader;
import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader;
import com.android.internal.power.MeasuredEnergyArray;
import com.android.internal.power.MeasuredEnergyStats;
+import com.android.internal.power.MeasuredEnergyStats.EnergyBucket;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.FrameworkStatsLog;
@@ -121,6 +123,8 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
@@ -166,7 +170,7 @@
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- static final int VERSION = 190 + (USE_OLD_HISTORY ? 1000 : 0);
+ static final int VERSION = 191 + (USE_OLD_HISTORY ? 1000 : 0);
// The maximum number of names wakelocks we will keep track of
// per uid; once the limit is reached, we batch the remaining wakelocks
@@ -644,9 +648,22 @@
int UPDATE_RADIO = 0x04;
int UPDATE_BT = 0x08;
int UPDATE_RPM = 0x10;
- int UPDATE_ENERGY = 0x20;
+ int UPDATE_DISPLAY = 0x20;
int UPDATE_ALL =
- UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT | UPDATE_RPM | UPDATE_ENERGY;
+ UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT | UPDATE_RPM | UPDATE_DISPLAY;
+
+ @IntDef(flag = true, prefix = "UPDATE_", value = {
+ UPDATE_CPU,
+ UPDATE_WIFI,
+ UPDATE_RADIO,
+ UPDATE_BT,
+ UPDATE_RPM,
+ UPDATE_DISPLAY,
+ UPDATE_ALL,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ExternalUpdateFlag {
+ }
Future<?> scheduleSync(String reason, int flags);
Future<?> scheduleCpuSyncDueToRemovedUid(int uid);
@@ -827,6 +844,13 @@
int mStartCount;
+ /**
+ * Set to true when a reset occurs, informing us that the next time BatteryExternalStatsWorker
+ * gives us data, we mustn't process it since this data includes pre-reset-period data.
+ */
+ @GuardedBy("this")
+ boolean mIgnoreNextExternalStats = false;
+
long mStartClockTimeMs;
String mStartPlatformVersion;
String mEndPlatformVersion;
@@ -895,7 +919,7 @@
int mGpsSignalQualityBin = -1;
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
protected final StopwatchTimer[] mGpsSignalQualityTimer =
- new StopwatchTimer[GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS];
+ new StopwatchTimer[GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS];
int mPhoneSignalStrengthBin = -1;
int mPhoneSignalStrengthBinRaw = -1;
@@ -929,7 +953,8 @@
/**
* The Bluetooth controller activity (time in tx, rx, idle, and power consumed) for the device.
*/
- ControllerActivityCounterImpl mBluetoothActivity;
+ @VisibleForTesting
+ protected ControllerActivityCounterImpl mBluetoothActivity;
/**
* The Modem controller activity (time in tx, rx, idle, and power consumed) for the device.
@@ -987,11 +1012,15 @@
int mWifiRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
/**
- * Accumulated energy consumption of various consumers while on battery.
- * If energy consumer data is unavailable this will be null.
+ * Accumulated energy consumption, that is not attributed to individual uids, of various
+ * consumers while on battery.
+ * If energy consumer data is completely unavailable this will be null.
*/
@GuardedBy("this")
- MeasuredEnergyStats mBatteryMeasuredEnergyStats;
+ @VisibleForTesting
+ protected @Nullable MeasuredEnergyStats mGlobalMeasuredEnergyStats;
+ /** Last known screen state. Needed for apportioning display energy. */
+ int mScreenStateAtLastEnergyMeasurement = Display.STATE_UNKNOWN;
/**
* These provide time bases that discount the time the device is plugged
@@ -1078,6 +1107,16 @@
private long[] mCpuFreqs;
/**
+ * Times spent by the system server process grouped by cluster and CPU speed.
+ */
+ private LongSamplingCounterArray mSystemServerCpuTimesUs;
+
+ /**
+ * Times spent by the system server threads grouped by cluster and CPU speed.
+ */
+ private LongSamplingCounterArray mSystemServerThreadCpuTimesUs;
+
+ /**
* Times spent by the system server threads handling incoming binder requests.
*/
private LongSamplingCounterArray mBinderThreadCpuTimesUs;
@@ -5049,7 +5088,7 @@
if (mGpsNesting == 0) {
return;
}
- if (signalLevel < 0 || signalLevel >= GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS) {
+ if (signalLevel < 0 || signalLevel >= mGpsSignalQualityTimer.length) {
stopAllGpsSignalQualityTimersLocked(-1, elapsedRealtimeMs);
return;
}
@@ -5145,14 +5184,11 @@
+ Display.stateToString(state));
addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
}
- int updateFlag = ExternalStatsSync.UPDATE_CPU;
- if (mBatteryMeasuredEnergyStats != null && mBatteryMeasuredEnergyStats.hasSubsystem(
- MeasuredEnergyArray.SUBSYSTEM_DISPLAY)) {
- updateFlag |= ExternalStatsSync.UPDATE_ENERGY;
- }
+ // TODO: (Probably overkill) Have mGlobalMeasuredEnergyStats store supported flags and
+ // only update DISPLAY if it is. Currently overkill since CPU is scheduled anyway.
+ final int updateFlag = ExternalStatsSync.UPDATE_CPU | ExternalStatsSync.UPDATE_DISPLAY;
mExternalSync.scheduleSyncDueToScreenStateChange(updateFlag,
- mOnBatteryTimeBase.isRunning(), mOnBatteryScreenOffTimeBase.isRunning(),
- mScreenState);
+ mOnBatteryTimeBase.isRunning(), mOnBatteryScreenOffTimeBase.isRunning(), state);
if (Display.isOnState(state)) {
updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), state,
uptimeMs * 1000, elapsedRealtimeMs * 1000);
@@ -5460,7 +5496,7 @@
}
void stopAllGpsSignalQualityTimersLocked(int except, long elapsedRealtimeMs) {
- for (int i = 0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+ for (int i = 0; i < mGpsSignalQualityTimer.length; i++) {
if (i == except) {
continue;
}
@@ -6911,7 +6947,7 @@
@Override public long getGpsSignalQualityTime(int strengthBin,
long elapsedRealtimeUs, int which) {
- if (strengthBin < 0 || strengthBin >= GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS) {
+ if (strengthBin < 0 || strengthBin >= mGpsSignalQualityTimer.length) {
return 0;
}
return mGpsSignalQualityTimer[strengthBin].getTotalTimeLocked(
@@ -6927,7 +6963,7 @@
double energyUsedMaMs = 0.0;
final int which = STATS_SINCE_CHARGED;
final long rawRealtimeUs = SystemClock.elapsedRealtime() * 1000;
- for(int i=0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+ for(int i=0; i < mGpsSignalQualityTimer.length; i++) {
energyUsedMaMs
+= mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_SIGNAL_QUALITY_BASED, i)
* (getGpsSignalQualityTime(i, rawRealtimeUs, which) / 1000);
@@ -7145,21 +7181,19 @@
@Override
public long getScreenOnEnergy() {
- if (mBatteryMeasuredEnergyStats == null || !mBatteryMeasuredEnergyStats.hasSubsystem(
- MeasuredEnergyArray.SUBSYSTEM_DISPLAY)) {
+ if (mGlobalMeasuredEnergyStats == null) {
return ENERGY_DATA_UNAVAILABLE;
}
- return mBatteryMeasuredEnergyStats.getAccumulatedBucketEnergy(
+ return mGlobalMeasuredEnergyStats.getAccumulatedBucketEnergy(
MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_ON);
}
@Override
public long getScreenDozeEnergy() {
- if (mBatteryMeasuredEnergyStats == null || !mBatteryMeasuredEnergyStats.hasSubsystem(
- MeasuredEnergyArray.SUBSYSTEM_DISPLAY)) {
+ if (mGlobalMeasuredEnergyStats == null) {
return ENERGY_DATA_UNAVAILABLE;
}
- return mBatteryMeasuredEnergyStats.getAccumulatedBucketEnergy(
+ return mGlobalMeasuredEnergyStats.getAccumulatedBucketEnergy(
MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_DOZE);
}
@@ -7509,6 +7543,11 @@
*/
private final ArraySet<BinderCallStats> mBinderCallStats = new ArraySet<>();
+ /** Measured energies attributed to this uid while on battery. */
+ // We do not use a SparseArray<LongSamplingCounters> since it would cause lots of
+ // unnecessary timebase references, and we're just going to use on-battery anyway...
+ private MeasuredEnergyStats mUidMeasuredEnergyStats;
+
/**
* Estimated total time spent by the system server handling requests from this uid.
*/
@@ -7911,6 +7950,66 @@
return mModemControllerActivity;
}
+ private MeasuredEnergyStats getOrCreateMeasuredEnergyStatsLocked() {
+ if (mUidMeasuredEnergyStats == null) {
+ mUidMeasuredEnergyStats =
+ MeasuredEnergyStats.createFromTemplate(mBsi.mGlobalMeasuredEnergyStats);
+ }
+ return mUidMeasuredEnergyStats;
+ }
+
+ /** Adds the given energy to the given energy bucket for this uid. */
+ private void addEnergyToEnergyBucketLocked(long energyDeltaUJ,
+ @MeasuredEnergyStats.EnergyBucket int energyBucket, boolean accumulate) {
+ getOrCreateMeasuredEnergyStatsLocked()
+ .updateBucket(energyBucket, energyDeltaUJ, accumulate);
+ }
+
+ /**
+ * Returns the energy used by this uid for an energy bucket of interest.
+ * @param bucket energy bucket of interest
+ * @return energy (in microjoules) used by this uid for this energy bucket
+ */
+ public long getMeasuredEnergyMicroJoules(@MeasuredEnergyStats.EnergyBucket int bucket) {
+ if (mBsi.mGlobalMeasuredEnergyStats == null
+ || !mBsi.mGlobalMeasuredEnergyStats.isEnergyBucketSupported(bucket)) {
+ return ENERGY_DATA_UNAVAILABLE;
+ }
+ if (mUidMeasuredEnergyStats == null) {
+ return 0L; // It is supported, but was never filled, so it must be 0
+ }
+ return mUidMeasuredEnergyStats.getAccumulatedBucketEnergy(bucket);
+ }
+
+ /**
+ * Gets the minimum of the uid's foreground activity time and its PROCESS_STATE_TOP time
+ * since last marked. Also sets the mark time for both these timers.
+ *
+ * @see BatteryStatsHelper#getProcessForegroundTimeMs
+ *
+ * @param doCalc if true, then calculate the minimum; else don't bother and return 0. Either
+ * way, the mark is set.
+ */
+ private long markProcessForegroundTimeUs(long elapsedRealtimeMs,
+ boolean doCalc) {
+ long fgTimeUs = 0;
+ final StopwatchTimer fgTimer = mForegroundActivityTimer;
+ if (fgTimer != null) {
+ if (doCalc) fgTimeUs = fgTimer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000);
+ fgTimer.setMark(elapsedRealtimeMs);
+ }
+
+ long topTimeUs = 0;
+ final StopwatchTimer topTimer = mProcessStateTimer[PROCESS_STATE_TOP];
+ if (topTimer != null) {
+ if (doCalc) topTimeUs = topTimer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000);
+ topTimer.setMark(elapsedRealtimeMs);
+ }
+
+ // Return the min of the two
+ return (topTimeUs < fgTimeUs) ? topTimeUs : fgTimeUs;
+ }
+
public StopwatchTimer createAudioTurnedOnTimerLocked() {
if (mAudioTurnedOnTimer == null) {
mAudioTurnedOnTimer = new StopwatchTimer(mBsi.mClocks, Uid.this, AUDIO_TURNED_ON,
@@ -8639,6 +8738,8 @@
resetIfNotNull(mBluetoothControllerActivity, false, realtimeUs);
resetIfNotNull(mModemControllerActivity, false, realtimeUs);
+ MeasuredEnergyStats.resetIfNotNull(mUidMeasuredEnergyStats);
+
resetIfNotNull(mUserCpuTime, false, realtimeUs);
resetIfNotNull(mSystemCpuTime, false, realtimeUs);
@@ -9078,6 +9179,13 @@
out.writeInt(0);
}
+ if (mUidMeasuredEnergyStats != null) {
+ out.writeInt(1);
+ mUidMeasuredEnergyStats.writeToParcel(out);
+ } else {
+ out.writeInt(0);
+ }
+
mUserCpuTime.writeToParcel(out);
mSystemCpuTime.writeToParcel(out);
@@ -9377,6 +9485,10 @@
mModemControllerActivity = null;
}
+ if (in.readInt() != 0) {
+ mUidMeasuredEnergyStats = new MeasuredEnergyStats(in);
+ }
+
mUserCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
mSystemCpuTime = new LongSamplingCounter(mBsi.mOnBatteryTimeBase, in);
@@ -10581,13 +10693,15 @@
}
public BatteryStatsImpl(File systemDir, Handler handler, PlatformIdleStateCallback cb,
- MeasuredEnergyRetriever energyStatsCb, UserInfoProvider userInfoProvider) {
- this(new SystemClocks(), systemDir, handler, cb, energyStatsCb, userInfoProvider);
+ MeasuredEnergyRetriever energyStatsCb, boolean[] supportedEnergyBuckets,
+ UserInfoProvider userInfoProvider) {
+ this(new SystemClocks(), systemDir, handler, cb, energyStatsCb, supportedEnergyBuckets,
+ userInfoProvider);
}
private BatteryStatsImpl(Clocks clocks, File systemDir, Handler handler,
PlatformIdleStateCallback cb, MeasuredEnergyRetriever energyStatsCb,
- UserInfoProvider userInfoProvider) {
+ boolean[] supportedEnergyBuckets, UserInfoProvider userInfoProvider) {
init(clocks);
if (systemDir == null) {
@@ -10659,7 +10773,7 @@
mOnBatteryTimeBase);
}
mWifiActiveTimer = new StopwatchTimer(mClocks, null, -900, null, mOnBatteryTimeBase);
- for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+ for (int i=0; i< mGpsSignalQualityTimer.length; i++) {
mGpsSignalQualityTimer[i] = new StopwatchTimer(mClocks, null, -1000-i, null,
mOnBatteryTimeBase);
}
@@ -10694,12 +10808,9 @@
mDeviceIdleMode = DEVICE_IDLE_MODE_OFF;
FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_IDLE_MODE_STATE_CHANGED, mDeviceIdleMode);
- final MeasuredEnergyArray energyStats = mMeasuredEnergyRetriever.getEnergyConsumptionData();
- // If measured energy is not available, it is not supported and
- // mBatteryMeasuredEnergyStats should be left null.
- if (energyStats != null) {
- mBatteryMeasuredEnergyStats = new MeasuredEnergyStats(energyStats, mScreenState);
- }
+ mGlobalMeasuredEnergyStats = supportedEnergyBuckets == null ? null :
+ new MeasuredEnergyStats(supportedEnergyBuckets);
+ mScreenStateAtLastEnergyMeasurement = mScreenState;
}
@UnsupportedAppUsage
@@ -10744,14 +10855,6 @@
}
}
- /**
- * Starts tracking CPU time-in-state for threads of the system server process,
- * keeping a separate account of threads receiving incoming binder calls.
- */
- public void startTrackingSystemServerCpuTime() {
- mSystemServerCpuThreadReader.startTrackingThreadCpuTime();
- }
-
public void setCallback(BatteryCallback cb) {
mCallback = cb;
}
@@ -11351,7 +11454,7 @@
mWifiMulticastWakelockTimer.reset(false, elapsedRealtimeUs);
mWifiActiveTimer.reset(false, elapsedRealtimeUs);
mWifiActivity.reset(false, elapsedRealtimeUs);
- for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+ for (int i=0; i< mGpsSignalQualityTimer.length; i++) {
mGpsSignalQualityTimer[i].reset(false, elapsedRealtimeUs);
}
mBluetoothActivity.reset(false, elapsedRealtimeUs);
@@ -11402,11 +11505,10 @@
mTmpRailStats.reset();
- if (mBatteryMeasuredEnergyStats != null) {
- mBatteryMeasuredEnergyStats.reset();
- mExternalSync.scheduleSync("reset", ExternalStatsSync.UPDATE_ENERGY);
- }
+ MeasuredEnergyStats.resetIfNotNull(mGlobalMeasuredEnergyStats);
+ resetIfNotNull(mSystemServerCpuTimesUs, false, elapsedRealtimeUs);
+ resetIfNotNull(mSystemServerThreadCpuTimesUs, false, elapsedRealtimeUs);
resetIfNotNull(mBinderThreadCpuTimesUs, false, elapsedRealtimeUs);
mLastHistoryStepDetails = null;
@@ -11429,6 +11531,10 @@
clearHistoryLocked();
mBatteryStatsHistory.resetAllFiles();
+ // Flush external data, gathering snapshots, but don't process it since it is pre-reset data
+ mIgnoreNextExternalStats = true;
+ mExternalSync.scheduleSync("reset", ExternalStatsSync.UPDATE_ALL);
+
mHandler.sendEmptyMessage(MSG_REPORT_RESET_STATS);
}
@@ -11559,7 +11665,7 @@
}
synchronized (this) {
- if (!mOnBatteryInternal) {
+ if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
if (delta != null) {
mNetworkStatsPool.release(delta);
}
@@ -11843,7 +11949,7 @@
}
synchronized (this) {
- if (!mOnBatteryInternal) {
+ if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
if (delta != null) {
mNetworkStatsPool.release(delta);
}
@@ -12057,7 +12163,14 @@
Slog.d(TAG, "Updating bluetooth stats: " + info);
}
- if (info == null || !mOnBatteryInternal) {
+ if (info == null) {
+ return;
+ }
+ if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
+ // TODO(174818545): mLastBluetoothActivityInfo is actually extremely suspicious.
+ // Firstly, the following line was originally missing. But even more so, BESW says that
+ // info is a delta, not a total, so this entire algorithm requires review.
+ mLastBluetoothActivityInfo.set(info);
return;
}
@@ -12279,6 +12392,88 @@
}
/**
+ * Accumulate Display energy and distribute it to the correct state and the apps.
+ *
+ * NOTE: The algorithm used makes the strong assumption that app foreground activity time
+ * is always 0 when the screen is not "ON" and whenever the rail energy is 0 (if supported).
+ * To the extent that those assumptions are violated, the algorithm will err.
+ *
+ * @param energyUJ amount of energy (microjoules) used by Display since this was last called.
+ * @param screenState screen state at the time this data collection was scheduled
+ */
+ @GuardedBy("this")
+ public void updateDisplayEnergyLocked(long energyUJ, int screenState, long elapsedRealtimeMs) {
+ if (DEBUG_ENERGY) Slog.d(TAG, "Updating display stats: " + energyUJ);
+ if (mGlobalMeasuredEnergyStats == null) {
+ return;
+ }
+
+ final @EnergyBucket int energyBucket =
+ MeasuredEnergyStats.getDisplayEnergyBucket(mScreenStateAtLastEnergyMeasurement);
+ mScreenStateAtLastEnergyMeasurement = screenState;
+
+ if (!mOnBatteryInternal || energyUJ <= 0) {
+ // There's nothing further to update.
+ return;
+ }
+ if (mIgnoreNextExternalStats) {
+ // Although under ordinary resets we won't get here, and typically a new sync will
+ // happen right after the reset, strictly speaking we need to set all mark times to now.
+ final int uidStatsSize = mUidStats.size();
+ for (int i = 0; i < uidStatsSize; i++) {
+ final Uid uid = mUidStats.valueAt(i);
+ uid.markProcessForegroundTimeUs(elapsedRealtimeMs, false);
+ }
+ return;
+ }
+
+ mGlobalMeasuredEnergyStats.updateBucket(energyBucket, energyUJ, true);
+
+ // Now we blame individual apps, but only if the display was ON.
+ if (energyBucket != MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_ON) {
+ return;
+ }
+ // TODO(b/175726779): Consider unifying the code with the non-rail display energy blaming.
+
+ // NOTE: fg time is NOT pooled. If two uids are both somehow in fg, then that time is
+ // 'double counted' and will simply exceed the realtime that elapsed.
+ // If multidisplay becomes a reality, this is probably more reasonable than pooling.
+
+ // On the first pass, collect total time since mark so that we can normalize power.
+ long totalFgTimeMs = 0L;
+ final ArrayMap<Uid, Long> fgTimeMsArray = new ArrayMap<>();
+ final long elapsedRealtimeUs = elapsedRealtimeMs * 1000;
+ // TODO(b/175726779): Update and optimize the algorithm (e.g. avoid iterating over ALL uids)
+ final int uidStatsSize = mUidStats.size();
+ for (int i = 0; i < uidStatsSize; i++) {
+ final Uid uid = mUidStats.valueAt(i);
+ final long fgTimeMs = uid.markProcessForegroundTimeUs(elapsedRealtimeMs, true) / 1000;
+ if (fgTimeMs == 0) continue;
+ fgTimeMsArray.put(uid, fgTimeMs);
+ totalFgTimeMs += fgTimeMs;
+ }
+ long totalDisplayEnergyMJ = energyUJ / 1000; // not final
+
+ // Actually assign and distribute power usage to apps based on their fg time since mark.
+ // TODO(b/175726326): Decide on 'energy' units and make sure algorithm won't overflow.
+ final long fgTimeArraySize = fgTimeMsArray.size();
+ for (int i = 0; i < fgTimeArraySize; i++) {
+ final Uid uid = fgTimeMsArray.keyAt(i);
+ final long fgTimeMs = fgTimeMsArray.valueAt(i);
+
+ // Using long division: "appEnergy = totalEnergy * appFg/totalFg + 0.5" with rounding
+ final long appDisplayEnergyMJ =
+ (totalDisplayEnergyMJ * fgTimeMs + (totalFgTimeMs / 2))
+ / totalFgTimeMs;
+ uid.addEnergyToEnergyBucketLocked(appDisplayEnergyMJ * 1000, energyBucket, true);
+
+ // To mitigate round-off errors, remove this app from numerator & denominator totals
+ totalDisplayEnergyMJ -= appDisplayEnergyMJ;
+ totalFgTimeMs -= fgTimeMs;
+ }
+ }
+
+ /**
* Read and record Rail Energy data.
*/
public void updateRailStatsLocked() {
@@ -12288,6 +12483,14 @@
mMeasuredEnergyRetriever.fillRailDataStats(mTmpRailStats);
}
+ /** Informs that external stats data has been completely flushed. */
+ public void informThatAllExternalStatsAreFlushed() {
+ synchronized (this) {
+ // Any data from the pre-reset era is flushed, so we can henceforth process future data.
+ mIgnoreNextExternalStats = false;
+ }
+ }
+
/**
* Get energy consumed (in microjoules) by a set of subsystems from the {@link
* MeasuredEnergyRetriever}, if available.
@@ -12505,17 +12708,27 @@
return;
}
- if (mBinderThreadCpuTimesUs == null) {
+ if (mSystemServerCpuTimesUs == null) {
+ mSystemServerCpuTimesUs = new LongSamplingCounterArray(mOnBatteryTimeBase);
+ mSystemServerThreadCpuTimesUs = new LongSamplingCounterArray(mOnBatteryTimeBase);
mBinderThreadCpuTimesUs = new LongSamplingCounterArray(mOnBatteryTimeBase);
}
+ mSystemServerCpuTimesUs.addCountLocked(systemServiceCpuThreadTimes.processCpuTimesUs);
+ mSystemServerThreadCpuTimesUs.addCountLocked(systemServiceCpuThreadTimes.threadCpuTimesUs);
mBinderThreadCpuTimesUs.addCountLocked(systemServiceCpuThreadTimes.binderThreadCpuTimesUs);
if (DEBUG_BINDER_STATS) {
- Slog.d(TAG, "System server threads per CPU cluster (incoming binder threads)");
+ Slog.d(TAG, "System server threads per CPU cluster (binder threads/total threads/%)");
+ long totalCpuTimeMs = 0;
+ long totalThreadTimeMs = 0;
long binderThreadTimeMs = 0;
int cpuIndex = 0;
- final long[] binderThreadCpuTimesUs = mBinderThreadCpuTimesUs.getCountsLocked(
- BatteryStats.STATS_SINCE_CHARGED);
+ final long[] systemServerCpuTimesUs =
+ mSystemServerCpuTimesUs.getCountsLocked(0);
+ final long[] systemServerThreadCpuTimesUs =
+ mSystemServerThreadCpuTimesUs.getCountsLocked(0);
+ final long[] binderThreadCpuTimesUs =
+ mBinderThreadCpuTimesUs.getCountsLocked(0);
int index = 0;
int numCpuClusters = mPowerProfile.getNumCpuClusters();
for (int cluster = 0; cluster < numCpuClusters; cluster++) {
@@ -12526,30 +12739,28 @@
if (speed != 0) {
sb.append(", ");
}
+ long totalCountMs = systemServerThreadCpuTimesUs[index] / 1000;
long binderCountMs = binderThreadCpuTimesUs[index] / 1000;
- sb.append(TextUtils.formatSimple("%10d", binderCountMs));
+ sb.append(String.format("%d/%d(%.1f%%)",
+ binderCountMs,
+ totalCountMs,
+ totalCountMs != 0 ? (double) binderCountMs * 100 / totalCountMs : 0));
+ totalCpuTimeMs += systemServerCpuTimesUs[index] / 1000;
+ totalThreadTimeMs += totalCountMs;
binderThreadTimeMs += binderCountMs;
index++;
}
cpuIndex += mPowerProfile.getNumCoresInCpuCluster(cluster);
Slog.d(TAG, sb.toString());
}
- }
- }
- /**
- * Update energy consumption data with a new snapshot of energy data.
- * Generally this should only be called from BatteryExternalStatsWorker.
- *
- * @param energyStats latest energy data to update with.
- */
- @GuardedBy("this")
- public void updateMeasuredEnergyStatsLocked(@NonNull MeasuredEnergyArray energyStats,
- int screenState) {
- if (mBatteryMeasuredEnergyStats != null) {
- mBatteryMeasuredEnergyStats.update(energyStats, screenState,
- mOnBatteryTimeBase.isRunning());
+ Slog.d(TAG, "Total system server CPU time (ms): " + totalCpuTimeMs);
+ Slog.d(TAG, "Total system server thread time (ms): " + totalThreadTimeMs);
+ Slog.d(TAG, String.format("Total Binder thread time (ms): %d (%.1f%%)",
+ binderThreadTimeMs,
+ binderThreadTimeMs != 0
+ ? (double) binderThreadTimeMs * 100 / totalThreadTimeMs : 0));
}
}
@@ -13641,7 +13852,7 @@
final long rawRealTimeUs = SystemClock.elapsedRealtime() * 1000;
s.setLoggingDurationMs(computeBatteryRealtime(rawRealTimeUs, which) / 1000);
s.setEnergyConsumedMaMs(getGpsBatteryDrainMaMs());
- long[] time = new long[GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS];
+ long[] time = new long[mGpsSignalQualityTimer.length];
for (int i=0; i<time.length; i++) {
time[i] = getGpsSignalQualityTime(i, rawRealTimeUs, which) / 1000;
}
@@ -13824,16 +14035,60 @@
}
- /**
- * Estimates the time spent by the system server handling incoming binder requests.
- */
@Override
public long[] getSystemServiceTimeAtCpuSpeeds() {
- if (mBinderThreadCpuTimesUs == null) {
+ // Estimates the time spent by the system server handling incoming binder requests.
+ //
+ // The data that we can get from the kernel is this:
+ // - CPU duration for a (thread - cluster - CPU speed) combination
+ // - CPU duration for a (UID - cluster - CPU speed) combination
+ //
+ // The configuration we have in the Power Profile is this:
+ // - Average CPU power for a (cluster - CPU speed) combination.
+ //
+ // The model used by BatteryStats can be illustrated with this example:
+ //
+ // - Let's say the system server has 10 threads.
+ // - These 10 threads spent 1000 ms of CPU time in aggregate
+ // - Of the 10 threads 4 were execute exclusively incoming binder calls.
+ // - These 4 "binder" threads consumed 600 ms of CPU time in aggregate
+ // - The real time spent by the system server process doing all of this is, say, 200 ms.
+ //
+ // We will assume that power consumption is proportional to the time spent by the CPU
+ // across all threads. This is a crude assumption, but we don't have more detailed data.
+ // Thus,
+ // binderRealTime = realTime * aggregateBinderThreadTime / aggregateAllThreadTime
+ //
+ // In our example,
+ // binderRealTime = 200 * 600 / 1000 = 120ms
+ //
+ // We can then multiply this estimated time by the average power to obtain an estimate
+ // of the total power consumed by incoming binder calls for the given cluster/speed
+ // combination.
+
+ if (mSystemServerCpuTimesUs == null) {
return null;
}
- return mBinderThreadCpuTimesUs.getCountsLocked(BatteryStats.STATS_SINCE_CHARGED);
+ final long[] systemServerCpuTimesUs = mSystemServerCpuTimesUs.getCountsLocked(
+ BatteryStats.STATS_SINCE_CHARGED);
+ final long [] systemServerThreadCpuTimesUs = mSystemServerThreadCpuTimesUs.getCountsLocked(
+ BatteryStats.STATS_SINCE_CHARGED);
+ final long[] binderThreadCpuTimesUs = mBinderThreadCpuTimesUs.getCountsLocked(
+ BatteryStats.STATS_SINCE_CHARGED);
+
+ final int size = systemServerCpuTimesUs.length;
+ final long[] results = new long[size];
+
+ for (int i = 0; i < size; i++) {
+ if (systemServerThreadCpuTimesUs[i] == 0) {
+ continue;
+ }
+
+ results[i] = systemServerCpuTimesUs[i] * binderThreadCpuTimesUs[i]
+ / systemServerThreadCpuTimesUs[i];
+ }
+ return results;
}
/**
@@ -14229,7 +14484,7 @@
}
updateSystemServiceCallStats();
- if (mBinderThreadCpuTimesUs != null) {
+ if (mSystemServerThreadCpuTimesUs != null) {
pw.println("Per UID System server binder time in ms:");
long[] systemServiceTimeAtCpuSpeeds = getSystemServiceTimeAtCpuSpeeds();
for (int i = 0; i < size; i++) {
@@ -14254,11 +14509,27 @@
*/
@GuardedBy("this")
public void dumpMeasuredEnergyStatsLocked(PrintWriter pw) {
- if (mBatteryMeasuredEnergyStats == null) return;
+ if (mGlobalMeasuredEnergyStats == null) return;
+ dumpMeasuredEnergyStatsLocked(pw, "non-uid usage", mGlobalMeasuredEnergyStats);
+
+ int size = mUidStats.size();
+ for (int i = 0; i < size; i++) {
+ final int u = mUidStats.keyAt(i);
+ final Uid uid = mUidStats.get(u);
+ final String name = "uid " + uid.mUid;
+ dumpMeasuredEnergyStatsLocked(pw, name, uid.mUidMeasuredEnergyStats);
+ }
+ }
+
+ /** Dump measured energy stats for the given uid */
+ @GuardedBy("this")
+ private void dumpMeasuredEnergyStatsLocked(PrintWriter pw, String name,
+ MeasuredEnergyStats stats) {
+ if (stats == null) return;
final IndentingPrintWriter iPw = new IndentingPrintWriter(pw, " ");
- iPw.println("On battery measured energy stats:");
+ iPw.printf("On battery measured energy stats for %s:\n", name);
iPw.increaseIndent();
- mBatteryMeasuredEnergyStats.dump(iPw);
+ stats.dump(iPw);
iPw.decreaseIndent();
}
@@ -14637,7 +14908,7 @@
mNextMaxDailyDeadlineMs = in.readLong();
mBatteryTimeToFullSeconds = in.readLong();
- MeasuredEnergyStats.readSummaryFromParcel(mBatteryMeasuredEnergyStats, in);
+ MeasuredEnergyStats.readSummaryFromParcel(mGlobalMeasuredEnergyStats, in);
mStartCount++;
@@ -14692,7 +14963,7 @@
}
mWifiActiveTimer.readSummaryFromParcelLocked(in);
mWifiActivity.readSummaryFromParcel(in);
- for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+ for (int i=0; i<mGpsSignalQualityTimer.length; i++) {
mGpsSignalQualityTimer[i].readSummaryFromParcelLocked(in);
}
mBluetoothActivity.readSummaryFromParcel(in);
@@ -14953,6 +15224,9 @@
u.mWifiRadioApWakeupCount = null;
}
+ u.mUidMeasuredEnergyStats = MeasuredEnergyStats.createAndReadSummaryFromParcel(in,
+ /* template */ mGlobalMeasuredEnergyStats);
+
int NW = in.readInt();
if (NW > (MAX_WAKELOCKS_PER_UID+1)) {
throw new ParcelFormatException("File corrupt: too many wake locks " + NW);
@@ -15132,7 +15406,7 @@
out.writeLong(mNextMaxDailyDeadlineMs);
out.writeLong(mBatteryTimeToFullSeconds);
- MeasuredEnergyStats.writeSummaryToParcel(mBatteryMeasuredEnergyStats, out);
+ MeasuredEnergyStats.writeSummaryToParcel(mGlobalMeasuredEnergyStats, out);
mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
mScreenDozeTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
@@ -15178,7 +15452,7 @@
}
mWifiActiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
mWifiActivity.writeSummaryToParcel(out);
- for (int i=0; i< GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+ for (int i=0; i< mGpsSignalQualityTimer.length; i++) {
mGpsSignalQualityTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS);
}
mBluetoothActivity.writeSummaryToParcel(out);
@@ -15457,6 +15731,8 @@
out.writeInt(0);
}
+ MeasuredEnergyStats.writeSummaryToParcel(u.mUidMeasuredEnergyStats, out);
+
final ArrayMap<String, Uid.Wakelock> wakeStats = u.mWakelockStats.getMap();
int NW = wakeStats.size();
out.writeInt(NW);
@@ -15672,7 +15948,7 @@
mOnBatteryTimeBase, in);
mWifiActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase,
NUM_WIFI_TX_LEVELS, in);
- for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+ for (int i=0; i<mGpsSignalQualityTimer.length; i++) {
mGpsSignalQualityTimer[i] = new StopwatchTimer(mClocks, null, -1000-i,
null, mOnBatteryTimeBase, in);
}
@@ -15719,7 +15995,7 @@
mBatteryTimeToFullSeconds = in.readLong();
if (in.readInt() != 0) {
- mBatteryMeasuredEnergyStats = new MeasuredEnergyStats(in);
+ mGlobalMeasuredEnergyStats = new MeasuredEnergyStats(in);
}
mRpmStats.clear();
@@ -15795,6 +16071,9 @@
mUidStats.append(uid, u);
}
+ mSystemServerCpuTimesUs = LongSamplingCounterArray.readFromParcel(in, mOnBatteryTimeBase);
+ mSystemServerThreadCpuTimesUs = LongSamplingCounterArray.readFromParcel(in,
+ mOnBatteryTimeBase);
mBinderThreadCpuTimesUs = LongSamplingCounterArray.readFromParcel(in, mOnBatteryTimeBase);
}
@@ -15886,7 +16165,7 @@
}
mWifiActiveTimer.writeToParcel(out, uSecRealtime);
mWifiActivity.writeToParcel(out, 0);
- for (int i = 0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+ for (int i = 0; i < mGpsSignalQualityTimer.length; i++) {
mGpsSignalQualityTimer[i].writeToParcel(out, uSecRealtime);
}
mBluetoothActivity.writeToParcel(out, 0);
@@ -15921,9 +16200,9 @@
out.writeLong(mLastWriteTimeMs);
out.writeLong(mBatteryTimeToFullSeconds);
- if (mBatteryMeasuredEnergyStats != null) {
+ if (mGlobalMeasuredEnergyStats != null) {
out.writeInt(1);
- mBatteryMeasuredEnergyStats.writeToParcel(out);
+ mGlobalMeasuredEnergyStats.writeToParcel(out);
} else {
out.writeInt(0);
}
@@ -16003,6 +16282,8 @@
} else {
out.writeInt(0);
}
+ LongSamplingCounterArray.writeToParcel(out, mSystemServerCpuTimesUs);
+ LongSamplingCounterArray.writeToParcel(out, mSystemServerThreadCpuTimesUs);
LongSamplingCounterArray.writeToParcel(out, mBinderThreadCpuTimesUs);
}
@@ -16197,7 +16478,7 @@
pr.println("*** Wifi signal strength #" + i + ":");
mWifiSignalStrengthsTimer[i].logState(pr, " ");
}
- for (int i=0; i<GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+ for (int i=0; i<mGpsSignalQualityTimer.length; i++) {
pr.println("*** GPS signal quality #" + i + ":");
mGpsSignalQualityTimer[i].logState(pr, " ");
}
diff --git a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
index b97fdc9..9904d30 100644
--- a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
+++ b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
@@ -21,6 +21,7 @@
import android.net.ConnectivityManager;
import android.os.BatteryStats;
import android.os.BatteryUsageStats;
+import android.os.BatteryUsageStatsQuery;
import android.os.Bundle;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -89,7 +90,7 @@
/**
* Returns a snapshot of battery attribution data.
*/
- public BatteryUsageStats getBatteryUsageStats() {
+ public BatteryUsageStats getBatteryUsageStats(BatteryUsageStatsQuery query) {
// TODO(b/174186345): instead of BatteryStatsHelper, use PowerCalculators directly.
final BatteryStatsHelper batteryStatsHelper = new BatteryStatsHelper(mContext,
@@ -109,8 +110,14 @@
// TODO(b/174186358): read extra power component number from configuration
final int customPowerComponentCount = 0;
final int customTimeComponentCount = 0;
+ final boolean includeModeledComponents =
+ (query.getFlags() & BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_MODELED)
+ != 0;
+
+
final BatteryUsageStats.Builder batteryUsageStatsBuilder =
- new BatteryUsageStats.Builder(customPowerComponentCount, customTimeComponentCount)
+ new BatteryUsageStats.Builder(customPowerComponentCount, customTimeComponentCount,
+ includeModeledComponents)
.setDischargePercentage(batteryStatsHelper.getStats().getDischargeAmount(0))
.setConsumedPower(batteryStatsHelper.getTotalPower());
@@ -129,8 +136,8 @@
final List<PowerCalculator> powerCalculators = getPowerCalculators();
for (PowerCalculator powerCalculator : powerCalculators) {
- powerCalculator.calculate(batteryUsageStatsBuilder, mStats, realtimeUs, uptimeUs,
- BatteryStats.STATS_SINCE_CHARGED, users);
+ powerCalculator.calculate(batteryUsageStatsBuilder, mStats, realtimeUs, uptimeUs, query,
+ users);
}
return batteryUsageStatsBuilder.build();
diff --git a/core/java/com/android/internal/os/BluetoothPowerCalculator.java b/core/java/com/android/internal/os/BluetoothPowerCalculator.java
index 11099be..f5690e0 100644
--- a/core/java/com/android/internal/os/BluetoothPowerCalculator.java
+++ b/core/java/com/android/internal/os/BluetoothPowerCalculator.java
@@ -15,8 +15,13 @@
*/
package com.android.internal.os;
+import android.os.BatteryConsumer;
import android.os.BatteryStats;
+import android.os.BatteryUsageStats;
+import android.os.BatteryUsageStatsQuery;
import android.os.Process;
+import android.os.SystemBatteryConsumer;
+import android.os.UidBatteryConsumer;
import android.os.UserHandle;
import android.util.Log;
import android.util.SparseArray;
@@ -30,8 +35,16 @@
private final double mRxMa;
private final double mTxMa;
private final boolean mHasBluetoothPowerController;
- private double mAppTotalPowerMah = 0;
- private long mAppTotalTimeMs = 0;
+
+ private static class PowerAndDuration {
+ public long durationMs;
+ public double powerMah;
+ }
+
+ // Objects used for passing calculation results. Fields are used to avoid allocations.
+ private final PowerAndDuration mUidPowerAndDuration = new PowerAndDuration();
+ private final PowerAndDuration mTotalPowerAndDuration = new PowerAndDuration();
+ private final PowerAndDuration mSystemPowerAndDuration = new PowerAndDuration();
public BluetoothPowerCalculator(PowerProfile profile) {
mIdleMa = profile.getAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_IDLE);
@@ -41,16 +54,90 @@
}
@Override
+ public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
+ long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query,
+ SparseArray<UserHandle> asUsers) {
+ if (!mHasBluetoothPowerController || !batteryStats.hasBluetoothActivityReporting()) {
+ return;
+ }
+
+ mTotalPowerAndDuration.durationMs = 0;
+ mTotalPowerAndDuration.powerMah = 0;
+
+ SystemBatteryConsumer.Builder systemBatteryConsumerBuilder =
+ builder.getOrCreateSystemBatteryConsumerBuilder(
+ SystemBatteryConsumer.DRAIN_TYPE_BLUETOOTH);
+
+ final SparseArray<UidBatteryConsumer.Builder> uidBatteryConsumerBuilders =
+ builder.getUidBatteryConsumerBuilders();
+ for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {
+ final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i);
+ calculateApp(app);
+ if (app.getUid() == Process.BLUETOOTH_UID) {
+ app.setSystemComponent(true);
+ systemBatteryConsumerBuilder.addUidBatteryConsumer(app);
+ }
+ }
+
+ final BatteryStats.ControllerActivityCounter counter =
+ batteryStats.getBluetoothControllerActivity();
+
+ calculatePowerAndDuration(counter, mSystemPowerAndDuration);
+
+ // Subtract what the apps used, but clamp to 0.
+ final long systemComponentDurationMs = Math.max(0,
+ mSystemPowerAndDuration.durationMs - mTotalPowerAndDuration.durationMs);
+ final double systemComponentPowerMah = Math.max(0,
+ mSystemPowerAndDuration.powerMah - mTotalPowerAndDuration.powerMah);
+
+ systemBatteryConsumerBuilder
+ .setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_BLUETOOTH,
+ systemComponentDurationMs)
+ .setConsumedPower(BatteryConsumer.POWER_COMPONENT_BLUETOOTH,
+ systemComponentPowerMah);
+ }
+
+ private void calculateApp(UidBatteryConsumer.Builder app) {
+ calculatePowerAndDuration(app.getBatteryStatsUid().getBluetoothControllerActivity(),
+ mUidPowerAndDuration);
+
+ app.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_BLUETOOTH,
+ mUidPowerAndDuration.durationMs)
+ .setConsumedPower(BatteryConsumer.POWER_COMPONENT_BLUETOOTH,
+ mUidPowerAndDuration.powerMah);
+
+ mTotalPowerAndDuration.powerMah += mUidPowerAndDuration.powerMah;
+ mTotalPowerAndDuration.durationMs += mUidPowerAndDuration.durationMs;
+ }
+
+ @Override
public void calculate(List<BatterySipper> sippers, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) {
if (!mHasBluetoothPowerController || !batteryStats.hasBluetoothActivityReporting()) {
return;
}
+ mTotalPowerAndDuration.durationMs = 0;
+ mTotalPowerAndDuration.powerMah = 0;
+
super.calculate(sippers, batteryStats, rawRealtimeUs, rawUptimeUs, statsType, asUsers);
BatterySipper bs = new BatterySipper(BatterySipper.DrainType.BLUETOOTH, null, 0);
- calculateRemaining(bs, batteryStats, rawRealtimeUs, rawUptimeUs, statsType);
+ calculatePowerAndDuration(batteryStats.getBluetoothControllerActivity(),
+ mSystemPowerAndDuration);
+
+ // Subtract what the apps used, but clamp to 0.
+ double powerMah =
+ Math.max(0, mSystemPowerAndDuration.powerMah - mTotalPowerAndDuration.powerMah);
+ final long durationMs =
+ Math.max(0, mSystemPowerAndDuration.durationMs - mTotalPowerAndDuration.durationMs);
+ if (DEBUG && powerMah != 0) {
+ Log.d(TAG, "Bluetooth active: time=" + (durationMs)
+ + " power=" + formatCharge(powerMah));
+ }
+
+ bs.bluetoothPowerMah = powerMah;
+ bs.bluetoothRunningTimeMs = durationMs;
for (int i = sippers.size() - 1; i >= 0; i--) {
BatterySipper app = sippers.get(i);
@@ -69,65 +156,42 @@
protected void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
long rawUptimeUs, int statsType) {
- final BatteryStats.ControllerActivityCounter counter = u.getBluetoothControllerActivity();
- if (counter == null) {
- return;
- }
+ calculatePowerAndDuration(u.getBluetoothControllerActivity(), mUidPowerAndDuration);
- final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(statsType);
- final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(statsType);
- final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(statsType);
- final long totalTimeMs = idleTimeMs + txTimeMs + rxTimeMs;
- double powerMah = counter.getPowerCounter().getCountLocked(statsType)
- / (double)(1000*60*60);
-
- if (powerMah == 0) {
- powerMah = ((idleTimeMs * mIdleMa) + (rxTimeMs * mRxMa) + (txTimeMs * mTxMa))
- / (1000*60*60);
- }
-
- app.bluetoothPowerMah = powerMah;
- app.bluetoothRunningTimeMs = totalTimeMs;
+ app.bluetoothPowerMah = mUidPowerAndDuration.powerMah;
+ app.bluetoothRunningTimeMs = mUidPowerAndDuration.durationMs;
app.btRxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_BT_RX_DATA, statsType);
app.btTxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_BT_TX_DATA, statsType);
- mAppTotalPowerMah += powerMah;
- mAppTotalTimeMs += totalTimeMs;
+ mTotalPowerAndDuration.powerMah += mUidPowerAndDuration.powerMah;
+ mTotalPowerAndDuration.durationMs += mUidPowerAndDuration.durationMs;
}
- private void calculateRemaining(BatterySipper app, BatteryStats stats, long rawRealtimeUs,
- long rawUptimeUs, int statsType) {
- final BatteryStats.ControllerActivityCounter counter =
- stats.getBluetoothControllerActivity();
+ private void calculatePowerAndDuration(BatteryStats.ControllerActivityCounter counter,
+ PowerAndDuration powerAndDuration) {
+ if (counter == null) {
+ powerAndDuration.durationMs = 0;
+ powerAndDuration.powerMah = 0;
+ return;
+ }
- final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(statsType);
- final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(statsType);
- final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(statsType);
+ final long idleTimeMs =
+ counter.getIdleTimeCounter().getCountLocked(BatteryStats.STATS_SINCE_CHARGED);
+ final long rxTimeMs =
+ counter.getRxTimeCounter().getCountLocked(BatteryStats.STATS_SINCE_CHARGED);
+ final long txTimeMs =
+ counter.getTxTimeCounters()[0].getCountLocked(BatteryStats.STATS_SINCE_CHARGED);
final long totalTimeMs = idleTimeMs + txTimeMs + rxTimeMs;
- double powerMah = counter.getPowerCounter().getCountLocked(statsType)
- / (double)(1000*60*60);
+ double powerMah =
+ counter.getPowerCounter().getCountLocked(BatteryStats.STATS_SINCE_CHARGED)
+ / (double) (1000 * 60 * 60);
if (powerMah == 0) {
- // Some devices do not report the power, so calculate it.
powerMah = ((idleTimeMs * mIdleMa) + (rxTimeMs * mRxMa) + (txTimeMs * mTxMa))
- / (1000*60*60);
+ / (1000 * 60 * 60);
}
- // Subtract what the apps used, but clamp to 0.
- powerMah = Math.max(0, powerMah - mAppTotalPowerMah);
-
- if (DEBUG && powerMah != 0) {
- Log.d(TAG, "Bluetooth active: time=" + (totalTimeMs)
- + " power=" + formatCharge(powerMah));
- }
-
- app.bluetoothPowerMah = powerMah;
- app.bluetoothRunningTimeMs = Math.max(0, totalTimeMs - mAppTotalTimeMs);
- }
-
- @Override
- public void reset() {
- mAppTotalPowerMah = 0;
- mAppTotalTimeMs = 0;
+ powerAndDuration.durationMs = totalTimeMs;
+ powerAndDuration.powerMah = powerMah;
}
}
diff --git a/core/java/com/android/internal/os/CpuPowerCalculator.java b/core/java/com/android/internal/os/CpuPowerCalculator.java
index 0f0839c..7972924 100644
--- a/core/java/com/android/internal/os/CpuPowerCalculator.java
+++ b/core/java/com/android/internal/os/CpuPowerCalculator.java
@@ -15,7 +15,9 @@
*/
package com.android.internal.os;
+import android.os.BatteryConsumer;
import android.os.BatteryStats;
+import android.os.BatteryUsageStatsQuery;
import android.os.UidBatteryConsumer;
import android.util.ArrayMap;
import android.util.Log;
@@ -32,7 +34,9 @@
@Override
protected void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u,
- long rawRealtimeUs, long rawUptimeUs, int statsType) {
+ long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
+ final int statsType = BatteryStats.STATS_SINCE_CHARGED;
+
long cpuTimeMs = (u.getUserCpuTimeUs(statsType) + u.getSystemCpuTimeUs(statsType)) / 1000;
final int numClusters = mProfile.getNumCpuClusters();
@@ -114,10 +118,15 @@
cpuTimeMs = cpuFgTimeMs;
}
- app.setConsumedPower(UidBatteryConsumer.POWER_COMPONENT_CPU, cpuPowerMah)
- .setUsageDurationMillis(UidBatteryConsumer.TIME_COMPONENT_CPU, cpuTimeMs)
- .setUsageDurationMillis(UidBatteryConsumer.TIME_COMPONENT_CPU_FOREGROUND,
- cpuFgTimeMs)
+ app.setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU, cpuPowerMah)
+ .setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_CPU, cpuTimeMs)
+ .setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_CPU_FOREGROUND, cpuFgTimeMs)
.setPackageWithHighestDrain(packageWithHighestDrain);
+
+ if ((query.getFlags()
+ & BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_MODELED) != 0) {
+ app.setConsumedPowerForCustomComponent(BatteryConsumer.FIRST_MODELED_POWER_COMPONENT_ID
+ + BatteryConsumer.POWER_COMPONENT_CPU, cpuPowerMah);
+ }
}
}
diff --git a/core/java/com/android/internal/os/KernelSingleProcessCpuThreadReader.java b/core/java/com/android/internal/os/KernelSingleProcessCpuThreadReader.java
index 4d2a08a..e6a9623 100644
--- a/core/java/com/android/internal/os/KernelSingleProcessCpuThreadReader.java
+++ b/core/java/com/android/internal/os/KernelSingleProcessCpuThreadReader.java
@@ -16,12 +16,23 @@
package com.android.internal.os;
+import static android.os.Process.PROC_OUT_LONG;
+import static android.os.Process.PROC_SPACE_TERM;
+
import android.annotation.Nullable;
+import android.os.Process;
+import android.system.Os;
+import android.system.OsConstants;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
import java.io.IOException;
+import java.nio.file.DirectoryIteratorException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.Arrays;
/**
@@ -34,65 +45,93 @@
private static final String TAG = "KernelSingleProcCpuThreadRdr";
private static final boolean DEBUG = false;
+ private static final boolean NATIVE_ENABLED = true;
+
+ /**
+ * The name of the file to read CPU statistics from, must be found in {@code
+ * /proc/$PID/task/$TID}
+ */
+ private static final String CPU_STATISTICS_FILENAME = "time_in_state";
+
+ private static final String PROC_STAT_FILENAME = "stat";
+
+ /** Directory under /proc/$PID containing CPU stats files for threads */
+ public static final String THREAD_CPU_STATS_DIRECTORY = "task";
+
+ /** Default mount location of the {@code proc} filesystem */
+ private static final Path DEFAULT_PROC_PATH = Paths.get("/proc");
+
+ /** The initial {@code time_in_state} file for {@link ProcTimeInStateReader} */
+ private static final Path INITIAL_TIME_IN_STATE_PATH = Paths.get("self/time_in_state");
+
+ /** See https://man7.org/linux/man-pages/man5/proc.5.html */
+ private static final int[] PROCESS_FULL_STATS_FORMAT = new int[] {
+ PROC_SPACE_TERM,
+ PROC_SPACE_TERM,
+ PROC_SPACE_TERM,
+ PROC_SPACE_TERM,
+ PROC_SPACE_TERM,
+ PROC_SPACE_TERM,
+ PROC_SPACE_TERM,
+ PROC_SPACE_TERM,
+ PROC_SPACE_TERM,
+ PROC_SPACE_TERM,
+ PROC_SPACE_TERM,
+ PROC_SPACE_TERM,
+ PROC_SPACE_TERM,
+ PROC_SPACE_TERM | PROC_OUT_LONG, // 14: utime
+ PROC_SPACE_TERM | PROC_OUT_LONG, // 15: stime
+ // Ignore remaining fields
+ };
+
+ private final long[] mProcessFullStatsData = new long[2];
+
+ private static final int PROCESS_FULL_STAT_UTIME = 0;
+ private static final int PROCESS_FULL_STAT_STIME = 1;
+
+ /** Used to read and parse {@code time_in_state} files */
+ private final ProcTimeInStateReader mProcTimeInStateReader;
private final int mPid;
- private final CpuTimeInStateReader mCpuTimeInStateReader;
+ /** Where the proc filesystem is mounted */
+ private final Path mProcPath;
- private int[] mSelectedThreadNativeTids = new int[0]; // Sorted
+ // How long a CPU jiffy is in milliseconds.
+ private final long mJiffyMillis;
+
+ // Path: /proc/<pid>/stat
+ private final String mProcessStatFilePath;
+
+ // Path: /proc/<pid>/task
+ private final Path mThreadsDirectoryPath;
/**
- * Count of frequencies read from the {@code time_in_state} file.
+ * Count of frequencies read from the {@code time_in_state} file. Read from {@link
+ * #mProcTimeInStateReader#getCpuFrequenciesKhz()}.
*/
private int mFrequencyCount;
- private boolean mIsTracking;
-
- /**
- * A CPU time-in-state provider for testing. Imitates the behavior of the corresponding
- * methods in frameworks/native/libs/cputimeinstate/cputimeinstate.c
- */
- @VisibleForTesting
- public interface CpuTimeInStateReader {
- /**
- * Returns the overall number of cluster-frequency combinations.
- */
- int getCpuFrequencyCount();
-
- /**
- * Returns true to indicate success.
- *
- * Called from native.
- */
- boolean startTrackingProcessCpuTimes(int tgid);
-
- /**
- * Returns true to indicate success.
- *
- * Called from native.
- */
- boolean startAggregatingTaskCpuTimes(int pid, int aggregationKey);
-
- /**
- * Must return an array of strings formatted like this:
- * "aggKey:t0_0 t0_1...:t1_0 t1_1..."
- * Times should be provided in nanoseconds.
- *
- * Called from native.
- */
- String[] getAggregatedTaskCpuFreqTimes(int pid);
- }
-
/**
* Create with a path where `proc` is mounted. Used primarily for testing
*
* @param pid PID of the process whose threads are to be read.
+ * @param procPath where `proc` is mounted (to find, see {@code mount | grep ^proc})
*/
@VisibleForTesting
- public KernelSingleProcessCpuThreadReader(int pid,
- @Nullable CpuTimeInStateReader cpuTimeInStateReader) throws IOException {
+ public KernelSingleProcessCpuThreadReader(
+ int pid,
+ Path procPath) throws IOException {
mPid = pid;
- mCpuTimeInStateReader = cpuTimeInStateReader;
+ mProcPath = procPath;
+ mProcTimeInStateReader = new ProcTimeInStateReader(
+ mProcPath.resolve(INITIAL_TIME_IN_STATE_PATH));
+ long jiffyHz = Os.sysconf(OsConstants._SC_CLK_TCK);
+ mJiffyMillis = 1000 / jiffyHz;
+ mProcessStatFilePath =
+ mProcPath.resolve(String.valueOf(mPid)).resolve(PROC_STAT_FILENAME).toString();
+ mThreadsDirectoryPath =
+ mProcPath.resolve(String.valueOf(mPid)).resolve(THREAD_CPU_STATS_DIRECTORY);
}
/**
@@ -103,7 +142,7 @@
@Nullable
public static KernelSingleProcessCpuThreadReader create(int pid) {
try {
- return new KernelSingleProcessCpuThreadReader(pid, null);
+ return new KernelSingleProcessCpuThreadReader(pid, DEFAULT_PROC_PATH);
} catch (IOException e) {
Slog.e(TAG, "Failed to initialize KernelSingleProcessCpuThreadReader", e);
return null;
@@ -111,98 +150,146 @@
}
/**
- * Starts tracking aggregated CPU time-in-state of all threads of the process with the PID
- * supplied in the constructor.
- */
- public void startTrackingThreadCpuTimes() {
- if (!mIsTracking) {
- if (!startTrackingProcessCpuTimes(mPid, mCpuTimeInStateReader)) {
- Slog.e(TAG, "Failed to start tracking process CPU times for " + mPid);
- }
- if (mSelectedThreadNativeTids.length > 0) {
- if (!startAggregatingThreadCpuTimes(mSelectedThreadNativeTids,
- mCpuTimeInStateReader)) {
- Slog.e(TAG, "Failed to start tracking aggregated thread CPU times for "
- + Arrays.toString(mSelectedThreadNativeTids));
- }
- }
- mIsTracking = true;
- }
- }
-
- /**
- * @param nativeTids an array of native Thread IDs whose CPU times should
- * be aggregated as a group. This is expected to be a subset
- * of all thread IDs owned by the process.
- */
- public void setSelectedThreadIds(int[] nativeTids) {
- mSelectedThreadNativeTids = nativeTids.clone();
- if (mIsTracking) {
- startAggregatingThreadCpuTimes(mSelectedThreadNativeTids, mCpuTimeInStateReader);
- }
- }
-
- /**
- * Get the CPU frequencies that correspond to the times reported in {@link ProcessCpuUsage}.
+ * Get the CPU frequencies that correspond to the times reported in {@link
+ * ProcessCpuUsage#processCpuTimesMillis} etc.
*/
public int getCpuFrequencyCount() {
if (mFrequencyCount == 0) {
- mFrequencyCount = getCpuFrequencyCount(mCpuTimeInStateReader);
+ mFrequencyCount = mProcTimeInStateReader.getFrequenciesKhz().length;
}
return mFrequencyCount;
}
/**
- * Get the total CPU usage of the process with the PID specified in the
- * constructor. The CPU usage time is aggregated across all threads and may
- * exceed the time the entire process has been running.
+ * Get the total and per-thread CPU usage of the process with the PID specified in the
+ * constructor.
+ *
+ * @param selectedThreadIds a SORTED array of native Thread IDs whose CPU times should
+ * be aggregated as a group. This is expected to be a subset
+ * of all thread IDs owned by the process.
*/
@Nullable
- public ProcessCpuUsage getProcessCpuUsage() {
+ public ProcessCpuUsage getProcessCpuUsage(int[] selectedThreadIds) {
if (DEBUG) {
- Slog.d(TAG, "Reading CPU thread usages for PID " + mPid);
+ Slog.d(TAG, "Reading CPU thread usages with directory " + mProcPath + " process ID "
+ + mPid);
}
- ProcessCpuUsage processCpuUsage = new ProcessCpuUsage(getCpuFrequencyCount());
+ int cpuFrequencyCount = getCpuFrequencyCount();
+ ProcessCpuUsage processCpuUsage = new ProcessCpuUsage(cpuFrequencyCount);
- boolean result = readProcessCpuUsage(mPid,
- processCpuUsage.threadCpuTimesMillis,
- processCpuUsage.selectedThreadCpuTimesMillis,
- mCpuTimeInStateReader);
- if (!result) {
+ if (NATIVE_ENABLED) {
+ boolean result = readProcessCpuUsage(mProcPath.toString(), mPid,
+ selectedThreadIds, processCpuUsage.processCpuTimesMillis,
+ processCpuUsage.threadCpuTimesMillis,
+ processCpuUsage.selectedThreadCpuTimesMillis);
+ if (!result) {
+ return null;
+ }
+ return processCpuUsage;
+ }
+
+ if (!isSorted(selectedThreadIds)) {
+ throw new IllegalArgumentException("selectedThreadIds is not sorted: "
+ + Arrays.toString(selectedThreadIds));
+ }
+
+ if (!Process.readProcFile(mProcessStatFilePath, PROCESS_FULL_STATS_FORMAT, null,
+ mProcessFullStatsData, null)) {
+ Slog.e(TAG, "Failed to read process stat file " + mProcessStatFilePath);
return null;
}
- if (DEBUG) {
- Slog.d(TAG, "threadCpuTimesMillis = "
- + Arrays.toString(processCpuUsage.threadCpuTimesMillis));
- Slog.d(TAG, "selectedThreadCpuTimesMillis = "
- + Arrays.toString(processCpuUsage.selectedThreadCpuTimesMillis));
+ long utime = mProcessFullStatsData[PROCESS_FULL_STAT_UTIME];
+ long stime = mProcessFullStatsData[PROCESS_FULL_STAT_STIME];
+
+ long processCpuTimeMillis = (utime + stime) * mJiffyMillis;
+
+ try (DirectoryStream<Path> threadPaths = Files.newDirectoryStream(mThreadsDirectoryPath)) {
+ for (Path threadDirectory : threadPaths) {
+ readThreadCpuUsage(processCpuUsage, selectedThreadIds, threadDirectory);
+ }
+ } catch (IOException | DirectoryIteratorException e) {
+ // Expected when a process finishes
+ return null;
+ }
+
+ // Estimate per cluster per frequency CPU time for the entire process
+ // by distributing the total process CPU time proportionately to how much
+ // CPU time its threads took on those clusters/frequencies. This algorithm
+ // works more accurately when when we have equally distributed concurrency.
+ // TODO(b/169279846): obtain actual process CPU times from the kernel
+ long totalCpuTimeAllThreads = 0;
+ for (int i = cpuFrequencyCount - 1; i >= 0; i--) {
+ totalCpuTimeAllThreads += processCpuUsage.threadCpuTimesMillis[i];
+ }
+
+ for (int i = cpuFrequencyCount - 1; i >= 0; i--) {
+ processCpuUsage.processCpuTimesMillis[i] =
+ processCpuTimeMillis * processCpuUsage.threadCpuTimesMillis[i]
+ / totalCpuTimeAllThreads;
}
return processCpuUsage;
}
+ /**
+ * Reads a thread's CPU usage and aggregates the per-cluster per-frequency CPU times.
+ *
+ * @param threadDirectory the {@code /proc} directory of the thread
+ */
+ private void readThreadCpuUsage(ProcessCpuUsage processCpuUsage, int[] selectedThreadIds,
+ Path threadDirectory) {
+ // Get the thread ID from the directory name
+ final int threadId;
+ try {
+ final String directoryName = threadDirectory.getFileName().toString();
+ threadId = Integer.parseInt(directoryName);
+ } catch (NumberFormatException e) {
+ Slog.w(TAG, "Failed to parse thread ID when iterating over /proc/*/task", e);
+ return;
+ }
+
+ // Get the CPU statistics from the directory
+ final Path threadCpuStatPath = threadDirectory.resolve(CPU_STATISTICS_FILENAME);
+ final long[] cpuUsages = mProcTimeInStateReader.getUsageTimesMillis(threadCpuStatPath);
+ if (cpuUsages == null) {
+ return;
+ }
+
+ final int cpuFrequencyCount = getCpuFrequencyCount();
+ final boolean isSelectedThread = Arrays.binarySearch(selectedThreadIds, threadId) >= 0;
+ for (int i = cpuFrequencyCount - 1; i >= 0; i--) {
+ processCpuUsage.threadCpuTimesMillis[i] += cpuUsages[i];
+ if (isSelectedThread) {
+ processCpuUsage.selectedThreadCpuTimesMillis[i] += cpuUsages[i];
+ }
+ }
+ }
+
/** CPU usage of a process, all of its threads and a selected subset of its threads */
public static class ProcessCpuUsage {
+ public long[] processCpuTimesMillis;
public long[] threadCpuTimesMillis;
public long[] selectedThreadCpuTimesMillis;
public ProcessCpuUsage(int cpuFrequencyCount) {
+ processCpuTimesMillis = new long[cpuFrequencyCount];
threadCpuTimesMillis = new long[cpuFrequencyCount];
selectedThreadCpuTimesMillis = new long[cpuFrequencyCount];
}
}
- private native int getCpuFrequencyCount(CpuTimeInStateReader reader);
+ private static boolean isSorted(int[] array) {
+ for (int i = 0; i < array.length - 1; i++) {
+ if (array[i] > array[i + 1]) {
+ return false;
+ }
+ }
+ return true;
+ }
- private native boolean startTrackingProcessCpuTimes(int pid, CpuTimeInStateReader reader);
-
- private native boolean startAggregatingThreadCpuTimes(int[] selectedThreadIds,
- CpuTimeInStateReader reader);
-
- private native boolean readProcessCpuUsage(int pid,
- long[] threadCpuTimesMillis,
- long[] selectedThreadCpuTimesMillis,
- CpuTimeInStateReader reader);
+ private native boolean readProcessCpuUsage(String procPath, int pid, int[] selectedThreadIds,
+ long[] processCpuTimesMillis, long[] threadCpuTimesMillis,
+ long[] selectedThreadCpuTimesMillis);
}
diff --git a/core/java/com/android/internal/os/KernelWakelockReader.java b/core/java/com/android/internal/os/KernelWakelockReader.java
index e595db3..c416814 100644
--- a/core/java/com/android/internal/os/KernelWakelockReader.java
+++ b/core/java/com/android/internal/os/KernelWakelockReader.java
@@ -78,13 +78,16 @@
boolean useSystemSuspend = (new File(sSysClassWakeupDir)).exists();
if (useSystemSuspend) {
- // Get both kernel and native wakelock stats from SystemSuspend
- updateVersion(staleStats);
- if (getWakelockStatsFromSystemSuspend(staleStats) == null) {
- Slog.w(TAG, "Failed to get wakelock stats from SystemSuspend");
- return null;
+ // static read/write lock protection for sKernelWakelockUpdateVersion
+ synchronized (KernelWakelockReader.class) {
+ // Get both kernel and native wakelock stats from SystemSuspend
+ updateVersion(staleStats);
+ if (getWakelockStatsFromSystemSuspend(staleStats) == null) {
+ Slog.w(TAG, "Failed to get wakelock stats from SystemSuspend");
+ return null;
+ }
+ return removeOldStats(staleStats);
}
- return removeOldStats(staleStats);
} else {
Arrays.fill(mKernelWakelockBuffer, (byte) 0);
int len = 0;
@@ -141,14 +144,17 @@
}
}
- updateVersion(staleStats);
- // Get native wakelock stats from SystemSuspend
- if (getWakelockStatsFromSystemSuspend(staleStats) == null) {
- Slog.w(TAG, "Failed to get Native wakelock stats from SystemSuspend");
+ // static read/write lock protection for sKernelWakelockUpdateVersion
+ synchronized (KernelWakelockReader.class) {
+ updateVersion(staleStats);
+ // Get native wakelock stats from SystemSuspend
+ if (getWakelockStatsFromSystemSuspend(staleStats) == null) {
+ Slog.w(TAG, "Failed to get Native wakelock stats from SystemSuspend");
+ }
+ // Get kernel wakelock stats
+ parseProcWakelocks(mKernelWakelockBuffer, len, wakeup_sources, staleStats);
+ return removeOldStats(staleStats);
}
- // Get kernel wakelock stats
- parseProcWakelocks(mKernelWakelockBuffer, len, wakeup_sources, staleStats);
- return removeOldStats(staleStats);
}
}
diff --git a/core/java/com/android/internal/os/PhonePowerCalculator.java b/core/java/com/android/internal/os/PhonePowerCalculator.java
index 27f19c0..992c487 100644
--- a/core/java/com/android/internal/os/PhonePowerCalculator.java
+++ b/core/java/com/android/internal/os/PhonePowerCalculator.java
@@ -19,6 +19,7 @@
import android.os.BatteryConsumer;
import android.os.BatteryStats;
import android.os.BatteryUsageStats;
+import android.os.BatteryUsageStatsQuery;
import android.os.SystemBatteryConsumer;
import android.os.UserHandle;
import android.util.SparseArray;
@@ -37,8 +38,10 @@
@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;
+ long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query,
+ SparseArray<UserHandle> asUsers) {
+ long phoneOnTimeMs = batteryStats.getPhoneOnTime(rawRealtimeUs,
+ BatteryStats.STATS_SINCE_CHARGED) / 1000;
double phoneOnPower = mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ACTIVE)
* phoneOnTimeMs / (60 * 60 * 1000);
if (phoneOnPower != 0) {
diff --git a/core/java/com/android/internal/os/PowerCalculator.java b/core/java/com/android/internal/os/PowerCalculator.java
index 23f96d9..974894f 100644
--- a/core/java/com/android/internal/os/PowerCalculator.java
+++ b/core/java/com/android/internal/os/PowerCalculator.java
@@ -17,6 +17,7 @@
import android.os.BatteryStats;
import android.os.BatteryUsageStats;
+import android.os.BatteryUsageStatsQuery;
import android.os.UidBatteryConsumer;
import android.os.UserHandle;
import android.util.SparseArray;
@@ -75,12 +76,13 @@
* should be performed for all users.
*/
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
- long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) {
+ long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query,
+ SparseArray<UserHandle> asUsers) {
final SparseArray<UidBatteryConsumer.Builder> uidBatteryConsumerBuilders =
builder.getUidBatteryConsumerBuilders();
for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {
final UidBatteryConsumer.Builder app = uidBatteryConsumerBuilders.valueAt(i);
- calculateApp(app, app.getBatteryStatsUid(), rawRealtimeUs, rawUptimeUs, statsType);
+ calculateApp(app, app.getBatteryStatsUid(), rawRealtimeUs, rawUptimeUs, query);
}
}
@@ -100,8 +102,8 @@
// TODO(b/175156498): Temporary code during the transition from BatterySippers to
// BatteryConsumers.
- UidBatteryConsumer.Builder builder = new UidBatteryConsumer.Builder(0, 0, u);
- calculateApp(builder, u, rawRealtimeUs, rawUptimeUs, statsType);
+ UidBatteryConsumer.Builder builder = new UidBatteryConsumer.Builder(0, 0, false, u);
+ calculateApp(builder, u, rawRealtimeUs, rawUptimeUs, BatteryUsageStatsQuery.DEFAULT);
final UidBatteryConsumer uidBatteryConsumer = builder.build();
app.cpuPowerMah = uidBatteryConsumer.getConsumedPower(
UidBatteryConsumer.POWER_COMPONENT_CPU);
@@ -118,13 +120,10 @@
* @param u The recorded stats for the app.
* @param rawRealtimeUs The raw system realtime in microseconds.
* @param rawUptimeUs The raw system uptime in microseconds.
- * @param statsType The type of stats. As of {@link android.os.Build.VERSION_CODES#Q}, this can
- * only be {@link BatteryStats#STATS_SINCE_CHARGED}, since
- * {@link BatteryStats#STATS_CURRENT} and
- * {@link BatteryStats#STATS_SINCE_UNPLUGGED} are deprecated.
+ * @param query Power calculation parameters.
*/
protected void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u,
- long rawRealtimeUs, long rawUptimeUs, int statsType) {
+ long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
}
/**
diff --git a/core/java/com/android/internal/os/SensorPowerCalculator.java b/core/java/com/android/internal/os/SensorPowerCalculator.java
index 5002daf..9c8aafb 100644
--- a/core/java/com/android/internal/os/SensorPowerCalculator.java
+++ b/core/java/com/android/internal/os/SensorPowerCalculator.java
@@ -17,12 +17,11 @@
import android.hardware.Sensor;
import android.hardware.SensorManager;
+import android.location.GnssSignalQuality;
import android.os.BatteryStats;
import android.os.UserHandle;
import android.util.SparseArray;
-import com.android.internal.location.gnssmetrics.GnssMetrics;
-
import java.util.List;
public class SensorPowerCalculator extends PowerCalculator {
@@ -83,7 +82,7 @@
averagePower = 0;
long totalTime = 0;
double totalPower = 0;
- for (int i = 0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+ for (int i = 0; i < GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS; i++) {
long timePerLevel = stats.getGpsSignalQualityTime(i, rawRealtimeUs, statsType);
totalTime += timePerLevel;
totalPower +=
diff --git a/core/java/com/android/internal/os/SystemServerCpuThreadReader.java b/core/java/com/android/internal/os/SystemServerCpuThreadReader.java
index fbad75e..fbbee94 100644
--- a/core/java/com/android/internal/os/SystemServerCpuThreadReader.java
+++ b/core/java/com/android/internal/os/SystemServerCpuThreadReader.java
@@ -22,6 +22,8 @@
import com.android.internal.annotations.VisibleForTesting;
import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Arrays;
/**
* Reads /proc/UID/task/TID/time_in_state files to obtain statistics on CPU usage
@@ -29,7 +31,9 @@
*/
public class SystemServerCpuThreadReader {
private final KernelSingleProcessCpuThreadReader mKernelCpuThreadReader;
+ private int[] mBinderThreadNativeTids = new int[0]; // Sorted
+ private long[] mLastProcessCpuTimeUs;
private long[] mLastThreadCpuTimesUs;
private long[] mLastBinderThreadCpuTimesUs;
@@ -37,6 +41,8 @@
* Times (in microseconds) spent by the system server UID.
*/
public static class SystemServiceCpuThreadTimes {
+ // The entire process
+ public long[] processCpuTimesUs;
// All threads
public long[] threadCpuTimesUs;
// Just the threads handling incoming binder calls
@@ -55,10 +61,8 @@
}
@VisibleForTesting
- public SystemServerCpuThreadReader(int pid,
- KernelSingleProcessCpuThreadReader.CpuTimeInStateReader cpuTimeInStateReader)
- throws IOException {
- this(new KernelSingleProcessCpuThreadReader(pid, cpuTimeInStateReader));
+ public SystemServerCpuThreadReader(Path procPath, int pid) throws IOException {
+ this(new KernelSingleProcessCpuThreadReader(pid, procPath));
}
@VisibleForTesting
@@ -66,15 +70,9 @@
mKernelCpuThreadReader = kernelCpuThreadReader;
}
- /**
- * Start tracking CPU time-in-state for the process specified in the constructor.
- */
- public void startTrackingThreadCpuTime() {
- mKernelCpuThreadReader.startTrackingThreadCpuTimes();
- }
-
public void setBinderThreadNativeTids(int[] nativeTids) {
- mKernelCpuThreadReader.setSelectedThreadIds(nativeTids);
+ mBinderThreadNativeTids = nativeTids.clone();
+ Arrays.sort(mBinderThreadNativeTids);
}
/**
@@ -83,27 +81,33 @@
@Nullable
public SystemServiceCpuThreadTimes readDelta() {
final int numCpuFrequencies = mKernelCpuThreadReader.getCpuFrequencyCount();
- if (mLastThreadCpuTimesUs == null) {
+ if (mLastProcessCpuTimeUs == null) {
+ mLastProcessCpuTimeUs = new long[numCpuFrequencies];
mLastThreadCpuTimesUs = new long[numCpuFrequencies];
mLastBinderThreadCpuTimesUs = new long[numCpuFrequencies];
+ mDeltaCpuThreadTimes.processCpuTimesUs = new long[numCpuFrequencies];
mDeltaCpuThreadTimes.threadCpuTimesUs = new long[numCpuFrequencies];
mDeltaCpuThreadTimes.binderThreadCpuTimesUs = new long[numCpuFrequencies];
}
final KernelSingleProcessCpuThreadReader.ProcessCpuUsage processCpuUsage =
- mKernelCpuThreadReader.getProcessCpuUsage();
+ mKernelCpuThreadReader.getProcessCpuUsage(mBinderThreadNativeTids);
if (processCpuUsage == null) {
return null;
}
for (int i = numCpuFrequencies - 1; i >= 0; i--) {
+ long processCpuTimesUs = processCpuUsage.processCpuTimesMillis[i] * 1000;
long threadCpuTimesUs = processCpuUsage.threadCpuTimesMillis[i] * 1000;
long binderThreadCpuTimesUs = processCpuUsage.selectedThreadCpuTimesMillis[i] * 1000;
+ mDeltaCpuThreadTimes.processCpuTimesUs[i] =
+ Math.max(0, processCpuTimesUs - mLastProcessCpuTimeUs[i]);
mDeltaCpuThreadTimes.threadCpuTimesUs[i] =
Math.max(0, threadCpuTimesUs - mLastThreadCpuTimesUs[i]);
mDeltaCpuThreadTimes.binderThreadCpuTimesUs[i] =
Math.max(0, binderThreadCpuTimesUs - mLastBinderThreadCpuTimesUs[i]);
+ mLastProcessCpuTimeUs[i] = processCpuTimesUs;
mLastThreadCpuTimesUs[i] = threadCpuTimesUs;
mLastBinderThreadCpuTimesUs[i] = binderThreadCpuTimesUs;
}
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 5e20cd0..fda87be 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -24,7 +24,6 @@
import android.net.Credentials;
import android.net.LocalServerSocket;
import android.net.LocalSocket;
-import android.net.NetworkUtils;
import android.os.FactoryTest;
import android.os.IVold;
import android.os.Process;
@@ -35,6 +34,8 @@
import android.system.Os;
import android.util.Log;
+import com.android.internal.net.NetworkUtilsInternal;
+
import dalvik.annotation.optimization.FastNative;
import dalvik.system.ZygoteHooks;
@@ -340,7 +341,7 @@
// If no GIDs were specified, don't make any permissions changes based on groups.
if (gids != null && gids.length > 0) {
- NetworkUtils.setAllowNetworkingForProcess(containsInetGid(gids));
+ NetworkUtilsInternal.setAllowNetworkingForProcess(containsInetGid(gids));
}
}
diff --git a/core/java/com/android/internal/power/MeasuredEnergyStats.java b/core/java/com/android/internal/power/MeasuredEnergyStats.java
index 7b6e079..b644df4 100644
--- a/core/java/com/android/internal/power/MeasuredEnergyStats.java
+++ b/core/java/com/android/internal/power/MeasuredEnergyStats.java
@@ -17,9 +17,12 @@
package com.android.internal.power;
+import static android.os.BatteryStats.ENERGY_DATA_UNAVAILABLE;
+
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.os.Parcel;
+import android.util.Slog;
import android.view.Display;
import com.android.internal.annotations.VisibleForTesting;
@@ -28,16 +31,19 @@
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.Arrays;
/**
- * MeasuredEnergyStats adds up the measured energy usage of various subsystems
+ * Tracks the measured energy usage of various subsystems according to their {@link EnergyBucket}.
+ *
+ * This class doesn't use a TimeBase, and instead requires manually decisions about when to
+ * accumulate since it is trivial. However, in the future, a TimeBase could be used instead.
*/
@VisibleForTesting
public class MeasuredEnergyStats {
- private static final long UNAVAILABLE = -1;
- private static final long RESET = -2;
+ private static final String TAG = "MeasuredEnergyStats";
+ // Note: {@link com.android.internal.os.BatteryStatsImpl#VERSION} must be updated if energy
+ // bucket integers are modified.
public static final int ENERGY_BUCKET_UNKNOWN = -1;
public static final int ENERGY_BUCKET_SCREEN_ON = 0;
public static final int ENERGY_BUCKET_SCREEN_DOZE = 1;
@@ -57,45 +63,59 @@
}
/**
- * Energy snapshots from the last time each {@link MeasuredEnergySubsystem} was updated.
- * An energy snapshot will be set to {@link #UNAVAILABLE} if the subsystem has never been
- * updated.
- * An energy snapshot will be set to {@link #RESET} on a reset. A subsystems energy will
- * need to be updated at least twice to start accumulating energy again.
- */
- private final long[] mMeasuredEnergySnapshots =
- new long[MeasuredEnergyArray.NUMBER_SUBSYSTEMS];
-
- /**
- * Total energy in microjoules since the last reset that an {@link EnergyBucket} has
- * accumulated.
+ * Total energy (in microjoules) that an {@link EnergyBucket} has accumulated since the last
+ * reset. Values MUST be non-zero or ENERGY_DATA_UNAVAILABLE. Accumulation only occurs
+ * while the necessary conditions are satisfied (e.g. on battery).
*
* Warning: Long array is used for access speed. If the number of supported subsystems
- * becomes too large, consider using an alternate data structure.
+ * becomes large, consider using an alternate data structure such as a SparseLongArray.
*/
private final long[] mAccumulatedEnergiesMicroJoules = new long[NUMBER_ENERGY_BUCKETS];
/**
- * Last known screen state.
+ * Creates a MeasuredEnergyStats set to support the provided energy buckets.
+ * supportedEnergyBuckets should generally be of size {@link #NUMBER_ENERGY_BUCKETS}.
*/
- private int mLastScreenState;
-
- public MeasuredEnergyStats(MeasuredEnergyArray energyArray, int screenState) {
- Arrays.fill(mMeasuredEnergySnapshots, UNAVAILABLE);
-
- update(energyArray, screenState, false);
- }
-
- public MeasuredEnergyStats(Parcel in) {
- in.readLongArray(mAccumulatedEnergiesMicroJoules);
+ public MeasuredEnergyStats(boolean[] supportedEnergyBuckets) {
+ // Initialize to all zeros where supported, otherwise ENERGY_DATA_UNAVAILABLE.
+ for (int bucket = 0; bucket < NUMBER_ENERGY_BUCKETS; bucket++) {
+ if (!supportedEnergyBuckets[bucket]) {
+ mAccumulatedEnergiesMicroJoules[bucket] = ENERGY_DATA_UNAVAILABLE;
+ }
+ }
}
/**
- * Constructor for creating a temp MeasuredEnergyStats
- * See {@link #readSummaryFromParcel(MeasuredEnergyStats, Parcel)}
+ * Creates a new zero'd MeasuredEnergyStats, using the template to determine which buckets are
+ * supported. This certainly does NOT produce an exact clone of the template.
+ */
+ private MeasuredEnergyStats(MeasuredEnergyStats template) {
+ // Initialize to all zeros where supported, otherwise ENERGY_DATA_UNAVAILABLE.
+ for (int bucket = 0; bucket < NUMBER_ENERGY_BUCKETS; bucket++) {
+ if (!template.isEnergyBucketSupported(bucket)) {
+ mAccumulatedEnergiesMicroJoules[bucket] = ENERGY_DATA_UNAVAILABLE;
+ }
+ }
+ }
+
+ /**
+ * Creates a new zero'd MeasuredEnergyStats, using the template to determine which buckets are
+ * supported.
+ */
+ public static MeasuredEnergyStats createFromTemplate(MeasuredEnergyStats template) {
+ return new MeasuredEnergyStats(template);
+ }
+
+ /**
+ * Constructor for creating a temp MeasuredEnergyStats.
+ * See {@link #readSummaryFromParcel(MeasuredEnergyStats, Parcel)}.
*/
private MeasuredEnergyStats() {
- Arrays.fill(mMeasuredEnergySnapshots, UNAVAILABLE);
+ }
+
+ /** Construct from parcel. */
+ public MeasuredEnergyStats(Parcel in) {
+ in.readLongArray(mAccumulatedEnergiesMicroJoules);
}
/** Write to parcel */
@@ -105,38 +125,32 @@
/**
* Read from summary parcel.
- * Note: Measured subsystem availability may be different from when the summary parcel was
- * written.
+ * Note: Measured subsystem (and therefore bucket) availability may be different from when the
+ * summary parcel was written. Availability has already been correctly set in the constructor.
+ * Note: {@link com.android.internal.os.BatteryStatsImpl#VERSION} must be updated if summary
+ * parceling changes.
*/
private void readSummaryFromParcel(Parcel in) {
final int size = in.readInt();
for (int i = 0; i < size; i++) {
final int bucket = in.readInt();
final long energyUJ = in.readLong();
-
- final int subsystem = getSubsystem(bucket);
- // Only accept the summary energy if subsystem is currently available
- if (subsystem != MeasuredEnergyArray.SUBSYSTEM_UNKNOWN
- && mMeasuredEnergySnapshots[subsystem] != UNAVAILABLE) {
- mAccumulatedEnergiesMicroJoules[bucket] = energyUJ;
- }
+ setValueIfSupported(bucket, energyUJ);
}
}
/**
* Write to summary parcel.
* Note: Measured subsystem availability may be different when the summary parcel is read.
- * Note: {@link com.android.internal.os.BatteryStatsImpl#VERSION} must be updated if summary
- * parceling changes.
*/
private void writeSummaryToParcel(Parcel out) {
final int sizePos = out.dataPosition();
out.writeInt(0);
int size = 0;
- // Write only the buckets with reported energy
+ // Write only the supported buckets with non-zero energy.
for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) {
- final int subsystem = getSubsystem(i);
- if (mMeasuredEnergySnapshots[subsystem] == UNAVAILABLE) continue;
+ final long energy = mAccumulatedEnergiesMicroJoules[i];
+ if (energy <= 0) continue;
out.writeInt(i);
out.writeLong(mAccumulatedEnergiesMicroJoules[i]);
@@ -148,91 +162,41 @@
out.setDataPosition(currPos);
}
- /**
- * Update with the latest measured energies and device state.
- *
- * @param energyArray measured energy array for some subsystems.
- * @param screenState screen state to attribute disaply energy to after this update.
- * @param accumulate whether or not to accumulate the latest energy
- */
- public void update(MeasuredEnergyArray energyArray, int screenState, boolean accumulate) {
- final int size = energyArray.size();
- if (!accumulate) {
- for (int i = 0; i < size; i++) {
- final int subsystem = energyArray.getSubsystem(i);
- mMeasuredEnergySnapshots[subsystem] = energyArray.getEnergy(i);
- }
- } else {
- for (int i = 0; i < size; i++) {
- final int subsystem = energyArray.getSubsystem(i);
- final long newEnergyUJ = energyArray.getEnergy(i);
- final long oldEnergyUJ = mMeasuredEnergySnapshots[subsystem];
- mMeasuredEnergySnapshots[subsystem] = newEnergyUJ;
-
- // This is the first valid energy, skip accumulating the delta
- if (oldEnergyUJ < 0) continue;
- final long deltaUJ = newEnergyUJ - oldEnergyUJ;
-
- final int bucket = getEnergyBucket(subsystem, mLastScreenState);
- mAccumulatedEnergiesMicroJoules[bucket] += deltaUJ;
+ /** Updates the given bucket with the given energy iff accumulate is true. */
+ public void updateBucket(@EnergyBucket int bucket, long energyDeltaUJ, boolean accumulate) {
+ if (accumulate) {
+ if (mAccumulatedEnergiesMicroJoules[bucket] >= 0L) {
+ mAccumulatedEnergiesMicroJoules[bucket] += energyDeltaUJ;
+ } else {
+ Slog.wtf(TAG, "Attempting to add " + energyDeltaUJ + " to unavailable bucket "
+ + ENERGY_BUCKET_NAMES[bucket] + " whose value was "
+ + mAccumulatedEnergiesMicroJoules[bucket]);
}
}
- mLastScreenState = screenState;
}
/**
- * Map {@link MeasuredEnergySubsystem} and device state to an {@link EnergyBucket}.
- * Keep in sync with {@link #getSubsystem}
- */
- @EnergyBucket
- private int getEnergyBucket(@MeasuredEnergySubsystem int subsystem, int screenState) {
- switch (subsystem) {
- case MeasuredEnergyArray.SUBSYSTEM_DISPLAY:
- if (Display.isOnState(screenState)) {
- return ENERGY_BUCKET_SCREEN_ON;
- } else if (Display.isDozeState(screenState)) {
- return ENERGY_BUCKET_SCREEN_DOZE;
- } else {
- return ENERGY_BUCKET_SCREEN_OTHER;
- }
- default:
- return ENERGY_BUCKET_UNKNOWN;
- }
- }
-
- /**
- * Map {@link EnergyBucket} to a {@link MeasuredEnergySubsystem}.
- * Keep in sync with {@link #getEnergyBucket}
- */
- @MeasuredEnergySubsystem
- private int getSubsystem(@EnergyBucket int bucket) {
- switch (bucket) {
- case ENERGY_BUCKET_SCREEN_ON: //fallthrough
- case ENERGY_BUCKET_SCREEN_DOZE: //fallthrough
- case ENERGY_BUCKET_SCREEN_OTHER:
- return MeasuredEnergyArray.SUBSYSTEM_DISPLAY;
- default:
- return MeasuredEnergyArray.SUBSYSTEM_UNKNOWN;
- }
- }
-
- /**
- * Check if a subsystem's measured energy is available.
- * @param subsystem which subsystem.
- * @return true if subsystem is avaiable.
- */
- public boolean hasSubsystem(@MeasuredEnergySubsystem int subsystem) {
- return mMeasuredEnergySnapshots[subsystem] != UNAVAILABLE;
- }
-
- /**
- * Return accumulated energy (in microjoules) since last reset.
+ * Return accumulated energy (in microjoules) for the given energy bucket since last reset.
+ * Returns {@link BatteryStats#ENERGY_DATA_UNAVAILABLE} if this energy data is unavailable.
*/
public long getAccumulatedBucketEnergy(@EnergyBucket int bucket) {
return mAccumulatedEnergiesMicroJoules[bucket];
}
/**
+ * Map {@link MeasuredEnergySubsystem} and device state to a Display {@link EnergyBucket}.
+ */
+ public static @EnergyBucket int getDisplayEnergyBucket(int screenState) {
+ if (Display.isOnState(screenState)) {
+ return ENERGY_BUCKET_SCREEN_ON;
+ }
+ if (Display.isDozeState(screenState)) {
+ return ENERGY_BUCKET_SCREEN_DOZE;
+ }
+ return ENERGY_BUCKET_SCREEN_OTHER;
+ }
+
+ /**
* Populate a MeasuredEnergyStats from a parcel. If the stats is null, consume and
* ignore the parcelled data.
*/
@@ -246,6 +210,46 @@
}
/**
+ * Create a MeasuredEnergyStats using the template to determine which buckets are supported,
+ * and populate this new object from the given parcel.
+ *
+ * @return a new MeasuredEnergyStats object as described.
+ * Returns null if the stats contain no non-0 information (such as if template is null
+ * or if the parcel indicates there is no data to populate).
+ *
+ * @see #createFromTemplate
+ */
+ public static @Nullable MeasuredEnergyStats createAndReadSummaryFromParcel(Parcel in,
+ @Nullable MeasuredEnergyStats template) {
+ // Check if any MeasuredEnergyStats exists on the parcel
+ if (in.readInt() == 0) return null;
+
+ if (template == null) {
+ // Nothing supported now. Create placeholder object just to consume the parcel data.
+ final MeasuredEnergyStats mes = new MeasuredEnergyStats();
+ mes.readSummaryFromParcel(in);
+ return null;
+ }
+
+ final MeasuredEnergyStats stats = createFromTemplate(template);
+ stats.readSummaryFromParcel(in);
+ if (stats.containsInterestingData()) {
+ return stats;
+ } else {
+ // Don't waste RAM on it (and make sure not to persist it in the next writeSummary)
+ return null;
+ }
+ }
+
+ /** Returns true iff any of the buckets are supported and non-zero. */
+ private boolean containsInterestingData() {
+ for (int bucket = 0; bucket < NUMBER_ENERGY_BUCKETS; bucket++) {
+ if (mAccumulatedEnergiesMicroJoules[bucket] > 0) return true;
+ }
+ return false;
+ }
+
+ /**
* Write a MeasuredEnergyStats to a parcel. If the stats is null, just write a 0.
*/
public static void writeSummaryToParcel(@Nullable MeasuredEnergyStats stats,
@@ -258,47 +262,42 @@
stats.writeSummaryToParcel(dest);
}
- /**
- * Reset accumulated energy.
- */
- public void reset() {
- for (int i = 0; i < MeasuredEnergyArray.NUMBER_SUBSYSTEMS; i++) {
- // Leave subsystems marked as unavailable alone.
- if (mMeasuredEnergySnapshots[i] == UNAVAILABLE) continue;
- mMeasuredEnergySnapshots[i] = RESET;
+ /** Reset accumulated energy. */
+ private void reset() {
+ for (int bucket = 0; bucket < NUMBER_ENERGY_BUCKETS; bucket++) {
+ setValueIfSupported(bucket, 0L);
}
- Arrays.fill(mAccumulatedEnergiesMicroJoules, 0);
}
- /**
- * Dump debug data.
- */
- public void dump(PrintWriter pw) {
- pw.println("Measured energy snapshot (microjoules):");
- pw.print(" ");
- for (int i = 0; i < MeasuredEnergyArray.NUMBER_SUBSYSTEMS; i++) {
- final long energyUJ = mMeasuredEnergySnapshots[i];
- if (energyUJ == UNAVAILABLE) continue;
- pw.print(MeasuredEnergyArray.SUBSYSTEM_NAMES[i]);
- pw.print(" : ");
- if (energyUJ == RESET) {
- pw.print("reset");
- } else {
- pw.print(energyUJ);
- }
- if (i != MeasuredEnergyArray.NUMBER_SUBSYSTEMS - 1) {
- pw.print(", ");
- }
- }
- pw.println();
+ /** Reset accumulated energy of the given stats. */
+ public static void resetIfNotNull(@Nullable MeasuredEnergyStats stats) {
+ if (stats != null) stats.reset();
+ }
+ /** If the bucket is AVAILABLE, overwrite its value; otherwise leave it as UNAVAILABLE. */
+ private void setValueIfSupported(@EnergyBucket int bucket, long value) {
+ if (mAccumulatedEnergiesMicroJoules[bucket] != ENERGY_DATA_UNAVAILABLE) {
+ mAccumulatedEnergiesMicroJoules[bucket] = value;
+ }
+ }
+
+ /** Check if measuring the energy of the given bucket is supported by this device. */
+ public boolean isEnergyBucketSupported(@EnergyBucket int bucket) {
+ return mAccumulatedEnergiesMicroJoules[bucket] != ENERGY_DATA_UNAVAILABLE;
+ }
+
+ /** Dump debug data. */
+ public void dump(PrintWriter pw) {
pw.println("Accumulated energy since last reset (microjoules):");
pw.print(" ");
- for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) {
- pw.print(ENERGY_BUCKET_NAMES[i]);
+ for (int bucket = 0; bucket < NUMBER_ENERGY_BUCKETS; bucket++) {
+ pw.print(ENERGY_BUCKET_NAMES[bucket]);
pw.print(" : ");
- pw.print(mAccumulatedEnergiesMicroJoules[i]);
- if (i != NUMBER_ENERGY_BUCKETS - 1) {
+ pw.print(mAccumulatedEnergiesMicroJoules[bucket]);
+ if (!isEnergyBucketSupported(bucket)) {
+ pw.print(" (unsupported)");
+ }
+ if (bucket != NUMBER_ENERGY_BUCKETS - 1) {
pw.print(", ");
}
}
diff --git a/core/java/com/android/internal/power/OWNERS b/core/java/com/android/internal/power/OWNERS
new file mode 100644
index 0000000..4068e2b
--- /dev/null
+++ b/core/java/com/android/internal/power/OWNERS
@@ -0,0 +1 @@
+include /BATTERY_STATS_OWNERS
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index 5388235..3cf00ae 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -745,6 +745,25 @@
}
/**
+ * Throws {@link ArrayIndexOutOfBoundsException} if the range is out of bounds.
+ * @param len length of the array. Must be non-negative
+ * @param offset start index of the range. Must be non-negative
+ * @param count length of the range. Must be non-negative
+ * @throws ArrayIndexOutOfBoundsException if the range from {@code offset} with length
+ * {@code count} is out of bounds of the array
+ */
+ public static void throwsIfOutOfBounds(int len, int offset, int count) {
+ if (len < 0) {
+ throw new ArrayIndexOutOfBoundsException("Negative length: " + len);
+ }
+
+ if ((offset | count) < 0 || offset > len - count) {
+ throw new ArrayIndexOutOfBoundsException(
+ "length=" + len + "; regionStart=" + offset + "; regionLength=" + count);
+ }
+ }
+
+ /**
* Returns an array with values from {@code val} minus {@code null} values
*
* @param arrayConstructor typically {@code T[]::new} e.g. {@code String[]::new}
diff --git a/core/java/com/android/internal/util/BinaryXmlPullParser.java b/core/java/com/android/internal/util/BinaryXmlPullParser.java
index 68921ad..57552f3 100644
--- a/core/java/com/android/internal/util/BinaryXmlPullParser.java
+++ b/core/java/com/android/internal/util/BinaryXmlPullParser.java
@@ -95,8 +95,8 @@
private Attribute[] mAttributes;
@Override
- public void setInput(InputStream is, String inputEncoding) throws XmlPullParserException {
- if (inputEncoding != null && !StandardCharsets.UTF_8.name().equals(inputEncoding)) {
+ public void setInput(InputStream is, String encoding) throws XmlPullParserException {
+ if (encoding != null && !StandardCharsets.UTF_8.name().equalsIgnoreCase(encoding)) {
throw new UnsupportedOperationException();
}
@@ -262,19 +262,27 @@
break;
}
case XmlPullParser.START_DOCUMENT: {
+ mCurrentName = null;
+ mCurrentText = null;
+ if (mAttributeCount > 0) resetAttributes();
break;
}
case XmlPullParser.END_DOCUMENT: {
+ mCurrentName = null;
+ mCurrentText = null;
+ if (mAttributeCount > 0) resetAttributes();
break;
}
case XmlPullParser.START_TAG: {
mCurrentName = mIn.readInternedUTF();
- resetAttributes();
+ mCurrentText = null;
+ if (mAttributeCount > 0) resetAttributes();
break;
}
case XmlPullParser.END_TAG: {
mCurrentName = mIn.readInternedUTF();
- resetAttributes();
+ mCurrentText = null;
+ if (mAttributeCount > 0) resetAttributes();
break;
}
case XmlPullParser.TEXT:
@@ -283,12 +291,15 @@
case XmlPullParser.COMMENT:
case XmlPullParser.DOCDECL:
case XmlPullParser.IGNORABLE_WHITESPACE: {
+ mCurrentName = null;
mCurrentText = mIn.readUTF();
+ if (mAttributeCount > 0) resetAttributes();
break;
}
case XmlPullParser.ENTITY_REF: {
mCurrentName = mIn.readUTF();
mCurrentText = resolveEntity(mCurrentName);
+ if (mAttributeCount > 0) resetAttributes();
break;
}
default: {
@@ -428,7 +439,11 @@
@Override
public String getAttributeValue(String namespace, String name) {
final int index = getAttributeIndex(namespace, name);
- return mAttributes[index].getValueString();
+ if (index != -1) {
+ return mAttributes[index].getValueString();
+ } else {
+ return null;
+ }
}
@Override
diff --git a/core/java/com/android/internal/util/BinaryXmlSerializer.java b/core/java/com/android/internal/util/BinaryXmlSerializer.java
index bc3b1f8..9df4bdb 100644
--- a/core/java/com/android/internal/util/BinaryXmlSerializer.java
+++ b/core/java/com/android/internal/util/BinaryXmlSerializer.java
@@ -120,7 +120,7 @@
@Override
public void setOutput(@NonNull OutputStream os, @Nullable String encoding) throws IOException {
- if (encoding != null && !StandardCharsets.UTF_8.name().equals(encoding)) {
+ if (encoding != null && !StandardCharsets.UTF_8.name().equalsIgnoreCase(encoding)) {
throw new UnsupportedOperationException();
}
@@ -144,7 +144,10 @@
@Override
public void startDocument(@Nullable String encoding, @Nullable Boolean standalone)
throws IOException {
- if (encoding != null && !StandardCharsets.UTF_8.name().equals(encoding)) {
+ if (encoding != null && !StandardCharsets.UTF_8.name().equalsIgnoreCase(encoding)) {
+ throw new UnsupportedOperationException();
+ }
+ if (standalone != null && !standalone) {
throw new UnsupportedOperationException();
}
mOut.writeByte(START_DOCUMENT | TYPE_NULL);
diff --git a/core/java/com/android/internal/util/OWNERS b/core/java/com/android/internal/util/OWNERS
index 8b9acd3..a045451 100644
--- a/core/java/com/android/internal/util/OWNERS
+++ b/core/java/com/android/internal/util/OWNERS
@@ -2,3 +2,4 @@
per-file MessageUtils*, Protocol*, RingBuffer*, TokenBucket* = jchalard@google.com, lorenzo@google.com, satk@google.com
per-file Protocol* = etancohen@google.com, lorenzo@google.com
per-file State* = jchalard@google.com, lorenzo@google.com, satk@google.com
+per-file DataClass* = eugenesusla@google.com
\ No newline at end of file
diff --git a/core/java/com/android/internal/util/XmlSerializerWrapper.java b/core/java/com/android/internal/util/XmlSerializerWrapper.java
index 2131db0..9f28d90a 100644
--- a/core/java/com/android/internal/util/XmlSerializerWrapper.java
+++ b/core/java/com/android/internal/util/XmlSerializerWrapper.java
@@ -28,7 +28,7 @@
/**
* Wrapper which delegates all calls through to the given {@link XmlSerializer}.
*/
-public class XmlSerializerWrapper {
+public class XmlSerializerWrapper implements XmlSerializer {
private final XmlSerializer mWrapped;
public XmlSerializerWrapper(@NonNull XmlSerializer wrapped) {
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index 8962dc3..ef2275d 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -158,10 +158,6 @@
}
@Override
- public void dispatchPointerCaptureChanged(boolean hasCapture) {
- }
-
- @Override
public void requestScrollCapture(IScrollCaptureCallbacks callbacks) {
try {
callbacks.onUnavailable();
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java
index 1d5935d..3a7e66c 100644
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java
@@ -72,6 +72,7 @@
private static final int DO_DELETE_SURROUNDING_TEXT_IN_CODE_POINTS = 81;
private static final int DO_BEGIN_BATCH_EDIT = 90;
private static final int DO_END_BATCH_EDIT = 95;
+ private static final int DO_PERFORM_SPELL_CHECK = 110;
private static final int DO_PERFORM_PRIVATE_COMMAND = 120;
private static final int DO_CLEAR_META_KEY_STATES = 130;
private static final int DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO = 140;
@@ -234,6 +235,15 @@
dispatchMessage(obtainMessage(DO_END_BATCH_EDIT));
}
+ /**
+ * Dispatches the request for performing spell check.
+ *
+ * @see InputConnection#performSpellCheck()
+ */
+ public void performSpellCheck() {
+ dispatchMessage(obtainMessage(DO_PERFORM_SPELL_CHECK));
+ }
+
public void performPrivateCommand(String action, Bundle data) {
dispatchMessage(obtainMessageOO(DO_PERFORM_PRIVATE_COMMAND, action, data));
}
@@ -681,6 +691,20 @@
}
return;
}
+ case DO_PERFORM_SPELL_CHECK: {
+ Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#performSpellCheck");
+ try {
+ InputConnection ic = getInputConnection();
+ if (ic == null || !isActive()) {
+ Log.w(TAG, "performSpellCheck on inactive InputConnection");
+ return;
+ }
+ ic.performSpellCheck();
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_INPUT);
+ }
+ return;
+ }
case DO_PERFORM_PRIVATE_COMMAND: {
final SomeArgs args = (SomeArgs) msg.obj;
Trace.traceBegin(Trace.TRACE_TAG_INPUT, "InputConnection#performPrivateCommand");
diff --git a/core/java/com/android/internal/view/IInputContext.aidl b/core/java/com/android/internal/view/IInputContext.aidl
index 074908a..53cbf96 100644
--- a/core/java/com/android/internal/view/IInputContext.aidl
+++ b/core/java/com/android/internal/view/IInputContext.aidl
@@ -70,6 +70,8 @@
void clearMetaKeyStates(int states);
+ void performSpellCheck();
+
void performPrivateCommand(String action, in Bundle data);
void setComposingRegion(int start, int end);
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index e78ed4e..1b5cf6c 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -24,7 +24,10 @@
import com.android.internal.view.InputBindResult;
import com.android.internal.view.IInputContext;
import com.android.internal.view.IInputMethodClient;
+import com.android.internal.inputmethod.IBooleanResultCallback;
import com.android.internal.inputmethod.IInputBindResultResultCallback;
+import com.android.internal.inputmethod.IInputMethodSubtypeResultCallback;
+import com.android.internal.inputmethod.IInputMethodSubtypeListResultCallback;
/**
* Public interface to the global input method manager, used by all client
@@ -38,14 +41,14 @@
List<InputMethodInfo> getInputMethodList(int userId);
// TODO: Use ParceledListSlice instead
List<InputMethodInfo> getEnabledInputMethodList(int userId);
- List<InputMethodSubtype> getEnabledInputMethodSubtypeList(in String imiId,
- boolean allowsImplicitlySelectedSubtypes);
- InputMethodSubtype getLastInputMethodSubtype();
+ void getEnabledInputMethodSubtypeList(in String imiId, boolean allowsImplicitlySelectedSubtypes,
+ in IInputMethodSubtypeListResultCallback resultCallback);
+ void getLastInputMethodSubtype(in IInputMethodSubtypeResultCallback resultCallback);
- boolean showSoftInput(in IInputMethodClient client, IBinder windowToken, int flags,
- in ResultReceiver resultReceiver);
- boolean hideSoftInput(in IInputMethodClient client, IBinder windowToken, int flags,
- in ResultReceiver resultReceiver);
+ void showSoftInput(in IInputMethodClient client, IBinder windowToken, int flags,
+ in ResultReceiver resultReceiver, in IBooleanResultCallback resultCallback);
+ void hideSoftInput(in IInputMethodClient client, IBinder windowToken, int flags,
+ in ResultReceiver resultReceiver, in IBooleanResultCallback resultCallback);
// If windowToken is null, this just does startInput(). Otherwise this reports that a window
// has gained focus, and if 'attribute' is non-null then also does startInput.
// @NonNull
@@ -64,8 +67,8 @@
void showInputMethodPickerFromSystem(in IInputMethodClient client, int auxiliarySubtypeMode,
int displayId);
void showInputMethodAndSubtypeEnablerFromClient(in IInputMethodClient client, String topId);
- boolean isInputMethodPickerShownForTest();
- InputMethodSubtype getCurrentInputMethodSubtype();
+ void isInputMethodPickerShownForTest(in IBooleanResultCallback resultCallback);
+ void getCurrentInputMethodSubtype(in IInputMethodSubtypeResultCallback resultCallback);
void setAdditionalInputMethodSubtypes(String id, in InputMethodSubtype[] subtypes);
// This is kept due to @UnsupportedAppUsage.
// TODO(Bug 113914148): Consider removing this.
@@ -80,7 +83,7 @@
/** Remove the IME surface. Requires passing the currently focused window. */
void removeImeSurfaceFromWindow(in IBinder windowToken);
void startProtoDump(in byte[] protoDump, int source, String where);
- boolean isImeTraceEnabled();
+ void isImeTraceEnabled(in IBooleanResultCallback resultCallback);
// Starts an ime trace.
void startImeTrace();
diff --git a/core/java/com/android/internal/view/InputConnectionWrapper.java b/core/java/com/android/internal/view/InputConnectionWrapper.java
index b70348a..af9c012 100644
--- a/core/java/com/android/internal/view/InputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/InputConnectionWrapper.java
@@ -442,6 +442,17 @@
}
@AnyThread
+ @Override
+ public boolean performSpellCheck() {
+ try {
+ mIInputContext.performSpellCheck();
+ return true;
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
+ @AnyThread
public boolean performPrivateCommand(String action, Bundle data) {
try {
mIInputContext.performPrivateCommand(action, data);
diff --git a/core/java/com/android/internal/view/RecyclerViewCaptureHelper.java b/core/java/com/android/internal/view/RecyclerViewCaptureHelper.java
index 461e116..934241a 100644
--- a/core/java/com/android/internal/view/RecyclerViewCaptureHelper.java
+++ b/core/java/com/android/internal/view/RecyclerViewCaptureHelper.java
@@ -189,7 +189,7 @@
@Override
public void onPrepareForEnd(@NonNull ViewGroup view) {
// Restore original position and state
- view.scrollBy(0, mScrollDelta);
+ view.scrollBy(0, -mScrollDelta);
view.setOverScrollMode(mOverScrollMode);
view.setVerticalScrollBarEnabled(mScrollBarWasEnabled);
if (DISABLE_ANIMATORS) {
diff --git a/core/java/com/android/internal/widget/EditableInputConnection.java b/core/java/com/android/internal/widget/EditableInputConnection.java
index 6cdf0df..767ad42 100644
--- a/core/java/com/android/internal/widget/EditableInputConnection.java
+++ b/core/java/com/android/internal/widget/EditableInputConnection.java
@@ -178,6 +178,12 @@
}
@Override
+ public boolean performSpellCheck() {
+ mTextView.onPerformSpellCheck();
+ return true;
+ }
+
+ @Override
public boolean performPrivateCommand(String action, Bundle data) {
mTextView.onPrivateIMECommand(action, data);
return true;
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 8c83d7c..c05e7a2 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -181,6 +181,7 @@
"android_content_res_Configuration.cpp",
"android_security_Scrypt.cpp",
"com_android_internal_content_om_OverlayConfig.cpp",
+ "com_android_internal_net_NetworkUtilsInternal.cpp",
"com_android_internal_os_ClassLoaderFactory.cpp",
"com_android_internal_os_FuseAppLoop.cpp",
"com_android_internal_os_KernelCpuUidBpfMapReader.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 14e74a8..cefa88c 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -187,6 +187,7 @@
extern int register_android_security_Scrypt(JNIEnv *env);
extern int register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env);
extern int register_com_android_internal_content_om_OverlayConfig(JNIEnv *env);
+extern int register_com_android_internal_net_NetworkUtilsInternal(JNIEnv* env);
extern int register_com_android_internal_os_ClassLoaderFactory(JNIEnv* env);
extern int register_com_android_internal_os_FuseAppLoop(JNIEnv* env);
extern int register_com_android_internal_os_KernelCpuUidBpfMapReader(JNIEnv *env);
@@ -1522,6 +1523,7 @@
REG_JNI(register_android_os_SharedMemory),
REG_JNI(register_android_os_incremental_IncrementalManager),
REG_JNI(register_com_android_internal_content_om_OverlayConfig),
+ REG_JNI(register_com_android_internal_net_NetworkUtilsInternal),
REG_JNI(register_com_android_internal_os_ClassLoaderFactory),
REG_JNI(register_com_android_internal_os_Zygote),
REG_JNI(register_com_android_internal_os_ZygoteInit),
diff --git a/core/jni/android_content_res_ApkAssets.cpp b/core/jni/android_content_res_ApkAssets.cpp
index 444bb66..66753e4 100644
--- a/core/jni/android_content_res_ApkAssets.cpp
+++ b/core/jni/android_content_res_ApkAssets.cpp
@@ -315,10 +315,14 @@
return reinterpret_cast<jlong>(apk_assets.release());
}
-static void NativeDestroy(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr) {
+static void NativeDestroy(void* ptr) {
delete reinterpret_cast<ApkAssets*>(ptr);
}
+static jlong NativeGetFinalizer(JNIEnv* /*env*/, jclass /*clazz*/) {
+ return reinterpret_cast<jlong>(&NativeDestroy);
+}
+
static jstring NativeGetAssetPath(JNIEnv* env, jclass /*clazz*/, jlong ptr) {
const ApkAssets* apk_assets = reinterpret_cast<const ApkAssets*>(ptr);
return env->NewStringUTF(apk_assets->GetPath().c_str());
@@ -427,7 +431,7 @@
{"nativeLoadFdOffsets",
"(ILjava/io/FileDescriptor;Ljava/lang/String;JJILandroid/content/res/loader/AssetsProvider;)J",
(void*)NativeLoadFromFdOffset},
- {"nativeDestroy", "(J)V", (void*)NativeDestroy},
+ {"nativeGetFinalizer", "()J", (void*)NativeGetFinalizer},
{"nativeGetAssetPath", "(J)Ljava/lang/String;", (void*)NativeGetAssetPath},
{"nativeGetStringBlock", "(J)J", (void*)NativeGetStringBlock},
{"nativeIsUpToDate", "(J)Z", (void*)NativeIsUpToDate},
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index a95ee4f..5cffbef 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -298,20 +298,25 @@
return old;
}
-#define check_AudioSystem_Command(status) _check_AudioSystem_Command(__func__, (status))
+#define check_AudioSystem_Command(...) _check_AudioSystem_Command(__func__, __VA_ARGS__)
-static int _check_AudioSystem_Command(const char* caller, status_t status)
-{
- ALOGE_IF(status, "Command failed for %s: %d", caller, status);
+static int _check_AudioSystem_Command(const char *caller, status_t status,
+ std::vector<status_t> ignoredErrors = {}) {
+ int jniStatus = kAudioStatusOk;
switch (status) {
case DEAD_OBJECT:
- return kAudioStatusMediaServerDied;
+ jniStatus = kAudioStatusMediaServerDied;
+ break;
case NO_ERROR:
- return kAudioStatusOk;
+ break;
default:
+ if (std::find(begin(ignoredErrors), end(ignoredErrors), status) == end(ignoredErrors)) {
+ jniStatus = kAudioStatusError;
+ }
break;
}
- return kAudioStatusError;
+ ALOGE_IF(jniStatus != kAudioStatusOk, "Command failed for %s: %d", caller, status);
+ return jniStatus;
}
static jint getVectorOfAudioDeviceTypeAddr(JNIEnv *env, jintArray deviceTypes,
@@ -2350,9 +2355,12 @@
static jint android_media_AudioSystem_removeDevicesRoleForStrategy(JNIEnv *env, jobject thiz,
jint strategy, jint role) {
- return (jint)check_AudioSystem_Command(
- AudioSystem::removeDevicesRoleForStrategy((product_strategy_t)strategy,
- (device_role_t)role));
+ return (jint)
+ check_AudioSystem_Command(AudioSystem::removeDevicesRoleForStrategy((product_strategy_t)
+ strategy,
+ (device_role_t)
+ role),
+ {NAME_NOT_FOUND});
}
static jint android_media_AudioSystem_getDevicesForRoleAndStrategy(JNIEnv *env, jobject thiz,
diff --git a/core/jni/android_media_ToneGenerator.cpp b/core/jni/android_media_ToneGenerator.cpp
index ecb3cd6..82611ee 100644
--- a/core/jni/android_media_ToneGenerator.cpp
+++ b/core/jni/android_media_ToneGenerator.cpp
@@ -23,6 +23,7 @@
#include <jni.h>
#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedUtfChars.h>
#include "core_jni_helpers.h"
#include <utils/Log.h>
@@ -85,9 +86,12 @@
delete lpToneGen;
}
-static void android_media_ToneGenerator_native_setup(JNIEnv *env, jobject thiz,
- jint streamType, jint volume) {
- ToneGenerator *lpToneGen = new ToneGenerator((audio_stream_type_t) streamType, AudioSystem::linearToLog(volume), true);
+static void android_media_ToneGenerator_native_setup(JNIEnv *env, jobject thiz, jint streamType,
+ jint volume, jstring opPackageName) {
+ ScopedUtfChars opPackageNameStr(env, opPackageName);
+ ToneGenerator *lpToneGen =
+ new ToneGenerator((audio_stream_type_t)streamType, AudioSystem::linearToLog(volume),
+ true /*threadCanCallJava*/, opPackageNameStr.c_str());
env->SetLongField(thiz, fields.context, 0);
@@ -123,15 +127,14 @@
// ----------------------------------------------------------------------------
-static const JNINativeMethod gMethods[] = {
- { "startTone", "(II)Z", (void *)android_media_ToneGenerator_startTone },
- { "stopTone", "()V", (void *)android_media_ToneGenerator_stopTone },
- { "getAudioSessionId", "()I", (void *)android_media_ToneGenerator_getAudioSessionId},
- { "release", "()V", (void *)android_media_ToneGenerator_release },
- { "native_setup", "(II)V", (void *)android_media_ToneGenerator_native_setup },
- { "native_finalize", "()V", (void *)android_media_ToneGenerator_native_finalize }
-};
-
+static const JNINativeMethod gMethods[] =
+ {{"startTone", "(II)Z", (void *)android_media_ToneGenerator_startTone},
+ {"stopTone", "()V", (void *)android_media_ToneGenerator_stopTone},
+ {"getAudioSessionId", "()I", (void *)android_media_ToneGenerator_getAudioSessionId},
+ {"release", "()V", (void *)android_media_ToneGenerator_release},
+ {"native_setup", "(IILjava/lang/String;)V",
+ (void *)android_media_ToneGenerator_native_setup},
+ {"native_finalize", "()V", (void *)android_media_ToneGenerator_native_finalize}};
int register_android_media_ToneGenerator(JNIEnv *env) {
jclass clazz = FindClassOrDie(env, "android/media/ToneGenerator");
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index 8d4c4e5..2155246 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2008, The Android Open Source Project
+ * Copyright 2020, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,7 +28,6 @@
#include <netinet/udp.h>
#include <DnsProxydProtocol.h> // NETID_USE_LOCAL_NAMESERVERS
-#include <android_runtime/AndroidRuntime.h>
#include <cutils/properties.h>
#include <nativehelper/JNIPlatformHelp.h>
#include <nativehelper/ScopedLocalRef.h>
@@ -226,11 +225,6 @@
class_Network, ctor, dnsNetId & ~NETID_USE_LOCAL_NAMESERVERS, privateDnsBypass);
}
-static void android_net_utils_setAllowNetworkingForProcess(JNIEnv *env, jobject thiz,
- jboolean hasConnectivity) {
- setAllowNetworkingForProcess(hasConnectivity == JNI_TRUE);
-}
-
static jobject android_net_utils_getTcpRepairWindow(JNIEnv *env, jobject thiz, jobject javaFd) {
if (javaFd == NULL) {
jniThrowNullPointerException(env, NULL);
@@ -288,7 +282,6 @@
{ "resNetworkResult", "(Ljava/io/FileDescriptor;)Landroid/net/DnsResolver$DnsResponse;", (void*) android_net_utils_resNetworkResult },
{ "resNetworkCancel", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_resNetworkCancel },
{ "getDnsNetwork", "()Landroid/net/Network;", (void*) android_net_utils_getDnsNetwork },
- { "setAllowNetworkingForProcess", "(Z)V", (void *)android_net_utils_setAllowNetworkingForProcess },
};
// clang-format on
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index bf79a44..bb51c57 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -847,6 +847,17 @@
return ionPss;
}
+static jlong android_os_Debug_getGpuTotalUsageKb(JNIEnv* env, jobject clazz) {
+ jlong sizeKb = -1;
+ uint64_t size;
+
+ if (meminfo::ReadGpuTotalUsageKb(&size)) {
+ sizeKb = size;
+ }
+
+ return sizeKb;
+}
+
static jboolean android_os_Debug_isVmapStack(JNIEnv *env, jobject clazz)
{
static enum {
@@ -915,6 +926,8 @@
(void*)android_os_Debug_getIonPoolsSizeKb },
{ "getIonMappedSizeKb", "()J",
(void*)android_os_Debug_getIonMappedSizeKb },
+ { "getGpuTotalUsageKb", "()J",
+ (void*)android_os_Debug_getGpuTotalUsageKb },
{ "isVmapStack", "()Z",
(void*)android_os_Debug_isVmapStack },
};
diff --git a/core/jni/android_view_InputDevice.cpp b/core/jni/android_view_InputDevice.cpp
index 9f4e3e5..4eaa016 100644
--- a/core/jni/android_view_InputDevice.cpp
+++ b/core/jni/android_view_InputDevice.cpp
@@ -60,13 +60,17 @@
// Not sure why, but JNI is complaining when I pass this through directly.
jboolean hasMic = deviceInfo.hasMic() ? JNI_TRUE : JNI_FALSE;
- ScopedLocalRef<jobject> inputDeviceObj(env, env->NewObject(gInputDeviceClassInfo.clazz,
- gInputDeviceClassInfo.ctor, deviceInfo.getId(), deviceInfo.getGeneration(),
- deviceInfo.getControllerNumber(), nameObj.get(),
- static_cast<int32_t>(ident.vendor), static_cast<int32_t>(ident.product),
- descriptorObj.get(), deviceInfo.isExternal(), deviceInfo.getSources(),
- deviceInfo.getKeyboardType(), kcmObj.get(), deviceInfo.hasVibrator(),
- hasMic, deviceInfo.hasButtonUnderPad()));
+ ScopedLocalRef<jobject>
+ inputDeviceObj(env,
+ env->NewObject(gInputDeviceClassInfo.clazz, gInputDeviceClassInfo.ctor,
+ deviceInfo.getId(), deviceInfo.getGeneration(),
+ deviceInfo.getControllerNumber(), nameObj.get(),
+ static_cast<int32_t>(ident.vendor),
+ static_cast<int32_t>(ident.product), descriptorObj.get(),
+ deviceInfo.isExternal(), deviceInfo.getSources(),
+ deviceInfo.getKeyboardType(), kcmObj.get(),
+ deviceInfo.hasVibrator(), hasMic,
+ deviceInfo.hasButtonUnderPad(), deviceInfo.hasSensor()));
const std::vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
for (const InputDeviceInfo::MotionRange& range: ranges) {
@@ -87,7 +91,8 @@
gInputDeviceClassInfo.clazz = MakeGlobalRefOrDie(env, gInputDeviceClassInfo.clazz);
gInputDeviceClassInfo.ctor = GetMethodIDOrDie(env, gInputDeviceClassInfo.clazz, "<init>",
- "(IIILjava/lang/String;IILjava/lang/String;ZIILandroid/view/KeyCharacterMap;ZZZ)V");
+ "(IIILjava/lang/String;IILjava/lang/"
+ "String;ZIILandroid/view/KeyCharacterMap;ZZZZ)V");
gInputDeviceClassInfo.addMotionRange = GetMethodIDOrDie(env, gInputDeviceClassInfo.clazz,
"addMotionRange", "(IIFFFFF)V");
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index a21545c..a6dbd19 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -1679,6 +1679,10 @@
return reinterpret_cast<jlong>(new JankDataListenerWrapper(env, jankDataListenerObject));
}
+static jint nativeGetGPUContextPriority(JNIEnv* env, jclass clazz) {
+ return static_cast<jint>(SurfaceComposerClient::getGPUContextPriority());
+}
+
// ----------------------------------------------------------------------------
static const JNINativeMethod sSurfaceControlMethods[] = {
@@ -1869,6 +1873,8 @@
(void*)nativeRemoveJankDataListener },
{"nativeCreateJankDataListenerWrapper", "(Landroid/view/SurfaceControl$OnJankDataListener;)J",
(void*)nativeCreateJankDataListenerWrapper },
+ {"nativeGetGPUContextPriority", "()I",
+ (void*)nativeGetGPUContextPriority },
// clang-format on
};
diff --git a/core/jni/com_android_internal_net_NetworkUtilsInternal.cpp b/core/jni/com_android_internal_net_NetworkUtilsInternal.cpp
new file mode 100644
index 0000000..10fc18d
--- /dev/null
+++ b/core/jni/com_android_internal_net_NetworkUtilsInternal.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "NetdClient.h"
+#include "core_jni_helpers.h"
+#include "jni.h"
+
+namespace android {
+static void android_net_utils_setAllowNetworkingForProcess(JNIEnv *env, jobject thiz,
+ jboolean hasConnectivity) {
+ setAllowNetworkingForProcess(hasConnectivity == JNI_TRUE);
+}
+
+static const JNINativeMethod gNetworkUtilMethods[] = {
+ {"setAllowNetworkingForProcess", "(Z)V",
+ (void *)android_net_utils_setAllowNetworkingForProcess},
+};
+
+int register_com_android_internal_net_NetworkUtilsInternal(JNIEnv *env) {
+ return RegisterMethodsOrDie(env, "com/android/internal/net/NetworkUtilsInternal",
+ gNetworkUtilMethods, NELEM(gNetworkUtilMethods));
+}
+
+} // namespace android
diff --git a/core/jni/com_android_internal_os_KernelSingleProcessCpuThreadReader.cpp b/core/jni/com_android_internal_os_KernelSingleProcessCpuThreadReader.cpp
index dfae684..52bed6b 100644
--- a/core/jni/com_android_internal_os_KernelSingleProcessCpuThreadReader.cpp
+++ b/core/jni/com_android_internal_os_KernelSingleProcessCpuThreadReader.cpp
@@ -26,230 +26,239 @@
#include <android_runtime/Log.h>
#include <nativehelper/ScopedPrimitiveArray.h>
+#include <nativehelper/ScopedUtfChars.h>
namespace android {
-static constexpr uint16_t DEFAULT_THREAD_AGGREGATION_KEY = 0;
-static constexpr uint16_t SELECTED_THREAD_AGGREGATION_KEY = 1;
-
-static constexpr uint64_t NSEC_PER_MSEC = 1000000;
-
// Number of milliseconds in a jiffy - the unit of time measurement for processes and threads
static const uint32_t gJiffyMillis = (uint32_t)(1000 / sysconf(_SC_CLK_TCK));
-// Abstract class for readers of CPU time-in-state. There are two implementations of
-// this class: BpfCpuTimeInStateReader and MockCpuTimeInStateReader. The former is used
-// by the production code. The latter is used by unit tests to provide mock
-// CPU time-in-state data via a Java implementation.
-class ICpuTimeInStateReader {
-public:
- virtual ~ICpuTimeInStateReader() {}
+// Given a PID, returns a vector of all TIDs for the process' tasks. Thread IDs are
+// file names in the /proc/<pid>/task directory.
+static bool getThreadIds(const std::string &procPath, const pid_t pid,
+ std::vector<pid_t> &outThreadIds) {
+ std::string taskPath = android::base::StringPrintf("%s/%u/task", procPath.c_str(), pid);
- // Returns the overall number of cluser-frequency combinations
- virtual size_t getCpuFrequencyCount();
+ struct dirent **dirlist;
+ int threadCount = scandir(taskPath.c_str(), &dirlist, NULL, NULL);
+ if (threadCount == -1) {
+ ALOGE("Cannot read directory %s", taskPath.c_str());
+ return false;
+ }
- // Marks the CPU time-in-state tracking for threads of the specified TGID
- virtual bool startTrackingProcessCpuTimes(pid_t) = 0;
+ outThreadIds.reserve(threadCount);
- // Marks the thread specified by its PID for CPU time-in-state tracking.
- virtual bool startAggregatingTaskCpuTimes(pid_t, uint16_t) = 0;
+ for (int i = 0; i < threadCount; i++) {
+ pid_t tid;
+ if (android::base::ParseInt<pid_t>(dirlist[i]->d_name, &tid)) {
+ outThreadIds.push_back(tid);
+ }
+ free(dirlist[i]);
+ }
+ free(dirlist);
- // Retrieves the accumulated time-in-state data, which is organized as a map
- // from aggregation keys to vectors of vectors using the format:
- // { aggKey0 -> [[t0_0_0, t0_0_1, ...], [t0_1_0, t0_1_1, ...], ...],
- // aggKey1 -> [[t1_0_0, t1_0_1, ...], [t1_1_0, t1_1_1, ...], ...], ... }
- // where ti_j_k is the ns tid i spent running on the jth cluster at the cluster's kth lowest
- // freq.
- virtual std::optional<std::unordered_map<uint16_t, std::vector<std::vector<uint64_t>>>>
- getAggregatedTaskCpuFreqTimes(pid_t, const std::vector<uint16_t> &);
-};
+ return true;
+}
-// ICpuTimeInStateReader that uses eBPF to provide a map of aggregated CPU time-in-state values.
-// See cputtimeinstate.h/.cpp
-class BpfCpuTimeInStateReader : public ICpuTimeInStateReader {
-public:
- size_t getCpuFrequencyCount() {
- std::optional<std::vector<std::vector<uint32_t>>> cpuFreqs = android::bpf::getCpuFreqs();
- if (!cpuFreqs) {
- ALOGE("Cannot obtain CPU frequency count");
- return 0;
+// Reads contents of a time_in_state file and returns times as a vector of times per frequency
+// A time_in_state file contains pairs of frequency - time (in jiffies):
+//
+// cpu0
+// 300000 30
+// 403200 0
+// cpu4
+// 710400 10
+// 825600 20
+// 940800 30
+//
+static bool getThreadTimeInState(const std::string &procPath, const pid_t pid, const pid_t tid,
+ const size_t frequencyCount,
+ std::vector<uint64_t> &outThreadTimeInState) {
+ std::string timeInStateFilePath =
+ android::base::StringPrintf("%s/%u/task/%u/time_in_state", procPath.c_str(), pid, tid);
+ std::string data;
+
+ if (!android::base::ReadFileToString(timeInStateFilePath, &data)) {
+ ALOGE("Cannot read file: %s", timeInStateFilePath.c_str());
+ return false;
+ }
+
+ auto lines = android::base::Split(data, "\n");
+ size_t index = 0;
+ for (const auto &line : lines) {
+ if (line.empty()) {
+ continue;
}
- size_t freqCount = 0;
- for (auto cluster : *cpuFreqs) {
- freqCount += cluster.size();
+ auto numbers = android::base::Split(line, " ");
+ if (numbers.size() != 2) {
+ continue;
}
-
- return freqCount;
- }
-
- bool startTrackingProcessCpuTimes(pid_t tgid) {
- return android::bpf::startTrackingProcessCpuTimes(tgid);
- }
-
- bool startAggregatingTaskCpuTimes(pid_t pid, uint16_t aggregationKey) {
- return android::bpf::startAggregatingTaskCpuTimes(pid, aggregationKey);
- }
-
- std::optional<std::unordered_map<uint16_t, std::vector<std::vector<uint64_t>>>>
- getAggregatedTaskCpuFreqTimes(pid_t pid, const std::vector<uint16_t> &aggregationKeys) {
- return android::bpf::getAggregatedTaskCpuFreqTimes(pid, aggregationKeys);
- }
-};
-
-// ICpuTimeInStateReader that uses JNI to provide a map of aggregated CPU time-in-state
-// values.
-// This version of CpuTimeInStateReader is used exclusively for providing mock data in tests.
-class MockCpuTimeInStateReader : public ICpuTimeInStateReader {
-private:
- JNIEnv *mEnv;
- jobject mCpuTimeInStateReader;
-
-public:
- MockCpuTimeInStateReader(JNIEnv *env, jobject cpuTimeInStateReader)
- : mEnv(env), mCpuTimeInStateReader(cpuTimeInStateReader) {}
-
- size_t getCpuFrequencyCount();
-
- bool startTrackingProcessCpuTimes(pid_t tgid);
-
- bool startAggregatingTaskCpuTimes(pid_t pid, uint16_t aggregationKey);
-
- std::optional<std::unordered_map<uint16_t, std::vector<std::vector<uint64_t>>>>
- getAggregatedTaskCpuFreqTimes(pid_t tgid, const std::vector<uint16_t> &aggregationKeys);
-};
-
-static ICpuTimeInStateReader *getCpuTimeInStateReader(JNIEnv *env,
- jobject cpuTimeInStateReaderObject) {
- if (cpuTimeInStateReaderObject) {
- return new MockCpuTimeInStateReader(env, cpuTimeInStateReaderObject);
- } else {
- return new BpfCpuTimeInStateReader();
- }
-}
-
-static jint getCpuFrequencyCount(JNIEnv *env, jclass, jobject cpuTimeInStateReaderObject) {
- std::unique_ptr<ICpuTimeInStateReader> cpuTimeInStateReader(
- getCpuTimeInStateReader(env, cpuTimeInStateReaderObject));
- return cpuTimeInStateReader->getCpuFrequencyCount();
-}
-
-static jboolean startTrackingProcessCpuTimes(JNIEnv *env, jclass, jint tgid,
- jobject cpuTimeInStateReaderObject) {
- std::unique_ptr<ICpuTimeInStateReader> cpuTimeInStateReader(
- getCpuTimeInStateReader(env, cpuTimeInStateReaderObject));
- return cpuTimeInStateReader->startTrackingProcessCpuTimes(tgid);
-}
-
-static jboolean startAggregatingThreadCpuTimes(JNIEnv *env, jclass, jintArray selectedThreadIdArray,
- jobject cpuTimeInStateReaderObject) {
- ScopedIntArrayRO selectedThreadIds(env, selectedThreadIdArray);
- std::unique_ptr<ICpuTimeInStateReader> cpuTimeInStateReader(
- getCpuTimeInStateReader(env, cpuTimeInStateReaderObject));
-
- for (int i = 0; i < selectedThreadIds.size(); i++) {
- if (!cpuTimeInStateReader->startAggregatingTaskCpuTimes(selectedThreadIds[i],
- SELECTED_THREAD_AGGREGATION_KEY)) {
+ uint64_t timeInState;
+ if (!android::base::ParseUint<uint64_t>(numbers[1], &timeInState)) {
+ ALOGE("Invalid time_in_state file format: %s", timeInStateFilePath.c_str());
return false;
}
- }
- return true;
-}
-
-// Converts time-in-state data from a vector of vectors to a flat array.
-// Also converts from nanoseconds to milliseconds.
-static bool flattenTimeInStateData(ScopedLongArrayRW &cpuTimesMillis,
- const std::vector<std::vector<uint64_t>> &data) {
- size_t frequencyCount = cpuTimesMillis.size();
- size_t index = 0;
- for (const auto &cluster : data) {
- for (const uint64_t &timeNanos : cluster) {
- if (index < frequencyCount) {
- cpuTimesMillis[index] = timeNanos / NSEC_PER_MSEC;
- }
- index++;
+ if (index < frequencyCount) {
+ outThreadTimeInState[index] = timeInState;
}
+ index++;
}
+
if (index != frequencyCount) {
- ALOGE("CPU time-in-state reader returned data for %zu frequencies; expected: %zu", index,
- frequencyCount);
+ ALOGE("Incorrect number of frequencies %u in %s. Expected %u",
+ (uint32_t)outThreadTimeInState.size(), timeInStateFilePath.c_str(),
+ (uint32_t)frequencyCount);
return false;
}
return true;
}
-// Reads all CPU time-in-state data accumulated by BPF and aggregates per-frequency
+static int pidCompare(const void *a, const void *b) {
+ return (*(pid_t *)a - *(pid_t *)b);
+}
+
+static inline bool isSelectedThread(const pid_t tid, const pid_t *selectedThreadIds,
+ const size_t selectedThreadCount) {
+ return bsearch(&tid, selectedThreadIds, selectedThreadCount, sizeof(pid_t), pidCompare) != NULL;
+}
+
+// Reads all /proc/<pid>/task/*/time_in_state files and aggregates per-frequency
// time in state data for all threads. Also, separately aggregates time in state for
// selected threads whose TIDs are passes as selectedThreadIds.
-static jboolean readProcessCpuUsage(JNIEnv *env, jclass, jint pid,
+static void aggregateThreadCpuTimes(const std::string &procPath, const pid_t pid,
+ const std::vector<pid_t> &threadIds,
+ const size_t frequencyCount, const pid_t *selectedThreadIds,
+ const size_t selectedThreadCount,
+ uint64_t *threadCpuTimesMillis,
+ uint64_t *selectedThreadCpuTimesMillis) {
+ for (size_t j = 0; j < frequencyCount; j++) {
+ threadCpuTimesMillis[j] = 0;
+ selectedThreadCpuTimesMillis[j] = 0;
+ }
+
+ for (size_t i = 0; i < threadIds.size(); i++) {
+ pid_t tid = threadIds[i];
+ std::vector<uint64_t> timeInState(frequencyCount);
+ if (!getThreadTimeInState(procPath, pid, tid, frequencyCount, timeInState)) {
+ continue;
+ }
+
+ bool selectedThread = isSelectedThread(tid, selectedThreadIds, selectedThreadCount);
+ for (size_t j = 0; j < frequencyCount; j++) {
+ threadCpuTimesMillis[j] += timeInState[j];
+ if (selectedThread) {
+ selectedThreadCpuTimesMillis[j] += timeInState[j];
+ }
+ }
+ }
+ for (size_t i = 0; i < frequencyCount; i++) {
+ threadCpuTimesMillis[i] *= gJiffyMillis;
+ selectedThreadCpuTimesMillis[i] *= gJiffyMillis;
+ }
+}
+
+// Reads process utime and stime from the /proc/<pid>/stat file.
+// Format of this file is described in https://man7.org/linux/man-pages/man5/proc.5.html.
+static bool getProcessCpuTime(const std::string &procPath, const pid_t pid,
+ uint64_t &outTimeMillis) {
+ std::string statFilePath = android::base::StringPrintf("%s/%u/stat", procPath.c_str(), pid);
+ std::string data;
+ if (!android::base::ReadFileToString(statFilePath, &data)) {
+ return false;
+ }
+
+ auto fields = android::base::Split(data, " ");
+ uint64_t utime, stime;
+
+ // Field 14 (counting from 1) is utime - process time in user space, in jiffies
+ // Field 15 (counting from 1) is stime - process time in system space, in jiffies
+ if (fields.size() < 15 || !android::base::ParseUint(fields[13], &utime) ||
+ !android::base::ParseUint(fields[14], &stime)) {
+ ALOGE("Invalid file format %s", statFilePath.c_str());
+ return false;
+ }
+
+ outTimeMillis = (utime + stime) * gJiffyMillis;
+ return true;
+}
+
+// Estimates per cluster per frequency CPU time for the entire process
+// by distributing the total process CPU time proportionately to how much
+// CPU time its threads took on those clusters/frequencies. This algorithm
+// works more accurately when when we have equally distributed concurrency.
+// TODO(b/169279846): obtain actual process CPU times from the kernel
+static void estimateProcessTimeInState(const uint64_t processCpuTimeMillis,
+ const uint64_t *threadCpuTimesMillis,
+ const size_t frequencyCount,
+ uint64_t *processCpuTimesMillis) {
+ uint64_t totalCpuTimeAllThreads = 0;
+ for (size_t i = 0; i < frequencyCount; i++) {
+ totalCpuTimeAllThreads += threadCpuTimesMillis[i];
+ }
+
+ if (totalCpuTimeAllThreads != 0) {
+ for (size_t i = 0; i < frequencyCount; i++) {
+ processCpuTimesMillis[i] =
+ processCpuTimeMillis * threadCpuTimesMillis[i] / totalCpuTimeAllThreads;
+ }
+ } else {
+ for (size_t i = 0; i < frequencyCount; i++) {
+ processCpuTimesMillis[i] = 0;
+ }
+ }
+}
+
+static jboolean readProcessCpuUsage(JNIEnv *env, jclass, jstring procPath, jint pid,
+ jintArray selectedThreadIdArray,
+ jlongArray processCpuTimesMillisArray,
jlongArray threadCpuTimesMillisArray,
- jlongArray selectedThreadCpuTimesMillisArray,
- jobject cpuTimeInStateReaderObject) {
+ jlongArray selectedThreadCpuTimesMillisArray) {
+ ScopedUtfChars procPathChars(env, procPath);
+ ScopedIntArrayRO selectedThreadIds(env, selectedThreadIdArray);
+ ScopedLongArrayRW processCpuTimesMillis(env, processCpuTimesMillisArray);
ScopedLongArrayRW threadCpuTimesMillis(env, threadCpuTimesMillisArray);
ScopedLongArrayRW selectedThreadCpuTimesMillis(env, selectedThreadCpuTimesMillisArray);
- std::unique_ptr<ICpuTimeInStateReader> cpuTimeInStateReader(
- getCpuTimeInStateReader(env, cpuTimeInStateReaderObject));
- const size_t frequencyCount = cpuTimeInStateReader->getCpuFrequencyCount();
+ std::string procPathStr(procPathChars.c_str());
+
+ // Get all thread IDs for the process.
+ std::vector<pid_t> threadIds;
+ if (!getThreadIds(procPathStr, pid, threadIds)) {
+ ALOGE("Could not obtain thread IDs from: %s", procPathStr.c_str());
+ return false;
+ }
+
+ size_t frequencyCount = processCpuTimesMillis.size();
if (threadCpuTimesMillis.size() != frequencyCount) {
- ALOGE("Invalid threadCpuTimesMillis array length: %zu frequencies; expected: %zu",
- threadCpuTimesMillis.size(), frequencyCount);
+ ALOGE("Invalid array length: threadCpuTimesMillis");
return false;
}
-
if (selectedThreadCpuTimesMillis.size() != frequencyCount) {
- ALOGE("Invalid selectedThreadCpuTimesMillis array length: %zu frequencies; expected: %zu",
- selectedThreadCpuTimesMillis.size(), frequencyCount);
+ ALOGE("Invalid array length: selectedThreadCpuTimesMillisArray");
return false;
}
- for (size_t i = 0; i < frequencyCount; i++) {
- threadCpuTimesMillis[i] = 0;
- selectedThreadCpuTimesMillis[i] = 0;
- }
+ aggregateThreadCpuTimes(procPathStr, pid, threadIds, frequencyCount, selectedThreadIds.get(),
+ selectedThreadIds.size(),
+ reinterpret_cast<uint64_t *>(threadCpuTimesMillis.get()),
+ reinterpret_cast<uint64_t *>(selectedThreadCpuTimesMillis.get()));
- std::optional<std::unordered_map<uint16_t, std::vector<std::vector<uint64_t>>>> data =
- cpuTimeInStateReader->getAggregatedTaskCpuFreqTimes(pid,
- {DEFAULT_THREAD_AGGREGATION_KEY,
- SELECTED_THREAD_AGGREGATION_KEY});
- if (!data) {
- ALOGE("Cannot read thread CPU times for PID %d", pid);
- return false;
+ uint64_t processCpuTime;
+ bool ret = getProcessCpuTime(procPathStr, pid, processCpuTime);
+ if (ret) {
+ estimateProcessTimeInState(processCpuTime,
+ reinterpret_cast<uint64_t *>(threadCpuTimesMillis.get()),
+ frequencyCount,
+ reinterpret_cast<uint64_t *>(processCpuTimesMillis.get()));
}
-
- if (!flattenTimeInStateData(threadCpuTimesMillis, (*data)[DEFAULT_THREAD_AGGREGATION_KEY])) {
- return false;
- }
-
- if (!flattenTimeInStateData(selectedThreadCpuTimesMillis,
- (*data)[SELECTED_THREAD_AGGREGATION_KEY])) {
- return false;
- }
-
- // threadCpuTimesMillis returns CPU times for _all_ threads, including the selected ones
- for (size_t i = 0; i < frequencyCount; i++) {
- threadCpuTimesMillis[i] += selectedThreadCpuTimesMillis[i];
- }
-
- return true;
+ return ret;
}
static const JNINativeMethod g_single_methods[] = {
- {"getCpuFrequencyCount",
- "(Lcom/android/internal/os/KernelSingleProcessCpuThreadReader$CpuTimeInStateReader;)I",
- (void *)getCpuFrequencyCount},
- {"startTrackingProcessCpuTimes",
- "(ILcom/android/internal/os/KernelSingleProcessCpuThreadReader$CpuTimeInStateReader;)Z",
- (void *)startTrackingProcessCpuTimes},
- {"startAggregatingThreadCpuTimes",
- "([ILcom/android/internal/os/KernelSingleProcessCpuThreadReader$CpuTimeInStateReader;)Z",
- (void *)startAggregatingThreadCpuTimes},
- {"readProcessCpuUsage",
- "(I[J[J"
- "Lcom/android/internal/os/KernelSingleProcessCpuThreadReader$CpuTimeInStateReader;)Z",
- (void *)readProcessCpuUsage},
+ {"readProcessCpuUsage", "(Ljava/lang/String;I[I[J[J[J)Z", (void *)readProcessCpuUsage},
};
int register_com_android_internal_os_KernelSingleProcessCpuThreadReader(JNIEnv *env) {
@@ -257,77 +266,4 @@
g_single_methods, NELEM(g_single_methods));
}
-size_t MockCpuTimeInStateReader::getCpuFrequencyCount() {
- jclass cls = mEnv->GetObjectClass(mCpuTimeInStateReader);
- jmethodID mid = mEnv->GetMethodID(cls, "getCpuFrequencyCount", "()I");
- if (mid == 0) {
- ALOGE("Couldn't find the method getCpuFrequencyCount");
- return false;
- }
- return (size_t)mEnv->CallIntMethod(mCpuTimeInStateReader, mid);
-}
-
-bool MockCpuTimeInStateReader::startTrackingProcessCpuTimes(pid_t tgid) {
- jclass cls = mEnv->GetObjectClass(mCpuTimeInStateReader);
- jmethodID mid = mEnv->GetMethodID(cls, "startTrackingProcessCpuTimes", "(I)Z");
- if (mid == 0) {
- ALOGE("Couldn't find the method startTrackingProcessCpuTimes");
- return false;
- }
- return mEnv->CallBooleanMethod(mCpuTimeInStateReader, mid, tgid);
-}
-
-bool MockCpuTimeInStateReader::startAggregatingTaskCpuTimes(pid_t pid, uint16_t aggregationKey) {
- jclass cls = mEnv->GetObjectClass(mCpuTimeInStateReader);
- jmethodID mid = mEnv->GetMethodID(cls, "startAggregatingTaskCpuTimes", "(II)Z");
- if (mid == 0) {
- ALOGE("Couldn't find the method startAggregatingTaskCpuTimes");
- return false;
- }
- return mEnv->CallBooleanMethod(mCpuTimeInStateReader, mid, pid, aggregationKey);
-}
-
-std::optional<std::unordered_map<uint16_t, std::vector<std::vector<uint64_t>>>>
-MockCpuTimeInStateReader::getAggregatedTaskCpuFreqTimes(
- pid_t pid, const std::vector<uint16_t> &aggregationKeys) {
- jclass cls = mEnv->GetObjectClass(mCpuTimeInStateReader);
- jmethodID mid =
- mEnv->GetMethodID(cls, "getAggregatedTaskCpuFreqTimes", "(I)[Ljava/lang/String;");
- if (mid == 0) {
- ALOGE("Couldn't find the method getAggregatedTaskCpuFreqTimes");
- return {};
- }
-
- std::unordered_map<uint16_t, std::vector<std::vector<uint64_t>>> map;
-
- jobjectArray stringArray =
- (jobjectArray)mEnv->CallObjectMethod(mCpuTimeInStateReader, mid, pid);
- int size = mEnv->GetArrayLength(stringArray);
- for (int i = 0; i < size; i++) {
- ScopedUtfChars line(mEnv, (jstring)mEnv->GetObjectArrayElement(stringArray, i));
- uint16_t aggregationKey;
- std::vector<std::vector<uint64_t>> times;
-
- // Each string is formatted like this: "aggKey:t0_0 t0_1...:t1_0 t1_1..."
- auto fields = android::base::Split(line.c_str(), ":");
- android::base::ParseUint(fields[0], &aggregationKey);
-
- for (int j = 1; j < fields.size(); j++) {
- auto numbers = android::base::Split(fields[j], " ");
-
- std::vector<uint64_t> chunk;
- for (int k = 0; k < numbers.size(); k++) {
- uint64_t time;
- android::base::ParseUint(numbers[k], &time);
- chunk.emplace_back(time);
- }
- times.emplace_back(chunk);
- }
-
- map.emplace(aggregationKey, times);
- }
-
- return map;
-}
-
} // namespace android
diff --git a/core/res/Android.bp b/core/res/Android.bp
index f94a2b0..9ee5e5e1 100644
--- a/core/res/Android.bp
+++ b/core/res/Android.bp
@@ -19,6 +19,13 @@
sdk_version: "core_platform",
certificate: "platform",
+ // Disable dexpreopt and verify_uses_libraries check as the app
+ // contains no Java code to be dexpreopted.
+ enforce_uses_libs: false,
+ dex_preopt: {
+ enabled: false,
+ },
+
// Soong special-cases framework-res to install this alongside
// the libraries at /system/framework/framework-res.apk.
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 4f9a8de..28f5e35 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -393,6 +393,7 @@
<protected-broadcast android:name="android.net.wifi.action.PASSPOINT_OSU_PROVIDERS_LIST" />
<protected-broadcast android:name="android.net.wifi.action.PASSPOINT_SUBSCRIPTION_REMEDIATION" />
<protected-broadcast android:name="android.net.wifi.action.PASSPOINT_LAUNCH_OSU_VIEW" />
+ <protected-broadcast android:name="android.net.wifi.action.REFRESH_USER_PROVISIONING" />
<protected-broadcast android:name="android.net.wifi.action.WIFI_NETWORK_SUGGESTION_POST_CONNECTION" />
<protected-broadcast android:name="android.net.wifi.action.WIFI_SCAN_AVAILABILITY_CHANGED" />
<protected-broadcast android:name="android.net.wifi.supplicant.CONNECTION_CHANGE" />
@@ -1536,7 +1537,8 @@
<permission android:name="android.permission.BIND_DIRECTORY_SEARCH"
android:protectionLevel="signature|privileged" />
- <!-- @SystemApi @hide Allows an application to modify cell broadcasts through the content provider.
+ <!-- @SystemApi @hide Allows an application to modify the cell broadcasts configuration
+ (i.e. enable or disable channels).
<p>Not for use by third-party applications. -->
<permission android:name="android.permission.MODIFY_CELL_BROADCASTS"
android:protectionLevel="signature|privileged" />
@@ -4104,6 +4106,14 @@
<permission android:name="android.permission.CONTROL_ALWAYS_ON_VPN"
android:protectionLevel="signature" />
+ <!-- @SystemApi Allows an application to capture the audio from tuner input devices types,
+ such as FM_TUNER.
+
+ <p>Not for use by third-party applications.</p>
+ @hide -->
+ <permission android:name="android.permission.CAPTURE_TUNER_AUDIO_INPUT"
+ android:protectionLevel="signature|privileged" />
+
<!-- Allows an application to capture audio output.
Use the {@code CAPTURE_MEDIA_OUTPUT} permission if only the {@code USAGE_UNKNOWN}),
{@code USAGE_MEDIA}) or {@code USAGE_GAME}) usages are intended to be captured.
@@ -5304,7 +5314,7 @@
<attribution android:tag="TwilightService" android:label="@string/twilight_service"/>
<!-- Attribution for the Offline LocationTimeZoneProvider, used to detect time zone using
on-device data -->
- <attribution android:tag="OfflineLocationTimeZoneProvider"
+ <attribution android:tag="OfflineLocationTimeZoneProviderService"
android:label="@string/offline_location_time_zone_detection_service_attribution"/>
<application android:process="system"
@@ -5774,11 +5784,10 @@
<!-- AOSP configures a default secondary LocationTimeZoneProvider that uses an on-device
data set from the com.android.geotz APEX. -->
- <uses-library android:name="com.android.location.provider" />
- <service android:name="com.android.timezone.geotz.provider.OfflineLocationTimeZoneService"
+ <service android:name="com.android.timezone.geotz.provider.OfflineLocationTimeZoneProviderService"
android:exported="false">
<intent-filter>
- <action android:name="com.android.location.timezone.service.v1.SecondaryLocationTimeZoneProvider" />
+ <action android:name="android.service.timezone.SecondaryLocationTimeZoneProviderService" />
</intent-filter>
<meta-data android:name="serviceVersion" android:value="1" />
<meta-data android:name="serviceIsMultiuser" android:value="true" />
diff --git a/core/res/OWNERS b/core/res/OWNERS
index 263d638..02cf0b7 100644
--- a/core/res/OWNERS
+++ b/core/res/OWNERS
@@ -6,6 +6,7 @@
hackbod@google.com
jsharkey@android.com
jsharkey@google.com
+juliacr@google.com
michaelwr@google.com
nandana@google.com
narayan@google.com
diff --git a/core/res/res/layout/notification_top_line_views.xml b/core/res/res/layout/notification_top_line_views.xml
index 361b7a3..7cda03f 100644
--- a/core/res/res/layout/notification_top_line_views.xml
+++ b/core/res/res/layout/notification_top_line_views.xml
@@ -112,11 +112,12 @@
android:id="@+id/feedback"
android:layout_width="@dimen/notification_feedback_size"
android:layout_height="@dimen/notification_feedback_size"
- android:layout_marginStart="4dp"
- android:layout_marginEnd="4dp"
+ android:layout_marginStart="@dimen/notification_header_separating_margin"
+ android:layout_gravity="center"
android:scaleType="fitCenter"
android:src="@drawable/ic_feedback_indicator"
android:background="?android:selectableItemBackgroundBorderless"
+ android:paddingTop="2dp"
android:visibility="gone"
android:contentDescription="@string/notification_feedback_indicator"
/>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index dea4aa6..bc40003 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -20,12 +20,12 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="byteShort" msgid="202579285008794431">"B"</string>
+ <string name="byteShort" msgid="202579285008794431">"ባ"</string>
<string name="kilobyteShort" msgid="2214285521564195803">"ኪባ"</string>
- <string name="megabyteShort" msgid="6649361267635823443">"MB"</string>
- <string name="gigabyteShort" msgid="7515809460261287991">"GB"</string>
- <string name="terabyteShort" msgid="1822367128583886496">"TB"</string>
- <string name="petabyteShort" msgid="5651571254228534832">"PB"</string>
+ <string name="megabyteShort" msgid="6649361267635823443">"ሜባ"</string>
+ <string name="gigabyteShort" msgid="7515809460261287991">"ጊባ"</string>
+ <string name="terabyteShort" msgid="1822367128583886496">"ቴባ"</string>
+ <string name="petabyteShort" msgid="5651571254228534832">"ፔባ"</string>
<string name="fileSizeSuffix" msgid="4233671691980131257">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
<string name="untitled" msgid="3381766946944136678">"<ርዕስ አልባ>"</string>
<string name="emptyPhoneNumber" msgid="5812172618020360048">"(ምንም ስልክ ቁጥር የለም)"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 7ad157c..5a18497 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -365,10 +365,8 @@
<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_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-as/strings.xml b/core/res/res/values-as/strings.xml
index e6ab01a..e087332 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -353,10 +353,8 @@
<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_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-az/strings.xml b/core/res/res/values-az/strings.xml
index 763bd2a..2e36aab 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -353,10 +353,8 @@
<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_manageOngoingCalls" msgid="281244770664231782">"Davam edən zəngləri idarə edin"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Tətbiqə cihazınızda davam edən zənglər haqqında məlumatları görmək və bu zəngləri idarə etmək imkanı verir."</string>
<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-be/strings.xml b/core/res/res/values-be/strings.xml
index d092ad6..8c06ad6 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -359,10 +359,8 @@
<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_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 6de7e2d..98ba23c 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -353,10 +353,8 @@
<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_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-de/strings.xml b/core/res/res/values-de/strings.xml
index 41f4f8a..8038fc9 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -353,10 +353,8 @@
<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_manageOngoingCalls" msgid="281244770664231782">"Aktuelle Anrufe verwalten"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Ermöglicht einer App, Details zu aktuellen Anrufen auf deinem Gerät zu sehen und diese Anrufe zu verwalten."</string>
<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-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index cdfa15d..55e916e 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -52,7 +52,6 @@
<string name="enablePin" msgid="2543771964137091212">"Opération infructueuse. Activez le verrouillage SIM/RUIM."</string>
<plurals name="pinpuk_attempts" formatted="false" msgid="1619867269012213584">
<item quantity="one">Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentative avant que votre carte SIM soit verrouillée.</item>
- <item quantity="many">You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts before SIM is locked.</item>
<item quantity="other">Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentatives avant que votre carte SIM soit verrouillée.</item>
</plurals>
<string name="imei" msgid="2157082351232630390">"Code IIEM"</string>
@@ -180,7 +179,6 @@
<string name="low_memory" product="default" msgid="2539532364144025569">"La mémoire du téléphone est pleine. Veuillez supprimer des fichiers pour libérer de l\'espace."</string>
<plurals name="ssl_ca_cert_warning" formatted="false" msgid="2288194355006173029">
<item quantity="one">Autorité de certification installée</item>
- <item quantity="many">Certificate authorities installed</item>
<item quantity="other">Autorités de certification installées</item>
</plurals>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4961102218216815242">"Par un tiers inconnu"</string>
@@ -256,7 +254,6 @@
<string name="bugreport_option_full_summary" msgid="1975130009258435885">"Utilisez cette option pour qu\'il y ait le moins d\'interférences système possible lorsque votre appareil ne répond pas ou qu\'il est trop lent, ou lorsque vous avez besoin de toutes les sections du rapport de bogue. Aucune capture d\'écran supplémentaire ne peut être capturée, et vous ne pouvez entrer aucune autre information."</string>
<plurals name="bugreport_countdown" formatted="false" msgid="3906120379260059206">
<item quantity="one">Saisie d\'écran pour le rapport de bogue dans <xliff:g id="NUMBER_1">%d</xliff:g> seconde.</item>
- <item quantity="many">Taking screenshot for bug report in <xliff:g id="NUMBER_1">%d</xliff:g> seconds.</item>
<item quantity="other">Saisie d\'écran pour le rapport de bogue dans <xliff:g id="NUMBER_1">%d</xliff:g> secondes.</item>
</plurals>
<string name="bugreport_screenshot_success_toast" msgid="7986095104151473745">"Capture d\'écran prise avec le rapport de bogue"</string>
@@ -356,10 +353,8 @@
<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_manageOngoingCalls" msgid="281244770664231782">"Gérer les appels en cours"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Autorise une application à afficher les renseignements concernant les appels en cours sur votre appareil et à les gérer."</string>
<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>
@@ -1010,7 +1005,6 @@
<string name="beforeOneMonthDurationPast" msgid="8315149541372065392">"Il y a plus d\'un mois"</string>
<plurals name="last_num_days" formatted="false" msgid="687443109145393632">
<item quantity="one">Le dernier <xliff:g id="COUNT_1">%d</xliff:g> jour</item>
- <item quantity="many">Last <xliff:g id="COUNT_1">%d</xliff:g> days</item>
<item quantity="other">Le dernier <xliff:g id="COUNT_1">%d</xliff:g> jours</item>
</plurals>
<string name="last_month" msgid="1528906781083518683">"Le mois dernier"</string>
@@ -1033,82 +1027,66 @@
<string name="now_string_shortest" msgid="3684914126941650330">"maintenant"</string>
<plurals name="duration_minutes_shortest" formatted="false" msgid="7519574894537185135">
<item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> m</item>
- <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g>m</item>
<item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> m</item>
</plurals>
<plurals name="duration_hours_shortest" formatted="false" msgid="2838655994500499651">
<item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> h</item>
- <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g>h</item>
<item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> h</item>
</plurals>
<plurals name="duration_days_shortest" formatted="false" msgid="3686058472983158496">
<item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> j</item>
- <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g>d</item>
<item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> j</item>
</plurals>
<plurals name="duration_years_shortest" formatted="false" msgid="8299112348723640338">
<item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> a</item>
- <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g>y</item>
<item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> a</item>
</plurals>
<plurals name="duration_minutes_shortest_future" formatted="false" msgid="849196137176399440">
<item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> m</item>
- <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g>m</item>
<item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> m</item>
</plurals>
<plurals name="duration_hours_shortest_future" formatted="false" msgid="5386373597343170388">
<item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> h</item>
- <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g>h</item>
<item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> h</item>
</plurals>
<plurals name="duration_days_shortest_future" formatted="false" msgid="814754627092787227">
<item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> j</item>
- <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g>d</item>
<item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> j</item>
</plurals>
<plurals name="duration_years_shortest_future" formatted="false" msgid="7683731800140202145">
<item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> a</item>
- <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g>y</item>
<item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> a</item>
</plurals>
<plurals name="duration_minutes_relative" formatted="false" msgid="6569851308583028344">
<item quantity="one">il y a <xliff:g id="COUNT_1">%d</xliff:g> minute</item>
- <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> minutes ago</item>
<item quantity="other">il y a <xliff:g id="COUNT_1">%d</xliff:g> minutes</item>
</plurals>
<plurals name="duration_hours_relative" formatted="false" msgid="420434788589102019">
<item quantity="one">il y a<xliff:g id="COUNT_1">%d</xliff:g> heure</item>
- <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> hours ago</item>
<item quantity="other">il y a<xliff:g id="COUNT_1">%d</xliff:g> heures</item>
</plurals>
<plurals name="duration_days_relative" formatted="false" msgid="6056425878237482431">
<item quantity="one">il y a <xliff:g id="COUNT_1">%d</xliff:g> jour</item>
- <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> days ago</item>
<item quantity="other">il y a <xliff:g id="COUNT_1">%d</xliff:g> jours</item>
</plurals>
<plurals name="duration_years_relative" formatted="false" msgid="2179998228861172159">
<item quantity="one">il y a <xliff:g id="COUNT_1">%d</xliff:g> an</item>
- <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> years ago</item>
<item quantity="other">il y a <xliff:g id="COUNT_1">%d</xliff:g> ans</item>
</plurals>
<plurals name="duration_minutes_relative_future" formatted="false" msgid="5759885720917567723">
<item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> minute</item>
- <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g> minutes</item>
<item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> minutes</item>
</plurals>
<plurals name="duration_hours_relative_future" formatted="false" msgid="8963511608507707959">
<item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> heure</item>
- <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g> hours</item>
<item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> heures</item>
</plurals>
<plurals name="duration_days_relative_future" formatted="false" msgid="1964709470979250702">
<item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> jour</item>
- <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g> days</item>
<item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> jours</item>
</plurals>
<plurals name="duration_years_relative_future" formatted="false" msgid="3985129025134896371">
<item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> ans</item>
- <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g> years</item>
<item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> ans</item>
</plurals>
<string name="VideoView_error_title" msgid="5750686717225068016">"Problème vidéo"</string>
@@ -1481,7 +1459,6 @@
<string name="find_on_page" msgid="5400537367077438198">"Rechercher sur la page"</string>
<plurals name="matches_found" formatted="false" msgid="1101758718194295554">
<item quantity="one"><xliff:g id="INDEX">%d</xliff:g> sur <xliff:g id="TOTAL">%d</xliff:g></item>
- <item quantity="many"><xliff:g id="INDEX">%d</xliff:g> of <xliff:g id="TOTAL">%d</xliff:g></item>
<item quantity="other"><xliff:g id="INDEX">%d</xliff:g> sur <xliff:g id="TOTAL">%d</xliff:g></item>
</plurals>
<string name="action_mode_done" msgid="2536182504764803222">"Terminé"</string>
@@ -1615,7 +1592,6 @@
<string name="kg_wrong_pin" msgid="3680925703673166482">"NIP incorrect."</string>
<plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="236717428673283568">
<item quantity="one">Réessayer dans <xliff:g id="NUMBER">%d</xliff:g> seconde.</item>
- <item quantity="many">Try again in <xliff:g id="NUMBER">%d</xliff:g> seconds.</item>
<item quantity="other">Réessayer dans <xliff:g id="NUMBER">%d</xliff:g> secondes.</item>
</plurals>
<string name="kg_pattern_instructions" msgid="8366024510502517748">"Dessinez votre schéma."</string>
@@ -1802,7 +1778,6 @@
<string name="restr_pin_error_too_short" msgid="1547007808237941065">"Le NIP est trop court. Il doit comporter au moins 4 chiffres."</string>
<plurals name="restr_pin_countdown" formatted="false" msgid="4427486903285216153">
<item quantity="one">Réessayer dans <xliff:g id="COUNT">%d</xliff:g> seconde</item>
- <item quantity="many">Try again in <xliff:g id="COUNT">%d</xliff:g> seconds</item>
<item quantity="other">Réessayer dans <xliff:g id="COUNT">%d</xliff:g> secondes</item>
</plurals>
<string name="restr_pin_try_later" msgid="5897719962541636727">"Réessayez plus tard"</string>
@@ -1834,42 +1809,34 @@
<string name="data_saver_enable_button" msgid="4399405762586419726">"Activer"</string>
<plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="2877101784123058273">
<item quantity="one">Pendant %1$d minute (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
- <item quantity="many">For %1$d minutes (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
<item quantity="other">Pendant %1$d minutes (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
</plurals>
<plurals name="zen_mode_duration_minutes_summary_short" formatted="false" msgid="4230730310318858312">
<item quantity="one">Pendant %1$d min (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
- <item quantity="many">For %1$d min (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
<item quantity="other">Pendant %1$d min (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
</plurals>
<plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="7725354244196466758">
<item quantity="one">Pendant %1$d heure (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
- <item quantity="many">For %1$d hours (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
<item quantity="other">Pendant %1$d heures (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
</plurals>
<plurals name="zen_mode_duration_hours_summary_short" formatted="false" msgid="588719069121765642">
<item quantity="one">Pendant %1$d h (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
- <item quantity="many">For %1$d hr (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
<item quantity="other">Pendant %1$d h (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
</plurals>
<plurals name="zen_mode_duration_minutes" formatted="false" msgid="1148568456958944998">
<item quantity="one">Pendant %d minute</item>
- <item quantity="many">For %d minutes</item>
<item quantity="other">Pendant %d minutes</item>
</plurals>
<plurals name="zen_mode_duration_minutes_short" formatted="false" msgid="2742377799995454859">
<item quantity="one">Pendant %d min</item>
- <item quantity="many">For %d min</item>
<item quantity="other">Pendant %d min</item>
</plurals>
<plurals name="zen_mode_duration_hours" formatted="false" msgid="525401855645490022">
<item quantity="one">Pendant %d heure</item>
- <item quantity="many">For %d hours</item>
<item quantity="other">Pendant %d heures</item>
</plurals>
<plurals name="zen_mode_duration_hours_short" formatted="false" msgid="7644653189680911640">
<item quantity="one">Pendant %d h</item>
- <item quantity="many">For %d hr</item>
<item quantity="other">Pendant %d h</item>
</plurals>
<string name="zen_mode_until_next_day" msgid="1403042784161725038">"Jusqu\'à <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
@@ -1911,7 +1878,6 @@
<string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g> : <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
<plurals name="selected_count" formatted="false" msgid="3946212171128200491">
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> élément sélectionné</item>
- <item quantity="many"><xliff:g id="COUNT_1">%1$d</xliff:g> selected</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> éléments sélectionnés</item>
</plurals>
<string name="default_notification_channel_label" msgid="3697928973567217330">"Sans catégorie"</string>
@@ -1979,7 +1945,6 @@
<string name="autofill_picker_no_suggestions" msgid="1076022650427481509">"Aucune suggestion de remplissage automatique"</string>
<plurals name="autofill_picker_some_suggestions" formatted="false" msgid="6651883186966959978">
<item quantity="one"><xliff:g id="COUNT">%1$s</xliff:g> suggestion de remplissage automatique</item>
- <item quantity="many"><xliff:g id="COUNT">%1$s</xliff:g> autofill suggestions</item>
<item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> suggestions de remplissage automatique</item>
</plurals>
<string name="autofill_save_title" msgid="7719802414283739775">"Enregistrer sous "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
@@ -2074,7 +2039,6 @@
<string name="car_loading_profile" msgid="8219978381196748070">"Chargement en cours…"</string>
<plurals name="file_count" formatted="false" msgid="7063513834724389247">
<item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> fichier</item>
- <item quantity="many"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> files</item>
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> fichiers</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"Aucune recommandation de personnes avec lesquelles effectuer un partage"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 9e0f60c..3a0d0cd 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -52,7 +52,6 @@
<string name="enablePin" msgid="2543771964137091212">"Échec de l\'opération. Veuillez activer le verrouillage de la carte SIM/RUIM."</string>
<plurals name="pinpuk_attempts" formatted="false" msgid="1619867269012213584">
<item quantity="one">Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentative avant que votre carte SIM ne soit verrouillée.</item>
- <item quantity="many">You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts before SIM is locked.</item>
<item quantity="other">Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentatives avant que votre carte SIM ne soit verrouillée.</item>
</plurals>
<string name="imei" msgid="2157082351232630390">"Code IMEI"</string>
@@ -180,7 +179,6 @@
<string name="low_memory" product="default" msgid="2539532364144025569">"La mémoire du téléphone est pleine. Veuillez supprimer des fichiers pour libérer de l\'espace."</string>
<plurals name="ssl_ca_cert_warning" formatted="false" msgid="2288194355006173029">
<item quantity="one">Autorité de certification installée</item>
- <item quantity="many">Certificate authorities installed</item>
<item quantity="other">Autorités de certification installées</item>
</plurals>
<string name="ssl_ca_cert_noti_by_unknown" msgid="4961102218216815242">"Par un tiers inconnu"</string>
@@ -256,7 +254,6 @@
<string name="bugreport_option_full_summary" msgid="1975130009258435885">"Utilisez cette option pour qu\'il y ait le moins d\'interférences système possible lorsque votre appareil ne répond pas ou qu\'il est trop lent, ou lorsque vous avez besoin de toutes les sections du rapport de bug. Aucune capture d\'écran supplémentaire ne peut être prise, et vous ne pouvez saisir aucune autre information."</string>
<plurals name="bugreport_countdown" formatted="false" msgid="3906120379260059206">
<item quantity="one">Capture d\'écran pour le rapport de bug dans <xliff:g id="NUMBER_1">%d</xliff:g> seconde</item>
- <item quantity="many">Taking screenshot for bug report in <xliff:g id="NUMBER_1">%d</xliff:g> seconds.</item>
<item quantity="other">Capture d\'écran pour le rapport de bug dans <xliff:g id="NUMBER_1">%d</xliff:g> secondes</item>
</plurals>
<string name="bugreport_screenshot_success_toast" msgid="7986095104151473745">"Capture d\'écran avec rapport de bug effectuée"</string>
@@ -356,10 +353,8 @@
<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_manageOngoingCalls" msgid="281244770664231782">"Gérer les appels en cours"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Autorise une application à afficher les détails concernant les appels en cours sur votre appareil et à contrôler ces appels."</string>
<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>
@@ -1010,7 +1005,6 @@
<string name="beforeOneMonthDurationPast" msgid="8315149541372065392">"Il y a plus d\'un mois"</string>
<plurals name="last_num_days" formatted="false" msgid="687443109145393632">
<item quantity="one">Le dernier jour (<xliff:g id="COUNT_1">%d</xliff:g>)</item>
- <item quantity="many">Last <xliff:g id="COUNT_1">%d</xliff:g> days</item>
<item quantity="other">Les <xliff:g id="COUNT_1">%d</xliff:g> derniers jours</item>
</plurals>
<string name="last_month" msgid="1528906781083518683">"Le mois dernier"</string>
@@ -1033,82 +1027,66 @@
<string name="now_string_shortest" msgid="3684914126941650330">"mainten."</string>
<plurals name="duration_minutes_shortest" formatted="false" msgid="7519574894537185135">
<item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> m</item>
- <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g>m</item>
<item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> m</item>
</plurals>
<plurals name="duration_hours_shortest" formatted="false" msgid="2838655994500499651">
<item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> h</item>
- <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g>h</item>
<item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> h</item>
</plurals>
<plurals name="duration_days_shortest" formatted="false" msgid="3686058472983158496">
<item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> j</item>
- <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g>d</item>
<item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> j</item>
</plurals>
<plurals name="duration_years_shortest" formatted="false" msgid="8299112348723640338">
<item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> a</item>
- <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g>y</item>
<item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> a</item>
</plurals>
<plurals name="duration_minutes_shortest_future" formatted="false" msgid="849196137176399440">
<item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> m</item>
- <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g>m</item>
<item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> m</item>
</plurals>
<plurals name="duration_hours_shortest_future" formatted="false" msgid="5386373597343170388">
<item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> h</item>
- <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g>h</item>
<item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> h</item>
</plurals>
<plurals name="duration_days_shortest_future" formatted="false" msgid="814754627092787227">
<item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> j</item>
- <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g>d</item>
<item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> j</item>
</plurals>
<plurals name="duration_years_shortest_future" formatted="false" msgid="7683731800140202145">
<item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> a</item>
- <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g>y</item>
<item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> a</item>
</plurals>
<plurals name="duration_minutes_relative" formatted="false" msgid="6569851308583028344">
<item quantity="one">il y a <xliff:g id="COUNT_1">%d</xliff:g> minute</item>
- <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> minutes ago</item>
<item quantity="other">il y a <xliff:g id="COUNT_1">%d</xliff:g> minutes</item>
</plurals>
<plurals name="duration_hours_relative" formatted="false" msgid="420434788589102019">
<item quantity="one">il y a <xliff:g id="COUNT_1">%d</xliff:g> heure</item>
- <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> hours ago</item>
<item quantity="other">il y a <xliff:g id="COUNT_1">%d</xliff:g> heures</item>
</plurals>
<plurals name="duration_days_relative" formatted="false" msgid="6056425878237482431">
<item quantity="one">il y a <xliff:g id="COUNT_1">%d</xliff:g> jour</item>
- <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> days ago</item>
<item quantity="other">il y a <xliff:g id="COUNT_1">%d</xliff:g> jours</item>
</plurals>
<plurals name="duration_years_relative" formatted="false" msgid="2179998228861172159">
<item quantity="one">il y a <xliff:g id="COUNT_1">%d</xliff:g> an</item>
- <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> years ago</item>
<item quantity="other">il y a <xliff:g id="COUNT_1">%d</xliff:g> ans</item>
</plurals>
<plurals name="duration_minutes_relative_future" formatted="false" msgid="5759885720917567723">
<item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> minute</item>
- <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g> minutes</item>
<item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> minutes</item>
</plurals>
<plurals name="duration_hours_relative_future" formatted="false" msgid="8963511608507707959">
<item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> heure</item>
- <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g> hours</item>
<item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> heures</item>
</plurals>
<plurals name="duration_days_relative_future" formatted="false" msgid="1964709470979250702">
<item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> jour</item>
- <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g> days</item>
<item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> jours</item>
</plurals>
<plurals name="duration_years_relative_future" formatted="false" msgid="3985129025134896371">
<item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> an</item>
- <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g> years</item>
<item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> ans</item>
</plurals>
<string name="VideoView_error_title" msgid="5750686717225068016">"Problème vidéo"</string>
@@ -1481,7 +1459,6 @@
<string name="find_on_page" msgid="5400537367077438198">"Rechercher sur la page"</string>
<plurals name="matches_found" formatted="false" msgid="1101758718194295554">
<item quantity="one"><xliff:g id="INDEX">%d</xliff:g> sur <xliff:g id="TOTAL">%d</xliff:g></item>
- <item quantity="many"><xliff:g id="INDEX">%d</xliff:g> of <xliff:g id="TOTAL">%d</xliff:g></item>
<item quantity="other"><xliff:g id="INDEX">%d</xliff:g> sur <xliff:g id="TOTAL">%d</xliff:g></item>
</plurals>
<string name="action_mode_done" msgid="2536182504764803222">"OK"</string>
@@ -1615,7 +1592,6 @@
<string name="kg_wrong_pin" msgid="3680925703673166482">"Code PIN incorrect."</string>
<plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="236717428673283568">
<item quantity="one">Réessayez dans <xliff:g id="NUMBER">%d</xliff:g> seconde.</item>
- <item quantity="many">Try again in <xliff:g id="NUMBER">%d</xliff:g> seconds.</item>
<item quantity="other">Réessayez dans <xliff:g id="NUMBER">%d</xliff:g> secondes.</item>
</plurals>
<string name="kg_pattern_instructions" msgid="8366024510502517748">"Dessinez votre schéma."</string>
@@ -1802,7 +1778,6 @@
<string name="restr_pin_error_too_short" msgid="1547007808237941065">"Le code PIN est trop court. Il doit comporter au moins 4 chiffres."</string>
<plurals name="restr_pin_countdown" formatted="false" msgid="4427486903285216153">
<item quantity="one">Réessayer dans <xliff:g id="COUNT">%d</xliff:g> seconde</item>
- <item quantity="many">Try again in <xliff:g id="COUNT">%d</xliff:g> seconds</item>
<item quantity="other">Réessayer dans <xliff:g id="COUNT">%d</xliff:g> secondes</item>
</plurals>
<string name="restr_pin_try_later" msgid="5897719962541636727">"Veuillez réessayer ultérieurement."</string>
@@ -1834,42 +1809,34 @@
<string name="data_saver_enable_button" msgid="4399405762586419726">"Activer"</string>
<plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="2877101784123058273">
<item quantity="one">Pendant %1$d minute (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
- <item quantity="many">For %1$d minutes (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
<item quantity="other">Pendant %1$d minutes (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
</plurals>
<plurals name="zen_mode_duration_minutes_summary_short" formatted="false" msgid="4230730310318858312">
<item quantity="one">Pendant %1$d min (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
- <item quantity="many">For %1$d min (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
<item quantity="other">Pendant %1$d min (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
</plurals>
<plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="7725354244196466758">
<item quantity="one">Pendant %1$d heure (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
- <item quantity="many">For %1$d hours (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
<item quantity="other">Pendant %1$d heures (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
</plurals>
<plurals name="zen_mode_duration_hours_summary_short" formatted="false" msgid="588719069121765642">
<item quantity="one">Pendant %1$d h (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
- <item quantity="many">For %1$d hr (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
<item quantity="other">Pendant %1$d h (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
</plurals>
<plurals name="zen_mode_duration_minutes" formatted="false" msgid="1148568456958944998">
<item quantity="one">Pendant %d minute</item>
- <item quantity="many">For %d minutes</item>
<item quantity="other">Pendant %d minutes</item>
</plurals>
<plurals name="zen_mode_duration_minutes_short" formatted="false" msgid="2742377799995454859">
<item quantity="one">Pendant %d min</item>
- <item quantity="many">For %d min</item>
<item quantity="other">Pendant %d min</item>
</plurals>
<plurals name="zen_mode_duration_hours" formatted="false" msgid="525401855645490022">
<item quantity="one">Pendant %d heure</item>
- <item quantity="many">For %d hours</item>
<item quantity="other">Pendant %d heures</item>
</plurals>
<plurals name="zen_mode_duration_hours_short" formatted="false" msgid="7644653189680911640">
<item quantity="one">Pendant %d h</item>
- <item quantity="many">For %d hr</item>
<item quantity="other">Pendant %d h</item>
</plurals>
<string name="zen_mode_until_next_day" msgid="1403042784161725038">"Jusqu\'à <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
@@ -1911,7 +1878,6 @@
<string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g> : <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
<plurals name="selected_count" formatted="false" msgid="3946212171128200491">
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> élément sélectionné</item>
- <item quantity="many"><xliff:g id="COUNT_1">%1$d</xliff:g> selected</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> éléments sélectionnés</item>
</plurals>
<string name="default_notification_channel_label" msgid="3697928973567217330">"Sans catégorie"</string>
@@ -1979,7 +1945,6 @@
<string name="autofill_picker_no_suggestions" msgid="1076022650427481509">"Aucune suggestion de saisie automatique"</string>
<plurals name="autofill_picker_some_suggestions" formatted="false" msgid="6651883186966959978">
<item quantity="one"><xliff:g id="COUNT">%1$s</xliff:g> suggestion de saisie automatique</item>
- <item quantity="many"><xliff:g id="COUNT">%1$s</xliff:g> autofill suggestions</item>
<item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> suggestions de saisie automatique</item>
</plurals>
<string name="autofill_save_title" msgid="7719802414283739775">"Enregistrer dans "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" ?"</string>
@@ -2074,7 +2039,6 @@
<string name="car_loading_profile" msgid="8219978381196748070">"Chargement…"</string>
<plurals name="file_count" formatted="false" msgid="7063513834724389247">
<item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> fichier</item>
- <item quantity="many"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> files</item>
<item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> fichiers</item>
</plurals>
<string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"Aucune recommandation de personnes avec lesquelles effectuer un partage"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index 423b97f..8c21193 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -353,10 +353,8 @@
<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_manageOngoingCalls" msgid="281244770664231782">"Xestionar as chamadas saíntes"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Permite que unha aplicación controle as chamadas saíntes do teu dispositivo e consulte os detalles sobre elas."</string>
<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 14347ee..48edb0c 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -353,10 +353,8 @@
<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_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-hu/strings.xml b/core/res/res/values-hu/strings.xml
index ec0715b..9525801 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -353,10 +353,8 @@
<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_manageOngoingCalls" msgid="281244770664231782">"Folyamatban lévő hívások kezelése"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Engedélyezi az alkalmazásnak, hogy az eszközén folyamatban lévő hívások részleteihez hozzáférjen, és vezérelje ezeket a hívásokat."</string>
<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-in/strings.xml b/core/res/res/values-in/strings.xml
index 099f819..e6b4977 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -353,10 +353,8 @@
<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_manageOngoingCalls" msgid="281244770664231782">"Mengelola panggilan yang sedang berlangsung"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Mengizinkan aplikasi untuk melihat detail panggilan yang sedang berlangsung di perangkat dan mengontrolnya."</string>
<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-ko/strings.xml b/core/res/res/values-ko/strings.xml
index dfa3770..b20a427 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -353,10 +353,8 @@
<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_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-ky/strings.xml b/core/res/res/values-ky/strings.xml
index bd6ecef..1e8b38b 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -353,10 +353,8 @@
<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_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-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 49d3f44..edc8728 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -356,10 +356,8 @@
<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_manageOngoingCalls" msgid="281244770664231782">"Aktīvo zvanu pārvaldība"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Ļauj lietotnei skatīt detalizētu informāciju par aktīvajiem zvaniem jūsu ierīcē, kā arī kontrolēt šos zvanus."</string>
<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-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 3eca56c..a027b4c 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -353,10 +353,8 @@
<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_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-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 635c5b7..705ab6b 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -353,10 +353,8 @@
<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_manageOngoingCalls" msgid="281244770664231782">"Urus panggilan yang sedang berjalan"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Benarkan apl melihat butiran panggilan yang sedang berjalan pada peranti anda dan mengawal panggilan ini."</string>
<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-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 295a54e..2feb6af 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -359,10 +359,8 @@
<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_manageOngoingCalls" msgid="281244770664231782">"Zarządzaj połączeniami w toku"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Zezwala aplikacji zobaczyć detale dotyczące połączeń w toku na Twoim urządzeniu i na kontrolę tych połączeń."</string>
<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-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 340b752..e73d96c 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -356,10 +356,8 @@
<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_manageOngoingCalls" msgid="281244770664231782">"Să gestioneze apelurile în desfășurare"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Permite unei aplicații să vadă detalii despre apelurile în desfășurare de pe dispozitiv și să gestioneze apelurile respective."</string>
<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 74d5bf9..7ca863a 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -359,10 +359,8 @@
<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_manageOngoingCalls" msgid="281244770664231782">"Управление текущими звонками"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Приложение сможет управлять текущими звонками на вашем устройстве, а также получит доступ к сведениям о них"</string>
<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-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 25989bd..18a1f98 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -353,10 +353,8 @@
<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_manageOngoingCalls" msgid="281244770664231782">"Menaxho telefonatat në vazhdim"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Lejon që një aplikacion të shikojë detaje rreth telefonatave në vazhdim dhe t\'i kontrollojë këto telefonata."</string>
<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-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 0818d80..2f342b1 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -353,10 +353,8 @@
<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_manageOngoingCalls" msgid="281244770664231782">"Dhibiti simu zinazoendelea"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Huruhusu programu kuangalia maelezo kuhusu simu zinazoendelea kwenye kifaa chako na kuzidhibiti."</string>
<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-te/strings.xml b/core/res/res/values-te/strings.xml
index b4d3380..4602abb8 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -353,10 +353,8 @@
<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_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-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 96c15b1..324101d 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -353,10 +353,8 @@
<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_manageOngoingCalls" msgid="281244770664231782">"Devam eden aramaları yönetme"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Uygulamanın, cihazınızda devam eden aramalarla ilgili bilgileri görüp kontrol etmesine izin verir."</string>
<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 8511edc..ba124a6 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -359,10 +359,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 шкідливі додатки можуть перешкоджати роботі вашого пристрою."</string>
- <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) -->
- <skip />
- <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) -->
- <skip />
+ <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-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 8b27cd0..702f693 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -353,10 +353,8 @@
<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_manageOngoingCalls" msgid="281244770664231782">"Quản lý cuộc gọi đang diễn ra"</string>
+ <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Cho phép một ứng dụng xem thông tin chi tiết về các cuộc gọi đang diễn ra trên thiết bị và kiểm soát các cuộc gọi này."</string>
<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 9826dfb..c8d8f11 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -353,10 +353,8 @@
<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_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 a034f0b..1194b49 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -353,10 +353,8 @@
<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_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/attrs.xml b/core/res/res/values/attrs.xml
index f4c3063..7ca3faf 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3871,6 +3871,9 @@
<!-- Component name of an activity that allows the user to modify
the settings for this service. -->
<attr name="settingsActivity"/>
+ <!-- Whether the device must be screen on before routing data to this service.
+ The default is true.-->
+ <attr name="requireDeviceScreenOn" format="boolean"/>
</declare-styleable>
<!-- Use <code>offhost-apdu-service</code> as the root tag of the XML resource that
@@ -3889,6 +3892,12 @@
<attr name="settingsActivity"/>
<!-- Secure Element which the AIDs should be routed to -->
<attr name="secureElementName" format="string"/>
+ <!-- Whether the device must be unlocked before routing data to this service.
+ The default is false.-->
+ <attr name="requireDeviceUnlock"/>
+ <!-- Whether the device must be screen on before routing data to this service.
+ The default is false.-->
+ <attr name="requireDeviceScreenOn"/>
</declare-styleable>
<!-- Specify one or more <code>aid-group</code> elements inside a
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 945b586..da658cc 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4585,4 +4585,7 @@
<!-- Package with global data query permissions for AppSearch -->
<string name="config_globalAppSearchDataQuerierPackage" translatable="false"></string>
+
+ <!-- If true, attach the navigation bar to the app during app transition -->
+ <bool name="config_attachNavBarToAppDuringTransition">false</bool>
</resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 4fd8ef6..5b19a48 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">16dp</dimen>
+ <dimen name="notification_feedback_size">20dp</dimen>
<!-- Size of the profile badge for notifications -->
<dimen name="notification_badge_size">12dp</dimen>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 1e9a747..4313d4a 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3049,6 +3049,7 @@
<public name="windowLayoutAffinity" />
<!-- @hide -->
<public name="windowBackgroundBlurRadius"/>
+ <public name="requireDeviceScreenOn" />
</public-group>
<public-group type="drawable" first-id="0x010800b5">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 31aee4a..3a593b9 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -5366,6 +5366,14 @@
<!-- Feedback Indicator -->
<!-- Content description of the feedback icon in the notification. [CHAR LIMIT=NONE] -->
<string name="notification_feedback_indicator">Provide Feedback</string>
+ <!-- Content description of the alerted feedback icon in the notification. [CHAR LIMIT=NONE] -->
+ <string name="notification_feedback_indicator_alerted">This notification was promoted to Default. Tap to provide feedback.</string>
+ <!-- Content description of the silenced feedback icon in the notification. [CHAR LIMIT=NONE] -->
+ <string name="notification_feedback_indicator_silenced">This notification was demoted to Silent. Tap to provide feedback.</string>
+ <!-- Content description of the promoted feedback icon in the notification. [CHAR LIMIT=NONE] -->
+ <string name="notification_feedback_indicator_promoted">This notification was ranked higher. Tap to provide feedback.</string>
+ <!-- Content description of the demoted feedback icon in the notification. [CHAR LIMIT=NONE] -->
+ <string name="notification_feedback_indicator_demoted">This notification was ranked lower. Tap to provide feedback.</string>
<!-- Dynamic mode battery saver strings -->
<!-- The user visible name of the notification channel for the routine mode battery saver fyi notification [CHAR_LIMIT=80]-->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index de275a5..fa66451 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2252,6 +2252,10 @@
<java-symbol type="string" name="ext_media_move_success_message" />
<java-symbol type="string" name="ext_media_move_failure_title" />
<java-symbol type="string" name="ext_media_move_failure_message" />
+ <java-symbol type="string" name="notification_feedback_indicator_alerted" />
+ <java-symbol type="string" name="notification_feedback_indicator_silenced" />
+ <java-symbol type="string" name="notification_feedback_indicator_promoted" />
+ <java-symbol type="string" name="notification_feedback_indicator_demoted" />
<java-symbol type="style" name="Animation.RecentApplications" />
<java-symbol type="integer" name="dock_enter_exit_duration" />
<java-symbol type="bool" name="config_battery_percentage_setting_available" />
@@ -4128,4 +4132,6 @@
<java-symbol type="color" name="accessibility_focus_highlight_color" />
<!-- Width of the outline stroke used by the accessibility focus rectangle -->
<java-symbol type="dimen" name="accessibility_focus_highlight_stroke_width" />
+
+ <java-symbol type="bool" name="config_attachNavBarToAppDuringTransition" />
</resources>
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 1d9d9e8..8086ff2 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
@@ -142,12 +142,16 @@
}
BatteryConsumer requestedBatteryConsumer = null;
+ double totalModeledCpuPowerMah = 0;
for (BatteryConsumer consumer : batteryUsageStats.getUidBatteryConsumers()) {
if (batteryConsumerId(consumer).equals(batteryConsumerId)) {
requestedBatteryConsumer = consumer;
- break;
}
+
+ totalModeledCpuPowerMah += consumer.getConsumedPowerForCustomComponent(
+ BatteryConsumer.FIRST_MODELED_POWER_COMPONENT_ID
+ + BatteryConsumer.POWER_COMPONENT_CPU);
}
if (requestedBatterySipper == null) {
@@ -190,9 +194,17 @@
addEntry("CPU", EntryType.POWER,
requestedBatteryConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU),
totalCpuPowerMah);
+ if (totalModeledCpuPowerMah != 0) {
+ addEntry("CPU (modeled)", EntryType.POWER,
+ requestedBatteryConsumer.getConsumedPowerForCustomComponent(
+ BatteryConsumer.FIRST_MODELED_POWER_COMPONENT_ID
+ + BatteryConsumer.POWER_COMPONENT_CPU),
+ totalModeledCpuPowerMah);
+ }
+ } else {
+ addEntry("CPU (sipper)", EntryType.POWER,
+ requestedBatterySipper.cpuPowerMah, totalCpuPowerMah);
}
- addEntry("CPU (sipper)", EntryType.POWER,
- requestedBatterySipper.cpuPowerMah, totalCpuPowerMah);
addEntry("System services", EntryType.POWER,
requestedBatterySipper.systemServiceCpuPowerMah, totalSystemServiceCpuPowerMah);
if (requestedBatteryConsumer != null) {
diff --git a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryStatsViewerActivity.java b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryStatsViewerActivity.java
index 4978010f..87a175a 100644
--- a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryStatsViewerActivity.java
+++ b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryStatsViewerActivity.java
@@ -21,6 +21,7 @@
import android.os.BatteryStats;
import android.os.BatteryStatsManager;
import android.os.BatteryUsageStats;
+import android.os.BatteryUsageStatsQuery;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
@@ -197,7 +198,10 @@
@Override
public BatteryUsageStats loadInBackground() {
- return mBatteryStatsManager.getBatteryUsageStats();
+ final BatteryUsageStatsQuery query = new BatteryUsageStatsQuery.Builder()
+ .includeModeled()
+ .build();
+ return mBatteryStatsManager.getBatteryUsageStats(query);
}
@Override
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchResultCtsTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchResultCtsTest.java
deleted file mode 100644
index 9c34b17..0000000
--- a/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchResultCtsTest.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app.appsearch.cts;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.app.appsearch.AppSearchResult;
-
-import org.junit.Test;
-
-public class AppSearchResultCtsTest {
-
- @Test
- public void testResultEquals_identical() {
- AppSearchResult<String> result1 = AppSearchResult.newSuccessfulResult("String");
- AppSearchResult<String> result2 = AppSearchResult.newSuccessfulResult("String");
-
- assertThat(result1).isEqualTo(result2);
- assertThat(result1.hashCode()).isEqualTo(result2.hashCode());
-
- AppSearchResult<String> result3 =
- AppSearchResult.newFailedResult(
- AppSearchResult.RESULT_INTERNAL_ERROR, "errorMessage");
- AppSearchResult<String> result4 =
- AppSearchResult.newFailedResult(
- AppSearchResult.RESULT_INTERNAL_ERROR, "errorMessage");
-
- assertThat(result3).isEqualTo(result4);
- assertThat(result3.hashCode()).isEqualTo(result4.hashCode());
- }
-
- @Test
- public void testResultEquals_failure() {
- AppSearchResult<String> result1 = AppSearchResult.newSuccessfulResult("String");
- AppSearchResult<String> result2 = AppSearchResult.newSuccessfulResult("Wrong");
- AppSearchResult<String> resultNull = AppSearchResult.newSuccessfulResult(/*value=*/ null);
-
- assertThat(result1).isNotEqualTo(result2);
- assertThat(result1.hashCode()).isNotEqualTo(result2.hashCode());
- assertThat(result1).isNotEqualTo(resultNull);
- assertThat(result1.hashCode()).isNotEqualTo(resultNull.hashCode());
-
- AppSearchResult<String> result3 =
- AppSearchResult.newFailedResult(
- AppSearchResult.RESULT_INTERNAL_ERROR, "errorMessage");
- AppSearchResult<String> result4 =
- AppSearchResult.newFailedResult(AppSearchResult.RESULT_IO_ERROR, "errorMessage");
-
- assertThat(result3).isNotEqualTo(result4);
- assertThat(result3.hashCode()).isNotEqualTo(result4.hashCode());
-
- AppSearchResult<String> result5 =
- AppSearchResult.newFailedResult(AppSearchResult.RESULT_INTERNAL_ERROR, "Wrong");
-
- assertThat(result3).isNotEqualTo(result5);
- assertThat(result3.hashCode()).isNotEqualTo(result5.hashCode());
-
- AppSearchResult<String> result6 =
- AppSearchResult.newFailedResult(
- AppSearchResult.RESULT_INTERNAL_ERROR, /*errorMessage=*/ null);
-
- assertThat(result3).isNotEqualTo(result6);
- assertThat(result3.hashCode()).isNotEqualTo(result6.hashCode());
- }
-}
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchSchemaCtsTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchSchemaCtsTest.java
deleted file mode 100644
index 7072a81..0000000
--- a/core/tests/coretests/src/android/app/appsearch/external/app/cts/AppSearchSchemaCtsTest.java
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app.appsearch.cts;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.testng.Assert.expectThrows;
-
-import android.app.appsearch.AppSearchSchema;
-import android.app.appsearch.AppSearchSchema.PropertyConfig;
-import android.app.appsearch.exceptions.IllegalSchemaException;
-
-import org.junit.Test;
-
-public class AppSearchSchemaCtsTest {
- @Test
- public void testInvalidEnums() {
- PropertyConfig.Builder builder = new PropertyConfig.Builder("test");
- expectThrows(IllegalArgumentException.class, () -> builder.setDataType(99));
- expectThrows(IllegalArgumentException.class, () -> builder.setCardinality(99));
- }
-
- @Test
- public void testMissingFields() {
- PropertyConfig.Builder builder = new PropertyConfig.Builder("test");
- IllegalSchemaException e = expectThrows(IllegalSchemaException.class, builder::build);
- assertThat(e).hasMessageThat().contains("Missing field: dataType");
-
- builder.setDataType(PropertyConfig.DATA_TYPE_DOCUMENT);
- e = expectThrows(IllegalSchemaException.class, builder::build);
- assertThat(e).hasMessageThat().contains("Missing field: schemaType");
-
- builder.setSchemaType("TestType");
- e = expectThrows(IllegalSchemaException.class, builder::build);
- assertThat(e).hasMessageThat().contains("Missing field: cardinality");
-
- builder.setCardinality(PropertyConfig.CARDINALITY_REPEATED);
- builder.build();
- }
-
- @Test
- public void testDuplicateProperties() {
- AppSearchSchema.Builder builder =
- new AppSearchSchema.Builder("Email")
- .addProperty(
- new PropertyConfig.Builder("subject")
- .setDataType(PropertyConfig.DATA_TYPE_STRING)
- .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
- .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
- .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
- .build());
- IllegalSchemaException e =
- expectThrows(
- IllegalSchemaException.class,
- () ->
- builder.addProperty(
- new PropertyConfig.Builder("subject")
- .setDataType(PropertyConfig.DATA_TYPE_STRING)
- .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
- .setIndexingType(
- PropertyConfig.INDEXING_TYPE_PREFIXES)
- .setTokenizerType(
- PropertyConfig.TOKENIZER_TYPE_PLAIN)
- .build()));
- assertThat(e).hasMessageThat().contains("Property defined more than once: subject");
- }
-
- @Test
- public void testEquals_identical() {
- AppSearchSchema schema1 =
- new AppSearchSchema.Builder("Email")
- .addProperty(
- new PropertyConfig.Builder("subject")
- .setDataType(PropertyConfig.DATA_TYPE_STRING)
- .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
- .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
- .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
- .build())
- .build();
- AppSearchSchema schema2 =
- new AppSearchSchema.Builder("Email")
- .addProperty(
- new PropertyConfig.Builder("subject")
- .setDataType(PropertyConfig.DATA_TYPE_STRING)
- .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
- .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
- .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
- .build())
- .build();
- assertThat(schema1).isEqualTo(schema2);
- assertThat(schema1.hashCode()).isEqualTo(schema2.hashCode());
- }
-
- @Test
- public void testEquals_differentOrder() {
- AppSearchSchema schema1 =
- new AppSearchSchema.Builder("Email")
- .addProperty(
- new PropertyConfig.Builder("subject")
- .setDataType(PropertyConfig.DATA_TYPE_STRING)
- .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
- .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
- .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
- .build())
- .build();
- AppSearchSchema schema2 =
- new AppSearchSchema.Builder("Email")
- .addProperty(
- new PropertyConfig.Builder("subject")
- .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
- .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
- .setDataType(PropertyConfig.DATA_TYPE_STRING)
- .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
- .build())
- .build();
- assertThat(schema1).isEqualTo(schema2);
- assertThat(schema1.hashCode()).isEqualTo(schema2.hashCode());
- }
-
- @Test
- public void testEquals_failure() {
- AppSearchSchema schema1 =
- new AppSearchSchema.Builder("Email")
- .addProperty(
- new PropertyConfig.Builder("subject")
- .setDataType(PropertyConfig.DATA_TYPE_STRING)
- .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
- .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
- .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
- .build())
- .build();
- AppSearchSchema schema2 =
- new AppSearchSchema.Builder("Email")
- .addProperty(
- new PropertyConfig.Builder("subject")
- .setDataType(PropertyConfig.DATA_TYPE_STRING)
- .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
- .setIndexingType(
- PropertyConfig
- .INDEXING_TYPE_EXACT_TERMS) // Different
- .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
- .build())
- .build();
- assertThat(schema1).isNotEqualTo(schema2);
- assertThat(schema1.hashCode()).isNotEqualTo(schema2.hashCode());
- }
-
- @Test
- public void testEquals_failure_differentOrder() {
- AppSearchSchema schema1 =
- new AppSearchSchema.Builder("Email")
- .addProperty(
- new PropertyConfig.Builder("subject")
- .setDataType(PropertyConfig.DATA_TYPE_STRING)
- .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
- .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
- .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
- .build())
- .addProperty(
- new PropertyConfig.Builder("body")
- .setDataType(PropertyConfig.DATA_TYPE_STRING)
- .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
- .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
- .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
- .build())
- .build();
- // Order of 'body' and 'subject' has been switched
- AppSearchSchema schema2 =
- new AppSearchSchema.Builder("Email")
- .addProperty(
- new PropertyConfig.Builder("body")
- .setDataType(PropertyConfig.DATA_TYPE_STRING)
- .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
- .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
- .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
- .build())
- .addProperty(
- new PropertyConfig.Builder("subject")
- .setDataType(PropertyConfig.DATA_TYPE_STRING)
- .setCardinality(PropertyConfig.CARDINALITY_OPTIONAL)
- .setIndexingType(PropertyConfig.INDEXING_TYPE_PREFIXES)
- .setTokenizerType(PropertyConfig.TOKENIZER_TYPE_PLAIN)
- .build())
- .build();
- assertThat(schema1).isNotEqualTo(schema2);
- assertThat(schema1.hashCode()).isNotEqualTo(schema2.hashCode());
- }
-}
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/cts/GenericDocumentCtsTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/cts/GenericDocumentCtsTest.java
deleted file mode 100644
index 657d556..0000000
--- a/core/tests/coretests/src/android/app/appsearch/external/app/cts/GenericDocumentCtsTest.java
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app.appsearch.cts;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.testng.Assert.expectThrows;
-
-import android.app.appsearch.GenericDocument;
-
-import org.junit.Test;
-
-public class GenericDocumentCtsTest {
- private static final byte[] sByteArray1 = new byte[] {(byte) 1, (byte) 2, (byte) 3};
- private static final byte[] sByteArray2 = new byte[] {(byte) 4, (byte) 5, (byte) 6, (byte) 7};
- private static final GenericDocument sDocumentProperties1 =
- new GenericDocument.Builder<>("sDocumentProperties1", "sDocumentPropertiesSchemaType1")
- .setCreationTimestampMillis(12345L)
- .build();
- private static final GenericDocument sDocumentProperties2 =
- new GenericDocument.Builder<>("sDocumentProperties2", "sDocumentPropertiesSchemaType2")
- .setCreationTimestampMillis(6789L)
- .build();
-
- @Test
- public void testDocumentEquals_identical() {
- GenericDocument document1 =
- new GenericDocument.Builder<>("uri1", "schemaType1")
- .setCreationTimestampMillis(5L)
- .setTtlMillis(1L)
- .setPropertyLong("longKey1", 1L, 2L, 3L)
- .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
- .setPropertyBoolean("booleanKey1", true, false, true)
- .setPropertyString(
- "stringKey1", "test-value1", "test-value2", "test-value3")
- .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
- .setPropertyDocument(
- "documentKey1", sDocumentProperties1, sDocumentProperties2)
- .build();
- GenericDocument document2 =
- new GenericDocument.Builder<>("uri1", "schemaType1")
- .setCreationTimestampMillis(5L)
- .setTtlMillis(1L)
- .setPropertyLong("longKey1", 1L, 2L, 3L)
- .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
- .setPropertyBoolean("booleanKey1", true, false, true)
- .setPropertyString(
- "stringKey1", "test-value1", "test-value2", "test-value3")
- .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
- .setPropertyDocument(
- "documentKey1", sDocumentProperties1, sDocumentProperties2)
- .build();
- assertThat(document1).isEqualTo(document2);
- assertThat(document1.hashCode()).isEqualTo(document2.hashCode());
- }
-
- @Test
- public void testDocumentEquals_differentOrder() {
- GenericDocument document1 =
- new GenericDocument.Builder<>("uri1", "schemaType1")
- .setCreationTimestampMillis(5L)
- .setPropertyLong("longKey1", 1L, 2L, 3L)
- .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
- .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
- .setPropertyBoolean("booleanKey1", true, false, true)
- .setPropertyDocument(
- "documentKey1", sDocumentProperties1, sDocumentProperties2)
- .setPropertyString(
- "stringKey1", "test-value1", "test-value2", "test-value3")
- .build();
-
- // Create second document with same parameter but different order.
- GenericDocument document2 =
- new GenericDocument.Builder<>("uri1", "schemaType1")
- .setCreationTimestampMillis(5L)
- .setPropertyBoolean("booleanKey1", true, false, true)
- .setPropertyDocument(
- "documentKey1", sDocumentProperties1, sDocumentProperties2)
- .setPropertyString(
- "stringKey1", "test-value1", "test-value2", "test-value3")
- .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
- .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
- .setPropertyLong("longKey1", 1L, 2L, 3L)
- .build();
- assertThat(document1).isEqualTo(document2);
- assertThat(document1.hashCode()).isEqualTo(document2.hashCode());
- }
-
- @Test
- public void testDocumentEquals_failure() {
- GenericDocument document1 =
- new GenericDocument.Builder<>("uri1", "schemaType1")
- .setCreationTimestampMillis(5L)
- .setPropertyLong("longKey1", 1L, 2L, 3L)
- .build();
-
- // Create second document with same order but different value.
- GenericDocument document2 =
- new GenericDocument.Builder<>("uri1", "schemaType1")
- .setCreationTimestampMillis(5L)
- .setPropertyLong("longKey1", 1L, 2L, 4L) // Different
- .build();
- assertThat(document1).isNotEqualTo(document2);
- assertThat(document1.hashCode()).isNotEqualTo(document2.hashCode());
- }
-
- @Test
- public void testDocumentEquals_repeatedFieldOrder_failure() {
- GenericDocument document1 =
- new GenericDocument.Builder<>("uri1", "schemaType1")
- .setCreationTimestampMillis(5L)
- .setPropertyBoolean("booleanKey1", true, false, true)
- .build();
-
- // Create second document with same order but different value.
- GenericDocument document2 =
- new GenericDocument.Builder<>("uri1", "schemaType1")
- .setCreationTimestampMillis(5L)
- .setPropertyBoolean("booleanKey1", true, true, false) // Different
- .build();
- assertThat(document1).isNotEqualTo(document2);
- assertThat(document1.hashCode()).isNotEqualTo(document2.hashCode());
- }
-
- @Test
- public void testDocumentGetSingleValue() {
- GenericDocument document =
- new GenericDocument.Builder<>("uri1", "schemaType1")
- .setCreationTimestampMillis(5L)
- .setScore(1)
- .setTtlMillis(1L)
- .setPropertyLong("longKey1", 1L)
- .setPropertyDouble("doubleKey1", 1.0)
- .setPropertyBoolean("booleanKey1", true)
- .setPropertyString("stringKey1", "test-value1")
- .setPropertyBytes("byteKey1", sByteArray1)
- .setPropertyDocument("documentKey1", sDocumentProperties1)
- .build();
- assertThat(document.getUri()).isEqualTo("uri1");
- assertThat(document.getTtlMillis()).isEqualTo(1L);
- assertThat(document.getSchemaType()).isEqualTo("schemaType1");
- assertThat(document.getCreationTimestampMillis()).isEqualTo(5);
- assertThat(document.getScore()).isEqualTo(1);
- assertThat(document.getPropertyLong("longKey1")).isEqualTo(1L);
- assertThat(document.getPropertyDouble("doubleKey1")).isEqualTo(1.0);
- assertThat(document.getPropertyBoolean("booleanKey1")).isTrue();
- assertThat(document.getPropertyString("stringKey1")).isEqualTo("test-value1");
- assertThat(document.getPropertyBytes("byteKey1"))
- .asList()
- .containsExactly((byte) 1, (byte) 2, (byte) 3);
- assertThat(document.getPropertyDocument("documentKey1")).isEqualTo(sDocumentProperties1);
- }
-
- @Test
- public void testDocumentGetArrayValues() {
- GenericDocument document =
- new GenericDocument.Builder<>("uri1", "schemaType1")
- .setCreationTimestampMillis(5L)
- .setPropertyLong("longKey1", 1L, 2L, 3L)
- .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
- .setPropertyBoolean("booleanKey1", true, false, true)
- .setPropertyString(
- "stringKey1", "test-value1", "test-value2", "test-value3")
- .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
- .setPropertyDocument(
- "documentKey1", sDocumentProperties1, sDocumentProperties2)
- .build();
-
- assertThat(document.getUri()).isEqualTo("uri1");
- assertThat(document.getSchemaType()).isEqualTo("schemaType1");
- assertThat(document.getPropertyLongArray("longKey1")).asList().containsExactly(1L, 2L, 3L);
- assertThat(document.getPropertyDoubleArray("doubleKey1"))
- .usingExactEquality()
- .containsExactly(1.0, 2.0, 3.0);
- assertThat(document.getPropertyBooleanArray("booleanKey1"))
- .asList()
- .containsExactly(true, false, true);
- assertThat(document.getPropertyStringArray("stringKey1"))
- .asList()
- .containsExactly("test-value1", "test-value2", "test-value3");
- assertThat(document.getPropertyBytesArray("byteKey1"))
- .asList()
- .containsExactly(sByteArray1, sByteArray2);
- assertThat(document.getPropertyDocumentArray("documentKey1"))
- .asList()
- .containsExactly(sDocumentProperties1, sDocumentProperties2);
- }
-
- @Test
- public void testDocument_toString() {
- GenericDocument document =
- new GenericDocument.Builder<>("uri1", "schemaType1")
- .setCreationTimestampMillis(5L)
- .setPropertyLong("longKey1", 1L, 2L, 3L)
- .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
- .setPropertyBoolean("booleanKey1", true, false, true)
- .setPropertyString("stringKey1", "String1", "String2", "String3")
- .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
- .setPropertyDocument(
- "documentKey1", sDocumentProperties1, sDocumentProperties2)
- .build();
- String exceptedString =
- "{ key: 'creationTimestampMillis' value: 5 } "
- + "{ key: 'namespace' value: } "
- + "{ key: 'properties' value: "
- + "{ key: 'booleanKey1' value: [ 'true' 'false' 'true' ] } "
- + "{ key: 'byteKey1' value: "
- + "{ key: 'byteArray' value: [ '1' '2' '3' ] } "
- + "{ key: 'byteArray' value: [ '4' '5' '6' '7' ] } } "
- + "{ key: 'documentKey1' value: [ '"
- + "{ key: 'creationTimestampMillis' value: 12345 } "
- + "{ key: 'namespace' value: } "
- + "{ key: 'properties' value: } "
- + "{ key: 'schemaType' value: sDocumentPropertiesSchemaType1 } "
- + "{ key: 'score' value: 0 } "
- + "{ key: 'ttlMillis' value: 0 } "
- + "{ key: 'uri' value: sDocumentProperties1 } ' '"
- + "{ key: 'creationTimestampMillis' value: 6789 } "
- + "{ key: 'namespace' value: } "
- + "{ key: 'properties' value: } "
- + "{ key: 'schemaType' value: sDocumentPropertiesSchemaType2 } "
- + "{ key: 'score' value: 0 } "
- + "{ key: 'ttlMillis' value: 0 } "
- + "{ key: 'uri' value: sDocumentProperties2 } ' ] } "
- + "{ key: 'doubleKey1' value: [ '1.0' '2.0' '3.0' ] } "
- + "{ key: 'longKey1' value: [ '1' '2' '3' ] } "
- + "{ key: 'stringKey1' value: [ 'String1' 'String2' 'String3' ] } } "
- + "{ key: 'schemaType' value: schemaType1 } "
- + "{ key: 'score' value: 0 } "
- + "{ key: 'ttlMillis' value: 0 } "
- + "{ key: 'uri' value: uri1 } ";
- assertThat(document.toString()).isEqualTo(exceptedString);
- }
-
- @Test
- public void testDocumentGetValues_differentTypes() {
- GenericDocument document =
- new GenericDocument.Builder<>("uri1", "schemaType1")
- .setScore(1)
- .setPropertyLong("longKey1", 1L)
- .setPropertyBoolean("booleanKey1", true, false, true)
- .setPropertyString(
- "stringKey1", "test-value1", "test-value2", "test-value3")
- .build();
-
- // Get a value for a key that doesn't exist
- assertThat(document.getPropertyDouble("doubleKey1")).isEqualTo(0.0);
- assertThat(document.getPropertyDoubleArray("doubleKey1")).isNull();
-
- // Get a value with a single element as an array and as a single value
- assertThat(document.getPropertyLong("longKey1")).isEqualTo(1L);
- assertThat(document.getPropertyLongArray("longKey1")).asList().containsExactly(1L);
-
- // Get a value with multiple elements as an array and as a single value
- assertThat(document.getPropertyString("stringKey1")).isEqualTo("test-value1");
- assertThat(document.getPropertyStringArray("stringKey1"))
- .asList()
- .containsExactly("test-value1", "test-value2", "test-value3");
-
- // Get a value of the wrong type
- assertThat(document.getPropertyDouble("longKey1")).isEqualTo(0.0);
- assertThat(document.getPropertyDoubleArray("longKey1")).isNull();
- }
-
- @Test
- public void testDocumentInvalid() {
- GenericDocument.Builder<?> builder = new GenericDocument.Builder<>("uri1", "schemaType1");
- expectThrows(
- IllegalArgumentException.class,
- () -> builder.setPropertyBoolean("test", new boolean[] {}));
- }
-}
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/cts/SearchSpecCtsTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/cts/SearchSpecCtsTest.java
deleted file mode 100644
index 50bca27..0000000
--- a/core/tests/coretests/src/android/app/appsearch/external/app/cts/SearchSpecCtsTest.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app.appsearch.cts;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.testng.Assert.expectThrows;
-
-import android.app.appsearch.SearchSpec;
-
-import org.junit.Test;
-
-public class SearchSpecCtsTest {
- @Test
- public void buildSearchSpecWithoutTermMatchType() {
- RuntimeException e =
- expectThrows(
- RuntimeException.class,
- () -> new SearchSpec.Builder().addSchemaType("testSchemaType").build());
- assertThat(e).hasMessageThat().contains("Missing termMatchType field");
- }
-
- @Test
- public void testBuildSearchSpec() {
- SearchSpec searchSpec =
- new SearchSpec.Builder()
- .setTermMatch(SearchSpec.TERM_MATCH_PREFIX)
- .addNamespace("namespace1", "namespace2")
- .addSchemaType("schemaTypes1", "schemaTypes2")
- .setSnippetCount(5)
- .setSnippetCountPerProperty(10)
- .setMaxSnippetSize(15)
- .setResultCountPerPage(42)
- .setOrder(SearchSpec.ORDER_ASCENDING)
- .setRankingStrategy(SearchSpec.RANKING_STRATEGY_DOCUMENT_SCORE)
- .build();
-
- assertThat(searchSpec.getTermMatch()).isEqualTo(SearchSpec.TERM_MATCH_PREFIX);
- assertThat(searchSpec.getNamespaces())
- .containsExactly("namespace1", "namespace2")
- .inOrder();
- assertThat(searchSpec.getSchemaTypes())
- .containsExactly("schemaTypes1", "schemaTypes2")
- .inOrder();
- assertThat(searchSpec.getSnippetCount()).isEqualTo(5);
- assertThat(searchSpec.getSnippetCountPerProperty()).isEqualTo(10);
- assertThat(searchSpec.getMaxSnippetSize()).isEqualTo(15);
- assertThat(searchSpec.getResultCountPerPage()).isEqualTo(42);
- assertThat(searchSpec.getOrder()).isEqualTo(SearchSpec.ORDER_ASCENDING);
- assertThat(searchSpec.getRankingStrategy())
- .isEqualTo(SearchSpec.RANKING_STRATEGY_DOCUMENT_SCORE);
- }
-}
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/cts/customer/CustomerDocumentTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/cts/customer/CustomerDocumentTest.java
deleted file mode 100644
index 29b5754..0000000
--- a/core/tests/coretests/src/android/app/appsearch/external/app/cts/customer/CustomerDocumentTest.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app.appsearch.cts.customer;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.annotation.NonNull;
-import android.app.appsearch.GenericDocument;
-
-import org.junit.Test;
-
-/**
- * Tests that {@link GenericDocument} and {@link GenericDocument.Builder} are extendable by
- * developers.
- *
- * <p>This class is intentionally in a different package than {@link GenericDocument} to make sure
- * there are no package-private methods required for external developers to add custom types.
- */
-public class CustomerDocumentTest {
-
- private static final byte[] BYTE_ARRAY1 = new byte[] {(byte) 1, (byte) 2, (byte) 3};
- private static final byte[] BYTE_ARRAY2 = new byte[] {(byte) 4, (byte) 5, (byte) 6};
- private static final GenericDocument DOCUMENT_PROPERTIES1 =
- new GenericDocument.Builder<>("sDocumentProperties1", "sDocumentPropertiesSchemaType1")
- .build();
- private static final GenericDocument DOCUMENT_PROPERTIES2 =
- new GenericDocument.Builder<>("sDocumentProperties2", "sDocumentPropertiesSchemaType2")
- .build();
-
- @Test
- public void testBuildCustomerDocument() {
- CustomerDocument customerDocument =
- new CustomerDocument.Builder("uri1")
- .setScore(1)
- .setCreationTimestampMillis(0)
- .setPropertyLong("longKey1", 1L, 2L, 3L)
- .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
- .setPropertyBoolean("booleanKey1", true, false, true)
- .setPropertyString(
- "stringKey1", "test-value1", "test-value2", "test-value3")
- .setPropertyBytes("byteKey1", BYTE_ARRAY1, BYTE_ARRAY2)
- .setPropertyDocument(
- "documentKey1", DOCUMENT_PROPERTIES1, DOCUMENT_PROPERTIES2)
- .build();
-
- assertThat(customerDocument.getUri()).isEqualTo("uri1");
- assertThat(customerDocument.getSchemaType()).isEqualTo("customerDocument");
- assertThat(customerDocument.getScore()).isEqualTo(1);
- assertThat(customerDocument.getCreationTimestampMillis()).isEqualTo(0L);
- assertThat(customerDocument.getPropertyLongArray("longKey1"))
- .asList()
- .containsExactly(1L, 2L, 3L);
- assertThat(customerDocument.getPropertyDoubleArray("doubleKey1"))
- .usingExactEquality()
- .containsExactly(1.0, 2.0, 3.0);
- assertThat(customerDocument.getPropertyBooleanArray("booleanKey1"))
- .asList()
- .containsExactly(true, false, true);
- assertThat(customerDocument.getPropertyStringArray("stringKey1"))
- .asList()
- .containsExactly("test-value1", "test-value2", "test-value3");
- assertThat(customerDocument.getPropertyBytesArray("byteKey1"))
- .asList()
- .containsExactly(BYTE_ARRAY1, BYTE_ARRAY2);
- assertThat(customerDocument.getPropertyDocumentArray("documentKey1"))
- .asList()
- .containsExactly(DOCUMENT_PROPERTIES1, DOCUMENT_PROPERTIES2);
- }
-
- /**
- * An example document type for test purposes, defined outside of {@link GenericDocument} (the
- * way an external developer would define it).
- */
- private static class CustomerDocument extends GenericDocument {
- private CustomerDocument(GenericDocument document) {
- super(document);
- }
-
- public static class Builder extends GenericDocument.Builder<CustomerDocument.Builder> {
- private Builder(@NonNull String uri) {
- super(uri, "customerDocument");
- }
-
- @Override
- @NonNull
- public CustomerDocument build() {
- return new CustomerDocument(super.build());
- }
- }
- }
-}
diff --git a/core/tests/coretests/src/android/hardware/input/InputDeviceSensorManagerTest.java b/core/tests/coretests/src/android/hardware/input/InputDeviceSensorManagerTest.java
new file mode 100644
index 0000000..b319886
--- /dev/null
+++ b/core/tests/coretests/src/android/hardware/input/InputDeviceSensorManagerTest.java
@@ -0,0 +1,251 @@
+/*
+ * 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.hardware.input;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertNotNull;
+import static junit.framework.TestCase.assertTrue;
+import static junit.framework.TestCase.fail;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.os.test.TestLooper;
+import android.platform.test.annotations.Presubmit;
+import android.view.InputDevice;
+
+import androidx.test.InstrumentationRegistry;
+
+import com.android.internal.annotations.GuardedBy;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.junit.MockitoRule;
+
+import java.util.List;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Tests for {@link InputDeviceSensorManager}.
+ *
+ * Build/Install/Run:
+ * atest FrameworksCoreTests:InputDeviceSensorManagerTest
+ */
+@Presubmit
+@RunWith(MockitoJUnitRunner.class)
+public class InputDeviceSensorManagerTest {
+ private static final String TAG = "InputDeviceSensorManagerTest";
+
+ private static final int DEVICE_ID = 1000;
+
+ @Rule public final MockitoRule mockito = MockitoJUnit.rule();
+
+ private TestLooper mTestLooper;
+ private ContextWrapper mContextSpy;
+ private InputManager mInputManager;
+ private InputDeviceSensorManager mSensorManager;
+ private IInputSensorEventListener mIInputSensorEventListener;
+ private final Object mLock = new Object();
+
+ @Mock private IInputManager mIInputManagerMock;
+
+ @Before
+ public void setUp() throws Exception {
+ mTestLooper = new TestLooper();
+ mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getContext()));
+ InputManager inputManager = InputManager.resetInstance(mIInputManagerMock);
+
+ when(mContextSpy.getSystemService(eq(Context.INPUT_SERVICE))).thenReturn(inputManager);
+
+ when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{DEVICE_ID});
+
+ when(mIInputManagerMock.getInputDevice(eq(DEVICE_ID))).thenReturn(
+ createInputDeviceWithSensor(DEVICE_ID));
+
+ when(mIInputManagerMock.getSensorList(eq(DEVICE_ID))).thenReturn(new InputSensorInfo[] {
+ createInputSensorInfo(DEVICE_ID, Sensor.TYPE_ACCELEROMETER),
+ createInputSensorInfo(DEVICE_ID, Sensor.TYPE_GYROSCOPE)});
+
+ when(mIInputManagerMock.enableSensor(eq(DEVICE_ID), anyInt(), anyInt(), anyInt()))
+ .thenReturn(true);
+
+ when(mIInputManagerMock.registerSensorListener(any())).thenReturn(true);
+
+ mInputManager = mContextSpy.getSystemService(InputManager.class);
+ }
+
+ @After
+ public void tearDown() {
+ InputManager.clearInstance();
+ }
+
+ private class InputTestSensorEventListener implements SensorEventListener {
+ @GuardedBy("mLock")
+ private final BlockingQueue<SensorEvent> mEvents = new LinkedBlockingQueue<>();
+ InputTestSensorEventListener() {
+ super();
+ }
+
+ public SensorEvent waitForSensorEvent() {
+ try {
+ return mEvents.poll(5, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ fail("unexpectedly interrupted while waiting for SensorEvent");
+ return null;
+ }
+ }
+
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ synchronized (mLock) {
+ try {
+ mEvents.put(event);
+ } catch (InterruptedException ex) {
+ fail("interrupted while adding a SensorEvent to the queue");
+ }
+ }
+ }
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ }
+ }
+
+ private InputDevice createInputDeviceWithSensor(int id) {
+ InputDevice d = new InputDevice(id, 0 /* generation */, 0 /* controllerNumber */, "name",
+ 0 /* vendorId */, 0 /* productId */, "descriptor", true /* isExternal */,
+ 0 /* sources */, 0 /* keyboardType */, null /* keyCharacterMap */,
+ false /* hasVibrator */, false /* hasMicrophone */, false /* hasButtonUnderpad */,
+ true /* hasSensor */);
+ assertTrue(d.hasSensor());
+ return d;
+ }
+
+ private InputSensorInfo createInputSensorInfo(int id, int type) {
+ InputSensorInfo info = new InputSensorInfo("name", "vendor", 0 /* version */,
+ 0 /* handle */, type, 100.0f /*maxRange */, 0.02f /* resolution */,
+ 0.8f /* power */, 1000 /* minDelay */, 0 /* fifoReservedEventCount */,
+ 0 /* fifoMaxEventCount */, "" /* stringType */, "" /* requiredPermission */,
+ 0 /* maxDelay */, 0 /* flags */, id);
+ return info;
+ }
+
+ private InputDevice getSensorDevice(int[] deviceIds) {
+ for (int i = 0; i < deviceIds.length; i++) {
+ InputDevice device = mInputManager.getInputDevice(deviceIds[i]);
+ if (device.hasSensor()) {
+ return device;
+ }
+ }
+ return null;
+ }
+
+ @Test
+ public void getInputDeviceSensors_withExpectedType() throws Exception {
+ InputDevice device = getSensorDevice(mInputManager.getInputDeviceIds());
+ assertTrue(device != null);
+
+ SensorManager sensorManager = device.getSensorManager();
+ List<Sensor> accelList = sensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
+ verify(mIInputManagerMock).getSensorList(eq(DEVICE_ID));
+ assertEquals(1, accelList.size());
+ assertEquals(DEVICE_ID, accelList.get(0).getId());
+ assertEquals(Sensor.TYPE_ACCELEROMETER, accelList.get(0).getType());
+
+ List<Sensor> gyroList = sensorManager.getSensorList(Sensor.TYPE_GYROSCOPE);
+ verify(mIInputManagerMock).getSensorList(eq(DEVICE_ID));
+ assertEquals(1, gyroList.size());
+ assertEquals(DEVICE_ID, gyroList.get(0).getId());
+ assertEquals(Sensor.TYPE_GYROSCOPE, gyroList.get(0).getType());
+
+ }
+
+ @Test
+ public void getInputDeviceSensors_withUnexpectedType() throws Exception {
+ InputDevice device = getSensorDevice(mInputManager.getInputDeviceIds());
+
+ assertTrue(device != null);
+ SensorManager sensorManager = device.getSensorManager();
+
+ List<Sensor> gameRotationList = sensorManager.getSensorList(
+ Sensor.TYPE_GAME_ROTATION_VECTOR);
+ verify(mIInputManagerMock).getSensorList(eq(DEVICE_ID));
+ assertEquals(0, gameRotationList.size());
+
+ List<Sensor> gravityList = sensorManager.getSensorList(Sensor.TYPE_GRAVITY);
+ verify(mIInputManagerMock).getSensorList(eq(DEVICE_ID));
+ assertEquals(0, gravityList.size());
+ }
+
+ @Test
+ public void testInputDeviceSensorListener() throws Exception {
+ InputDevice device = getSensorDevice(mInputManager.getInputDeviceIds());
+ assertTrue(device != null);
+
+ SensorManager sensorManager = device.getSensorManager();
+ Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
+ assertEquals(Sensor.TYPE_ACCELEROMETER, sensor.getType());
+
+ doAnswer(invocation -> {
+ mIInputSensorEventListener = invocation.getArgument(0);
+ assertNotNull(mIInputSensorEventListener);
+ return true;
+ }).when(mIInputManagerMock).registerSensorListener(any());
+
+ InputTestSensorEventListener listener = new InputTestSensorEventListener();
+ assertTrue(sensorManager.registerListener(listener, sensor,
+ SensorManager.SENSOR_DELAY_NORMAL));
+ verify(mIInputManagerMock).registerSensorListener(any());
+ verify(mIInputManagerMock).enableSensor(eq(DEVICE_ID), eq(sensor.getType()),
+ anyInt(), anyInt());
+
+ float[] values = new float[] {0.12f, 9.8f, 0.2f};
+ mIInputSensorEventListener.onInputSensorChanged(DEVICE_ID, Sensor.TYPE_ACCELEROMETER,
+ SensorManager.SENSOR_STATUS_ACCURACY_HIGH, /* timestamp */ 0x1234abcd, values);
+
+ SensorEvent event = listener.waitForSensorEvent();
+ assertNotNull(event);
+ assertEquals(0x1234abcd, event.timestamp);
+ assertEquals(values.length, event.values.length);
+ for (int i = 0; i < values.length; i++) {
+ assertEquals(values[i], event.values[i], 0.001f);
+ }
+
+ sensorManager.unregisterListener(listener);
+ verify(mIInputManagerMock).disableSensor(eq(DEVICE_ID), eq(sensor.getType()));
+ }
+
+}
diff --git a/core/tests/coretests/src/android/os/FileUtilsTest.java b/core/tests/coretests/src/android/os/FileUtilsTest.java
index 5bce227c..1a86678 100644
--- a/core/tests/coretests/src/android/os/FileUtilsTest.java
+++ b/core/tests/coretests/src/android/os/FileUtilsTest.java
@@ -16,6 +16,7 @@
package android.os;
+import static android.os.FileUtils.convertToModernFd;
import static android.os.FileUtils.roundStorageSize;
import static android.os.FileUtils.translateModeAccessToPosix;
import static android.os.FileUtils.translateModePfdToPosix;
@@ -45,6 +46,8 @@
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -67,6 +70,7 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Arrays;
@@ -562,6 +566,55 @@
assertEquals(O_RDWR, translateModeAccessToPosix(R_OK | W_OK | X_OK));
}
+ @Test
+ public void testConvertToModernFd() throws Exception {
+ final String nonce = String.valueOf(System.nanoTime());
+
+ final File cameraDir = new File("/storage/emulated/0/DCIM/Camera");
+ final File nonCameraDir = new File("/storage/emulated/0/Pictures");
+ cameraDir.mkdirs();
+ nonCameraDir.mkdirs();
+
+ final File validVideoCameraDir = new File(cameraDir, "validVideo-" + nonce + ".mp4");
+ final File validImageCameraDir = new File(cameraDir, "validImage-" + nonce + ".jpg");
+ final File invalidVideoCameraDir = new File(cameraDir, ".invalidVideo-" + nonce + ".mp4");
+
+ final File validVideoNonCameraDir = new File(nonCameraDir, "validVideo-" + nonce + ".mp4");
+ final File validImageNonCameraDir = new File(nonCameraDir, "validImage-" + nonce + ".jpg");
+
+ try {
+ FileDescriptor pfdValidVideoCameraDir =
+ ParcelFileDescriptor.open(validVideoCameraDir,
+ MODE_CREATE | MODE_READ_WRITE).getFileDescriptor();
+ FileDescriptor pfdValidImageCameraDir =
+ ParcelFileDescriptor.open(validImageCameraDir,
+ MODE_CREATE | MODE_READ_WRITE).getFileDescriptor();
+ FileDescriptor pfdInvalidVideoCameraDir =
+ ParcelFileDescriptor.open(invalidVideoCameraDir,
+ MODE_CREATE | MODE_READ_WRITE).getFileDescriptor();
+
+ FileDescriptor pfdValidVideoNonCameraDir =
+ ParcelFileDescriptor.open(validVideoNonCameraDir,
+ MODE_CREATE | MODE_READ_WRITE).getFileDescriptor();
+ FileDescriptor pfdValidImageNonCameraDir =
+ ParcelFileDescriptor.open(validImageNonCameraDir,
+ MODE_CREATE | MODE_READ_WRITE).getFileDescriptor();
+
+ assertNotNull(convertToModernFd(pfdValidVideoCameraDir));
+
+ assertNull(convertToModernFd(pfdValidImageCameraDir));
+ assertNull(convertToModernFd(pfdInvalidVideoCameraDir));
+ assertNull(convertToModernFd(pfdValidVideoNonCameraDir));
+ assertNull(convertToModernFd(pfdValidImageNonCameraDir));
+ } finally {
+ validVideoCameraDir.delete();
+ validImageCameraDir.delete();
+ invalidVideoCameraDir.delete();
+ validVideoNonCameraDir.delete();
+ validImageNonCameraDir.delete();
+ }
+ }
+
private static void assertTranslate(String string, int posix, int pfd) {
assertEquals(posix, translateModeStringToPosix(string));
assertEquals(string, translateModePosixToString(posix));
diff --git a/core/tests/coretests/src/android/os/storage/OWNERS b/core/tests/coretests/src/android/os/storage/OWNERS
new file mode 100644
index 0000000..6f9dbea
--- /dev/null
+++ b/core/tests/coretests/src/android/os/storage/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/os/storage/OWNERS
diff --git a/core/tests/coretests/src/android/service/timezone/ParcelableTestSupport.java b/core/tests/coretests/src/android/service/timezone/ParcelableTestSupport.java
new file mode 100644
index 0000000..777bda9
--- /dev/null
+++ b/core/tests/coretests/src/android/service/timezone/ParcelableTestSupport.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.timezone;
+
+import static org.junit.Assert.assertEquals;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.reflect.Field;
+
+/** Utility methods related to {@link Parcelable} objects used in several tests. */
+final class ParcelableTestSupport {
+
+ private ParcelableTestSupport() {}
+
+ /** Returns the result of parceling and unparceling the argument. */
+ @SuppressWarnings("unchecked")
+ public static <T extends Parcelable> T roundTripParcelable(T parcelable) {
+ Parcel parcel = Parcel.obtain();
+ parcel.writeTypedObject(parcelable, 0);
+ parcel.setDataPosition(0);
+
+ Parcelable.Creator<T> creator;
+ try {
+ Field creatorField = parcelable.getClass().getField("CREATOR");
+ creator = (Parcelable.Creator<T>) creatorField.get(null);
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ throw new AssertionError(e);
+ }
+ T toReturn = parcel.readTypedObject(creator);
+ parcel.recycle();
+ return toReturn;
+ }
+
+ public static <T extends Parcelable> void assertRoundTripParcelable(T instance) {
+ assertEquals(instance, roundTripParcelable(instance));
+ }
+}
diff --git a/core/tests/coretests/src/android/service/timezone/TimeZoneProviderSuggestionTest.java b/core/tests/coretests/src/android/service/timezone/TimeZoneProviderSuggestionTest.java
new file mode 100644
index 0000000..f805555
--- /dev/null
+++ b/core/tests/coretests/src/android/service/timezone/TimeZoneProviderSuggestionTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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.service.timezone;
+
+import static android.service.timezone.ParcelableTestSupport.assertRoundTripParcelable;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import static java.util.Collections.singletonList;
+
+import org.junit.Test;
+
+import java.util.List;
+
+public class TimeZoneProviderSuggestionTest {
+
+ private static final long ARBITRARY_ELAPSED_REALTIME_MILLIS = 9999;
+
+ private static final List<String> ARBITRARY_TIME_ZONE_IDS = singletonList("Europe/London");
+
+ @Test(expected = RuntimeException.class)
+ public void testInvalidTimeZoneIds() {
+ new TimeZoneProviderSuggestion.Builder()
+ .setTimeZoneIds(null);
+ }
+
+ @Test
+ public void testEquals() {
+ TimeZoneProviderSuggestion.Builder builder1 = new TimeZoneProviderSuggestion.Builder()
+ .setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS);
+ {
+ TimeZoneProviderSuggestion one = builder1.build();
+ assertEquals(one, one);
+ }
+
+ TimeZoneProviderSuggestion.Builder builder2 = new TimeZoneProviderSuggestion.Builder()
+ .setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS);
+ {
+ TimeZoneProviderSuggestion one = builder1.build();
+ TimeZoneProviderSuggestion two = builder2.build();
+ assertEquals(one, two);
+ assertEquals(two, one);
+ }
+
+ builder1.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS + 1);
+ {
+ TimeZoneProviderSuggestion one = builder1.build();
+ TimeZoneProviderSuggestion two = builder2.build();
+ assertNotEquals(one, two);
+ assertNotEquals(two, one);
+ }
+
+ builder2.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS + 1);
+ {
+ TimeZoneProviderSuggestion one = builder1.build();
+ TimeZoneProviderSuggestion two = builder2.build();
+ assertEquals(one, two);
+ assertEquals(two, one);
+ }
+
+ builder2.setTimeZoneIds(ARBITRARY_TIME_ZONE_IDS);
+ {
+ TimeZoneProviderSuggestion one = builder1.build();
+ TimeZoneProviderSuggestion two = builder2.build();
+ assertNotEquals(one, two);
+ assertNotEquals(two, one);
+ }
+
+ builder1.setTimeZoneIds(ARBITRARY_TIME_ZONE_IDS);
+ {
+ TimeZoneProviderSuggestion one = builder1.build();
+ TimeZoneProviderSuggestion two = builder2.build();
+ assertEquals(one, two);
+ assertEquals(two, one);
+ }
+ }
+
+ @Test
+ public void testParcelable_noTimeZoneIds() {
+ TimeZoneProviderSuggestion.Builder builder = new TimeZoneProviderSuggestion.Builder()
+ .setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS);
+ assertRoundTripParcelable(builder.build());
+ }
+
+ @Test
+ public void testParcelable_withTimeZoneIds() {
+ TimeZoneProviderSuggestion.Builder builder = new TimeZoneProviderSuggestion.Builder()
+ .setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS)
+ .setTimeZoneIds(ARBITRARY_TIME_ZONE_IDS);
+ assertRoundTripParcelable(builder.build());
+ }
+}
diff --git a/core/tests/coretests/src/android/util/BinaryXmlTest.java b/core/tests/coretests/src/android/util/BinaryXmlTest.java
index 6fa5a23..fd625dc 100644
--- a/core/tests/coretests/src/android/util/BinaryXmlTest.java
+++ b/core/tests/coretests/src/android/util/BinaryXmlTest.java
@@ -66,7 +66,7 @@
final TypedXmlPullParser in = Xml.newBinaryPullParser();
final ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
in.setInput(is, StandardCharsets.UTF_8.name());
- assertNext(in, START_TAG, "tag", 1);
+ assertNext(in, START_TAG, "tag");
assertEquals(count, in.getAttributeCount());
}
@@ -140,7 +140,12 @@
doVerifyWrite(xml);
data = os.toByteArray();
}
- try (InputStream is = new ByteArrayInputStream(data)) {
+ try (InputStream is = new ByteArrayInputStream(data) {
+ @Override
+ public boolean markSupported() {
+ return false;
+ }
+ }) {
doVerifyRead(Xml.resolvePullParser(is));
}
}
@@ -152,7 +157,12 @@
doVerifyWrite(xml);
data = os.toByteArray();
}
- try (InputStream is = new ByteArrayInputStream(data)) {
+ try (InputStream is = new ByteArrayInputStream(data) {
+ @Override
+ public boolean markSupported() {
+ return false;
+ }
+ }) {
doVerifyRead(Xml.resolvePullParser(is));
}
}
diff --git a/core/tests/coretests/src/android/util/XmlTest.java b/core/tests/coretests/src/android/util/XmlTest.java
index a8fc6f9..4e10ea9 100644
--- a/core/tests/coretests/src/android/util/XmlTest.java
+++ b/core/tests/coretests/src/android/util/XmlTest.java
@@ -53,6 +53,14 @@
}
@Test
+ public void testLargeValues_FastIndenting() throws Exception {
+ final TypedXmlSerializer out = Xml.newFastSerializer();
+ out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
+ doLargeValues(out,
+ Xml.newFastPullParser());
+ }
+
+ @Test
public void testLargeValues_Binary() throws Exception {
doLargeValues(Xml.newBinarySerializer(),
Xml.newBinaryPullParser());
@@ -81,7 +89,7 @@
final ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
in.setInput(is, StandardCharsets.UTF_8.name());
- assertNext(in, START_TAG, "tag", 1);
+ assertNext(in, START_TAG, "tag");
assertEquals(2, in.getAttributeCount());
assertEquals(string, in.getAttributeValue(null, "string"));
assertArrayEquals(bytes, in.getAttributeBytesBase64(null, "bytes"));
@@ -100,6 +108,14 @@
}
@Test
+ public void testPersistableBundle_FastIndenting() throws Exception {
+ final TypedXmlSerializer out = Xml.newFastSerializer();
+ out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
+ doPersistableBundle(out,
+ Xml.newFastPullParser());
+ }
+
+ @Test
public void testPersistableBundle_Binary() throws Exception {
doPersistableBundle(Xml.newBinarySerializer(),
Xml.newBinaryPullParser());
@@ -180,6 +196,14 @@
}
@Test
+ public void testVerify_FastIndenting() throws Exception {
+ final TypedXmlSerializer out = Xml.newFastSerializer();
+ out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
+ doVerify(out,
+ Xml.newFastPullParser());
+ }
+
+ @Test
public void testVerify_Binary() throws Exception {
doVerify(Xml.newBinarySerializer(),
Xml.newBinaryPullParser());
@@ -246,9 +270,12 @@
static void doVerifyRead(TypedXmlPullParser in) throws Exception {
assertEquals(START_DOCUMENT, in.getEventType());
- assertNext(in, START_TAG, "one", 1);
+ assertDepth(in, 0);
+ assertNext(in, START_TAG, "one");
+ assertDepth(in, 1);
{
- assertNext(in, START_TAG, "two", 2);
+ assertNext(in, START_TAG, "two");
+ assertDepth(in, 2);
{
assertEquals(14, in.getAttributeCount());
assertEquals(TEST_STRING,
@@ -285,27 +312,36 @@
assertEquals("49", in.getAttributeValue(null, "stringNumber"));
assertEquals(49, in.getAttributeInt(null, "stringNumber"));
}
- assertNext(in, END_TAG, "two", 2);
+ assertNext(in, END_TAG, "two");
+ assertDepth(in, 2);
- assertNext(in, START_TAG, "three", 2);
+ assertNext(in, START_TAG, "three");
+ assertDepth(in, 2);
{
- assertNext(in, TEXT);
+ assertNext(in, TEXT, null);
+ assertDepth(in, 2);
assertEquals("foo", in.getText().trim());
- assertNext(in, START_TAG, "four", 3);
+ assertNext(in, START_TAG, "four");
+ assertDepth(in, 3);
{
assertEquals(0, in.getAttributeCount());
}
- assertNext(in, END_TAG, "four", 3);
- assertNext(in, TEXT);
+ assertNext(in, END_TAG, "four");
+ assertDepth(in, 3);
+ assertNext(in, TEXT, null);
+ assertDepth(in, 2);
assertEquals("barbaz", in.getText().trim());
}
- assertNext(in, END_TAG, "three", 2);
+ assertNext(in, END_TAG, "three");
+ assertDepth(in, 2);
}
- assertNext(in, END_TAG, "one", 1);
- assertNext(in, END_DOCUMENT);
+ assertNext(in, END_TAG, "one");
+ assertDepth(in, 1);
+ assertNext(in, END_DOCUMENT, null);
+ assertDepth(in, 0);
}
- static void assertNext(TypedXmlPullParser in, int token) throws Exception {
+ static void assertNext(TypedXmlPullParser in, int token, String name) throws Exception {
// We're willing to skip over empty text regions, which some
// serializers emit transparently
int event;
@@ -313,12 +349,10 @@
}
assertEquals("next", token, event);
assertEquals("getEventType", token, in.getEventType());
+ assertEquals("getName", name, in.getName());
}
- static void assertNext(TypedXmlPullParser in, int token, String name, int depth)
- throws Exception {
- assertNext(in, token);
- assertEquals("getName", name, in.getName());
+ static void assertDepth(TypedXmlPullParser in, int depth) throws Exception {
assertEquals("getDepth", depth, in.getDepth());
}
}
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java
index ab24f89..7e1e7f4 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java
@@ -33,9 +33,6 @@
import org.junit.runner.RunWith;
import org.mockito.Mock;
-import java.util.Arrays;
-import java.util.List;
-
/**
* Tests for AccessibilityInteractionClient
*/
@@ -65,7 +62,7 @@
final long accessibilityNodeId = 0x4321L;
AccessibilityNodeInfo nodeFromConnection = AccessibilityNodeInfo.obtain();
nodeFromConnection.setSourceNodeId(accessibilityNodeId, windowId);
- mMockConnection.mInfosToReturn = Arrays.asList(nodeFromConnection);
+ mMockConnection.mInfoToReturn = nodeFromConnection;
AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
AccessibilityNodeInfo node = client.findAccessibilityNodeInfoByAccessibilityId(
MOCK_CONNECTION_ID, windowId, accessibilityNodeId, true, 0, null);
@@ -75,7 +72,7 @@
}
private static class MockConnection extends AccessibilityServiceConnectionImpl {
- List<AccessibilityNodeInfo> mInfosToReturn;
+ AccessibilityNodeInfo mInfoToReturn;
@Override
public String[] findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId,
@@ -83,7 +80,7 @@
IAccessibilityInteractionConnectionCallback callback, int flags, long threadId,
Bundle arguments) {
try {
- callback.setFindAccessibilityNodeInfosResult(mInfosToReturn, interactionId);
+ callback.setFindAccessibilityNodeInfoResult(mInfoToReturn, interactionId);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
diff --git a/core/tests/coretests/src/android/widget/TextViewTest.java b/core/tests/coretests/src/android/widget/TextViewTest.java
index 40ecf9a..66fdfff 100644
--- a/core/tests/coretests/src/android/widget/TextViewTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewTest.java
@@ -16,6 +16,9 @@
package android.widget;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
@@ -30,6 +33,7 @@
import android.text.Layout;
import android.text.PrecomputedText;
import android.view.View;
+import android.view.inputmethod.EditorInfo;
import android.widget.TextView.BufferType;
import androidx.test.InstrumentationRegistry;
@@ -254,6 +258,24 @@
assertEquals("", mTextView.getTransformed().toString());
}
+ @Test
+ @UiThreadTest
+ public void testPortraitDoesntSupportFullscreenIme() {
+ mActivity.setRequestedOrientation(SCREEN_ORIENTATION_PORTRAIT);
+ mTextView = new NullSetTextTextView(mActivity);
+ mTextView.requestFocus();
+ assertEquals("IME_FLAG_NO_FULLSCREEN should be set",
+ mTextView.getImeOptions(),
+ mTextView.getImeOptions() & EditorInfo.IME_FLAG_NO_FULLSCREEN);
+
+ mTextView.clearFocus();
+ mActivity.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
+ mTextView = new NullSetTextTextView(mActivity);
+ mTextView.requestFocus();
+ assertEquals("IME_FLAG_NO_FULLSCREEN should not be set",
+ 0, mTextView.getImeOptions() & EditorInfo.IME_FLAG_NO_FULLSCREEN);
+ }
+
private String createLongText() {
int size = 600 * 1000;
final StringBuilder builder = new StringBuilder(size);
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
index 8f5dfc5..97c07ea 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
@@ -30,6 +30,7 @@
import com.android.internal.os.BatteryStatsImpl.DualTimer;
import com.android.internal.os.BatteryStatsImpl.Uid;
+import com.android.internal.power.MeasuredEnergyStats;
import junit.framework.TestCase;
@@ -497,4 +498,116 @@
t = bi.getUidStatsLocked(UID).getSensorTimerLocked(Sensor.GPS, false);
assertFalse(t.isRunningLocked());
}
+
+ @SmallTest
+ public void testUpdateDisplayEnergyLocked() {
+ final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
+ final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
+
+ clocks.realtime = 0;
+ int screen = Display.STATE_OFF;
+ boolean battery = false;
+
+ final int uid1 = 10500;
+ final int uid2 = 10501;
+ long blame1 = 0;
+ long blame2 = 0;
+ long globalDoze = 0;
+
+ // Case A: uid1 off, uid2 off, battery off, screen off
+ bi.updateTimeBasesLocked(battery, screen, clocks.realtime*1000, 0);
+ bi.setOnBatteryInternal(battery);
+ bi.updateDisplayEnergyLocked(500_000, screen, clocks.realtime);
+ checkMeasuredEnergy("A", uid1, blame1, uid2, blame2, globalDoze, bi);
+
+ // Case B: uid1 off, uid2 off, battery ON, screen off
+ clocks.realtime += 17;
+ battery = true;
+ bi.updateTimeBasesLocked(battery, screen, clocks.realtime*1000, 0);
+ bi.setOnBatteryInternal(battery);
+ clocks.realtime += 19;
+ bi.updateDisplayEnergyLocked(510_000, screen, clocks.realtime);
+ checkMeasuredEnergy("B", uid1, blame1, uid2, blame2, globalDoze, bi);
+
+ // Case C: uid1 ON, uid2 off, battery on, screen off
+ clocks.realtime += 18;
+ setFgState(uid1, true, bi);
+ clocks.realtime += 18;
+ bi.updateDisplayEnergyLocked(520_000, screen, clocks.realtime);
+ checkMeasuredEnergy("C", uid1, blame1, uid2, blame2, globalDoze, bi);
+
+ // Case D: uid1 on, uid2 off, battery on, screen ON
+ clocks.realtime += 17;
+ screen = Display.STATE_ON;
+ bi.updateDisplayEnergyLocked(521_000, screen, clocks.realtime);
+ blame1 += 0; // Screen had been off during the measurement period
+ checkMeasuredEnergy("D.1", uid1, blame1, uid2, blame2, globalDoze, bi);
+ clocks.realtime += 101;
+ bi.updateDisplayEnergyLocked(530_000, screen, clocks.realtime);
+ blame1 += 530_000;
+ checkMeasuredEnergy("D.2", uid1, blame1, uid2, blame2, globalDoze, bi);
+
+ // Case E: uid1 on, uid2 ON, battery on, screen on
+ clocks.realtime += 20;
+ setFgState(uid2, true, bi);
+ clocks.realtime += 40;
+ bi.updateDisplayEnergyLocked(540_000, screen, clocks.realtime);
+ // In the past 60ms, sum of fg is 20+40+40=100ms. uid1 is blamed for 60/100; uid2 for 40/100
+ blame1 += 540_000 * (20 + 40) / (20 + 40 + 40);
+ blame2 += 540_000 * ( 0 + 40) / (20 + 40 + 40);
+ checkMeasuredEnergy("E", uid1, blame1, uid2, blame2, globalDoze, bi);
+
+ // Case F: uid1 on, uid2 OFF, battery on, screen on
+ clocks.realtime += 40;
+ setFgState(uid2, false, bi);
+ clocks.realtime += 120;
+ bi.updateDisplayEnergyLocked(550_000, screen, clocks.realtime);
+ // In the past 160ms, sum f fg is 200ms. uid1 is blamed for 40+120 of it; uid2 for 40 of it.
+ blame1 += 550_000 * (40 + 120) / (40 + 40 + 120);
+ blame2 += 550_000 * (40 + 0 ) / (40 + 40 + 120);
+ checkMeasuredEnergy("F", uid1, blame1, uid2, blame2, globalDoze, bi);
+
+ // Case G: uid1 on, uid2 off, battery on, screen DOZE
+ clocks.realtime += 5;
+ screen = Display.STATE_DOZE;
+ bi.updateDisplayEnergyLocked(570_000, screen, clocks.realtime);
+ blame1 += 570_000; // All of this pre-doze time is blamed on uid1.
+ checkMeasuredEnergy("G", uid1, blame1, uid2, blame2, globalDoze, bi);
+
+ // Case H: uid1 on, uid2 off, battery on, screen ON
+ clocks.realtime += 6;
+ screen = Display.STATE_ON;
+ bi.updateDisplayEnergyLocked(580_000, screen, clocks.realtime);
+ blame1 += 0; // The screen had been doze during the energy period
+ globalDoze += 580_000;
+ checkMeasuredEnergy("H", uid1, blame1, uid2, blame2, globalDoze, bi);
+ }
+
+ private void setFgState(int uid, boolean fgOn, MockBatteryStatsImpl bi) {
+ // Note that noteUidProcessStateLocked uses ActivityManager process states.
+ if (fgOn) {
+ bi.noteActivityResumedLocked(uid);
+ bi.noteUidProcessStateLocked(uid, ActivityManager.PROCESS_STATE_TOP);
+ } else {
+ bi.noteActivityPausedLocked(uid);
+ bi.noteUidProcessStateLocked(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
+ }
+ }
+
+ private void checkMeasuredEnergy(String caseName, int uid1, long blame1, int uid2, long blame2,
+ long globalDoze, MockBatteryStatsImpl bi) {
+ final int bucket = MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_ON;
+
+ assertEquals("Wrong uid1 blame for Case " + caseName, blame1,
+ bi.getUidStatsLocked(uid1).getMeasuredEnergyMicroJoules(bucket));
+
+ assertEquals("Wrong uid2 blame for Case " + caseName, blame2,
+ bi.getUidStatsLocked(uid2).getMeasuredEnergyMicroJoules(bucket));
+
+ assertEquals("Wrong total blame for Case " + caseName, blame1 + blame2,
+ bi.getScreenOnEnergy());
+
+ assertEquals("Wrong doze for Case " + caseName, globalDoze,
+ bi.getScreenDozeEnergy());
+ }
}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
index bef27e2..bd41542 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
@@ -38,7 +38,9 @@
BatteryStatsTimeBaseTest.class,
BatteryStatsTimerTest.class,
BatteryStatsUidTest.class,
+ BatteryUsageStatsTest.class,
BatteryStatsUserLifecycleTests.class,
+ BluetoothPowerCalculatorTest.class,
BstatsCpuTimesValidationTest.class,
KernelCpuProcStringReaderTest.class,
KernelCpuUidActiveTimeReaderTest.class,
@@ -52,7 +54,9 @@
LongSamplingCounterTest.class,
LongSamplingCounterArrayTest.class,
PowerCalculatorTest.class,
- PowerProfileTest.class
+ PowerProfileTest.class,
+
+ com.android.internal.power.MeasuredEnergyStatsTest.class
})
public class BatteryStatsTests {
}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java
new file mode 100644
index 0000000..96e9c4a
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsTest.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.fail;
+
+import android.os.BatteryConsumer;
+import android.os.BatteryUsageStats;
+import android.os.Parcel;
+import android.os.SystemBatteryConsumer;
+import android.os.UidBatteryConsumer;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class BatteryUsageStatsTest {
+
+ @Test
+ public void testBuilder() {
+ BatteryUsageStats batteryUsageStats = buildBatteryUsageStats();
+ validateBatteryUsageStats(batteryUsageStats);
+ }
+
+ @Test
+ public void testParcelability() {
+ final BatteryUsageStats outBatteryUsageStats = buildBatteryUsageStats();
+ final Parcel outParcel = Parcel.obtain();
+ outParcel.writeParcelable(outBatteryUsageStats, 0);
+ final byte[] bytes = outParcel.marshall();
+ outParcel.recycle();
+
+ final Parcel inParcel = Parcel.obtain();
+ inParcel.unmarshall(bytes, 0, bytes.length);
+ inParcel.setDataPosition(0);
+ final BatteryUsageStats inBatteryUsageStats =
+ inParcel.readParcelable(getClass().getClassLoader());
+ assertThat(inBatteryUsageStats).isNotNull();
+ validateBatteryUsageStats(inBatteryUsageStats);
+ }
+
+ private BatteryUsageStats buildBatteryUsageStats() {
+ final MockClocks clocks = new MockClocks();
+ final MockBatteryStatsImpl batteryStats = new MockBatteryStatsImpl(clocks);
+ final BatteryStatsImpl.Uid batteryStatsUid = batteryStats.getUidStatsLocked(2000);
+
+ final BatteryUsageStats.Builder builder = new BatteryUsageStats.Builder(1, 1, true);
+ builder.setConsumedPower(100);
+ builder.setDischargePercentage(20);
+
+ final UidBatteryConsumer.Builder uidBatteryConsumerBuilder =
+ builder.getOrCreateUidBatteryConsumerBuilder(batteryStatsUid);
+ uidBatteryConsumerBuilder.setPackageWithHighestDrain("foo");
+ uidBatteryConsumerBuilder.setConsumedPower(200);
+ uidBatteryConsumerBuilder.setConsumedPower(BatteryConsumer.POWER_COMPONENT_USAGE, 300);
+ uidBatteryConsumerBuilder.setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU, 400);
+ uidBatteryConsumerBuilder.setConsumedPowerForCustomComponent(
+ BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, 500);
+ uidBatteryConsumerBuilder.setConsumedPowerForCustomComponent(
+ BatteryConsumer.FIRST_MODELED_POWER_COMPONENT_ID
+ + BatteryConsumer.POWER_COMPONENT_CPU, 510);
+ uidBatteryConsumerBuilder.setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_CPU, 600);
+ uidBatteryConsumerBuilder.setUsageDurationMillis(
+ BatteryConsumer.TIME_COMPONENT_CPU_FOREGROUND, 700);
+ uidBatteryConsumerBuilder.setUsageDurationForCustomComponentMillis(
+ BatteryConsumer.FIRST_CUSTOM_TIME_COMPONENT_ID, 800);
+
+ final SystemBatteryConsumer.Builder systemBatteryConsumerBuilder =
+ builder.getOrCreateSystemBatteryConsumerBuilder(
+ SystemBatteryConsumer.DRAIN_TYPE_CAMERA);
+ systemBatteryConsumerBuilder.setConsumedPower(10000);
+ systemBatteryConsumerBuilder.setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU, 10100);
+ systemBatteryConsumerBuilder.setConsumedPowerForCustomComponent(
+ BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID, 10200);
+ systemBatteryConsumerBuilder.setConsumedPowerForCustomComponent(
+ BatteryConsumer.FIRST_MODELED_POWER_COMPONENT_ID
+ + BatteryConsumer.POWER_COMPONENT_CPU, 10210);
+ systemBatteryConsumerBuilder.setUsageDurationMillis(
+ BatteryConsumer.TIME_COMPONENT_CPU, 10300);
+ systemBatteryConsumerBuilder.setUsageDurationForCustomComponentMillis(
+ BatteryConsumer.FIRST_CUSTOM_TIME_COMPONENT_ID, 10400);
+
+ return builder.build();
+ }
+
+ public void validateBatteryUsageStats(BatteryUsageStats batteryUsageStats) {
+ assertThat(batteryUsageStats.getConsumedPower()).isEqualTo(100);
+ assertThat(batteryUsageStats.getDischargePercentage()).isEqualTo(20);
+
+ final List<UidBatteryConsumer> uidBatteryConsumers =
+ batteryUsageStats.getUidBatteryConsumers();
+ for (UidBatteryConsumer uidBatteryConsumer : uidBatteryConsumers) {
+ if (uidBatteryConsumer.getUid() == 2000) {
+ assertThat(uidBatteryConsumer.getPackageWithHighestDrain()).isEqualTo("foo");
+ assertThat(uidBatteryConsumer.getConsumedPower()).isEqualTo(200);
+ assertThat(uidBatteryConsumer.getConsumedPower(
+ BatteryConsumer.POWER_COMPONENT_USAGE)).isEqualTo(300);
+ assertThat(uidBatteryConsumer.getConsumedPower(
+ BatteryConsumer.POWER_COMPONENT_CPU)).isEqualTo(400);
+ assertThat(uidBatteryConsumer.getConsumedPowerForCustomComponent(
+ BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo(500);
+ assertThat(uidBatteryConsumer.getConsumedPowerForCustomComponent(
+ BatteryConsumer.FIRST_MODELED_POWER_COMPONENT_ID
+ + BatteryConsumer.POWER_COMPONENT_CPU)).isEqualTo(510);
+ assertThat(uidBatteryConsumer.getUsageDurationMillis(
+ BatteryConsumer.TIME_COMPONENT_CPU)).isEqualTo(600);
+ assertThat(uidBatteryConsumer.getUsageDurationMillis(
+ BatteryConsumer.TIME_COMPONENT_CPU_FOREGROUND)).isEqualTo(700);
+ assertThat(uidBatteryConsumer.getUsageDurationForCustomComponentMillis(
+ BatteryConsumer.FIRST_CUSTOM_TIME_COMPONENT_ID)).isEqualTo(800);
+ } else {
+ fail("Unexpected UID " + uidBatteryConsumer.getUid());
+ }
+ }
+
+ final List<SystemBatteryConsumer> systemBatteryConsumers =
+ batteryUsageStats.getSystemBatteryConsumers();
+ for (SystemBatteryConsumer systemBatteryConsumer : systemBatteryConsumers) {
+ if (systemBatteryConsumer.getDrainType() == SystemBatteryConsumer.DRAIN_TYPE_CAMERA) {
+ assertThat(systemBatteryConsumer.getConsumedPower()).isEqualTo(10000);
+ assertThat(systemBatteryConsumer.getConsumedPower(
+ BatteryConsumer.POWER_COMPONENT_CPU)).isEqualTo(10100);
+ assertThat(systemBatteryConsumer.getConsumedPowerForCustomComponent(
+ BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID)).isEqualTo(10200);
+ assertThat(systemBatteryConsumer.getConsumedPowerForCustomComponent(
+ BatteryConsumer.FIRST_MODELED_POWER_COMPONENT_ID
+ + BatteryConsumer.POWER_COMPONENT_CPU)).isEqualTo(10210);
+ assertThat(systemBatteryConsumer.getUsageDurationMillis(
+ BatteryConsumer.TIME_COMPONENT_CPU)).isEqualTo(10300);
+ assertThat(systemBatteryConsumer.getUsageDurationForCustomComponentMillis(
+ BatteryConsumer.FIRST_CUSTOM_TIME_COMPONENT_ID)).isEqualTo(10400);
+ } else {
+ fail("Unexpected drain type " + systemBatteryConsumer.getDrainType());
+ }
+ }
+ }
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java
new file mode 100644
index 0000000..96eb8da
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/BluetoothPowerCalculatorTest.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import android.annotation.Nullable;
+import android.os.BatteryConsumer;
+import android.os.BatteryUsageStats;
+import android.os.BatteryUsageStatsQuery;
+import android.os.Process;
+import android.os.SystemBatteryConsumer;
+import android.os.UidBatteryConsumer;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+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 BluetoothPowerCalculatorTest {
+ private static final double PRECISION = 0.00001;
+ private static final int APP_UID = Process.FIRST_APPLICATION_UID + 42;
+
+ @Mock
+ private PowerProfile mMockPowerProfile;
+ private MockBatteryStatsImpl mMockBatteryStats;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mMockBatteryStats = new MockBatteryStatsImpl(new MockClocks()) {
+ @Override
+ public boolean hasBluetoothActivityReporting() {
+ return true;
+ }
+ };
+ mMockBatteryStats.getOnBatteryTimeBase().setRunning(true, 100_000, 100_000);
+ when(mMockPowerProfile.getAveragePower(
+ PowerProfile.POWER_BLUETOOTH_CONTROLLER_IDLE)).thenReturn(10.0);
+ when(mMockPowerProfile.getAveragePower(
+ PowerProfile.POWER_BLUETOOTH_CONTROLLER_RX)).thenReturn(50.0);
+ when(mMockPowerProfile.getAveragePower(
+ PowerProfile.POWER_BLUETOOTH_CONTROLLER_TX)).thenReturn(100.0);
+ }
+
+ @Test
+ public void testTimerBasedModel() {
+ setDurationsAndPower(
+ mMockBatteryStats.getUidStatsLocked(Process.BLUETOOTH_UID)
+ .getOrCreateBluetoothControllerActivityLocked(),
+ 1000, 2000, 3000, 0);
+
+ setDurationsAndPower(mMockBatteryStats.getUidStatsLocked(APP_UID)
+ .getOrCreateBluetoothControllerActivityLocked(),
+ 4000, 5000, 6000, 0);
+
+ setDurationsAndPower((BatteryStatsImpl.ControllerActivityCounterImpl)
+ mMockBatteryStats.getBluetoothControllerActivity(),
+ 6000, 8000, 10000, 0);
+
+ BatteryUsageStats batteryUsageStats = buildBatteryUsageStats();
+
+ assertBluetoothPowerAndDuration(
+ getUidBatteryConsumer(batteryUsageStats, Process.BLUETOOTH_UID),
+ 0.11388, 6000);
+ assertBluetoothPowerAndDuration(
+ getUidBatteryConsumer(batteryUsageStats, APP_UID),
+ 0.24722, 15000);
+ assertBluetoothPowerAndDuration(
+ getBluetoothSystemBatteryConsumer(batteryUsageStats,
+ SystemBatteryConsumer.DRAIN_TYPE_BLUETOOTH),
+ 0.15833, 9000);
+ }
+
+ @Test
+ public void testReportedPowerBasedModel() {
+ setDurationsAndPower(
+ mMockBatteryStats.getUidStatsLocked(Process.BLUETOOTH_UID)
+ .getOrCreateBluetoothControllerActivityLocked(),
+ 1000, 2000, 3000, 360000);
+
+ setDurationsAndPower(mMockBatteryStats.getUidStatsLocked(APP_UID)
+ .getOrCreateBluetoothControllerActivityLocked(),
+ 4000, 5000, 6000, 720000);
+
+ setDurationsAndPower((BatteryStatsImpl.ControllerActivityCounterImpl)
+ mMockBatteryStats.getBluetoothControllerActivity(),
+ 6000, 8000, 10000, 1260000);
+
+ BatteryUsageStats batteryUsageStats = buildBatteryUsageStats();
+
+ assertBluetoothPowerAndDuration(
+ getUidBatteryConsumer(batteryUsageStats, Process.BLUETOOTH_UID),
+ 0.1, 6000);
+ assertBluetoothPowerAndDuration(
+ getUidBatteryConsumer(batteryUsageStats, APP_UID),
+ 0.2, 15000);
+ assertBluetoothPowerAndDuration(
+ getBluetoothSystemBatteryConsumer(batteryUsageStats,
+ SystemBatteryConsumer.DRAIN_TYPE_BLUETOOTH),
+ 0.15, 9000);
+ }
+
+ private void setDurationsAndPower(
+ BatteryStatsImpl.ControllerActivityCounterImpl controllerActivity, int idleDurationMs,
+ int rxDurationMs, int txDurationMs, long powerMaMs) {
+ controllerActivity.getIdleTimeCounter().addCountLocked(idleDurationMs);
+ controllerActivity.getRxTimeCounter().addCountLocked(rxDurationMs);
+ controllerActivity.getTxTimeCounters()[0].addCountLocked(txDurationMs);
+ controllerActivity.getPowerCounter().addCountLocked(powerMaMs);
+ }
+
+ private BatteryUsageStats buildBatteryUsageStats() {
+ BatteryUsageStats.Builder builder = new BatteryUsageStats.Builder(0, 0, false);
+ builder.getOrCreateUidBatteryConsumerBuilder(
+ mMockBatteryStats.getUidStatsLocked(Process.BLUETOOTH_UID));
+ builder.getOrCreateUidBatteryConsumerBuilder(
+ mMockBatteryStats.getUidStatsLocked(APP_UID));
+
+ BluetoothPowerCalculator bpc = new BluetoothPowerCalculator(mMockPowerProfile);
+ bpc.calculate(builder, mMockBatteryStats, 200_000, 200_000, BatteryUsageStatsQuery.DEFAULT,
+ null);
+ return builder.build();
+ }
+
+ private UidBatteryConsumer getUidBatteryConsumer(BatteryUsageStats batteryUsageStats, int uid) {
+ for (UidBatteryConsumer ubc : batteryUsageStats.getUidBatteryConsumers()) {
+ if (ubc.getUid() == uid) {
+ return ubc;
+ }
+ }
+ return null;
+ }
+
+ private SystemBatteryConsumer getBluetoothSystemBatteryConsumer(
+ BatteryUsageStats batteryUsageStats, int drainType) {
+ for (SystemBatteryConsumer sbc : batteryUsageStats.getSystemBatteryConsumers()) {
+ if (sbc.getDrainType() == drainType) {
+ return sbc;
+ }
+ }
+ return null;
+ }
+
+ private void assertBluetoothPowerAndDuration(@Nullable BatteryConsumer batteryConsumer,
+ double powerMah, int durationMs) {
+ assertThat(batteryConsumer).isNotNull();
+
+ double consumedPower = batteryConsumer.getConsumedPower(
+ BatteryConsumer.POWER_COMPONENT_BLUETOOTH);
+ assertThat(consumedPower).isWithin(PRECISION).of(powerMah);
+
+ long usageDurationMillis = batteryConsumer.getUsageDurationMillis(
+ BatteryConsumer.TIME_COMPONENT_BLUETOOTH);
+
+ assertThat(usageDurationMillis).isEqualTo(durationMs);
+ }
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelSingleProcessCpuThreadReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelSingleProcessCpuThreadReaderTest.java
index 2de800b..b5720a2 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelSingleProcessCpuThreadReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelSingleProcessCpuThreadReaderTest.java
@@ -19,87 +19,122 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import android.content.Context;
+import android.os.FileUtils;
+
+import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import org.junit.After;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.io.File;
import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class KernelSingleProcessCpuThreadReaderTest {
+ private File mProcDirectory;
+
+ @Before
+ public void setUp() {
+ Context context = InstrumentationRegistry.getContext();
+ mProcDirectory = context.getDir("proc", Context.MODE_PRIVATE);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ FileUtils.deleteContents(mProcDirectory);
+ }
+
@Test
public void getProcessCpuUsage() throws IOException {
- // Units are nanoseconds
- MockCpuTimeInStateReader mockReader = new MockCpuTimeInStateReader(4, new String[] {
- "0:1000000000 2000000000 3000000000:4000000000",
- "1:100000000 200000000 300000000:400000000",
- });
+ setupDirectory(42,
+ new int[] {42, 1, 2, 3},
+ new int[] {1000, 2000},
+ // Units are 10ms aka 10000Us
+ new int[][] {{100, 200}, {0, 200}, {100, 300}, {0, 600}},
+ new int[] {4500, 500});
KernelSingleProcessCpuThreadReader reader = new KernelSingleProcessCpuThreadReader(42,
- mockReader);
- reader.setSelectedThreadIds(new int[] {2, 3});
- reader.startTrackingThreadCpuTimes();
+ mProcDirectory.toPath());
KernelSingleProcessCpuThreadReader.ProcessCpuUsage processCpuUsage =
- reader.getProcessCpuUsage();
- assertThat(mockReader.mTrackedTgid).isEqualTo(42);
- // The strings are formatted as <TID TGID AGG_KEY>, where AGG_KEY is 1 for binder
- // threads and 0 for all other threads.
- assertThat(mockReader.mTrackedTasks).containsExactly(
- "2 1",
- "3 1");
- assertThat(processCpuUsage.threadCpuTimesMillis).isEqualTo(
- new long[] {1100, 2200, 3300, 4400});
- assertThat(processCpuUsage.selectedThreadCpuTimesMillis).isEqualTo(
- new long[] {100, 200, 300, 400});
+ reader.getProcessCpuUsage(new int[] {2, 3});
+ assertThat(processCpuUsage.threadCpuTimesMillis).isEqualTo(new long[] {2000, 13000});
+ assertThat(processCpuUsage.selectedThreadCpuTimesMillis).isEqualTo(new long[] {1000, 9000});
+ assertThat(processCpuUsage.processCpuTimesMillis).isEqualTo(new long[] {6666, 43333});
}
@Test
public void getCpuFrequencyCount() throws IOException {
- MockCpuTimeInStateReader mockReader = new MockCpuTimeInStateReader(3, new String[0]);
+ setupDirectory(13,
+ new int[] {13},
+ new int[] {1000, 2000, 3000},
+ new int[][] {{100, 200, 300}},
+ new int[] {14, 15});
KernelSingleProcessCpuThreadReader reader = new KernelSingleProcessCpuThreadReader(13,
- mockReader);
+ mProcDirectory.toPath());
int cpuFrequencyCount = reader.getCpuFrequencyCount();
assertThat(cpuFrequencyCount).isEqualTo(3);
}
- public static class MockCpuTimeInStateReader implements
- KernelSingleProcessCpuThreadReader.CpuTimeInStateReader {
- private final int mCpuFrequencyCount;
- private final String[] mAggregatedTaskCpuFreqTimes;
- public int mTrackedTgid;
- public List<String> mTrackedTasks = new ArrayList<>();
+ private void setupDirectory(int pid, int[] threadIds, int[] cpuFrequencies,
+ int[][] threadCpuTimes, int[] processCpuTimes)
+ throws IOException {
- public MockCpuTimeInStateReader(int cpuFrequencyCount,
- String[] aggregatedTaskCpuFreqTimes) {
- mCpuFrequencyCount = cpuFrequencyCount;
- mAggregatedTaskCpuFreqTimes = aggregatedTaskCpuFreqTimes;
+ assertTrue(mProcDirectory.toPath().resolve("self").toFile().mkdirs());
+
+ try (OutputStream timeInStateStream =
+ Files.newOutputStream(
+ mProcDirectory.toPath().resolve("self").resolve("time_in_state"))) {
+ for (int i = 0; i < cpuFrequencies.length; i++) {
+ final String line = cpuFrequencies[i] + " 0\n";
+ timeInStateStream.write(line.getBytes());
+ }
}
- @Override
- public int getCpuFrequencyCount() {
- return mCpuFrequencyCount;
+ Path processPath = mProcDirectory.toPath().resolve(String.valueOf(pid));
+
+ // Make /proc/$PID
+ assertTrue(processPath.toFile().mkdirs());
+
+ // Write /proc/$PID/stat. Only the fields 14-17 matter.
+ try (OutputStream timeInStateStream = Files.newOutputStream(processPath.resolve("stat"))) {
+ timeInStateStream.write(
+ (pid + " (test) S 4 5 6 7 8 9 10 11 12 13 "
+ + processCpuTimes[0] + " "
+ + processCpuTimes[1] + " "
+ + "16 17 18 19 20 ...").getBytes());
}
- @Override
- public boolean startTrackingProcessCpuTimes(int tgid) {
- mTrackedTgid = tgid;
- return true;
- }
+ // Make /proc/$PID/task
+ final Path selfThreadsPath = processPath.resolve("task");
+ assertTrue(selfThreadsPath.toFile().mkdirs());
- public boolean startAggregatingTaskCpuTimes(int pid, int aggregationKey) {
- mTrackedTasks.add(pid + " " + aggregationKey);
- return true;
- }
+ // Make thread directories
+ for (int i = 0; i < threadIds.length; i++) {
+ // Make /proc/$PID/task/$TID
+ final Path threadPath = selfThreadsPath.resolve(String.valueOf(threadIds[i]));
+ assertTrue(threadPath.toFile().mkdirs());
- public String[] getAggregatedTaskCpuFreqTimes(int pid) {
- return mAggregatedTaskCpuFreqTimes;
+ // Make /proc/$PID/task/$TID/time_in_state
+ try (OutputStream timeInStateStream =
+ Files.newOutputStream(threadPath.resolve("time_in_state"))) {
+ for (int j = 0; j < cpuFrequencies.length; j++) {
+ final String line = cpuFrequencies[j] + " " + threadCpuTimes[i][j] + "\n";
+ timeInStateStream.write(line.getBytes());
+ }
+ }
}
}
}
diff --git a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
index ff1d965c..c775137 100644
--- a/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
+++ b/core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java
@@ -16,17 +16,19 @@
package com.android.internal.os;
+import android.location.GnssSignalQuality;
import android.os.Handler;
import android.os.Looper;
import android.util.SparseIntArray;
-import com.android.internal.location.gnssmetrics.GnssMetrics;
import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidActiveTimeReader;
import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidClusterTimeReader;
import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader;
import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader;
+import com.android.internal.power.MeasuredEnergyStats;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Queue;
import java.util.concurrent.Future;
@@ -45,13 +47,18 @@
mScreenDozeTimer = new BatteryStatsImpl.StopwatchTimer(clocks, null, -1, null,
mOnBatteryTimeBase);
mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
+ mBluetoothActivity = new ControllerActivityCounterImpl(mOnBatteryTimeBase, 1);
setExternalStatsSyncLocked(new DummyExternalStatsSync());
- for (int i = 0; i < GnssMetrics.NUM_GPS_SIGNAL_QUALITY_LEVELS; i++) {
+ for (int i = 0; i < GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS; i++) {
mGpsSignalQualityTimer[i] = new StopwatchTimer(clocks, null, -1000 - i, null,
mOnBatteryTimeBase);
}
+ final boolean[] supportedBuckets = new boolean[MeasuredEnergyStats.NUMBER_ENERGY_BUCKETS];
+ Arrays.fill(supportedBuckets, true);
+ mGlobalMeasuredEnergyStats = new MeasuredEnergyStats(supportedBuckets);
+
// A no-op handler.
mHandler = new Handler(Looper.getMainLooper()) {
};
diff --git a/core/tests/coretests/src/com/android/internal/os/MockClocks.java b/core/tests/coretests/src/com/android/internal/os/MockClocks.java
index f750c37..d0fa756 100644
--- a/core/tests/coretests/src/com/android/internal/os/MockClocks.java
+++ b/core/tests/coretests/src/com/android/internal/os/MockClocks.java
@@ -17,7 +17,9 @@
package com.android.internal.os;
public class MockClocks implements BatteryStatsImpl.Clocks {
+ /** ElapsedRealtime in ms */
public long realtime;
+ /** Uptime in ms */
public long uptime;
@Override
diff --git a/core/tests/coretests/src/com/android/internal/os/SystemServerCpuThreadReaderTest.java b/core/tests/coretests/src/com/android/internal/os/SystemServerCpuThreadReaderTest.java
index d116d4d..121c637 100644
--- a/core/tests/coretests/src/com/android/internal/os/SystemServerCpuThreadReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/SystemServerCpuThreadReaderTest.java
@@ -16,86 +16,146 @@
package com.android.internal.os;
-import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertTrue;
+import android.content.Context;
+import android.os.FileUtils;
+
+import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import org.junit.After;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.io.File;
import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class SystemServerCpuThreadReaderTest {
+ private File mProcDirectory;
+
+ @Before
+ public void setUp() {
+ Context context = InstrumentationRegistry.getContext();
+ mProcDirectory = context.getDir("proc", Context.MODE_PRIVATE);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ FileUtils.deleteContents(mProcDirectory);
+ }
@Test
- public void testReadDelta() throws IOException {
+ public void testReaderDelta_firstTime() throws IOException {
int pid = 42;
+ setupDirectory(
+ pid,
+ new int[] {42, 1, 2, 3},
+ new int[] {1000, 2000},
+ // Units are 10ms aka 10000Us
+ new int[][] {{100, 200}, {0, 200}, {0, 300}, {0, 400}},
+ new int[] {1400, 1500});
- MockCpuTimeInStateReader mockReader = new MockCpuTimeInStateReader(4);
- // Units are nanoseconds
- mockReader.setAggregatedTaskCpuFreqTimes(new String[] {
- "0:1000000000 2000000000 3000000000:4000000000",
- "1:100000000 200000000 300000000:400000000",
- });
+ SystemServerCpuThreadReader reader = new SystemServerCpuThreadReader(
+ mProcDirectory.toPath(), pid);
+ reader.setBinderThreadNativeTids(new int[] {1, 3});
+ SystemServerCpuThreadReader.SystemServiceCpuThreadTimes systemServiceCpuThreadTimes =
+ reader.readDelta();
+ assertArrayEquals(new long[] {100 * 10000, 1100 * 10000},
+ systemServiceCpuThreadTimes.threadCpuTimesUs);
+ assertArrayEquals(new long[] {0, 600 * 10000},
+ systemServiceCpuThreadTimes.binderThreadCpuTimesUs);
+ }
- SystemServerCpuThreadReader reader = new SystemServerCpuThreadReader(pid, mockReader);
+ @Test
+ public void testReaderDelta_nextTime() throws IOException {
+ int pid = 42;
+ setupDirectory(
+ pid,
+ new int[] {42, 1, 2, 3},
+ new int[] {1000, 2000},
+ new int[][] {{100, 200}, {0, 200}, {0, 300}, {0, 400}},
+ new int[] {1400, 1500});
+
+ SystemServerCpuThreadReader reader = new SystemServerCpuThreadReader(
+ mProcDirectory.toPath(), pid);
reader.setBinderThreadNativeTids(new int[] {1, 3});
- // The first invocation of readDelta populates the "last" snapshot
+ // First time, populate "last" snapshot
+ reader.readDelta();
+
+ FileUtils.deleteContents(mProcDirectory);
+ setupDirectory(
+ pid,
+ new int[] {42, 1, 2, 3},
+ new int[] {1000, 2000},
+ new int[][] {{500, 600}, {700, 800}, {900, 1000}, {1100, 1200}},
+ new int[] {2400, 2500});
+
+ // Second time, get the actual delta
SystemServerCpuThreadReader.SystemServiceCpuThreadTimes systemServiceCpuThreadTimes =
reader.readDelta();
- assertThat(systemServiceCpuThreadTimes.threadCpuTimesUs)
- .isEqualTo(new long[] {1100000, 2200000, 3300000, 4400000});
- assertThat(systemServiceCpuThreadTimes.binderThreadCpuTimesUs)
- .isEqualTo(new long[] {100000, 200000, 300000, 400000});
-
- mockReader.setAggregatedTaskCpuFreqTimes(new String[] {
- "0:1010000000 2020000000 3030000000:4040000000",
- "1:101000000 202000000 303000000:404000000",
- });
-
- // The second invocation gets the actual delta
- systemServiceCpuThreadTimes = reader.readDelta();
-
- assertThat(systemServiceCpuThreadTimes.threadCpuTimesUs)
- .isEqualTo(new long[] {11000, 22000, 33000, 44000});
- assertThat(systemServiceCpuThreadTimes.binderThreadCpuTimesUs)
- .isEqualTo(new long[] {1000, 2000, 3000, 4000});
+ assertArrayEquals(new long[] {3100 * 10000, 2500 * 10000},
+ systemServiceCpuThreadTimes.threadCpuTimesUs);
+ assertArrayEquals(new long[] {1800 * 10000, 1400 * 10000},
+ systemServiceCpuThreadTimes.binderThreadCpuTimesUs);
}
- public static class MockCpuTimeInStateReader implements
- KernelSingleProcessCpuThreadReader.CpuTimeInStateReader {
- private final int mCpuFrequencyCount;
- private String[] mAggregatedTaskCpuFreqTimes;
+ private void setupDirectory(int pid, int[] threadIds, int[] cpuFrequencies, int[][] cpuTimes,
+ int[] processCpuTimes)
+ throws IOException {
- MockCpuTimeInStateReader(int frequencyCount) {
- mCpuFrequencyCount = frequencyCount;
+ assertTrue(mProcDirectory.toPath().resolve("self").toFile().mkdirs());
+
+ try (OutputStream timeInStateStream =
+ Files.newOutputStream(
+ mProcDirectory.toPath().resolve("self").resolve("time_in_state"))) {
+ for (int i = 0; i < cpuFrequencies.length; i++) {
+ final String line = cpuFrequencies[i] + " 0\n";
+ timeInStateStream.write(line.getBytes());
+ }
}
- @Override
- public int getCpuFrequencyCount() {
- return mCpuFrequencyCount;
+ Path processPath = mProcDirectory.toPath().resolve(String.valueOf(pid));
+ // Make /proc/$PID
+ assertTrue(processPath.toFile().mkdirs());
+
+ // Write /proc/$PID/stat. Only the fields 14-17 matter.
+ try (OutputStream timeInStateStream = Files.newOutputStream(processPath.resolve("stat"))) {
+ timeInStateStream.write(
+ (pid + " (test) S 4 5 6 7 8 9 10 11 12 13 "
+ + processCpuTimes[0] + " "
+ + processCpuTimes[1] + " "
+ + "16 17 18 19 20 ...").getBytes());
}
- @Override
- public boolean startTrackingProcessCpuTimes(int tgid) {
- return true;
- }
+ // Make /proc/$PID/task
+ final Path selfThreadsPath = processPath.resolve("task");
+ assertTrue(selfThreadsPath.toFile().mkdirs());
- public boolean startAggregatingTaskCpuTimes(int pid, int aggregationKey) {
- return true;
- }
+ // Make thread directories
+ for (int i = 0; i < threadIds.length; i++) {
+ // Make /proc/$PID/task/$TID
+ final Path threadPath = selfThreadsPath.resolve(String.valueOf(threadIds[i]));
+ assertTrue(threadPath.toFile().mkdirs());
- public void setAggregatedTaskCpuFreqTimes(String[] mAggregatedTaskCpuFreqTimes) {
- this.mAggregatedTaskCpuFreqTimes = mAggregatedTaskCpuFreqTimes;
- }
-
- public String[] getAggregatedTaskCpuFreqTimes(int pid) {
- return mAggregatedTaskCpuFreqTimes;
+ // Make /proc/$PID/task/$TID/time_in_state
+ try (OutputStream timeInStateStream =
+ Files.newOutputStream(threadPath.resolve("time_in_state"))) {
+ for (int j = 0; j < cpuFrequencies.length; j++) {
+ final String line = cpuFrequencies[j] + " " + cpuTimes[i][j] + "\n";
+ timeInStateStream.write(line.getBytes());
+ }
+ }
}
}
}
diff --git a/core/tests/coretests/src/com/android/internal/os/SystemServicePowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/SystemServicePowerCalculatorTest.java
index c8e8585..dbb36fb 100644
--- a/core/tests/coretests/src/com/android/internal/os/SystemServicePowerCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/SystemServicePowerCalculatorTest.java
@@ -66,6 +66,7 @@
public void testCalculateApp() {
// Test Power Profile has two CPU clusters with 3 and 4 speeds, thus 7 freq times total
mMockSystemServerCpuThreadReader.setCpuTimes(
+ new long[] {10000, 15000, 20000, 25000, 30000, 35000, 40000},
new long[] {30000, 40000, 50000, 60000, 70000, 80000, 90000},
new long[] {20000, 30000, 40000, 50000, 60000, 70000, 80000});
@@ -145,7 +146,9 @@
super(null);
}
- public void setCpuTimes(long[] threadCpuTimesUs, long[] binderThreadCpuTimesUs) {
+ public void setCpuTimes(long[] processCpuTimesUs, long[] threadCpuTimesUs,
+ long[] binderThreadCpuTimesUs) {
+ mThreadTimes.processCpuTimesUs = processCpuTimesUs;
mThreadTimes.threadCpuTimesUs = threadCpuTimesUs;
mThreadTimes.binderThreadCpuTimesUs = binderThreadCpuTimesUs;
}
diff --git a/core/tests/coretests/src/com/android/internal/power/MeasuredEnergyStatsTest.java b/core/tests/coretests/src/com/android/internal/power/MeasuredEnergyStatsTest.java
index 88295ef..2ede751 100644
--- a/core/tests/coretests/src/com/android/internal/power/MeasuredEnergyStatsTest.java
+++ b/core/tests/coretests/src/com/android/internal/power/MeasuredEnergyStatsTest.java
@@ -16,18 +16,22 @@
package com.android.internal.power;
-import static com.android.internal.power.MeasuredEnergyArray.NUMBER_SUBSYSTEMS;
-import static com.android.internal.power.MeasuredEnergyArray.SUBSYSTEM_DISPLAY;
+import static android.os.BatteryStats.ENERGY_DATA_UNAVAILABLE;
+
import static com.android.internal.power.MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_DOZE;
import static com.android.internal.power.MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_ON;
+import static com.android.internal.power.MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_OTHER;
import static com.android.internal.power.MeasuredEnergyStats.NUMBER_ENERGY_BUCKETS;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import android.os.Parcel;
import android.view.Display;
-import org.junit.Before;
+import androidx.test.filters.SmallTest;
+
import org.junit.Test;
/**
@@ -36,243 +40,225 @@
* To run the tests, use
* atest FrameworksCoreTests:com.android.internal.power.MeasuredEnergyStatsTest
*/
+@SmallTest
public class MeasuredEnergyStatsTest {
- private MeasuredEnergyStats mStats;
- private int[] mAllSubsystems = new int[NUMBER_SUBSYSTEMS];
- private long[] mCurrentSubsystemEnergyUJ = new long[NUMBER_SUBSYSTEMS];
- MeasuredEnergyArray mMeasuredEnergyArray = new MeasuredEnergyArray() {
- @Override
- public int getSubsystem(int index) {
- return mAllSubsystems[index];
+ @Test
+ public void testConstruction() {
+ final boolean[] supportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS];
+ supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
+ supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false;
+ supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true;
+
+ final MeasuredEnergyStats stats = new MeasuredEnergyStats(supportedEnergyBuckets);
+
+ for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) {
+ if (supportedEnergyBuckets[i]) {
+ assertTrue(stats.isEnergyBucketSupported(i));
+ assertEquals(0L, stats.getAccumulatedBucketEnergy(i));
+ } else {
+ assertFalse(stats.isEnergyBucketSupported(i));
+ assertEquals(ENERGY_DATA_UNAVAILABLE, stats.getAccumulatedBucketEnergy(i));
+ }
}
+ }
- @Override
- public long getEnergy(int index) {
- return mCurrentSubsystemEnergyUJ[index];
+ @Test
+ public void testCreateFromTemplate() {
+ final boolean[] supportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS];
+ supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
+ supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false;
+ supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true;
+
+ final MeasuredEnergyStats stats = new MeasuredEnergyStats(supportedEnergyBuckets);
+ stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
+ stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
+ stats.updateBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
+
+ final MeasuredEnergyStats newStats = MeasuredEnergyStats.createFromTemplate(stats);
+
+ for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) {
+ if (supportedEnergyBuckets[i]) {
+ assertTrue(newStats.isEnergyBucketSupported(i));
+ assertEquals(0, newStats.getAccumulatedBucketEnergy(i));
+ } else {
+ assertFalse(newStats.isEnergyBucketSupported(i));
+ assertEquals(ENERGY_DATA_UNAVAILABLE, newStats.getAccumulatedBucketEnergy(i));
+ }
}
-
- @Override
- public int size() {
- return NUMBER_SUBSYSTEMS;
- }
- };
-
- @Before
- public void setUp() {
- // Populate all supported subsystems indexes and arbitrary starting energy values.
- mAllSubsystems[SUBSYSTEM_DISPLAY] = SUBSYSTEM_DISPLAY;
- mCurrentSubsystemEnergyUJ[SUBSYSTEM_DISPLAY] = 111;
-
- mStats = new MeasuredEnergyStats(mMeasuredEnergyArray, Display.STATE_UNKNOWN);
}
@Test
public void testReadWriteParcel() {
- // update with some arbitrary data
- mCurrentSubsystemEnergyUJ[SUBSYSTEM_DISPLAY] += 222;
- mStats.update(mMeasuredEnergyArray, Display.STATE_ON, true);
- mCurrentSubsystemEnergyUJ[SUBSYSTEM_DISPLAY] += 321;
- mStats.update(mMeasuredEnergyArray, Display.STATE_DOZE, true);
- mCurrentSubsystemEnergyUJ[SUBSYSTEM_DISPLAY] += 456;
- mStats.update(mMeasuredEnergyArray, Display.STATE_OFF, true);
+ final boolean[] supportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS];
+ supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
+ supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false;
+ supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true;
+
+ final MeasuredEnergyStats stats = new MeasuredEnergyStats(supportedEnergyBuckets);
+ stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
+ stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
+ stats.updateBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
final Parcel parcel = Parcel.obtain();
- mStats.writeToParcel(parcel);
+ stats.writeToParcel(parcel);
parcel.setDataPosition(0);
- MeasuredEnergyStats stats = new MeasuredEnergyStats(parcel);
+ MeasuredEnergyStats newStats = new MeasuredEnergyStats(parcel);
for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) {
- assertEquals(mStats.getAccumulatedBucketEnergy(i), stats.getAccumulatedBucketEnergy(i));
+ assertEquals(stats.getAccumulatedBucketEnergy(i),
+ newStats.getAccumulatedBucketEnergy(i));
}
parcel.recycle();
}
@Test
public void testReadWriteSummaryParcel() {
- // update with some arbitrary data
- mCurrentSubsystemEnergyUJ[SUBSYSTEM_DISPLAY] += 222;
- mStats.update(mMeasuredEnergyArray, Display.STATE_ON, true);
- mCurrentSubsystemEnergyUJ[SUBSYSTEM_DISPLAY] += 321;
- mStats.update(mMeasuredEnergyArray, Display.STATE_DOZE, true);
- mCurrentSubsystemEnergyUJ[SUBSYSTEM_DISPLAY] += 456;
- mStats.update(mMeasuredEnergyArray, Display.STATE_OFF, true);
+ final boolean[] supportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS];
+ supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
+ supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false;
+ supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true;
+
+ final MeasuredEnergyStats stats = new MeasuredEnergyStats(supportedEnergyBuckets);
+ stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
+ stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
+ stats.updateBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
final Parcel parcel = Parcel.obtain();
- MeasuredEnergyStats.writeSummaryToParcel(mStats, parcel);
+ MeasuredEnergyStats.writeSummaryToParcel(stats, parcel);
+
+ final boolean[] newSupportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS];
+ newSupportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
+ newSupportedEnergyBuckets[ENERGY_BUCKET_SCREEN_DOZE] = true; // switched from false to true
+ newSupportedEnergyBuckets[ENERGY_BUCKET_SCREEN_OTHER] = false; // switched true to false
+ MeasuredEnergyStats newStats = new MeasuredEnergyStats(newSupportedEnergyBuckets);
parcel.setDataPosition(0);
- MeasuredEnergyStats stats = new MeasuredEnergyStats(mMeasuredEnergyArray,
- Display.STATE_UNKNOWN);
- MeasuredEnergyStats.readSummaryFromParcel(stats, parcel);
+ MeasuredEnergyStats.readSummaryFromParcel(newStats, parcel);
for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) {
- assertEquals(mStats.getAccumulatedBucketEnergy(i), stats.getAccumulatedBucketEnergy(i));
+ if (!newSupportedEnergyBuckets[i]) {
+ assertFalse(newStats.isEnergyBucketSupported(i));
+ assertEquals(ENERGY_DATA_UNAVAILABLE, newStats.getAccumulatedBucketEnergy(i));
+ } else if (!supportedEnergyBuckets[i]) {
+ assertTrue(newStats.isEnergyBucketSupported(i));
+ assertEquals(0L, newStats.getAccumulatedBucketEnergy(i));
+ } else {
+ assertTrue(newStats.isEnergyBucketSupported(i));
+ assertEquals(stats.getAccumulatedBucketEnergy(i),
+ newStats.getAccumulatedBucketEnergy(i));
+ }
}
parcel.recycle();
}
@Test
- public void testDisplayStateEnergyAttribution() {
- long expectedScreenOnEnergy = 0;
- long expectedScreenDozeEnergy = 0;
+ public void testCreateAndReadSummaryFromParcel() {
+ final boolean[] supportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS];
+ supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
+ supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false;
+ supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true;
- // Display energy should be attributed to the previous screen state.
- mStats.update(mMeasuredEnergyArray, Display.STATE_UNKNOWN, true);
+ final MeasuredEnergyStats template = new MeasuredEnergyStats(supportedEnergyBuckets);
+ template.updateBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
+ template.updateBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
+ template.updateBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
- incrementDisplayState(222, Display.STATE_ON, true, expectedScreenOnEnergy,
- expectedScreenDozeEnergy);
+ final MeasuredEnergyStats stats = MeasuredEnergyStats.createFromTemplate(template);
+ stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 200, true);
+ stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 7, true);
+ stats.updateBucket(ENERGY_BUCKET_SCREEN_OTHER, 63, true);
- expectedScreenOnEnergy += 321;
- incrementDisplayState(321, Display.STATE_DOZE, true, expectedScreenOnEnergy,
- expectedScreenDozeEnergy);
+ final Parcel parcel = Parcel.obtain();
+ MeasuredEnergyStats.writeSummaryToParcel(stats, parcel);
- expectedScreenDozeEnergy += 456;
- incrementDisplayState(456, Display.STATE_OFF, true, expectedScreenOnEnergy,
- expectedScreenDozeEnergy);
+ final boolean[] newSupportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS];
+ newSupportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
+ newSupportedEnergyBuckets[ENERGY_BUCKET_SCREEN_DOZE] = true; // switched from false to true
+ newSupportedEnergyBuckets[ENERGY_BUCKET_SCREEN_OTHER] = false; // switched true to false
+ final MeasuredEnergyStats newTemplate = new MeasuredEnergyStats(newSupportedEnergyBuckets);
+ parcel.setDataPosition(0);
- incrementDisplayState(1111, Display.STATE_DOZE_SUSPEND, true, expectedScreenOnEnergy,
- expectedScreenDozeEnergy);
+ final MeasuredEnergyStats newStats =
+ MeasuredEnergyStats.createAndReadSummaryFromParcel(parcel, newTemplate);
- expectedScreenDozeEnergy += 2345;
- incrementDisplayState(2345, Display.STATE_ON_SUSPEND, true, expectedScreenOnEnergy,
- expectedScreenDozeEnergy);
-
- expectedScreenOnEnergy += 767;
- incrementDisplayState(767, Display.STATE_VR, true, expectedScreenOnEnergy,
- expectedScreenDozeEnergy);
-
- expectedScreenOnEnergy += 999;
- incrementDisplayState(999, Display.STATE_UNKNOWN, true, expectedScreenOnEnergy,
- expectedScreenDozeEnergy);
+ for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) {
+ if (!newSupportedEnergyBuckets[i]) {
+ assertFalse(newStats.isEnergyBucketSupported(i));
+ assertEquals(ENERGY_DATA_UNAVAILABLE, newStats.getAccumulatedBucketEnergy(i));
+ } else if (!supportedEnergyBuckets[i]) {
+ assertTrue(newStats.isEnergyBucketSupported(i));
+ assertEquals(0L, newStats.getAccumulatedBucketEnergy(i));
+ } else {
+ assertTrue(newStats.isEnergyBucketSupported(i));
+ assertEquals(stats.getAccumulatedBucketEnergy(i),
+ newStats.getAccumulatedBucketEnergy(i));
+ }
+ }
+ parcel.recycle();
}
@Test
- public void testDisplayStateEnergyAttribution_notRunning() {
- long expectedScreenOnEnergy = 0;
- long expectedScreenDozeEnergy = 0;
+ public void testUpdateBucket() {
+ final boolean[] supportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS];
+ supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
+ supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false;
+ supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true;
- // Display energy should be attributed to the previous screen state.
- mStats.update(mMeasuredEnergyArray, Display.STATE_UNKNOWN, true);
+ final MeasuredEnergyStats stats = new MeasuredEnergyStats(supportedEnergyBuckets);
+ stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
+ stats.updateBucket(ENERGY_BUCKET_SCREEN_DOZE, 30, true);
+ stats.updateBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
+ stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
- incrementDisplayState(222, Display.STATE_ON, true, expectedScreenOnEnergy,
- expectedScreenDozeEnergy);
-
- expectedScreenOnEnergy += 321;
- incrementDisplayState(321, Display.STATE_DOZE, true, expectedScreenOnEnergy,
- expectedScreenDozeEnergy);
-
- // Updates after this point should not result in energy accumulation.
- incrementDisplayState(456, Display.STATE_OFF, false, expectedScreenOnEnergy,
- expectedScreenDozeEnergy);
-
- incrementDisplayState(1111, Display.STATE_DOZE_SUSPEND, false, expectedScreenOnEnergy,
- expectedScreenDozeEnergy);
-
- incrementDisplayState(2345, Display.STATE_ON_SUSPEND, false, expectedScreenOnEnergy,
- expectedScreenDozeEnergy);
-
- incrementDisplayState(767, Display.STATE_VR, false, expectedScreenOnEnergy,
- expectedScreenDozeEnergy);
-
- // Resume energy accumulation.
- expectedScreenOnEnergy += 999;
- incrementDisplayState(999, Display.STATE_UNKNOWN, true, expectedScreenOnEnergy,
- expectedScreenDozeEnergy);
+ assertEquals(15, stats.getAccumulatedBucketEnergy(ENERGY_BUCKET_SCREEN_ON));
+ assertEquals(ENERGY_DATA_UNAVAILABLE,
+ stats.getAccumulatedBucketEnergy(ENERGY_BUCKET_SCREEN_DOZE));
+ assertEquals(40, stats.getAccumulatedBucketEnergy(ENERGY_BUCKET_SCREEN_OTHER));
}
@Test
public void testReset() {
- // update with some arbitrary data.
- mCurrentSubsystemEnergyUJ[SUBSYSTEM_DISPLAY] += 222;
- mStats.update(mMeasuredEnergyArray, Display.STATE_ON, true);
- mCurrentSubsystemEnergyUJ[SUBSYSTEM_DISPLAY] += 321;
- mStats.update(mMeasuredEnergyArray, Display.STATE_DOZE, true);
- mCurrentSubsystemEnergyUJ[SUBSYSTEM_DISPLAY] += 456;
- mStats.update(mMeasuredEnergyArray, Display.STATE_OFF, true);
+ final boolean[] supportedEnergyBuckets = new boolean[NUMBER_ENERGY_BUCKETS];
+ supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_ON] = true;
+ supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_DOZE] = false;
+ supportedEnergyBuckets[ENERGY_BUCKET_SCREEN_OTHER] = true;
- mStats.reset();
+ final MeasuredEnergyStats stats = new MeasuredEnergyStats(supportedEnergyBuckets);
+ stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 10, true);
+ stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 5, true);
+ stats.updateBucket(ENERGY_BUCKET_SCREEN_OTHER, 40, true);
+
+ MeasuredEnergyStats.resetIfNotNull(stats);
// All energy should be reset to 0
for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) {
- assertEquals(mStats.getAccumulatedBucketEnergy(i), 0);
+ if (supportedEnergyBuckets[i]) {
+ assertTrue(stats.isEnergyBucketSupported(i));
+ assertEquals(0, stats.getAccumulatedBucketEnergy(i));
+ } else {
+ assertFalse(stats.isEnergyBucketSupported(i));
+ assertEquals(ENERGY_DATA_UNAVAILABLE, stats.getAccumulatedBucketEnergy(i));
+ }
}
- // Increment all subsystem energy by some arbitrary amount and update
- for (int i = 0; i < NUMBER_SUBSYSTEMS; i++) {
- mCurrentSubsystemEnergyUJ[i] += 100 * i;
- }
- mStats.update(mMeasuredEnergyArray, Display.STATE_OFF, true);
-
- // All energy should still be 0 after the first post-reset update.
- for (int i = 0; i < NUMBER_ENERGY_BUCKETS; i++) {
- assertEquals(mStats.getAccumulatedBucketEnergy(i), 0);
- }
-
- // Energy accumulation should continue like normal.
- long expectedScreenOnEnergy = 0;
- long expectedScreenDozeEnergy = 0;
- incrementDisplayState(222, Display.STATE_ON, true, expectedScreenOnEnergy,
- expectedScreenDozeEnergy);
-
- expectedScreenOnEnergy += 321;
- incrementDisplayState(321, Display.STATE_DOZE, true, expectedScreenOnEnergy,
- expectedScreenDozeEnergy);
-
- expectedScreenDozeEnergy += 456;
- incrementDisplayState(456, Display.STATE_OFF, true, expectedScreenOnEnergy,
- expectedScreenDozeEnergy);
+ // Values should increase as usual.
+ stats.updateBucket(ENERGY_BUCKET_SCREEN_ON, 70, true);
+ assertEquals(70L, stats.getAccumulatedBucketEnergy(ENERGY_BUCKET_SCREEN_ON));
}
+ /** Test that states are mapped to the expected energy buckets. Beware of mapping changes. */
@Test
- public void testHasSubsystem() {
- for (int i = 0; i < NUMBER_SUBSYSTEMS; i++) {
- assertEquals(mStats.hasSubsystem(i), true);
- }
- }
+ public void testEnergyBucketMapping() {
+ int exp;
- @Test
- public void testHasSubsystem_unavailable() {
- // Setup MeasuredEnergyStats with not available subsystems.
- int[] subsystems = new int[0];
- long[] energies = new long[0];
- MeasuredEnergyArray measuredEnergyArray = new MeasuredEnergyArray() {
- @Override
- public int getSubsystem(int index) {
- return subsystems[index];
- }
+ exp = ENERGY_BUCKET_SCREEN_ON;
+ assertEquals(exp, MeasuredEnergyStats.getDisplayEnergyBucket(Display.STATE_ON));
+ assertEquals(exp, MeasuredEnergyStats.getDisplayEnergyBucket(Display.STATE_VR));
+ assertEquals(exp, MeasuredEnergyStats.getDisplayEnergyBucket(Display.STATE_ON_SUSPEND));
- @Override
- public long getEnergy(int index) {
- return energies[index];
- }
-
- @Override
- public int size() {
- return 0;
- }
- };
- MeasuredEnergyStats stats = new MeasuredEnergyStats(measuredEnergyArray,
- Display.STATE_UNKNOWN);
-
- for (int i = 0; i < NUMBER_SUBSYSTEMS; i++) {
- assertEquals(stats.hasSubsystem(i), false);
- }
-
- stats.reset();
- // a reset should not change the state of an unavailable subsystem.
- for (int i = 0; i < NUMBER_SUBSYSTEMS; i++) {
- assertEquals(stats.hasSubsystem(i), false);
- }
- }
-
- private void incrementDisplayState(long deltaEnergy, int nextState, boolean accumulate,
- long expectScreenEnergy, long expectedDozeEnergy) {
- mCurrentSubsystemEnergyUJ[SUBSYSTEM_DISPLAY] += deltaEnergy;
- mStats.update(mMeasuredEnergyArray, nextState, accumulate);
- assertEquals(expectScreenEnergy,
- mStats.getAccumulatedBucketEnergy(ENERGY_BUCKET_SCREEN_ON));
- assertEquals(expectedDozeEnergy,
- mStats.getAccumulatedBucketEnergy(ENERGY_BUCKET_SCREEN_DOZE));
+ exp = ENERGY_BUCKET_SCREEN_DOZE;
+ assertEquals(exp, MeasuredEnergyStats.getDisplayEnergyBucket(Display.STATE_DOZE));
+ assertEquals(exp, MeasuredEnergyStats.getDisplayEnergyBucket(Display.STATE_DOZE_SUSPEND));
}
}
diff --git a/core/tests/coretests/src/com/android/internal/power/OWNERS b/core/tests/coretests/src/com/android/internal/power/OWNERS
index d68066b..4068e2b 100644
--- a/core/tests/coretests/src/com/android/internal/power/OWNERS
+++ b/core/tests/coretests/src/com/android/internal/power/OWNERS
@@ -1 +1 @@
-include /services/core/java/com/android/server/power/OWNERS
+include /BATTERY_STATS_OWNERS
diff --git a/core/tests/coretests/src/com/android/internal/util/ArrayUtilsTest.java b/core/tests/coretests/src/com/android/internal/util/ArrayUtilsTest.java
index d026735..e8793a9 100644
--- a/core/tests/coretests/src/com/android/internal/util/ArrayUtilsTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/ArrayUtilsTest.java
@@ -118,4 +118,89 @@
assertEquals(3, ArrayUtils.unstableRemoveIf(collection, isNull));
assertEquals(0, collection.size());
}
+
+ @SmallTest
+ public void testThrowsIfOutOfBounds_passesWhenRangeInsideArray() {
+ ArrayUtils.throwsIfOutOfBounds(10, 2, 6);
+ }
+
+ @SmallTest
+ public void testThrowsIfOutOfBounds_passesWhenRangeIsWholeArray() {
+ ArrayUtils.throwsIfOutOfBounds(10, 0, 10);
+ }
+
+ @SmallTest
+ public void testThrowsIfOutOfBounds_passesWhenEmptyRangeAtStart() {
+ ArrayUtils.throwsIfOutOfBounds(10, 0, 0);
+ }
+
+ @SmallTest
+ public void testThrowsIfOutOfBounds_passesWhenEmptyRangeAtEnd() {
+ ArrayUtils.throwsIfOutOfBounds(10, 10, 0);
+ }
+
+ @SmallTest
+ public void testThrowsIfOutOfBounds_passesWhenEmptyArray() {
+ ArrayUtils.throwsIfOutOfBounds(0, 0, 0);
+ }
+
+ @SmallTest
+ public void testThrowsIfOutOfBounds_failsWhenRangeStartNegative() {
+ try {
+ ArrayUtils.throwsIfOutOfBounds(10, -1, 5);
+ fail();
+ } catch (ArrayIndexOutOfBoundsException expected) {
+ // expected
+ }
+ }
+
+ @SmallTest
+ public void testThrowsIfOutOfBounds_failsWhenCountNegative() {
+ try {
+ ArrayUtils.throwsIfOutOfBounds(10, 5, -1);
+ fail();
+ } catch (ArrayIndexOutOfBoundsException expected) {
+ // expected
+ }
+ }
+
+ @SmallTest
+ public void testThrowsIfOutOfBounds_failsWhenRangeStartTooHigh() {
+ try {
+ ArrayUtils.throwsIfOutOfBounds(10, 11, 0);
+ fail();
+ } catch (ArrayIndexOutOfBoundsException expected) {
+ // expected
+ }
+ }
+
+ @SmallTest
+ public void testThrowsIfOutOfBounds_failsWhenRangeEndTooHigh() {
+ try {
+ ArrayUtils.throwsIfOutOfBounds(10, 5, 6);
+ fail();
+ } catch (ArrayIndexOutOfBoundsException expected) {
+ // expected
+ }
+ }
+
+ @SmallTest
+ public void testThrowsIfOutOfBounds_failsWhenLengthNegative() {
+ try {
+ ArrayUtils.throwsIfOutOfBounds(-1, 0, 0);
+ fail();
+ } catch (ArrayIndexOutOfBoundsException expected) {
+ // expected
+ }
+ }
+
+ @SmallTest
+ public void testThrowsIfOutOfBounds_failsWhenOverflowRangeEndTooHigh() {
+ try {
+ ArrayUtils.throwsIfOutOfBounds(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
+ fail();
+ } catch (ArrayIndexOutOfBoundsException expected) {
+ // expected
+ }
+ }
}
diff --git a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
index 306388f..9531181d 100644
--- a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
+++ b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
@@ -195,6 +195,11 @@
}
@Override
+ public boolean shouldHandleTvPowerKey() {
+ return false;
+ }
+
+ @Override
public void queryDisplayStatus(final IHdmiControlCallback callback) {
}
diff --git a/core/tests/uwbtests/src/android/uwb/RangingManagerTest.java b/core/tests/uwbtests/src/android/uwb/RangingManagerTest.java
new file mode 100644
index 0000000..6df1c3e
--- /dev/null
+++ b/core/tests/uwbtests/src/android/uwb/RangingManagerTest.java
@@ -0,0 +1,260 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.uwb;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.os.PersistableBundle;
+import android.os.RemoteException;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Test of {@link AdapterStateListener}.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class RangingManagerTest {
+
+ private static final IUwbAdapter ADAPTER = mock(IUwbAdapter.class);
+ private static final Executor EXECUTOR = UwbTestUtils.getExecutor();
+ private static final PersistableBundle PARAMS = new PersistableBundle();
+ private static final @CloseReason int CLOSE_REASON = CloseReason.UNKNOWN;
+
+ @Test
+ public void testOpenSession_StartRangingInvoked() throws RemoteException {
+ RangingManager rangingManager = new RangingManager(ADAPTER);
+ RangingSession.Callback callback = mock(RangingSession.Callback.class);
+ rangingManager.openSession(PARAMS, EXECUTOR, callback);
+ verify(ADAPTER, times(1)).startRanging(eq(rangingManager), eq(PARAMS));
+ }
+
+ @Test
+ public void testOpenSession_ErrorIfSameSessionHandleReturned() throws RemoteException {
+ RangingManager rangingManager = new RangingManager(ADAPTER);
+ RangingSession.Callback callback = mock(RangingSession.Callback.class);
+ SessionHandle handle = new SessionHandle(1);
+ when(ADAPTER.startRanging(any(), any())).thenReturn(handle);
+
+ rangingManager.openSession(PARAMS, EXECUTOR, callback);
+
+ // Calling openSession will cause the same session handle to be returned. The onClosed
+ // callback should be invoked
+ RangingSession.Callback callback2 = mock(RangingSession.Callback.class);
+ rangingManager.openSession(PARAMS, EXECUTOR, callback2);
+ verify(callback, times(0)).onClosed(anyInt(), any());
+ verify(callback2, times(1)).onClosed(anyInt(), any());
+ }
+
+ @Test
+ public void testOnRangingStarted_ValidSessionHandle() throws RemoteException {
+ RangingManager rangingManager = new RangingManager(ADAPTER);
+ RangingSession.Callback callback = mock(RangingSession.Callback.class);
+ SessionHandle handle = new SessionHandle(1);
+ when(ADAPTER.startRanging(any(), any())).thenReturn(handle);
+
+ rangingManager.openSession(PARAMS, EXECUTOR, callback);
+ rangingManager.onRangingStarted(handle, PARAMS);
+ verify(callback, times(1)).onOpenSuccess(any(), any());
+ }
+
+ @Test
+ public void testOnRangingStarted_InvalidSessionHandle() throws RemoteException {
+ RangingManager rangingManager = new RangingManager(ADAPTER);
+ RangingSession.Callback callback = mock(RangingSession.Callback.class);
+
+ rangingManager.onRangingStarted(new SessionHandle(2), PARAMS);
+ verify(callback, times(0)).onOpenSuccess(any(), any());
+ }
+
+ @Test
+ public void testOnRangingStarted_MultipleSessionsRegistered() throws RemoteException {
+ SessionHandle sessionHandle1 = new SessionHandle(1);
+ SessionHandle sessionHandle2 = new SessionHandle(2);
+ RangingSession.Callback callback1 = mock(RangingSession.Callback.class);
+ RangingSession.Callback callback2 = mock(RangingSession.Callback.class);
+
+ when(ADAPTER.startRanging(any(), any()))
+ .thenReturn(sessionHandle1)
+ .thenReturn(sessionHandle2);
+
+ RangingManager rangingManager = new RangingManager(ADAPTER);
+ rangingManager.openSession(PARAMS, EXECUTOR, callback1);
+ rangingManager.openSession(PARAMS, EXECUTOR, callback2);
+
+ rangingManager.onRangingStarted(sessionHandle1, PARAMS);
+ verify(callback1, times(1)).onOpenSuccess(any(), any());
+ verify(callback2, times(0)).onOpenSuccess(any(), any());
+
+ rangingManager.onRangingStarted(sessionHandle2, PARAMS);
+ verify(callback1, times(1)).onOpenSuccess(any(), any());
+ verify(callback2, times(1)).onOpenSuccess(any(), any());
+ }
+
+ @Test
+ public void testOnRangingClosed_OnRangingClosedCalled() throws RemoteException {
+ RangingManager rangingManager = new RangingManager(ADAPTER);
+ RangingSession.Callback callback = mock(RangingSession.Callback.class);
+ SessionHandle handle = new SessionHandle(1);
+ when(ADAPTER.startRanging(any(), any())).thenReturn(handle);
+ rangingManager.openSession(PARAMS, EXECUTOR, callback);
+
+ rangingManager.onRangingClosed(handle, CLOSE_REASON, PARAMS);
+ verify(callback, times(1)).onClosed(anyInt(), any());
+ }
+
+ @Test
+ public void testOnRangingClosed_MultipleSessionsRegistered() throws RemoteException {
+ // Verify that if multiple sessions are registered, only the session that is
+ // requested to close receives the associated callbacks
+ SessionHandle sessionHandle1 = new SessionHandle(1);
+ SessionHandle sessionHandle2 = new SessionHandle(2);
+ RangingSession.Callback callback1 = mock(RangingSession.Callback.class);
+ RangingSession.Callback callback2 = mock(RangingSession.Callback.class);
+
+ when(ADAPTER.startRanging(any(), any()))
+ .thenReturn(sessionHandle1)
+ .thenReturn(sessionHandle2);
+
+ RangingManager rangingManager = new RangingManager(ADAPTER);
+ rangingManager.openSession(PARAMS, EXECUTOR, callback1);
+ rangingManager.openSession(PARAMS, EXECUTOR, callback2);
+
+ rangingManager.onRangingClosed(sessionHandle1, CLOSE_REASON, PARAMS);
+ verify(callback1, times(1)).onClosed(anyInt(), any());
+ verify(callback2, times(0)).onClosed(anyInt(), any());
+
+ rangingManager.onRangingClosed(sessionHandle2, CLOSE_REASON, PARAMS);
+ verify(callback1, times(1)).onClosed(anyInt(), any());
+ verify(callback2, times(1)).onClosed(anyInt(), any());
+ }
+
+ @Test
+ public void testOnRangingReport_OnReportReceived() throws RemoteException {
+ RangingManager rangingManager = new RangingManager(ADAPTER);
+ RangingSession.Callback callback = mock(RangingSession.Callback.class);
+ SessionHandle handle = new SessionHandle(1);
+ when(ADAPTER.startRanging(any(), any())).thenReturn(handle);
+ rangingManager.openSession(PARAMS, EXECUTOR, callback);
+ rangingManager.onRangingStarted(handle, PARAMS);
+
+ RangingReport report = UwbTestUtils.getRangingReports(1);
+ rangingManager.onRangingResult(handle, report);
+ verify(callback, times(1)).onReportReceived(eq(report));
+ }
+
+ @Test
+ public void testOnRangingReport_MultipleSessionsRegistered() throws RemoteException {
+ SessionHandle sessionHandle1 = new SessionHandle(1);
+ SessionHandle sessionHandle2 = new SessionHandle(2);
+ RangingSession.Callback callback1 = mock(RangingSession.Callback.class);
+ RangingSession.Callback callback2 = mock(RangingSession.Callback.class);
+
+ when(ADAPTER.startRanging(any(), any()))
+ .thenReturn(sessionHandle1)
+ .thenReturn(sessionHandle2);
+
+ RangingManager rangingManager = new RangingManager(ADAPTER);
+ rangingManager.openSession(PARAMS, EXECUTOR, callback1);
+ rangingManager.onRangingStarted(sessionHandle1, PARAMS);
+ rangingManager.openSession(PARAMS, EXECUTOR, callback2);
+ rangingManager.onRangingStarted(sessionHandle2, PARAMS);
+
+ rangingManager.onRangingResult(sessionHandle1, UwbTestUtils.getRangingReports(1));
+ verify(callback1, times(1)).onReportReceived(any());
+ verify(callback2, times(0)).onReportReceived(any());
+
+ rangingManager.onRangingResult(sessionHandle2, UwbTestUtils.getRangingReports(1));
+ verify(callback1, times(1)).onReportReceived(any());
+ verify(callback2, times(1)).onReportReceived(any());
+ }
+
+ @Test
+ public void testOnClose_Reasons() throws RemoteException {
+ runOnClose_Reason(CloseReason.LOCAL_API,
+ RangingSession.Callback.CLOSE_REASON_LOCAL_CLOSE_API);
+
+ runOnClose_Reason(CloseReason.MAX_SESSIONS_REACHED,
+ RangingSession.Callback.CLOSE_REASON_LOCAL_MAX_SESSIONS_REACHED);
+
+ runOnClose_Reason(CloseReason.PROTOCOL_SPECIFIC,
+ RangingSession.Callback.CLOSE_REASON_PROTOCOL_SPECIFIC);
+
+ runOnClose_Reason(CloseReason.REMOTE_REQUEST,
+ RangingSession.Callback.CLOSE_REASON_REMOTE_REQUEST);
+
+ runOnClose_Reason(CloseReason.SYSTEM_POLICY,
+ RangingSession.Callback.CLOSE_REASON_LOCAL_SYSTEM_POLICY);
+
+ runOnClose_Reason(CloseReason.UNKNOWN,
+ RangingSession.Callback.CLOSE_REASON_UNKNOWN);
+ }
+
+ private void runOnClose_Reason(@CloseReason int reasonIn,
+ @RangingSession.Callback.CloseReason int reasonOut) throws RemoteException {
+ RangingManager rangingManager = new RangingManager(ADAPTER);
+ RangingSession.Callback callback = mock(RangingSession.Callback.class);
+ SessionHandle handle = new SessionHandle(1);
+ when(ADAPTER.startRanging(any(), any())).thenReturn(handle);
+ rangingManager.openSession(PARAMS, EXECUTOR, callback);
+
+ rangingManager.onRangingClosed(handle, reasonIn, PARAMS);
+ verify(callback, times(1)).onClosed(eq(reasonOut), eq(PARAMS));
+ }
+
+ @Test
+ public void testStartFailureReasons() throws RemoteException {
+ runOnRangingStartFailed_Reason(StartFailureReason.BAD_PARAMETERS,
+ RangingSession.Callback.CLOSE_REASON_LOCAL_BAD_PARAMETERS);
+
+ runOnRangingStartFailed_Reason(StartFailureReason.MAX_SESSIONS_REACHED,
+ RangingSession.Callback.CLOSE_REASON_LOCAL_MAX_SESSIONS_REACHED);
+
+ runOnRangingStartFailed_Reason(StartFailureReason.PROTOCOL_SPECIFIC,
+ RangingSession.Callback.CLOSE_REASON_PROTOCOL_SPECIFIC);
+
+ runOnRangingStartFailed_Reason(StartFailureReason.SYSTEM_POLICY,
+ RangingSession.Callback.CLOSE_REASON_LOCAL_SYSTEM_POLICY);
+
+ runOnRangingStartFailed_Reason(StartFailureReason.UNKNOWN,
+ RangingSession.Callback.CLOSE_REASON_UNKNOWN);
+ }
+
+ private void runOnRangingStartFailed_Reason(@StartFailureReason int reasonIn,
+ @RangingSession.Callback.CloseReason int reasonOut) throws RemoteException {
+ RangingManager rangingManager = new RangingManager(ADAPTER);
+ RangingSession.Callback callback = mock(RangingSession.Callback.class);
+ SessionHandle handle = new SessionHandle(1);
+ when(ADAPTER.startRanging(any(), any())).thenReturn(handle);
+ rangingManager.openSession(PARAMS, EXECUTOR, callback);
+
+ rangingManager.onRangingStartFailed(handle, reasonIn, PARAMS);
+ verify(callback, times(1)).onClosed(eq(reasonOut), eq(PARAMS));
+ }
+}
diff --git a/core/tests/uwbtests/src/android/uwb/RangingSessionTest.java b/core/tests/uwbtests/src/android/uwb/RangingSessionTest.java
new file mode 100644
index 0000000..702c68e
--- /dev/null
+++ b/core/tests/uwbtests/src/android/uwb/RangingSessionTest.java
@@ -0,0 +1,194 @@
+/*
+ * 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.uwb;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.os.PersistableBundle;
+import android.os.RemoteException;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Test of {@link RangingSession}.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class RangingSessionTest {
+ private static final IUwbAdapter ADAPTER = mock(IUwbAdapter.class);
+ private static final Executor EXECUTOR = UwbTestUtils.getExecutor();
+ private static final PersistableBundle PARAMS = new PersistableBundle();
+ private static final @RangingSession.Callback.CloseReason int CLOSE_REASON =
+ RangingSession.Callback.CLOSE_REASON_LOCAL_GENERIC_ERROR;
+
+ @Test
+ public void testOnRangingStarted_OnOpenSuccessCalled() {
+ SessionHandle handle = new SessionHandle(123);
+ RangingSession.Callback callback = mock(RangingSession.Callback.class);
+ RangingSession session = new RangingSession(EXECUTOR, callback, ADAPTER, handle);
+ verifyOpenState(session, false);
+
+ session.onRangingStarted(PARAMS);
+ verifyOpenState(session, true);
+
+ // Verify that the onOpenSuccess callback was invoked
+ verify(callback, times(1)).onOpenSuccess(eq(session), any());
+ verify(callback, times(0)).onClosed(anyInt(), any());
+ }
+
+ @Test
+ public void testOnRangingStarted_CannotOpenClosedSession() {
+ SessionHandle handle = new SessionHandle(123);
+ RangingSession.Callback callback = mock(RangingSession.Callback.class);
+ RangingSession session = new RangingSession(EXECUTOR, callback, ADAPTER, handle);
+
+ session.onRangingStarted(PARAMS);
+ verifyOpenState(session, true);
+ verify(callback, times(1)).onOpenSuccess(eq(session), any());
+ verify(callback, times(0)).onClosed(anyInt(), any());
+
+ session.onRangingClosed(CLOSE_REASON, PARAMS);
+ verifyOpenState(session, false);
+ verify(callback, times(1)).onOpenSuccess(eq(session), any());
+ verify(callback, times(1)).onClosed(anyInt(), any());
+
+ // Now invoke the ranging started callback and ensure the session remains closed
+ session.onRangingStarted(PARAMS);
+ verifyOpenState(session, false);
+ verify(callback, times(1)).onOpenSuccess(eq(session), any());
+ verify(callback, times(1)).onClosed(anyInt(), any());
+ }
+
+ @Test
+ public void testOnRangingClosed_OnClosedCalledWhenSessionNotOpen() {
+ SessionHandle handle = new SessionHandle(123);
+ RangingSession.Callback callback = mock(RangingSession.Callback.class);
+ RangingSession session = new RangingSession(EXECUTOR, callback, ADAPTER, handle);
+ verifyOpenState(session, false);
+
+ session.onRangingClosed(CLOSE_REASON, PARAMS);
+ verifyOpenState(session, false);
+
+ // Verify that the onOpenSuccess callback was invoked
+ verify(callback, times(0)).onOpenSuccess(eq(session), any());
+ verify(callback, times(1)).onClosed(anyInt(), any());
+ }
+
+ @Test public void testOnRangingClosed_OnClosedCalled() {
+ SessionHandle handle = new SessionHandle(123);
+ RangingSession.Callback callback = mock(RangingSession.Callback.class);
+ RangingSession session = new RangingSession(EXECUTOR, callback, ADAPTER, handle);
+ session.onRangingStarted(PARAMS);
+ session.onRangingClosed(CLOSE_REASON, PARAMS);
+ verify(callback, times(1)).onClosed(anyInt(), any());
+
+ verifyOpenState(session, false);
+ session.onRangingClosed(CLOSE_REASON, PARAMS);
+ verify(callback, times(2)).onClosed(anyInt(), any());
+ }
+
+ @Test
+ public void testOnRangingResult_OnReportReceivedCalled() {
+ SessionHandle handle = new SessionHandle(123);
+ RangingSession.Callback callback = mock(RangingSession.Callback.class);
+ RangingSession session = new RangingSession(EXECUTOR, callback, ADAPTER, handle);
+ verifyOpenState(session, false);
+
+ session.onRangingStarted(PARAMS);
+ verifyOpenState(session, true);
+
+ RangingReport report = UwbTestUtils.getRangingReports(1);
+ session.onRangingResult(report);
+ verify(callback, times(1)).onReportReceived(eq(report));
+ }
+
+ @Test
+ public void testClose() throws RemoteException {
+ SessionHandle handle = new SessionHandle(123);
+ RangingSession.Callback callback = mock(RangingSession.Callback.class);
+ RangingSession session = new RangingSession(EXECUTOR, callback, ADAPTER, handle);
+ session.onRangingStarted(PARAMS);
+
+ // Calling close multiple times should invoke closeRanging until the session receives
+ // the onClosed callback.
+ int totalCallsBeforeOnRangingClosed = 3;
+ for (int i = 1; i <= totalCallsBeforeOnRangingClosed; i++) {
+ session.close();
+ verifyOpenState(session, true);
+ verify(ADAPTER, times(i)).closeRanging(handle);
+ verify(callback, times(0)).onClosed(anyInt(), any());
+ }
+
+ // After onClosed is invoked, then the adapter should no longer be called for each call to
+ // the session's close.
+ final int totalCallsAfterOnRangingClosed = 2;
+ for (int i = 1; i <= totalCallsAfterOnRangingClosed; i++) {
+ session.onRangingClosed(CLOSE_REASON, PARAMS);
+ verifyOpenState(session, false);
+ verify(ADAPTER, times(totalCallsBeforeOnRangingClosed)).closeRanging(handle);
+ verify(callback, times(i)).onClosed(anyInt(), any());
+ }
+ }
+
+ @Test
+ public void testOnRangingResult_OnReportReceivedCalledWhenOpen() {
+ SessionHandle handle = new SessionHandle(123);
+ RangingSession.Callback callback = mock(RangingSession.Callback.class);
+ RangingSession session = new RangingSession(EXECUTOR, callback, ADAPTER, handle);
+
+ assertFalse(session.isOpen());
+ session.onRangingStarted(PARAMS);
+ assertTrue(session.isOpen());
+
+ // Verify that the onReportReceived callback was invoked
+ RangingReport report = UwbTestUtils.getRangingReports(1);
+ session.onRangingResult(report);
+ verify(callback, times(1)).onReportReceived(report);
+ }
+
+ @Test
+ public void testOnRangingResult_OnReportReceivedNotCalledWhenNotOpen() {
+ SessionHandle handle = new SessionHandle(123);
+ RangingSession.Callback callback = mock(RangingSession.Callback.class);
+ RangingSession session = new RangingSession(EXECUTOR, callback, ADAPTER, handle);
+
+ assertFalse(session.isOpen());
+
+ // Verify that the onReportReceived callback was invoked
+ RangingReport report = UwbTestUtils.getRangingReports(1);
+ session.onRangingResult(report);
+ verify(callback, times(0)).onReportReceived(report);
+ }
+
+ private void verifyOpenState(RangingSession session, boolean expected) {
+ assertEquals(expected, session.isOpen());
+ }
+}
diff --git a/core/tests/uwbtests/src/android/uwb/UwbTestUtils.java b/core/tests/uwbtests/src/android/uwb/UwbTestUtils.java
index fb75092..b4b2e30 100644
--- a/core/tests/uwbtests/src/android/uwb/UwbTestUtils.java
+++ b/core/tests/uwbtests/src/android/uwb/UwbTestUtils.java
@@ -22,6 +22,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.Executor;
public class UwbTestUtils {
private UwbTestUtils() {}
@@ -96,4 +97,13 @@
}
return UwbAddress.fromBytes(addressBytes);
}
+
+ public static Executor getExecutor() {
+ return new Executor() {
+ @Override
+ public void execute(Runnable command) {
+ command.run();
+ }
+ };
+ }
}
diff --git a/data/etc/com.android.cellbroadcastreceiver.xml b/data/etc/com.android.cellbroadcastreceiver.xml
index dd2df42..ef49bfa 100644
--- a/data/etc/com.android.cellbroadcastreceiver.xml
+++ b/data/etc/com.android.cellbroadcastreceiver.xml
@@ -19,6 +19,7 @@
<permission name="android.permission.INTERACT_ACROSS_USERS"/>
<permission name="android.permission.MANAGE_USERS"/>
<permission name="android.permission.MODIFY_PHONE_STATE"/>
+ <permission name="android.permission.MODIFY_CELL_BROADCASTS"/>
<permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
<permission name="android.permission.RECEIVE_EMERGENCY_BROADCAST"/>
<permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"/>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 0a77be9..2e12795 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -49,6 +49,7 @@
<permission name="android.permission.INTERACT_ACROSS_USERS"/>
<permission name="android.permission.MANAGE_USERS"/>
<permission name="android.permission.MODIFY_PHONE_STATE"/>
+ <permission name="android.permission.MODIFY_CELL_BROADCASTS"/>
<permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
<permission name="android.permission.RECEIVE_EMERGENCY_BROADCAST"/>
<permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"/>
@@ -452,6 +453,8 @@
<permission name="android.permission.TEST_BIOMETRIC" />
<!-- Permissions required for CTS test - CtsContactsProviderTestCases -->
<permission name="android.contacts.permission.MANAGE_SIM_ACCOUNTS" />
+ <!-- Permissions required for CTS test - CtsHdmiCecHostTestCases -->
+ <permission name="android.permission.HDMI_CEC"/>
</privapp-permissions>
<privapp-permissions package="com.android.statementservice">
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index d8a735c..faf4973 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -901,6 +901,12 @@
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "-1069336896": {
+ "message": "onRootTaskOrderChanged(): rootTask=%s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_RECENTS_ANIMATIONS",
+ "at": "com\/android\/server\/wm\/RecentsAnimation.java"
+ },
"-1066383762": {
"message": "Sleep still waiting to pause %s",
"level": "VERBOSE",
@@ -1303,6 +1309,12 @@
"group": "WM_DEBUG_CONFIGURATION",
"at": "com\/android\/server\/am\/ActivityManagerService.java"
},
+ "-592371899": {
+ "message": "Skipping rootTask: (mismatch activity\/rootTask) %s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_TASKS",
+ "at": "com\/android\/server\/wm\/TaskDisplayArea.java"
+ },
"-583031528": {
"message": "%s",
"level": "INFO",
@@ -2119,12 +2131,6 @@
"group": "WM_DEBUG_APP_TRANSITIONS",
"at": "com\/android\/server\/wm\/AppTransition.java"
},
- "349443311": {
- "message": "pauseBackStacks: task=%s mResumedActivity=%s",
- "level": "DEBUG",
- "group": "WM_DEBUG_STATES",
- "at": "com\/android\/server\/wm\/TaskDisplayArea.java"
- },
"355720268": {
"message": "stopFreezingDisplayLocked: Unfreezing now",
"level": "DEBUG",
@@ -2161,6 +2167,12 @@
"group": "WM_DEBUG_BOOT",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "391189028": {
+ "message": "pauseBackTasks: task=%s mResumedActivity=%s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_STATES",
+ "at": "com\/android\/server\/wm\/TaskDisplayArea.java"
+ },
"397105698": {
"message": "grantEmbeddedWindowFocus remove request for win=%s dropped since no candidate was found",
"level": "VERBOSE",
@@ -2245,12 +2257,6 @@
"group": "WM_DEBUG_WINDOW_ORGANIZER",
"at": "com\/android\/server\/wm\/DisplayAreaOrganizerController.java"
},
- "490877640": {
- "message": "onStackOrderChanged(): stack=%s",
- "level": "DEBUG",
- "group": "WM_DEBUG_RECENTS_ANIMATIONS",
- "at": "com\/android\/server\/wm\/RecentsAnimation.java"
- },
"495032901": {
"message": "Expected target stack=%s to restored behind stack=%s but it is behind stack=%s",
"level": "WARN",
@@ -2575,12 +2581,6 @@
"group": "WM_DEBUG_REMOTE_ANIMATIONS",
"at": "com\/android\/server\/wm\/RemoteAnimationController.java"
},
- "875196661": {
- "message": "Skipping stack: (mismatch activity\/stack) %s",
- "level": "DEBUG",
- "group": "WM_DEBUG_TASKS",
- "at": "com\/android\/server\/wm\/TaskDisplayArea.java"
- },
"883475718": {
"message": "Report configuration: %s %s %s",
"level": "VERBOSE",
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index ba2e52a..2db4c5d 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -377,16 +377,44 @@
</font>
</family>
<family lang="und-Deva" variant="elegant">
- <font weight="400" style="normal">NotoSansDevanagari-Regular.otf</font>
- <font weight="500" style="normal">NotoSansDevanagari-Medium.otf</font>
- <font weight="700" style="normal">NotoSansDevanagari-Bold.otf</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifDevanagari-Regular.ttf</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifDevanagari-Bold.ttf</font>
+ <font weight="400" style="normal">NotoSansDevanagari-VF.ttf
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal">NotoSansDevanagari-VF.ttf
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal">NotoSansDevanagari-VF.ttf
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal">NotoSansDevanagari-VF.ttf
+ <axis tag="wght" stylevalue="700"/>
+ </font>
+ <font weight="400" style="normal" fallbackFor="serif">NotoSerifDevanagari-VF.ttf
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal" fallbackFor="serif">NotoSerifDevanagari-VF.ttf
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal" fallbackFor="serif">NotoSerifDevanagari-VF.ttf
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal" fallbackFor="serif">NotoSerifDevanagari-VF.ttf
+ <axis tag="wght" stylevalue="700"/>
+ </font>
</family>
<family lang="und-Deva" variant="compact">
- <font weight="400" style="normal">NotoSansDevanagariUI-Regular.otf</font>
- <font weight="500" style="normal">NotoSansDevanagariUI-Medium.otf</font>
- <font weight="700" style="normal">NotoSansDevanagariUI-Bold.otf</font>
+ <font weight="400" style="normal">NotoSansDevanagariUI-VF.ttf
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal">NotoSansDevanagariUI-VF.ttf
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal">NotoSansDevanagariUI-VF.ttf
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal">NotoSansDevanagariUI-VF.ttf
+ <axis tag="wght" stylevalue="700"/>
+ </font>
</family>
<!-- All scripts of India should come after Devanagari, due to shared
@@ -395,78 +423,262 @@
<family lang="und-Gujr" variant="elegant">
<font weight="400" style="normal">NotoSansGujarati-Regular.ttf</font>
<font weight="700" style="normal">NotoSansGujarati-Bold.ttf</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifGujarati-Regular.ttf</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifGujarati-Bold.ttf</font>
+ <font weight="400" style="normal" fallbackFor="serif">NotoSerifGujarati-VF.ttf
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal" fallbackFor="serif">NotoSerifGujarati-VF.ttf
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal" fallbackFor="serif">NotoSerifGujarati-VF.ttf
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal" fallbackFor="serif">NotoSerifGujarati-VF.ttf
+ <axis tag="wght" stylevalue="700"/>
+ </font>
</family>
<family lang="und-Gujr" variant="compact">
<font weight="400" style="normal">NotoSansGujaratiUI-Regular.ttf</font>
<font weight="700" style="normal">NotoSansGujaratiUI-Bold.ttf</font>
</family>
<family lang="und-Guru" variant="elegant">
- <font weight="400" style="normal">NotoSansGurmukhi-Regular.ttf</font>
- <font weight="700" style="normal">NotoSansGurmukhi-Bold.ttf</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifGurmukhi-Regular.otf</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifGurmukhi-Bold.otf</font>
+ <font weight="400" style="normal">NotoSansGurmukhi-VF.ttf
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal">NotoSansGurmukhi-VF.ttf
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal">NotoSansGurmukhi-VF.ttf
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal">NotoSansGurmukhi-VF.ttf
+ <axis tag="wght" stylevalue="700"/>
+ </font>
+ <font weight="400" style="normal" fallbackFor="serif">NotoSerifGurmukhi-VF.ttf
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal" fallbackFor="serif">NotoSerifGurmukhi-VF.ttf
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal" fallbackFor="serif">NotoSerifGurmukhi-VF.ttf
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal" fallbackFor="serif">NotoSerifGurmukhi-VF.ttf
+ <axis tag="wght" stylevalue="700"/>
+ </font>
</family>
<family lang="und-Guru" variant="compact">
- <font weight="400" style="normal">NotoSansGurmukhiUI-Regular.ttf</font>
- <font weight="700" style="normal">NotoSansGurmukhiUI-Bold.ttf</font>
+ <font weight="400" style="normal">NotoSansGurmukhiUI-VF.ttf
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal">NotoSansGurmukhiUI-VF.ttf
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal">NotoSansGurmukhiUI-VF.ttf
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal">NotoSansGurmukhiUI-VF.ttf
+ <axis tag="wght" stylevalue="700"/>
+ </font>
</family>
<family lang="und-Taml" variant="elegant">
- <font weight="400" style="normal">NotoSansTamil-Regular.otf</font>
- <font weight="500" style="normal">NotoSansTamil-Medium.otf</font>
- <font weight="700" style="normal">NotoSansTamil-Bold.otf</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifTamil-Regular.otf</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifTamil-Bold.otf</font>
+ <font weight="400" style="normal">NotoSansTamil-VF.ttf
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal">NotoSansTamil-VF.ttf
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal">NotoSansTamil-VF.ttf
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal">NotoSansTamil-VF.ttf
+ <axis tag="wght" stylevalue="700"/>
+ </font>
+ <font weight="400" style="normal" fallbackFor="serif">NotoSerifTamil-VF.ttf
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal" fallbackFor="serif">NotoSerifTamil-VF.ttf
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal" fallbackFor="serif">NotoSerifTamil-VF.ttf
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal" fallbackFor="serif">NotoSerifTamil-VF.ttf
+ <axis tag="wght" stylevalue="700"/>
+ </font>
</family>
<family lang="und-Taml" variant="compact">
- <font weight="400" style="normal">NotoSansTamilUI-Regular.otf</font>
- <font weight="500" style="normal">NotoSansTamilUI-Medium.otf</font>
- <font weight="700" style="normal">NotoSansTamilUI-Bold.otf</font>
+ <font weight="400" style="normal">NotoSansTamilUI-VF.ttf
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal">NotoSansTamilUI-VF.ttf
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal">NotoSansTamilUI-VF.ttf
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal">NotoSansTamilUI-VF.ttf
+ <axis tag="wght" stylevalue="700"/>
+ </font>
</family>
<family lang="und-Mlym" variant="elegant">
- <font weight="400" style="normal">NotoSansMalayalam-Regular.otf</font>
- <font weight="500" style="normal">NotoSansMalayalam-Medium.otf</font>
- <font weight="700" style="normal">NotoSansMalayalam-Bold.otf</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifMalayalam-Regular.ttf</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifMalayalam-Bold.ttf</font>
+ <font weight="400" style="normal">NotoSansMalayalam-VF.ttf
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal">NotoSansMalayalam-VF.ttf
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal">NotoSansMalayalam-VF.ttf
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal">NotoSansMalayalam-VF.ttf
+ <axis tag="wght" stylevalue="700"/>
+ </font>
+ <font weight="400" style="normal" fallbackFor="serif">NotoSerifMalayalam-VF.ttf
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal" fallbackFor="serif">NotoSerifMalayalam-VF.ttf
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal" fallbackFor="serif">NotoSerifMalayalam-VF.ttf
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal" fallbackFor="serif">NotoSerifMalayalam-VF.ttf
+ <axis tag="wght" stylevalue="700"/>
+ </font>
</family>
<family lang="und-Mlym" variant="compact">
- <font weight="400" style="normal">NotoSansMalayalamUI-Regular.otf</font>
- <font weight="500" style="normal">NotoSansMalayalamUI-Medium.otf</font>
- <font weight="700" style="normal">NotoSansMalayalamUI-Bold.otf</font>
+ <font weight="400" style="normal">NotoSansMalayalamUI-VF.ttf
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal">NotoSansMalayalamUI-VF.ttf
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal">NotoSansMalayalamUI-VF.ttf
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal">NotoSansMalayalamUI-VF.ttf
+ <axis tag="wght" stylevalue="700"/>
+ </font>
</family>
<family lang="und-Beng" variant="elegant">
- <font weight="400" style="normal">NotoSansBengali-Regular.otf</font>
- <font weight="500" style="normal">NotoSansBengali-Medium.otf</font>
- <font weight="700" style="normal">NotoSansBengali-Bold.otf</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifBengali-Regular.ttf</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifBengali-Bold.ttf</font>
+ <font weight="400" style="normal">NotoSansBengali-VF.ttf
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal">NotoSansBengali-VF.ttf
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal">NotoSansBengali-VF.ttf
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal">NotoSansBengali-VF.ttf
+ <axis tag="wght" stylevalue="700"/>
+ </font>
+ <font weight="400" style="normal" fallbackFor="serif">NotoSerifBengali-VF.ttf
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal" fallbackFor="serif">NotoSerifBengali-VF.ttf
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal" fallbackFor="serif">NotoSerifBengali-VF.ttf
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal" fallbackFor="serif">NotoSerifBengali-VF.ttf
+ <axis tag="wght" stylevalue="700"/>
+ </font>
</family>
<family lang="und-Beng" variant="compact">
- <font weight="400" style="normal">NotoSansBengaliUI-Regular.otf</font>
- <font weight="500" style="normal">NotoSansBengaliUI-Medium.otf</font>
- <font weight="700" style="normal">NotoSansBengaliUI-Bold.otf</font>
+ <font weight="400" style="normal">NotoSansBengaliUI-VF.ttf
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal">NotoSansBengaliUI-VF.ttf
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal">NotoSansBengaliUI-VF.ttf
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal">NotoSansBengaliUI-VF.ttf
+ <axis tag="wght" stylevalue="700"/>
+ </font>
</family>
<family lang="und-Telu" variant="elegant">
- <font weight="400" style="normal">NotoSansTelugu-Regular.ttf</font>
- <font weight="700" style="normal">NotoSansTelugu-Bold.ttf</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifTelugu-Regular.ttf</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifTelugu-Bold.ttf</font>
+ <font weight="400" style="normal">NotoSansTelugu-VF.ttf
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal">NotoSansTelugu-VF.ttf
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal">NotoSansTelugu-VF.ttf
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal">NotoSansTelugu-VF.ttf
+ <axis tag="wght" stylevalue="700"/>
+ </font>
+ <font weight="400" style="normal" fallbackFor="serif">NotoSerifTelugu-VF.ttf
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal" fallbackFor="serif">NotoSerifTelugu-VF.ttf
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal" fallbackFor="serif">NotoSerifTelugu-VF.ttf
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal" fallbackFor="serif">NotoSerifTelugu-VF.ttf
+ <axis tag="wght" stylevalue="700"/>
+ </font>
</family>
<family lang="und-Telu" variant="compact">
- <font weight="400" style="normal">NotoSansTeluguUI-Regular.ttf</font>
- <font weight="700" style="normal">NotoSansTeluguUI-Bold.ttf</font>
+ <font weight="400" style="normal">NotoSansTeluguUI-VF.ttf
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal">NotoSansTeluguUI-VF.ttf
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal">NotoSansTeluguUI-VF.ttf
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal">NotoSansTeluguUI-VF.ttf
+ <axis tag="wght" stylevalue="700"/>
+ </font>
</family>
<family lang="und-Knda" variant="elegant">
- <font weight="400" style="normal">NotoSansKannada-Regular.ttf</font>
- <font weight="700" style="normal">NotoSansKannada-Bold.ttf</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifKannada-Regular.ttf</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifKannada-Bold.ttf</font>
+ <font weight="400" style="normal">NotoSansKannada-VF.ttf
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal">NotoSansKannada-VF.ttf
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal">NotoSansKannada-VF.ttf
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal">NotoSansKannada-VF.ttf
+ <axis tag="wght" stylevalue="700"/>
+ </font>
+ <font weight="400" style="normal" fallbackFor="serif">NotoSerifKannada-VF.ttf
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal" fallbackFor="serif">NotoSerifKannada-VF.ttf
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal" fallbackFor="serif">NotoSerifKannada-VF.ttf
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal" fallbackFor="serif">NotoSerifKannada-VF.ttf
+ <axis tag="wght" stylevalue="700"/>
+ </font>
</family>
<family lang="und-Knda" variant="compact">
- <font weight="400" style="normal">NotoSansKannadaUI-Regular.ttf</font>
- <font weight="700" style="normal">NotoSansKannadaUI-Bold.ttf</font>
+ <font weight="400" style="normal">NotoSansKannadaUI-VF.ttf
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal">NotoSansKannadaUI-VF.ttf
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal">NotoSansKannadaUI-VF.ttf
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal">NotoSansKannadaUI-VF.ttf
+ <axis tag="wght" stylevalue="700"/>
+ </font>
</family>
<family lang="und-Orya" variant="elegant">
<font weight="400" style="normal">NotoSansOriya-Regular.ttf</font>
@@ -476,18 +688,45 @@
<font weight="400" style="normal">NotoSansOriyaUI-Regular.ttf</font>
<font weight="700" style="normal">NotoSansOriyaUI-Bold.ttf</font>
</family>
-
<family lang="und-Sinh" variant="elegant">
- <font weight="400" style="normal">NotoSansSinhala-Regular.otf</font>
- <font weight="500" style="normal">NotoSansSinhala-Medium.otf</font>
- <font weight="700" style="normal">NotoSansSinhala-Bold.otf</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifSinhala-Regular.otf</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifSinhala-Bold.otf</font>
+ <font weight="400" style="normal">NotoSansSinhala-VF.ttf
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal">NotoSansSinhala-VF.ttf
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal">NotoSansSinhala-VF.ttf
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal">NotoSansSinhala-VF.ttf
+ <axis tag="wght" stylevalue="700"/>
+ </font>
+ <font weight="400" style="normal" fallbackFor="serif">NotoSerifSinhala-VF.ttf
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal" fallbackFor="serif">NotoSerifSinhala-VF.ttf
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal" fallbackFor="serif">NotoSerifSinhala-VF.ttf
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal" fallbackFor="serif">NotoSerifSinhala-VF.ttf
+ <axis tag="wght" stylevalue="700"/>
+ </font>
</family>
<family lang="und-Sinh" variant="compact">
- <font weight="400" style="normal">NotoSansSinhalaUI-Regular.otf</font>
- <font weight="500" style="normal">NotoSansSinhalaUI-Medium.otf</font>
- <font weight="700" style="normal">NotoSansSinhalaUI-Bold.otf</font>
+ <font weight="400" style="normal">NotoSansSinhalaUI-VF.ttf
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal">NotoSansSinhalaUI-VF.ttf
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal">NotoSansSinhalaUI-VF.ttf
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal">NotoSansSinhalaUI-VF.ttf
+ <axis tag="wght" stylevalue="700"/>
+ </font>
</family>
<family lang="und-Khmr" variant="elegant">
<font weight="100" style="normal">NotoSansKhmer-VF.ttf
@@ -650,7 +889,7 @@
<font weight="400" style="normal">NotoSansInscriptionalParthian-Regular.ttf</font>
</family>
<family lang="und-Java">
- <font weight="400" style="normal">NotoSansJavanese-Regular.ttf</font>
+ <font weight="400" style="normal">NotoSansJavanese-Regular.otf</font>
</family>
<family lang="und-Kthi">
<font weight="400" style="normal">NotoSansKaithi-Regular.ttf</font>
diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl
index 6ac73b1..bd0e56a 100644
--- a/data/keyboards/Generic.kl
+++ b/data/keyboards/Generic.kl
@@ -445,3 +445,11 @@
led 0x08 MISC
led 0x09 MAIL
led 0x0a CHARGING
+
+# SENSORs
+sensor 0x00 ACCELEROMETER X
+sensor 0x01 ACCELEROMETER Y
+sensor 0x02 ACCELEROMETER Z
+sensor 0x03 GYROSCOPE X
+sensor 0x04 GYROSCOPE Y
+sensor 0x05 GYROSCOPE Z
diff --git a/data/keyboards/Vendor_054c_Product_05c4.idc b/data/keyboards/Vendor_054c_Product_05c4.idc
new file mode 100644
index 0000000..2cb3f7b
--- /dev/null
+++ b/data/keyboards/Vendor_054c_Product_05c4.idc
@@ -0,0 +1,35 @@
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# Sony DS4 motion sensor configuration file.
+#
+
+# reporting mode 0 - continuous
+sensor.accelerometer.reportingMode = 0
+# The delay between sensor events corresponding to the lowest frequency in microsecond
+sensor.accelerometer.maxDelay = 100000
+# The minimum delay allowed between two events in microsecond
+sensor.accelerometer.minDelay = 5000
+# The power in mA used by this sensor while in use
+sensor.accelerometer.power = 1.5
+
+# reporting mode 0 - continuous
+sensor.gyroscope.reportingMode = 0
+# The delay between sensor events corresponding to the lowest frequency in microsecond
+sensor.gyroscope.maxDelay = 100000
+# The minimum delay allowed between two events in microsecond
+sensor.gyroscope.minDelay = 5000
+# The power in mA used by this sensor while in use
+sensor.gyroscope.power = 0.8
diff --git a/data/keyboards/Vendor_054c_Product_05c4.kl b/data/keyboards/Vendor_054c_Product_05c4.kl
index cd7ab1f..c8b4fc3 100644
--- a/data/keyboards/Vendor_054c_Product_05c4.kl
+++ b/data/keyboards/Vendor_054c_Product_05c4.kl
@@ -68,3 +68,11 @@
# and this button will be equivalent to left mouse button
# Therefore, map it to KEYCODE_BUTTON_1 here to allow apps to still handle this on earlier versions
key 0x13d BUTTON_1
+
+# SENSORs
+sensor 0x00 ACCELEROMETER X
+sensor 0x01 ACCELEROMETER Y
+sensor 0x02 ACCELEROMETER Z
+sensor 0x03 GYROSCOPE X
+sensor 0x04 GYROSCOPE Y
+sensor 0x05 GYROSCOPE Z
diff --git a/data/keyboards/Vendor_054c_Product_05c4_Version_8000.kl b/data/keyboards/Vendor_054c_Product_05c4_Version_8000.kl
index 19fcb86..a877c4c 100644
--- a/data/keyboards/Vendor_054c_Product_05c4_Version_8000.kl
+++ b/data/keyboards/Vendor_054c_Product_05c4_Version_8000.kl
@@ -66,3 +66,11 @@
# In kernel versions >= 4.10, the touchpad is a separate input device,
# so the touchpad button click will not be covered by this layout.
+
+# SENSORs
+sensor 0x00 ACCELEROMETER X
+sensor 0x01 ACCELEROMETER Y
+sensor 0x02 ACCELEROMETER Z
+sensor 0x03 GYROSCOPE X
+sensor 0x04 GYROSCOPE Y
+sensor 0x05 GYROSCOPE Z
diff --git a/data/keyboards/Vendor_054c_Product_05c4_Version_8100.kl b/data/keyboards/Vendor_054c_Product_05c4_Version_8100.kl
index 19fcb86..a877c4c 100644
--- a/data/keyboards/Vendor_054c_Product_05c4_Version_8100.kl
+++ b/data/keyboards/Vendor_054c_Product_05c4_Version_8100.kl
@@ -66,3 +66,11 @@
# In kernel versions >= 4.10, the touchpad is a separate input device,
# so the touchpad button click will not be covered by this layout.
+
+# SENSORs
+sensor 0x00 ACCELEROMETER X
+sensor 0x01 ACCELEROMETER Y
+sensor 0x02 ACCELEROMETER Z
+sensor 0x03 GYROSCOPE X
+sensor 0x04 GYROSCOPE Y
+sensor 0x05 GYROSCOPE Z
diff --git a/data/keyboards/Vendor_054c_Product_05c4_Version_8111.kl b/data/keyboards/Vendor_054c_Product_05c4_Version_8111.kl
index d38bdec..1473c4e 100644
--- a/data/keyboards/Vendor_054c_Product_05c4_Version_8111.kl
+++ b/data/keyboards/Vendor_054c_Product_05c4_Version_8111.kl
@@ -66,3 +66,11 @@
# In kernel versions >= 4.10, the touchpad is a separate input device,
# so the touchpad button click will not be covered by this layout.
+
+# SENSORs
+sensor 0x00 ACCELEROMETER X
+sensor 0x01 ACCELEROMETER Y
+sensor 0x02 ACCELEROMETER Z
+sensor 0x03 GYROSCOPE X
+sensor 0x04 GYROSCOPE Y
+sensor 0x05 GYROSCOPE Z
diff --git a/data/keyboards/Vendor_054c_Product_09cc.idc b/data/keyboards/Vendor_054c_Product_09cc.idc
new file mode 100644
index 0000000..2cb3f7b
--- /dev/null
+++ b/data/keyboards/Vendor_054c_Product_09cc.idc
@@ -0,0 +1,35 @@
+# Copyright (C) 2020 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# Sony DS4 motion sensor configuration file.
+#
+
+# reporting mode 0 - continuous
+sensor.accelerometer.reportingMode = 0
+# The delay between sensor events corresponding to the lowest frequency in microsecond
+sensor.accelerometer.maxDelay = 100000
+# The minimum delay allowed between two events in microsecond
+sensor.accelerometer.minDelay = 5000
+# The power in mA used by this sensor while in use
+sensor.accelerometer.power = 1.5
+
+# reporting mode 0 - continuous
+sensor.gyroscope.reportingMode = 0
+# The delay between sensor events corresponding to the lowest frequency in microsecond
+sensor.gyroscope.maxDelay = 100000
+# The minimum delay allowed between two events in microsecond
+sensor.gyroscope.minDelay = 5000
+# The power in mA used by this sensor while in use
+sensor.gyroscope.power = 0.8
diff --git a/data/keyboards/Vendor_054c_Product_09cc.kl b/data/keyboards/Vendor_054c_Product_09cc.kl
index cd7ab1f..c8b4fc3 100644
--- a/data/keyboards/Vendor_054c_Product_09cc.kl
+++ b/data/keyboards/Vendor_054c_Product_09cc.kl
@@ -68,3 +68,11 @@
# and this button will be equivalent to left mouse button
# Therefore, map it to KEYCODE_BUTTON_1 here to allow apps to still handle this on earlier versions
key 0x13d BUTTON_1
+
+# SENSORs
+sensor 0x00 ACCELEROMETER X
+sensor 0x01 ACCELEROMETER Y
+sensor 0x02 ACCELEROMETER Z
+sensor 0x03 GYROSCOPE X
+sensor 0x04 GYROSCOPE Y
+sensor 0x05 GYROSCOPE Z
diff --git a/data/keyboards/Vendor_054c_Product_09cc_Version_8000.kl b/data/keyboards/Vendor_054c_Product_09cc_Version_8000.kl
index 19fcb86..a877c4c 100644
--- a/data/keyboards/Vendor_054c_Product_09cc_Version_8000.kl
+++ b/data/keyboards/Vendor_054c_Product_09cc_Version_8000.kl
@@ -66,3 +66,11 @@
# In kernel versions >= 4.10, the touchpad is a separate input device,
# so the touchpad button click will not be covered by this layout.
+
+# SENSORs
+sensor 0x00 ACCELEROMETER X
+sensor 0x01 ACCELEROMETER Y
+sensor 0x02 ACCELEROMETER Z
+sensor 0x03 GYROSCOPE X
+sensor 0x04 GYROSCOPE Y
+sensor 0x05 GYROSCOPE Z
diff --git a/data/keyboards/Vendor_054c_Product_09cc_Version_8100.kl b/data/keyboards/Vendor_054c_Product_09cc_Version_8100.kl
index 19fcb86..a877c4c 100644
--- a/data/keyboards/Vendor_054c_Product_09cc_Version_8100.kl
+++ b/data/keyboards/Vendor_054c_Product_09cc_Version_8100.kl
@@ -66,3 +66,11 @@
# In kernel versions >= 4.10, the touchpad is a separate input device,
# so the touchpad button click will not be covered by this layout.
+
+# SENSORs
+sensor 0x00 ACCELEROMETER X
+sensor 0x01 ACCELEROMETER Y
+sensor 0x02 ACCELEROMETER Z
+sensor 0x03 GYROSCOPE X
+sensor 0x04 GYROSCOPE Y
+sensor 0x05 GYROSCOPE Z
diff --git a/data/keyboards/Vendor_054c_Product_09cc_Version_8111.kl b/data/keyboards/Vendor_054c_Product_09cc_Version_8111.kl
index d38bdec..1473c4e 100644
--- a/data/keyboards/Vendor_054c_Product_09cc_Version_8111.kl
+++ b/data/keyboards/Vendor_054c_Product_09cc_Version_8111.kl
@@ -66,3 +66,11 @@
# In kernel versions >= 4.10, the touchpad is a separate input device,
# so the touchpad button click will not be covered by this layout.
+
+# SENSORs
+sensor 0x00 ACCELEROMETER X
+sensor 0x01 ACCELEROMETER Y
+sensor 0x02 ACCELEROMETER Z
+sensor 0x03 GYROSCOPE X
+sensor 0x04 GYROSCOPE Y
+sensor 0x05 GYROSCOPE Z
diff --git a/data/keyboards/keyboards.mk b/data/keyboards/keyboards.mk
index 68cbd29..c7ce8cd 100644
--- a/data/keyboards/keyboards.mk
+++ b/data/keyboards/keyboards.mk
@@ -14,13 +14,9 @@
# Warning: this is actually a product definition, to be inherited from
-include $(LOCAL_PATH)/common.mk
+PRODUCT_COPY_FILES := \
+ $(call find-copy-subdir-files,*.kl,$(LOCAL_PATH),system/usr/keylayout) \
+ $(call find-copy-subdir-files,*.kcm,$(LOCAL_PATH),system/usr/keychars) \
+ $(call find-copy-subdir-files,*.idc,$(LOCAL_PATH),system/usr/idc)
-PRODUCT_COPY_FILES := $(foreach file,$(framework_keylayouts),\
- $(file):system/usr/keylayout/$(notdir $(file)))
-PRODUCT_COPY_FILES += $(foreach file,$(framework_keycharmaps),\
- $(file):system/usr/keychars/$(notdir $(file)))
-
-PRODUCT_COPY_FILES += $(foreach file,$(framework_keyconfigs),\
- $(file):system/usr/idc/$(notdir $(file)))
diff --git a/drm/java/android/drm/DrmOutputStream.java b/drm/java/android/drm/DrmOutputStream.java
index 73e7f23..2a3f530 100644
--- a/drm/java/android/drm/DrmOutputStream.java
+++ b/drm/java/android/drm/DrmOutputStream.java
@@ -25,9 +25,10 @@
import android.system.Os;
import android.util.Log;
+import com.android.internal.util.ArrayUtils;
+
import libcore.io.IoBridge;
import libcore.io.Streams;
-import libcore.util.ArrayUtils;
import java.io.FileDescriptor;
import java.io.FilterOutputStream;
diff --git a/graphics/java/android/graphics/BitmapShader.java b/graphics/java/android/graphics/BitmapShader.java
index 1cb5912..e6ff187 100644
--- a/graphics/java/android/graphics/BitmapShader.java
+++ b/graphics/java/android/graphics/BitmapShader.java
@@ -31,6 +31,23 @@
private int mTileX;
private int mTileY;
+ /*
+ * This is cache of the last value from the Paint of bitmap-filtering.
+ * In the future, BitmapShaders will carry their own (expanded) data for this
+ * (e.g. including mipmap options, or bicubic weights)
+ *
+ * When that happens, this bool will become those extended values, and we will
+ * need to track whether this Shader was created with those new constructors,
+ * or from the current "legacy" constructor, which (for compatibility) will
+ * still need to know the Paint's setting.
+ *
+ * When the filter Paint setting is finally gone, we will be able to remove
+ * the filterFromPaint parameter currently being passed to createNativeInstance()
+ * and shouldDiscardNativeInstance(), as shaders will always know their filter
+ * settings.
+ */
+ private boolean mFilterFromPaint;
+
/**
* Call this to create a new shader that will draw with a bitmap.
*
@@ -49,14 +66,24 @@
mBitmap = bitmap;
mTileX = tileX;
mTileY = tileY;
+ mFilterFromPaint = false;
}
/** @hide */
@Override
- protected long createNativeInstance(long nativeMatrix) {
- return nativeCreate(nativeMatrix, mBitmap.getNativeInstance(), mTileX, mTileY);
+ protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
+ mFilterFromPaint = filterFromPaint;
+ return nativeCreate(nativeMatrix, mBitmap.getNativeInstance(), mTileX, mTileY,
+ mFilterFromPaint);
+ }
+
+ /** @hide */
+ @Override
+ protected boolean shouldDiscardNativeInstance(boolean filterFromPaint) {
+ return mFilterFromPaint != filterFromPaint;
}
private static native long nativeCreate(long nativeMatrix, long bitmapHandle,
- int shaderTileModeX, int shaderTileModeY);
+ int shaderTileModeX, int shaderTileModeY, boolean filter);
}
+
diff --git a/graphics/java/android/graphics/BlurShader.java b/graphics/java/android/graphics/BlurShader.java
index 3bc8119..2e4bd7d 100644
--- a/graphics/java/android/graphics/BlurShader.java
+++ b/graphics/java/android/graphics/BlurShader.java
@@ -69,16 +69,18 @@
/** @hide **/
@Override
- protected long createNativeInstance(long nativeMatrix) {
- mNativeInputShader = mInputShader != null ? mInputShader.getNativeInstance() : 0;
+ protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
+ mNativeInputShader = mInputShader != null
+ ? mInputShader.getNativeInstance(filterFromPaint) : 0;
return nativeCreate(nativeMatrix, mRadiusX, mRadiusY, mNativeInputShader,
mEdgeTreatment.nativeInt);
}
/** @hide **/
@Override
- protected boolean shouldDiscardNativeInstance() {
- long currentNativeInstance = mInputShader != null ? mInputShader.getNativeInstance() : 0;
+ protected boolean shouldDiscardNativeInstance(boolean filterFromPaint) {
+ long currentNativeInstance = mInputShader != null
+ ? mInputShader.getNativeInstance(filterFromPaint) : 0;
return mNativeInputShader != currentNativeInstance;
}
diff --git a/graphics/java/android/graphics/ComposeShader.java b/graphics/java/android/graphics/ComposeShader.java
index b840f3f..977aeaa 100644
--- a/graphics/java/android/graphics/ComposeShader.java
+++ b/graphics/java/android/graphics/ComposeShader.java
@@ -86,18 +86,18 @@
/** @hide */
@Override
- protected long createNativeInstance(long nativeMatrix) {
- mNativeInstanceShaderA = mShaderA.getNativeInstance();
- mNativeInstanceShaderB = mShaderB.getNativeInstance();
+ protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
+ mNativeInstanceShaderA = mShaderA.getNativeInstance(filterFromPaint);
+ mNativeInstanceShaderB = mShaderB.getNativeInstance(filterFromPaint);
return nativeCreate(nativeMatrix,
mShaderA.getNativeInstance(), mShaderB.getNativeInstance(), mPorterDuffMode);
}
/** @hide */
@Override
- protected boolean shouldDiscardNativeInstance() {
- return mShaderA.getNativeInstance() != mNativeInstanceShaderA
- || mShaderB.getNativeInstance() != mNativeInstanceShaderB;
+ protected boolean shouldDiscardNativeInstance(boolean filterFromPaint) {
+ return mShaderA.getNativeInstance(filterFromPaint) != mNativeInstanceShaderA
+ || mShaderB.getNativeInstance(filterFromPaint) != mNativeInstanceShaderB;
}
private static native long nativeCreate(long nativeMatrix,
diff --git a/graphics/java/android/graphics/LinearGradient.java b/graphics/java/android/graphics/LinearGradient.java
index 4eedbf5..56d912b 100644
--- a/graphics/java/android/graphics/LinearGradient.java
+++ b/graphics/java/android/graphics/LinearGradient.java
@@ -154,7 +154,7 @@
/** @hide */
@Override
- protected long createNativeInstance(long nativeMatrix) {
+ protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
return nativeCreate(nativeMatrix, mX0, mY0, mX1, mY1,
mColorLongs, mPositions, mTileMode.nativeInt,
colorSpace().getNativeInstance());
diff --git a/graphics/java/android/graphics/OWNERS b/graphics/java/android/graphics/OWNERS
index a8a3631..9fa8f1b 100644
--- a/graphics/java/android/graphics/OWNERS
+++ b/graphics/java/android/graphics/OWNERS
@@ -4,6 +4,8 @@
jreck@google.com
njawad@google.com
sumir@google.com
+djsollen@google.com
+scroggo@google.com
per-file BLASTBufferQueue.java = file:/services/core/java/com/android/server/wm/OWNERS
per-file FontFamily.java = file:fonts/OWNERS
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 4b6e4d1..f1f9a5f 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -698,7 +698,8 @@
*/
@UnsupportedAppUsage
public synchronized long getNativeInstance() {
- long newNativeShader = mShader == null ? 0 : mShader.getNativeInstance();
+ boolean filter = isFilterBitmap();
+ long newNativeShader = mShader == null ? 0 : mShader.getNativeInstance(filter);
if (newNativeShader != mNativeShader) {
mNativeShader = newNativeShader;
nSetShader(mNativePaint, mNativeShader);
diff --git a/graphics/java/android/graphics/RadialGradient.java b/graphics/java/android/graphics/RadialGradient.java
index dd1be15..199365e 100644
--- a/graphics/java/android/graphics/RadialGradient.java
+++ b/graphics/java/android/graphics/RadialGradient.java
@@ -207,7 +207,7 @@
/** @hide */
@Override
- protected long createNativeInstance(long nativeMatrix) {
+ protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
return nativeCreate(nativeMatrix, mFocalX, mFocalY, mFocalRadius, mX, mY, mRadius,
mColorLongs, mPositions, mTileMode.nativeInt, colorSpace().getNativeInstance());
}
diff --git a/graphics/java/android/graphics/RuntimeShader.java b/graphics/java/android/graphics/RuntimeShader.java
index 63089e2..fb0983a 100644
--- a/graphics/java/android/graphics/RuntimeShader.java
+++ b/graphics/java/android/graphics/RuntimeShader.java
@@ -105,10 +105,10 @@
/** @hide */
@Override
- protected long createNativeInstance(long nativeMatrix) {
+ protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
long[] nativeShaders = mInputShaders.length > 0 ? new long[mInputShaders.length] : null;
for (int i = 0; i < mInputShaders.length; i++) {
- nativeShaders[i] = mInputShaders[i].getNativeInstance();
+ nativeShaders[i] = mInputShaders[i].getNativeInstance(filterFromPaint);
}
return nativeCreate(mNativeInstanceRuntimeShaderFactory, nativeMatrix, mUniforms,
diff --git a/graphics/java/android/graphics/Shader.java b/graphics/java/android/graphics/Shader.java
index 7651d01..4d6bead 100644
--- a/graphics/java/android/graphics/Shader.java
+++ b/graphics/java/android/graphics/Shader.java
@@ -148,7 +148,7 @@
/**
* @hide Only to be used by subclasses in the graphics package.
*/
- protected long createNativeInstance(long nativeMatrix) {
+ protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
return 0;
}
@@ -173,7 +173,7 @@
* constructed native instance is still valid.
* @hide Only to be used by subclasses in the graphics package.
*/
- protected boolean shouldDiscardNativeInstance() {
+ protected boolean shouldDiscardNativeInstance(boolean filterBitmap) {
return false;
}
@@ -182,14 +182,14 @@
* @hide so it can be called by android.graphics.drawable but must not be called from outside
* the module.
*/
- public synchronized final long getNativeInstance() {
- if (shouldDiscardNativeInstance()) {
+ public final synchronized long getNativeInstance(boolean filterFromPaint) {
+ if (shouldDiscardNativeInstance(filterFromPaint)) {
discardNativeInstanceLocked();
}
if (mNativeInstance == 0) {
mNativeInstance = createNativeInstance(mLocalMatrix == null
- ? 0 : mLocalMatrix.ni());
+ ? 0 : mLocalMatrix.ni(), filterFromPaint);
if (mNativeInstance != 0) {
mCleaner = NoImagePreloadHolder.sRegistry.registerNativeAllocation(
this, mNativeInstance);
@@ -199,6 +199,15 @@
}
/**
+ * @hide so it can be called by android.graphics.drawable but must not be called from outside
+ * the module.
+ */
+ public final long getNativeInstance() {
+ // If the caller has no paint flag for filtering bitmaps, we just pass false
+ return getNativeInstance(false);
+ }
+
+ /**
* @hide Only to be called by subclasses in the android.graphics package.
*/
protected static @ColorLong long[] convertColors(@NonNull @ColorInt int[] colors) {
diff --git a/graphics/java/android/graphics/SweepGradient.java b/graphics/java/android/graphics/SweepGradient.java
index 2280780..3a29395 100644
--- a/graphics/java/android/graphics/SweepGradient.java
+++ b/graphics/java/android/graphics/SweepGradient.java
@@ -133,7 +133,7 @@
/** @hide */
@Override
- protected long createNativeInstance(long nativeMatrix) {
+ protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
return nativeCreate(nativeMatrix, mCx, mCy, mColorLongs, mPositions,
colorSpace().getNativeInstance());
}
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index d6b4f18..48b474d 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -25,6 +25,7 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UiThread;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.AssetManager;
import android.graphics.fonts.Font;
@@ -149,8 +150,8 @@
static final Map<String, Typeface> sSystemFontMap = new HashMap<>();
// DirectByteBuffer object to hold sSystemFontMap's backing memory mapping.
- @GuardedBy("SYSTEM_FONT_MAP_LOCK")
static ByteBuffer sSystemFontMapBuffer = null;
+ static SharedMemory sSystemFontMapSharedMemory = null;
// Lock to guard sSystemFontMap and derived default or public typefaces.
// sStyledCacheLock may be held while this lock is held. Holding them in the reverse order may
@@ -1252,14 +1253,27 @@
* per process.
*/
/** @hide */
- public static void setSystemFontMap(SharedMemory sharedMemory)
+ @UiThread
+ public static void setSystemFontMap(@Nullable SharedMemory sharedMemory)
throws IOException, ErrnoException {
if (sSystemFontMapBuffer != null) {
+ // Apps can re-send BIND_APPLICATION message from their code. This is a work around to
+ // detect it and avoid crashing.
+ if (sharedMemory == null || sharedMemory == sSystemFontMapSharedMemory) {
+ return;
+ }
throw new UnsupportedOperationException(
"Once set, buffer-based system font map cannot be updated");
}
+ sSystemFontMapSharedMemory = sharedMemory;
Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "setSystemFontMap");
try {
+ if (sharedMemory == null) {
+ // FontManagerService is not started. This may happen in FACTORY_TEST_LOW_LEVEL
+ // mode for example.
+ loadPreinstalledSystemFontMap();
+ return;
+ }
sSystemFontMapBuffer = sharedMemory.mapReadOnly().order(ByteOrder.BIG_ENDIAN);
Map<String, Typeface> systemFontMap = deserializeFontMap(sSystemFontMapBuffer);
setSystemFontMap(systemFontMap);
@@ -1319,6 +1333,7 @@
SharedMemory.unmap(sSystemFontMapBuffer);
}
sSystemFontMapBuffer = null;
+ sSystemFontMapSharedMemory = null;
}
}
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 6dcc251..9298d9fc 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -84,10 +84,10 @@
* <dd>Defines the name of this vector drawable.</dd>
* <dt><code>android:width</code></dt>
* <dd>Used to define the intrinsic width of the drawable.
- * This support all the dimension units, normally specified with dp.</dd>
+ * This supports all the dimension units, normally specified with dp.</dd>
* <dt><code>android:height</code></dt>
- * <dd>Used to define the intrinsic height the drawable.
- * This support all the dimension units, normally specified with dp.</dd>
+ * <dd>Used to define the intrinsic height of the drawable.
+ * This supports all the dimension units, normally specified with dp.</dd>
* <dt><code>android:viewportWidth</code></dt>
* <dd>Used to define the width of the viewport space. Viewport is basically
* the virtual canvas where the paths are drawn on.</dd>
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStore3DESCipherSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStore3DESCipherSpi.java
index 0775a1a..56f7ea8 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStore3DESCipherSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStore3DESCipherSpi.java
@@ -41,7 +41,7 @@
*
* @hide
*/
-public class AndroidKeyStore3DESCipherSpi extends AndroidKeyStoreCipherSpiBase {
+public abstract class AndroidKeyStore3DESCipherSpi extends AndroidKeyStoreCipherSpiBase {
private static final int BLOCK_SIZE_BYTES = 8;
@@ -73,12 +73,22 @@
public NoPadding() {
super(KeymasterDefs.KM_PAD_NONE);
}
+
+ @Override
+ protected final String getTransform() {
+ return "DESede/ECB/NoPadding";
+ }
}
public static class PKCS7Padding extends ECB {
public PKCS7Padding() {
super(KeymasterDefs.KM_PAD_PKCS7);
}
+
+ @Override
+ protected final String getTransform() {
+ return "DESede/ECB/PKCS7Padding";
+ }
}
}
@@ -91,12 +101,23 @@
public NoPadding() {
super(KeymasterDefs.KM_PAD_NONE);
}
+
+ @Override
+ protected final String getTransform() {
+ return "DESede/CBC/NoPadding";
+ }
+
}
public static class PKCS7Padding extends CBC {
public PKCS7Padding() {
super(KeymasterDefs.KM_PAD_PKCS7);
}
+
+ @Override
+ protected final String getTransform() {
+ return "DESede/CBC/PKCS7Padding";
+ }
}
}
@@ -288,7 +309,7 @@
if (parameters != null) {
for (KeyParameter p : parameters) {
if (p.tag == KeymasterDefs.KM_TAG_NONCE) {
- returnedIv = p.blob;
+ returnedIv = p.value.getBlob();
break;
}
}
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreAuthenticatedAESCipherSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreAuthenticatedAESCipherSpi.java
index bc56f01..64da837 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreAuthenticatedAESCipherSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreAuthenticatedAESCipherSpi.java
@@ -64,6 +64,11 @@
}
@Override
+ protected final String getTransform() {
+ return "AES/GCM/NoPadding";
+ }
+
+ @Override
protected final void resetAll() {
mTagLengthBits = DEFAULT_TAG_LENGTH_BITS;
super.resetAll();
@@ -325,7 +330,7 @@
if (parameters != null) {
for (KeyParameter p : parameters) {
if (p.tag == KeymasterDefs.KM_TAG_NONCE) {
- returnedIv = p.blob;
+ returnedIv = p.value.getBlob();
break;
}
}
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreBCWorkaroundProvider.java b/keystore/java/android/security/keystore2/AndroidKeyStoreBCWorkaroundProvider.java
index dd943d4..9ad6f3a 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreBCWorkaroundProvider.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreBCWorkaroundProvider.java
@@ -254,13 +254,13 @@
private void putAsymmetricCipherImpl(String transformation, String implClass) {
put("Cipher." + transformation, implClass);
put("Cipher." + transformation + " SupportedKeyClasses",
- KEYSTORE_PRIVATE_KEY_CLASS_NAME + "|" + KEYSTORE_PUBLIC_KEY_CLASS_NAME);
+ KEYSTORE_PRIVATE_KEY_CLASS_NAME);
}
private void putSignatureImpl(String algorithm, String implClass) {
put("Signature." + algorithm, implClass);
put("Signature." + algorithm + " SupportedKeyClasses",
- KEYSTORE_PRIVATE_KEY_CLASS_NAME + "|" + KEYSTORE_PUBLIC_KEY_CLASS_NAME);
+ KEYSTORE_PRIVATE_KEY_CLASS_NAME);
}
public static String[] getSupportedEcdsaSignatureDigests() {
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java b/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java
index a3b04ab..2ee952c 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java
@@ -43,6 +43,7 @@
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidKeySpecException;
+import java.security.spec.MGF1ParameterSpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
@@ -57,6 +58,8 @@
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.ShortBufferException;
+import javax.crypto.spec.OAEPParameterSpec;
+import javax.crypto.spec.PSource;
import javax.crypto.spec.SecretKeySpec;
/**
@@ -99,6 +102,8 @@
*/
private Exception mCachedException;
+ private Cipher mCipher;
+
AndroidKeyStoreCipherSpiBase() {
mOperation = null;
mEncrypting = false;
@@ -110,6 +115,7 @@
mAdditionalAuthenticationDataStreamer = null;
mAdditionalAuthenticationDataStreamerClosed = false;
mCachedException = null;
+ mCipher = null;
}
@Override
@@ -117,6 +123,45 @@
throws InvalidKeyException {
resetAll();
+ if (!(key instanceof AndroidKeyStorePrivateKey
+ || key instanceof AndroidKeyStoreSecretKey)) {
+ try {
+ mCipher = Cipher.getInstance(getTransform());
+ String transform = getTransform();
+
+ if ("RSA/ECB/OAEPWithSHA-224AndMGF1Padding".equals(transform)) {
+ OAEPParameterSpec spec =
+ new OAEPParameterSpec("SHA-224", "MGF1",
+ new MGF1ParameterSpec("SHA1"), PSource.PSpecified.DEFAULT);
+ mCipher.init(opmode, key, spec, random);
+ } else if ("RSA/ECB/OAEPWithSHA-256AndMGF1Padding".equals(transform)) {
+ OAEPParameterSpec spec =
+ new OAEPParameterSpec("SHA-256", "MGF1",
+ new MGF1ParameterSpec("SHA1"), PSource.PSpecified.DEFAULT);
+ mCipher.init(opmode, key, spec, random);
+
+ } else if ("RSA/ECB/OAEPWithSHA-384AndMGF1Padding".equals(transform)) {
+ OAEPParameterSpec spec =
+ new OAEPParameterSpec("SHA-384", "MGF1",
+ new MGF1ParameterSpec("SHA1"), PSource.PSpecified.DEFAULT);
+ mCipher.init(opmode, key, spec, random);
+
+ } else if ("RSA/ECB/OAEPWithSHA-512AndMGF1Padding".equals(transform)) {
+ OAEPParameterSpec spec =
+ new OAEPParameterSpec("SHA-512", "MGF1",
+ new MGF1ParameterSpec("SHA1"), PSource.PSpecified.DEFAULT);
+ mCipher.init(opmode, key, spec, random);
+ } else {
+ mCipher.init(opmode, key, random);
+ }
+ return;
+ } catch (NoSuchAlgorithmException
+ | NoSuchPaddingException
+ | InvalidAlgorithmParameterException e) {
+ throw new InvalidKeyException(e);
+ }
+ }
+
boolean success = false;
try {
init(opmode, key, random);
@@ -139,6 +184,17 @@
SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
resetAll();
+ if (!(key instanceof AndroidKeyStorePrivateKey
+ || key instanceof AndroidKeyStoreSecretKey)) {
+ try {
+ mCipher = Cipher.getInstance(getTransform());
+ mCipher.init(opmode, key, params, random);
+ return;
+ } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
+ throw new InvalidKeyException(e);
+ }
+ }
+
boolean success = false;
try {
init(opmode, key, random);
@@ -157,6 +213,17 @@
SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
resetAll();
+ if (!(key instanceof AndroidKeyStorePrivateKey
+ || key instanceof AndroidKeyStoreSecretKey)) {
+ try {
+ mCipher = Cipher.getInstance(getTransform());
+ mCipher.init(opmode, key, params, random);
+ return;
+ } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
+ throw new InvalidKeyException(e);
+ }
+ }
+
boolean success = false;
try {
init(opmode, key, random);
@@ -214,6 +281,7 @@
mAdditionalAuthenticationDataStreamer = null;
mAdditionalAuthenticationDataStreamerClosed = false;
mCachedException = null;
+ mCipher = null;
}
/**
@@ -320,6 +388,10 @@
@Override
protected final byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) {
+ if (mCipher != null) {
+ return mCipher.update(input, inputOffset, inputLen);
+ }
+
if (mCachedException != null) {
return null;
}
@@ -371,6 +443,9 @@
@Override
protected final int engineUpdate(byte[] input, int inputOffset, int inputLen, byte[] output,
int outputOffset) throws ShortBufferException {
+ if (mCipher != null) {
+ return mCipher.update(input, inputOffset, inputLen, output);
+ }
byte[] outputCopy = engineUpdate(input, inputOffset, inputLen);
if (outputCopy == null) {
return 0;
@@ -387,6 +462,10 @@
@Override
protected final int engineUpdate(ByteBuffer input, ByteBuffer output)
throws ShortBufferException {
+ if (mCipher != null) {
+ return mCipher.update(input, output);
+ }
+
if (input == null) {
throw new NullPointerException("input == null");
}
@@ -423,6 +502,11 @@
@Override
protected final void engineUpdateAAD(byte[] input, int inputOffset, int inputLen) {
+ if (mCipher != null) {
+ mCipher.updateAAD(input, inputOffset, inputLen);
+ return;
+ }
+
if (mCachedException != null) {
return;
}
@@ -459,6 +543,11 @@
@Override
protected final void engineUpdateAAD(ByteBuffer src) {
+ if (mCipher != null) {
+ mCipher.updateAAD(src);
+ return;
+ }
+
if (src == null) {
throw new IllegalArgumentException("src == null");
}
@@ -486,6 +575,10 @@
@Override
protected final byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen)
throws IllegalBlockSizeException, BadPaddingException {
+ if (mCipher != null) {
+ return mCipher.doFinal(input, inputOffset, inputLen);
+ }
+
if (mCachedException != null) {
throw (IllegalBlockSizeException)
new IllegalBlockSizeException().initCause(mCachedException);
@@ -522,6 +615,10 @@
protected final int engineDoFinal(byte[] input, int inputOffset, int inputLen, byte[] output,
int outputOffset) throws ShortBufferException, IllegalBlockSizeException,
BadPaddingException {
+ if (mCipher != null) {
+ return mCipher.doFinal(input, inputOffset, inputLen, output);
+ }
+
byte[] outputCopy = engineDoFinal(input, inputOffset, inputLen);
if (outputCopy == null) {
return 0;
@@ -538,6 +635,10 @@
@Override
protected final int engineDoFinal(ByteBuffer input, ByteBuffer output)
throws ShortBufferException, IllegalBlockSizeException, BadPaddingException {
+ if (mCipher != null) {
+ return mCipher.doFinal(input, output);
+ }
+
if (input == null) {
throw new NullPointerException("input == null");
}
@@ -575,6 +676,10 @@
@Override
protected final byte[] engineWrap(Key key)
throws IllegalBlockSizeException, InvalidKeyException {
+ if (mCipher != null) {
+ return mCipher.wrap(key);
+ }
+
if (mKey == null) {
throw new IllegalStateException("Not initilized");
}
@@ -656,6 +761,10 @@
@Override
protected final Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
int wrappedKeyType) throws InvalidKeyException, NoSuchAlgorithmException {
+ if (mCipher != null) {
+ return mCipher.unwrap(wrappedKey, wrappedKeyAlgorithm, wrappedKeyType);
+ }
+
if (mKey == null) {
throw new IllegalStateException("Not initilized");
}
@@ -902,4 +1011,6 @@
*/
protected abstract void loadAlgorithmSpecificParametersFromBeginResult(
KeyParameter[] parameters);
+
+ protected abstract String getTransform();
}
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java
index d1ef1df..8289671 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java
@@ -44,6 +44,11 @@
}
@Override
+ protected String getAlgorithm() {
+ return "NONEwithECDSA";
+ }
+
+ @Override
protected KeyStoreCryptoOperationStreamer createMainDataStreamer(
KeyStoreOperation operation) {
return new TruncateToFieldSizeMessageStreamer(
@@ -113,30 +118,50 @@
public SHA1() {
super(KeymasterDefs.KM_DIGEST_SHA1);
}
+ @Override
+ protected String getAlgorithm() {
+ return "SHA1withECDSA";
+ }
}
public final static class SHA224 extends AndroidKeyStoreECDSASignatureSpi {
public SHA224() {
super(KeymasterDefs.KM_DIGEST_SHA_2_224);
}
+ @Override
+ protected String getAlgorithm() {
+ return "SHA224withECDSA";
+ }
}
public final static class SHA256 extends AndroidKeyStoreECDSASignatureSpi {
public SHA256() {
super(KeymasterDefs.KM_DIGEST_SHA_2_256);
}
+ @Override
+ protected String getAlgorithm() {
+ return "SHA256withECDSA";
+ }
}
public final static class SHA384 extends AndroidKeyStoreECDSASignatureSpi {
public SHA384() {
super(KeymasterDefs.KM_DIGEST_SHA_2_384);
}
+ @Override
+ protected String getAlgorithm() {
+ return "SHA384withECDSA";
+ }
}
public final static class SHA512 extends AndroidKeyStoreECDSASignatureSpi {
public SHA512() {
super(KeymasterDefs.KM_DIGEST_SHA_2_512);
}
+ @Override
+ protected String getAlgorithm() {
+ return "SHA512withECDSA";
+ }
}
private final int mKeymasterDigest;
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreLoadStoreParameter.java b/keystore/java/android/security/keystore2/AndroidKeyStoreLoadStoreParameter.java
index afb1054..0c6744f 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreLoadStoreParameter.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreLoadStoreParameter.java
@@ -22,11 +22,11 @@
/**
* @hide
*/
-class AndroidKeyStoreLoadStoreParameter implements KeyStore.LoadStoreParameter {
+public class AndroidKeyStoreLoadStoreParameter implements KeyStore.LoadStoreParameter {
private final int mNamespace;
- AndroidKeyStoreLoadStoreParameter(int namespace) {
+ public AndroidKeyStoreLoadStoreParameter(int namespace) {
mNamespace = namespace;
}
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
index b2e32a3..403da18 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
@@ -31,9 +31,7 @@
import android.system.keystore2.KeyMetadata;
import android.system.keystore2.ResponseCode;
-import java.security.KeyFactory;
import java.security.KeyPair;
-import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.ProviderException;
import java.security.PublicKey;
@@ -42,8 +40,6 @@
import java.security.UnrecoverableKeyException;
import java.security.interfaces.ECPublicKey;
import java.security.interfaces.RSAPublicKey;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import javax.crypto.Mac;
@@ -237,28 +233,11 @@
throw new UnrecoverableKeyException("Failed to obtain X.509 form of public key."
+ " Keystore has no public certificate stored.");
}
- final byte[] x509EncodedPublicKey = metadata.certificate;
+ final byte[] x509PublicCert = metadata.certificate;
- String jcaKeyAlgorithm;
- try {
- jcaKeyAlgorithm = KeyProperties.KeyAlgorithm.fromKeymasterAsymmetricKeyAlgorithm(
- algorithm);
- } catch (IllegalArgumentException e) {
- throw (UnrecoverableKeyException)
- new UnrecoverableKeyException("Failed to load private key")
- .initCause(e);
- }
+ PublicKey publicKey = AndroidKeyStoreSpi.toCertificate(x509PublicCert).getPublicKey();
- PublicKey publicKey;
- try {
- KeyFactory keyFactory = KeyFactory.getInstance(jcaKeyAlgorithm);
- publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(x509EncodedPublicKey));
- } catch (NoSuchAlgorithmException e) {
- throw new ProviderException(
- "Failed to obtain " + jcaKeyAlgorithm + " KeyFactory", e);
- } catch (InvalidKeySpecException e) {
- throw new ProviderException("Invalid X.509 encoding of public key", e);
- }
+ String jcaKeyAlgorithm = publicKey.getAlgorithm();
KeyStoreSecurityLevel securityLevel = iSecurityLevel;
if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(jcaKeyAlgorithm)) {
@@ -358,7 +337,7 @@
KeyDescriptor descriptor = new KeyDescriptor();
if (namespace == KeyProperties.NAMESPACE_APPLICATION) {
- descriptor.nspace = 0; // ignored;
+ descriptor.nspace = KeyProperties.NAMESPACE_APPLICATION; // ignored;
descriptor.domain = Domain.APP;
} else {
descriptor.nspace = namespace;
@@ -387,10 +366,10 @@
for (Authorization a : response.metadata.authorizations) {
switch (a.keyParameter.tag) {
case KeymasterDefs.KM_TAG_ALGORITHM:
- keymasterAlgorithm = a.keyParameter.integer;
+ keymasterAlgorithm = a.keyParameter.value.getAlgorithm();
break;
case KeymasterDefs.KM_TAG_DIGEST:
- if (keymasterDigest == -1) keymasterDigest = a.keyParameter.integer;
+ if (keymasterDigest == -1) keymasterDigest = a.keyParameter.value.getDigest();
break;
}
}
@@ -407,7 +386,7 @@
keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_EC) {
return makeAndroidKeyStorePublicKeyFromKeyEntryResponse(descriptor, response.metadata,
new KeyStoreSecurityLevel(response.iSecurityLevel),
- keymasterAlgorithm);
+ keymasterAlgorithm).getPrivateKey();
} else {
throw new UnrecoverableKeyException("Key algorithm unknown");
}
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java
index 951f918..6ff9432 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java
@@ -158,7 +158,7 @@
}
/**
- * RSA cipher with OAEP encryption padding. Only SHA-1 based MGF1 is supported as MGF.
+ * RSA cipher with OAEP encryption padding.
*/
abstract static class OAEPWithMGF1Padding extends AndroidKeyStoreRSACipherSpi {
@@ -316,6 +316,25 @@
protected final int getAdditionalEntropyAmountForFinish() {
return (isEncrypting()) ? mDigestOutputSizeBytes : 0;
}
+
+ @Override
+ protected final String getTransform() {
+ switch (mKeymasterDigest) {
+ case KeymasterDefs.KM_DIGEST_SHA1:
+ return "RSA/ECB/OAEPWithSHA-1AndMGF1Padding";
+ case KeymasterDefs.KM_DIGEST_SHA_2_224:
+ return "RSA/ECB/OAEPWithSHA-224AndMGF1Padding";
+ case KeymasterDefs.KM_DIGEST_SHA_2_256:
+ return "RSA/ECB/OAEPWithSHA-256AndMGF1Padding";
+ case KeymasterDefs.KM_DIGEST_SHA_2_384:
+ return "RSA/ECB/OAEPWithSHA-384AndMGF1Padding";
+ case KeymasterDefs.KM_DIGEST_SHA_2_512:
+ return "RSA/ECB/OAEPWithSHA-512AndMGF1Padding";
+ default:
+ return "RSA/ECB/OAEPPadding";
+ }
+ }
+
}
public static class OAEPWithSHA1AndMGF1Padding extends OAEPWithMGF1Padding {
@@ -358,6 +377,11 @@
}
@Override
+ protected String getTransform() {
+ return "RSA/ECB/" + KeyProperties.EncryptionPadding.fromKeymaster(mKeymasterPadding);
+ }
+
+ @Override
protected final void initKey(int opmode, Key key) throws InvalidKeyException {
if (key == null) {
throw new InvalidKeyException("Unsupported key: null");
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreRSASignatureSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreRSASignatureSpi.java
index ab75591..931c2f8 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreRSASignatureSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreRSASignatureSpi.java
@@ -48,42 +48,70 @@
public NONEWithPKCS1Padding() {
super(KeymasterDefs.KM_DIGEST_NONE);
}
+ @Override
+ protected String getAlgorithm() {
+ return "NONEwithRSA";
+ }
}
public static final class MD5WithPKCS1Padding extends PKCS1Padding {
public MD5WithPKCS1Padding() {
super(KeymasterDefs.KM_DIGEST_MD5);
}
+ @Override
+ protected String getAlgorithm() {
+ return "MD5withRSA";
+ }
}
public static final class SHA1WithPKCS1Padding extends PKCS1Padding {
public SHA1WithPKCS1Padding() {
super(KeymasterDefs.KM_DIGEST_SHA1);
}
+ @Override
+ protected String getAlgorithm() {
+ return "SHA1withRSA";
+ }
}
public static final class SHA224WithPKCS1Padding extends PKCS1Padding {
public SHA224WithPKCS1Padding() {
super(KeymasterDefs.KM_DIGEST_SHA_2_224);
}
+ @Override
+ protected String getAlgorithm() {
+ return "SHA224withRSA";
+ }
}
public static final class SHA256WithPKCS1Padding extends PKCS1Padding {
public SHA256WithPKCS1Padding() {
super(KeymasterDefs.KM_DIGEST_SHA_2_256);
}
+ @Override
+ protected String getAlgorithm() {
+ return "SHA256withRSA";
+ }
}
public static final class SHA384WithPKCS1Padding extends PKCS1Padding {
public SHA384WithPKCS1Padding() {
super(KeymasterDefs.KM_DIGEST_SHA_2_384);
}
+ @Override
+ protected String getAlgorithm() {
+ return "SHA384withRSA";
+ }
}
public static final class SHA512WithPKCS1Padding extends PKCS1Padding {
public SHA512WithPKCS1Padding() {
super(KeymasterDefs.KM_DIGEST_SHA_2_512);
}
+ @Override
+ protected String getAlgorithm() {
+ return "SHA512withRSA";
+ }
}
abstract static class PSSPadding extends AndroidKeyStoreRSASignatureSpi {
@@ -103,30 +131,50 @@
public SHA1WithPSSPadding() {
super(KeymasterDefs.KM_DIGEST_SHA1);
}
+ @Override
+ protected String getAlgorithm() {
+ return "SHA1withRSA/PSS";
+ }
}
public static final class SHA224WithPSSPadding extends PSSPadding {
public SHA224WithPSSPadding() {
super(KeymasterDefs.KM_DIGEST_SHA_2_224);
}
+ @Override
+ protected String getAlgorithm() {
+ return "SHA224withRSA/PSS";
+ }
}
public static final class SHA256WithPSSPadding extends PSSPadding {
public SHA256WithPSSPadding() {
super(KeymasterDefs.KM_DIGEST_SHA_2_256);
}
+ @Override
+ protected String getAlgorithm() {
+ return "SHA256withRSA/PSS";
+ }
}
public static final class SHA384WithPSSPadding extends PSSPadding {
public SHA384WithPSSPadding() {
super(KeymasterDefs.KM_DIGEST_SHA_2_384);
}
+ @Override
+ protected String getAlgorithm() {
+ return "SHA384withRSA/PSS";
+ }
}
public static final class SHA512WithPSSPadding extends PSSPadding {
public SHA512WithPSSPadding() {
super(KeymasterDefs.KM_DIGEST_SHA_2_512);
}
+ @Override
+ protected String getAlgorithm() {
+ return "SHA512withRSA/PSS";
+ }
}
private final int mKeymasterDigest;
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java
index 9d3b970..74503e1 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSecretKeyFactorySpi.java
@@ -102,7 +102,8 @@
insideSecureHardware =
KeyStore2ParameterUtils.isSecureHardware(a.securityLevel);
securityLevel = a.securityLevel;
- origin = KeyProperties.Origin.fromKeymaster(a.keyParameter.integer);
+ origin = KeyProperties.Origin.fromKeymaster(
+ a.keyParameter.value.getOrigin());
break;
case KeymasterDefs.KM_TAG_KEY_SIZE:
long keySizeUnsigned = KeyStore2ParameterUtils.getUnsignedInt(a);
@@ -113,45 +114,51 @@
keySize = (int) keySizeUnsigned;
break;
case KeymasterDefs.KM_TAG_PURPOSE:
- purposes |= KeyProperties.Purpose.fromKeymaster(a.keyParameter.integer);
+ purposes |= KeyProperties.Purpose.fromKeymaster(
+ a.keyParameter.value.getKeyPurpose());
break;
case KeymasterDefs.KM_TAG_PADDING:
+ int paddingMode = a.keyParameter.value.getPaddingMode();
try {
- if (a.keyParameter.integer == KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN
- || a.keyParameter.integer == KeymasterDefs.KM_PAD_RSA_PSS) {
+ if (paddingMode == KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN
+ || paddingMode == KeymasterDefs.KM_PAD_RSA_PSS) {
@KeyProperties.SignaturePaddingEnum String padding =
KeyProperties.SignaturePadding.fromKeymaster(
- a.keyParameter.integer);
+ paddingMode);
signaturePaddingsList.add(padding);
} else {
@KeyProperties.EncryptionPaddingEnum String jcaPadding =
KeyProperties.EncryptionPadding.fromKeymaster(
- a.keyParameter.integer);
+ paddingMode);
encryptionPaddingsList.add(jcaPadding);
}
} catch (IllegalArgumentException e) {
throw new ProviderException("Unsupported padding: "
- + a.keyParameter.integer);
+ + paddingMode);
}
break;
case KeymasterDefs.KM_TAG_DIGEST:
- digestsList.add(KeyProperties.Digest.fromKeymaster(a.keyParameter.integer));
+ digestsList.add(KeyProperties.Digest.fromKeymaster(
+ a.keyParameter.value.getDigest()));
break;
case KeymasterDefs.KM_TAG_BLOCK_MODE:
blockModesList.add(
- KeyProperties.BlockMode.fromKeymaster(a.keyParameter.integer)
+ KeyProperties.BlockMode.fromKeymaster(
+ a.keyParameter.value.getBlockMode())
);
break;
case KeymasterDefs.KM_TAG_USER_AUTH_TYPE:
+ int authenticatorType = a.keyParameter.value.getHardwareAuthenticatorType();
if (KeyStore2ParameterUtils.isSecureHardware(a.securityLevel)) {
- keymasterHwEnforcedUserAuthenticators = a.keyParameter.integer;
+ keymasterHwEnforcedUserAuthenticators = authenticatorType;
} else {
- keymasterSwEnforcedUserAuthenticators = a.keyParameter.integer;
+ keymasterSwEnforcedUserAuthenticators = authenticatorType;
}
break;
case KeymasterDefs.KM_TAG_USER_SECURE_ID:
keymasterSecureUserIds.add(
- KeymasterArguments.toUint64(a.keyParameter.longInteger));
+ KeymasterArguments.toUint64(
+ a.keyParameter.value.getLongInteger()));
break;
case KeymasterDefs.KM_TAG_ACTIVE_DATETIME:
keyValidityStart = KeyStore2ParameterUtils.getDate(a);
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSignatureSpiBase.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSignatureSpiBase.java
index 9b4f01e..96da1e0 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreSignatureSpiBase.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSignatureSpiBase.java
@@ -30,10 +30,12 @@
import java.nio.ByteBuffer;
import java.security.InvalidKeyException;
import java.security.InvalidParameterException;
+import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.ProviderException;
import java.security.PublicKey;
import java.security.SecureRandom;
+import java.security.Signature;
import java.security.SignatureException;
import java.security.SignatureSpi;
import java.util.ArrayList;
@@ -76,6 +78,13 @@
*/
private Exception mCachedException;
+ /**
+ * This signature object is used for public key operations, i.e, signatrue verification.
+ * The Android Keystore backend does not perform public key operations and defers to the
+ * Highest priority provider.
+ */
+ private Signature mSignature;
+
AndroidKeyStoreSignatureSpiBase() {
mOperation = null;
mOperationChallenge = 0;
@@ -84,6 +93,7 @@
appRandom = null;
mMessageStreamer = null;
mCachedException = null;
+ mSignature = null;
}
@Override
@@ -123,27 +133,13 @@
protected final void engineInitVerify(PublicKey publicKey) throws InvalidKeyException {
resetAll();
- boolean success = false;
try {
- if (publicKey == null) {
- throw new InvalidKeyException("Unsupported key: null");
- }
- AndroidKeyStoreKey keystoreKey;
- if (publicKey instanceof AndroidKeyStorePublicKey) {
- keystoreKey = (AndroidKeyStorePublicKey) publicKey;
- } else {
- throw new InvalidKeyException("Unsupported public key type: " + publicKey);
- }
- mSigning = false;
- initKey(keystoreKey);
- appRandom = null;
- ensureKeystoreOperationInitialized();
- success = true;
- } finally {
- if (!success) {
- resetAll();
- }
+ mSignature = Signature.getInstance(getAlgorithm());
+ } catch (NoSuchAlgorithmException e) {
+ throw new InvalidKeyException(e);
}
+
+ mSignature.initVerify(publicKey);
}
/**
@@ -251,6 +247,11 @@
@Override
protected final void engineUpdate(byte[] b, int off, int len) throws SignatureException {
+ if (mSignature != null) {
+ mSignature.update(b, off, len);
+ return;
+ }
+
if (mCachedException != null) {
throw new SignatureException(mCachedException);
}
@@ -337,39 +338,10 @@
@Override
protected final boolean engineVerify(byte[] signature) throws SignatureException {
- if (mCachedException != null) {
- throw new SignatureException(mCachedException);
+ if (mSignature != null) {
+ return mSignature.verify(signature);
}
-
- try {
- ensureKeystoreOperationInitialized();
- } catch (InvalidKeyException e) {
- throw new SignatureException(e);
- }
-
- boolean verified;
- try {
- byte[] output = mMessageStreamer.doFinal(
- EmptyArray.BYTE, 0, 0,
- signature);
- if (output.length != 0) {
- throw new ProviderException(
- "Signature verification unexpected produced output: " + output.length
- + " bytes");
- }
- verified = true;
- } catch (KeyStoreException e) {
- switch (e.getErrorCode()) {
- case KeymasterDefs.KM_ERROR_VERIFICATION_FAILED:
- verified = false;
- break;
- default:
- throw new SignatureException(e);
- }
- }
-
- resetWhilePreservingInitState();
- return verified;
+ throw new IllegalStateException("Not initialised.");
}
@Override
@@ -392,6 +364,13 @@
}
/**
+ * Implementations need to report the algorithm they implement so that we can delegate to the
+ * highest priority provider.
+ * @return Algorithm string.
+ */
+ protected abstract String getAlgorithm();
+
+ /**
* Returns {@code true} if this signature is initialized for signing, {@code false} if this
* signature is initialized for verification.
*/
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
index aca5314..5e7f648 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
@@ -219,7 +219,7 @@
return null;
}
- private static X509Certificate toCertificate(byte[] bytes) {
+ static X509Certificate toCertificate(byte[] bytes) {
try {
final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
return (X509Certificate) certFactory.generateCertificate(
@@ -250,13 +250,10 @@
return null;
}
-
- // TODO add modification time to key metadata.
- return null;
- // if (response.metadata.modificationTime == -1) {
- // return null;
- // }
- // return new Date(response.metadata.modificationTime);
+ if (response.metadata.modificationTimeMs == -1) {
+ return null;
+ }
+ return new Date(response.metadata.modificationTimeMs);
}
@Override
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreUnauthenticatedAESCipherSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreUnauthenticatedAESCipherSpi.java
index 4d4b0d8..5c048a1 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreUnauthenticatedAESCipherSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreUnauthenticatedAESCipherSpi.java
@@ -42,7 +42,7 @@
*
* @hide
*/
-class AndroidKeyStoreUnauthenticatedAESCipherSpi extends AndroidKeyStoreCipherSpiBase {
+abstract class AndroidKeyStoreUnauthenticatedAESCipherSpi extends AndroidKeyStoreCipherSpiBase {
abstract static class ECB extends AndroidKeyStoreUnauthenticatedAESCipherSpi {
protected ECB(int keymasterPadding) {
@@ -53,12 +53,22 @@
public NoPadding() {
super(KeymasterDefs.KM_PAD_NONE);
}
+
+ @Override
+ protected final String getTransform() {
+ return "AES/ECB/NoPadding";
+ }
}
public static class PKCS7Padding extends ECB {
public PKCS7Padding() {
super(KeymasterDefs.KM_PAD_PKCS7);
}
+
+ @Override
+ protected final String getTransform() {
+ return "AES/ECB/PKCS7Padding";
+ }
}
}
@@ -71,12 +81,22 @@
public NoPadding() {
super(KeymasterDefs.KM_PAD_NONE);
}
+
+ @Override
+ protected final String getTransform() {
+ return "AES/CBC/NoPadding";
+ }
}
public static class PKCS7Padding extends CBC {
public PKCS7Padding() {
super(KeymasterDefs.KM_PAD_PKCS7);
}
+
+ @Override
+ protected final String getTransform() {
+ return "AES/CBC/PKCS7Padding";
+ }
}
}
@@ -89,6 +109,11 @@
public NoPadding() {
super(KeymasterDefs.KM_PAD_NONE);
}
+
+ @Override
+ protected final String getTransform() {
+ return "AES/CTR/NoPadding";
+ }
}
}
@@ -275,7 +300,7 @@
if (parameters != null) {
for (KeyParameter p : parameters) {
if (p.tag == KeymasterDefs.KM_TAG_NONCE) {
- returnedIv = p.blob;
+ returnedIv = p.value.getBlob();
break;
}
}
diff --git a/keystore/java/android/security/keystore2/KeyStore2ParameterUtils.java b/keystore/java/android/security/keystore2/KeyStore2ParameterUtils.java
index 18c786a..4c8ab8d 100644
--- a/keystore/java/android/security/keystore2/KeyStore2ParameterUtils.java
+++ b/keystore/java/android/security/keystore2/KeyStore2ParameterUtils.java
@@ -19,7 +19,9 @@
import android.annotation.NonNull;
import android.hardware.biometrics.BiometricManager;
import android.hardware.security.keymint.KeyParameter;
+import android.hardware.security.keymint.KeyParameterValue;
import android.hardware.security.keymint.SecurityLevel;
+import android.hardware.security.keymint.Tag;
import android.security.GateKeeper;
import android.security.keymaster.KeymasterDefs;
import android.security.keystore.KeyProperties;
@@ -50,7 +52,7 @@
}
KeyParameter p = new KeyParameter();
p.tag = tag;
- p.boolValue = true;
+ p.value = KeyParameterValue.boolValue(true);
return p;
}
@@ -62,14 +64,40 @@
* @hide
*/
static @NonNull KeyParameter makeEnum(int tag, int v) {
- int type = KeymasterDefs.getTagType(tag);
- if (type != KeymasterDefs.KM_ENUM && type != KeymasterDefs.KM_ENUM_REP) {
- throw new IllegalArgumentException("Not an enum or repeatable enum tag: " + tag);
+ KeyParameter kp = new KeyParameter();
+ kp.tag = tag;
+ switch (tag) {
+ case Tag.PURPOSE:
+ kp.value = KeyParameterValue.keyPurpose(v);
+ break;
+ case Tag.ALGORITHM:
+ kp.value = KeyParameterValue.algorithm(v);
+ break;
+ case Tag.BLOCK_MODE:
+ kp.value = KeyParameterValue.blockMode(v);
+ break;
+ case Tag.DIGEST:
+ kp.value = KeyParameterValue.digest(v);
+ break;
+ case Tag.EC_CURVE:
+ kp.value = KeyParameterValue.ecCurve(v);
+ break;
+ case Tag.ORIGIN:
+ kp.value = KeyParameterValue.origin(v);
+ break;
+ case Tag.PADDING:
+ kp.value = KeyParameterValue.paddingMode(v);
+ break;
+ case Tag.USER_AUTH_TYPE:
+ kp.value = KeyParameterValue.hardwareAuthenticatorType(v);
+ break;
+ case Tag.HARDWARE_TYPE:
+ kp.value = KeyParameterValue.securityLevel(v);
+ break;
+ default:
+ throw new IllegalArgumentException("Not an enum or repeatable enum tag: " + tag);
}
- KeyParameter p = new KeyParameter();
- p.tag = tag;
- p.integer = v;
- return p;
+ return kp;
}
/**
@@ -86,7 +114,7 @@
}
KeyParameter p = new KeyParameter();
p.tag = tag;
- p.integer = v;
+ p.value = KeyParameterValue.integer(v);
return p;
}
@@ -104,7 +132,7 @@
}
KeyParameter p = new KeyParameter();
p.tag = tag;
- p.longInteger = v;
+ p.value = KeyParameterValue.longInteger(v);
return p;
}
@@ -121,7 +149,7 @@
}
KeyParameter p = new KeyParameter();
p.tag = tag;
- p.blob = b;
+ p.value = KeyParameterValue.blob(b);
return p;
}
@@ -138,9 +166,10 @@
}
KeyParameter p = new KeyParameter();
p.tag = tag;
- p.longInteger = date.getTime();
- if (p.longInteger < 0) {
- throw new IllegalArgumentException("Date tag value out of range: " + p.longInteger);
+ p.value = KeyParameterValue.dateTime(date.getTime());
+ if (p.value.getDateTime() < 0) {
+ throw new IllegalArgumentException("Date tag value out of range: "
+ + p.value.getDateTime());
}
return p;
}
@@ -160,24 +189,24 @@
throw new IllegalArgumentException("Not an int tag: " + param.keyParameter.tag);
}
// KM_UINT is 32 bits wide so we must suppress sign extension.
- return ((long) param.keyParameter.integer) & 0xffffffffL;
+ return ((long) param.keyParameter.value.getInteger()) & 0xffffffffL;
}
static @NonNull Date getDate(@NonNull Authorization param) {
if (KeymasterDefs.getTagType(param.keyParameter.tag) != KeymasterDefs.KM_DATE) {
throw new IllegalArgumentException("Not a date tag: " + param.keyParameter.tag);
}
- if (param.keyParameter.longInteger < 0) {
+ if (param.keyParameter.value.getDateTime() < 0) {
throw new IllegalArgumentException("Date Value too large: "
- + param.keyParameter.longInteger);
+ + param.keyParameter.value.getDateTime());
}
- return new Date(param.keyParameter.longInteger);
+ return new Date(param.keyParameter.value.getDateTime());
}
static void forEachSetFlag(int flags, Consumer<Integer> consumer) {
int offset = 0;
while (flags != 0) {
- if ((flags & 1) == 0) {
+ if ((flags & 1) == 1) {
consumer.accept(1 << offset);
}
offset += 1;
diff --git a/keystore/java/android/security/keystore2/KeyStoreCryptoOperationUtils.java b/keystore/java/android/security/keystore2/KeyStoreCryptoOperationUtils.java
index 3b11854..f87a3d2 100644
--- a/keystore/java/android/security/keystore2/KeyStoreCryptoOperationUtils.java
+++ b/keystore/java/android/security/keystore2/KeyStoreCryptoOperationUtils.java
@@ -57,7 +57,7 @@
for (Authorization p : key.getAuthorizations()) {
switch(p.keyParameter.tag) {
case KeymasterDefs.KM_TAG_USER_SECURE_ID:
- keySids.add(p.keyParameter.longInteger);
+ keySids.add(p.keyParameter.value.getLongInteger());
break;
default:
break;
diff --git a/libs/WindowManager/Shell/res/layout/docked_stack_divider.xml b/libs/WindowManager/Shell/res/layout/docked_stack_divider.xml
index ea21eb9..ed5d2e1 100644
--- a/libs/WindowManager/Shell/res/layout/docked_stack_divider.xml
+++ b/libs/WindowManager/Shell/res/layout/docked_stack_divider.xml
@@ -27,9 +27,9 @@
<com.android.wm.shell.legacysplitscreen.MinimizedDockShadow
style="@style/DockedDividerMinimizedShadow"
android:id="@+id/minimized_dock_shadow"
- android:alpha="0"/>">
+ android:alpha="0"/>
- <com.android.wm.shell.legacysplitscreen.DividerHandleView
+ <com.android.wm.shell.common.split.DividerHandleView
style="@style/DockedDividerHandle"
android:id="@+id/docked_divider_handle"
android:contentDescription="@string/accessibility_divider"
diff --git a/libs/WindowManager/Shell/res/layout/split_divider.xml b/libs/WindowManager/Shell/res/layout/split_divider.xml
index 341fe61..7f583f3 100644
--- a/libs/WindowManager/Shell/res/layout/split_divider.xml
+++ b/libs/WindowManager/Shell/res/layout/split_divider.xml
@@ -24,4 +24,10 @@
android:id="@+id/docked_divider_background"
android:background="@color/docked_divider_background"/>
+ <com.android.wm.shell.common.split.DividerHandleView
+ style="@style/DockedDividerHandle"
+ android:id="@+id/docked_divider_handle"
+ android:contentDescription="@string/accessibility_divider"
+ android:background="@null"/>
+
</com.android.wm.shell.common.split.DividerView>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/RootTaskDisplayAreaOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/RootTaskDisplayAreaOrganizer.java
index f741a42..4a8b450 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/RootTaskDisplayAreaOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/RootTaskDisplayAreaOrganizer.java
@@ -18,6 +18,7 @@
import android.util.SparseArray;
import android.view.SurfaceControl;
+import android.window.DisplayAreaAppearedInfo;
import android.window.DisplayAreaInfo;
import android.window.DisplayAreaOrganizer;
@@ -43,7 +44,10 @@
public RootTaskDisplayAreaOrganizer(Executor executor) {
super(executor);
- registerOrganizer(FEATURE_DEFAULT_TASK_CONTAINER);
+ List<DisplayAreaAppearedInfo> infos = registerOrganizer(FEATURE_DEFAULT_TASK_CONTAINER);
+ for (int i = infos.size() - 1; i >= 0; --i) {
+ onDisplayAreaAppeared(infos.get(i).getDisplayAreaInfo(), infos.get(i).getLeash());
+ }
}
public void registerListener(int displayId, RootTaskDisplayAreaListener listener) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index 10cec6d..faa4a0e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -34,6 +34,7 @@
import android.util.SparseArray;
import android.view.SurfaceControl;
import android.window.ITaskOrganizerController;
+import android.window.StartingWindowInfo;
import android.window.TaskAppearedInfo;
import android.window.TaskOrganizer;
@@ -112,7 +113,7 @@
// TODO(b/131727939) temporarily live here, the starting surface drawer should be controlled
// by a controller, that class should be create while porting
// ActivityRecord#addStartingWindow to WMShell.
- mStartingSurfaceDrawer = new StartingSurfaceDrawer(context);
+ mStartingSurfaceDrawer = new StartingSurfaceDrawer(context, mainExecutor);
}
@Override
@@ -229,13 +230,13 @@
}
@Override
- public void addStartingWindow(RunningTaskInfo taskInfo, IBinder appToken) {
- mStartingSurfaceDrawer.addStartingWindow(taskInfo, appToken);
+ public void addStartingWindow(StartingWindowInfo info, IBinder appToken) {
+ mStartingSurfaceDrawer.addStartingWindow(info, appToken);
}
@Override
- public void removeStartingWindow(RunningTaskInfo taskInfo) {
- mStartingSurfaceDrawer.removeStartingWindow(taskInfo);
+ public void removeStartingWindow(int taskId) {
+ mStartingSurfaceDrawer.removeStartingWindow(taskId);
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java
index 7440f19..d588419 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java
@@ -237,7 +237,7 @@
// so go ahead and hide the task entirely
updateTaskVisibility();
}
-
+ mTaskOrganizer.setInterceptBackPressedOnTaskRoot(mTaskToken, true);
// TODO: Synchronize show with the resize
onLocationChanged();
setResizeBackgroundColor(taskInfo.taskDescription.getBackgroundColor());
@@ -257,6 +257,7 @@
if (mListener != null) {
mListener.onTaskRemovalStarted(taskInfo.taskId);
}
+ mTaskOrganizer.setInterceptBackPressedOnTaskRoot(mTaskToken, false);
// Unparent the task when this surface is destroyed
mTransaction.reparent(mTaskLeash, null).apply();
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 9754f51..563de06 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,8 @@
mTaskInfo2 = task2;
mSplitLayout = new SplitLayout(
mDisplayController.getDisplayContext(mRootTaskInfo.displayId),
- mRootTaskInfo.configuration, this, b -> b.setParent(mRootTaskLeash));
+ mRootTaskInfo.configuration, this /* layoutChangeListener */,
+ b -> b.setParent(mRootTaskLeash));
final WindowContainerToken token1 = task1.token;
final WindowContainerToken token2 = task2.token;
@@ -191,22 +192,7 @@
if (mSplitLayout != null
&& mSplitLayout.updateConfiguration(mRootTaskInfo.configuration)) {
- // Update bounds when root bounds or its orientation changed.
- final WindowContainerTransaction wct = new WindowContainerTransaction();
- final SurfaceControl dividerLeash = mSplitLayout.getDividerLeash();
- final Rect dividerBounds = mSplitLayout.getDividerBounds();
- final Rect bounds1 = mSplitLayout.getBounds1();
- final Rect bounds2 = mSplitLayout.getBounds2();
-
- wct.setBounds(mTaskInfo1.token, bounds1)
- .setBounds(mTaskInfo2.token, bounds2);
- mController.getTaskOrganizer().applyTransaction(wct);
- mSyncQueue.runInSync(t -> t
- .setPosition(mTaskLeash1, bounds1.left, bounds1.top)
- .setPosition(mTaskLeash2, bounds2.left, bounds2.top)
- .setPosition(dividerLeash, dividerBounds.left, dividerBounds.top)
- // Resets layer to divider bar to make sure it is always on top.
- .setLayer(dividerLeash, Integer.MAX_VALUE));
+ onBoundsChanged(mSplitLayout);
}
} else if (taskInfo.taskId == getTaskId1()) {
mTaskInfo1 = taskInfo;
@@ -262,6 +248,10 @@
final Rect bounds1 = layout.getBounds1();
final Rect bounds2 = layout.getBounds2();
mSyncQueue.runInSync(t -> t
+ // Ignores the original surface bounds so that the app could fill up the gap
+ // between each surface with corresponding background while resizing.
+ .setWindowCrop(mTaskLeash1, bounds1.width(), bounds1.height())
+ .setWindowCrop(mTaskLeash2, bounds2.width(), bounds2.height())
.setPosition(dividerLeash, dividerBounds.left, dividerBounds.top)
.setPosition(mTaskLeash1, bounds1.left, bounds1.top)
.setPosition(mTaskLeash2, bounds2.left, bounds2.top));
@@ -279,6 +269,10 @@
.setBounds(mTaskInfo2.token, bounds2);
mController.getTaskOrganizer().applyTransaction(wct);
mSyncQueue.runInSync(t -> t
+ // Resets layer of divider bar to make sure it is always on top.
+ .setLayer(dividerLeash, Integer.MAX_VALUE)
+ .setWindowCrop(mTaskLeash1, bounds1.width(), bounds1.height())
+ .setWindowCrop(mTaskLeash2, bounds2.width(), bounds2.height())
.setPosition(dividerLeash, dividerBounds.left, dividerBounds.top)
.setPosition(mTaskLeash1, bounds1.left, bounds1.top)
.setPosition(mTaskLeash2, bounds2.left, bounds2.top));
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
index 4c06a2c..616f24a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
@@ -339,9 +339,6 @@
public void requestAppKeyboardShortcuts(IResultReceiver receiver, int deviceId) {}
@Override
- public void dispatchPointerCaptureChanged(boolean hasCapture) {}
-
- @Override
public void requestScrollCapture(IScrollCaptureCallbacks callbacks) {
try {
callbacks.onUnavailable();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerCallback.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerCallback.java
index 5e07718..00bd9e5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerCallback.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerCallback.java
@@ -16,11 +16,11 @@
package com.android.wm.shell.common;
-import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ITaskStackListener;
import android.content.ComponentName;
import android.os.IBinder;
+import android.window.TaskSnapshot;
import androidx.annotation.BinderThread;
@@ -55,7 +55,7 @@
default void onTaskDescriptionChanged(RunningTaskInfo taskInfo) { }
- default void onTaskSnapshotChanged(int taskId, ActivityManager.TaskSnapshot snapshot) { }
+ default void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) { }
default void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) { }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java
index 7efacc7..718f7a0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/TaskStackListenerImpl.java
@@ -26,6 +26,7 @@
import android.os.Message;
import android.os.Trace;
import android.util.Log;
+import android.window.TaskSnapshot;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.SomeArgs;
@@ -181,7 +182,7 @@
}
@Override
- public void onTaskSnapshotChanged(int taskId, ActivityManager.TaskSnapshot snapshot) {
+ public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) {
mHandler.obtainMessage(ON_TASK_SNAPSHOT_CHANGED, taskId, 0, snapshot).sendToTarget();
}
@@ -283,7 +284,7 @@
Trace.beginSection("onTaskSnapshotChanged");
for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
mTaskStackListeners.get(i).onTaskSnapshotChanged(msg.arg1,
- (ActivityManager.TaskSnapshot) msg.obj);
+ (TaskSnapshot) msg.obj);
}
Trace.endSection();
break;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerHandleView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerHandleView.java
similarity index 91%
rename from libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerHandleView.java
rename to libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerHandleView.java
index 17ca110..218bf47 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerHandleView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerHandleView.java
@@ -14,7 +14,10 @@
* limitations under the License.
*/
-package com.android.wm.shell.legacysplitscreen;
+package com.android.wm.shell.common.split;
+
+import static com.android.wm.shell.common.split.DividerView.TOUCH_ANIMATION_DURATION;
+import static com.android.wm.shell.common.split.DividerView.TOUCH_RELEASE_ANIMATION_DURATION;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -84,7 +87,8 @@
mCircleDiameter = (mWidth + mHeight) / 3;
}
- void setTouching(boolean touching, boolean animate) {
+ /** Sets touching state for this handle view. */
+ public void setTouching(boolean touching, boolean animate) {
if (touching == mTouching) {
return;
}
@@ -116,8 +120,8 @@
mAnimator = new AnimatorSet();
mAnimator.playTogether(widthAnimator, heightAnimator);
mAnimator.setDuration(touching
- ? DividerView.TOUCH_ANIMATION_DURATION
- : DividerView.TOUCH_RELEASE_ANIMATION_DURATION);
+ ? TOUCH_ANIMATION_DURATION
+ : TOUCH_RELEASE_ANIMATION_DURATION);
mAnimator.setInterpolator(touching
? Interpolators.TOUCH_RESPONSE
: Interpolators.FAST_OUT_SLOW_IN);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
index e97fe0a..707747b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
@@ -33,17 +33,23 @@
import androidx.annotation.Nullable;
import com.android.internal.policy.DividerSnapAlgorithm;
+import com.android.wm.shell.R;
+import com.android.wm.shell.animation.Interpolators;
/**
* Stack divider for app pair.
*/
-// TODO(b/172704238): add handle view to indicate touching status.
public class DividerView extends FrameLayout implements View.OnTouchListener {
+ public static final long TOUCH_ANIMATION_DURATION = 150;
+ public static final long TOUCH_RELEASE_ANIMATION_DURATION = 200;
+
private final int mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
private SplitLayout mSplitLayout;
private SurfaceControlViewHost mViewHost;
- private DragListener mDragListener;
+ private DividerHandleView mHandle;
+ private View mBackground;
+ private int mTouchElevation;
private VelocityTracker mVelocityTracker;
private boolean mMoving;
@@ -70,16 +76,18 @@
/** Sets up essential dependencies of the divider bar. */
public void setup(
SplitLayout layout,
- SurfaceControlViewHost viewHost,
- @Nullable DragListener dragListener) {
+ SurfaceControlViewHost viewHost) {
mSplitLayout = layout;
mViewHost = viewHost;
- mDragListener = dragListener;
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
+ mHandle = findViewById(R.id.docked_divider_handle);
+ mBackground = findViewById(R.id.docked_divider_background);
+ mTouchElevation = getResources().getDimensionPixelSize(
+ R.dimen.docked_stack_divider_lift_elevation);
setOnTouchListener(this);
}
@@ -97,7 +105,7 @@
case MotionEvent.ACTION_DOWN:
mVelocityTracker = VelocityTracker.obtain();
mVelocityTracker.addMovement(event);
- setSlippery(false);
+ setTouching();
mStartPos = touchPos;
mMoving = false;
break;
@@ -106,9 +114,6 @@
if (!mMoving && Math.abs(touchPos - mStartPos) > mTouchSlop) {
mStartPos = touchPos;
mMoving = true;
- if (mDragListener != null) {
- mDragListener.onDragStart();
- }
}
if (mMoving) {
final int position = mSplitLayout.getDividePosition() + touchPos - mStartPos;
@@ -122,11 +127,8 @@
final float velocity = isLandscape
? mVelocityTracker.getXVelocity()
: mVelocityTracker.getYVelocity();
- setSlippery(true);
+ releaseTouching();
mMoving = false;
- if (mDragListener != null) {
- mDragListener.onDragEnd();
- }
final int position = mSplitLayout.getDividePosition() + touchPos - mStartPos;
final DividerSnapAlgorithm.SnapTarget snapTarget =
@@ -137,6 +139,45 @@
return true;
}
+ private void setTouching() {
+ setSlippery(false);
+ mHandle.setTouching(true, true);
+ if (isLandscape()) {
+ mBackground.animate().scaleX(1.4f);
+ } else {
+ mBackground.animate().scaleY(1.4f);
+ }
+ mBackground.animate()
+ .setInterpolator(Interpolators.TOUCH_RESPONSE)
+ .setDuration(TOUCH_ANIMATION_DURATION)
+ .translationZ(mTouchElevation)
+ .start();
+ // Lift handle as well so it doesn't get behind the background, even though it doesn't
+ // cast shadow.
+ mHandle.animate()
+ .setInterpolator(Interpolators.TOUCH_RESPONSE)
+ .setDuration(TOUCH_ANIMATION_DURATION)
+ .translationZ(mTouchElevation)
+ .start();
+ }
+
+ private void releaseTouching() {
+ setSlippery(true);
+ mHandle.setTouching(false, true);
+ mBackground.animate()
+ .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+ .setDuration(TOUCH_RELEASE_ANIMATION_DURATION)
+ .translationZ(0)
+ .scaleX(1f)
+ .scaleY(1f)
+ .start();
+ mHandle.animate()
+ .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
+ .setDuration(TOUCH_RELEASE_ANIMATION_DURATION)
+ .translationZ(0)
+ .start();
+ }
+
private void setSlippery(boolean slippery) {
if (mViewHost == null) {
return;
@@ -159,13 +200,4 @@
private boolean isLandscape() {
return getResources().getConfiguration().orientation == ORIENTATION_LANDSCAPE;
}
-
- /** Monitors dragging action of the divider bar. */
- // TODO(b/172704238): add listeners to deal with resizing state of the app windows.
- public interface DragListener {
- /** Called when start dragging. */
- void onDragStart();
- /** Called when stop dragging. */
- void onDragEnd();
- }
}
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 6b9bf2d..291e9bd 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
@@ -156,12 +156,14 @@
void updateDivideBounds(int position) {
updateBounds(position);
mLayoutChangeListener.onBoundsChanging(this);
+ mSplitWindowManager.setResizingSplits(true);
}
void setDividePosition(int position) {
mDividePosition = position;
updateBounds(mDividePosition);
mLayoutChangeListener.onBoundsChanged(this);
+ mSplitWindowManager.setResizingSplits(false);
}
/**
@@ -172,9 +174,11 @@
switch (snapTarget.flag) {
case FLAG_DISMISS_START:
mLayoutChangeListener.onSnappedToDismiss(false /* snappedToEnd */);
+ mSplitWindowManager.setResizingSplits(false);
break;
case FLAG_DISMISS_END:
mLayoutChangeListener.onSnappedToDismiss(true /* snappedToEnd */);
+ mSplitWindowManager.setResizingSplits(false);
break;
default:
flingDividePosition(currentPosition, snapTarget.position);
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 238caef..29116bd 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
@@ -25,6 +25,7 @@
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
+import android.app.ActivityTaskManager;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
@@ -32,6 +33,8 @@
import android.graphics.Region;
import android.os.Binder;
import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Slog;
import android.view.IWindow;
import android.view.LayoutInflater;
import android.view.SurfaceControl;
@@ -47,11 +50,13 @@
* Holds view hierarchy of a root surface and helps to inflate {@link DividerView} for a split.
*/
public final class SplitWindowManager extends WindowlessWindowManager {
+ private static final String TAG = SplitWindowManager.class.getSimpleName();
private static final String DIVIDER_WINDOW_TITLE = "SplitDivider";
+ private final ParentContainerCallbacks mParentContainerCallbacks;
private Context mContext;
private SurfaceControlViewHost mViewHost;
- final private ParentContainerCallbacks mParentContainerCallbacks;
+ private boolean mResizingSplits;
public interface ParentContainerCallbacks {
void attachToParentSurface(SurfaceControl.Builder b);
@@ -104,7 +109,7 @@
lp.setTitle(DIVIDER_WINDOW_TITLE);
lp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION | PRIVATE_FLAG_TRUSTED_OVERLAY;
mViewHost.setView(dividerView, lp);
- dividerView.setup(splitLayout, mViewHost, null /* dragListener */);
+ dividerView.setup(splitLayout, mViewHost);
}
/**
@@ -117,6 +122,16 @@
mViewHost = null;
}
+ void setResizingSplits(boolean resizing) {
+ if (resizing == mResizingSplits) return;
+ try {
+ ActivityTaskManager.getService().setSplitScreenResizing(resizing);
+ mResizingSplits = resizing;
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Error calling setSplitScreenResizing", e);
+ }
+ }
+
/**
* Gets {@link SurfaceControl} of the surface holding divider view. @return {@code null} if not
* feasible.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java
index 16c966f..c1b6c4f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java
@@ -20,6 +20,9 @@
import static android.view.PointerIcon.TYPE_VERTICAL_DOUBLE_ARROW;
import static android.view.WindowManager.DOCKED_RIGHT;
+import static com.android.wm.shell.common.split.DividerView.TOUCH_ANIMATION_DURATION;
+import static com.android.wm.shell.common.split.DividerView.TOUCH_RELEASE_ANIMATION_DURATION;
+
import android.animation.AnimationHandler;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -66,6 +69,7 @@
import com.android.wm.shell.R;
import com.android.wm.shell.animation.FlingAnimationUtils;
import com.android.wm.shell.animation.Interpolators;
+import com.android.wm.shell.common.split.DividerHandleView;
import java.util.function.Consumer;
@@ -82,9 +86,6 @@
void onDraggingEnd();
}
- static final long TOUCH_ANIMATION_DURATION = 150;
- static final long TOUCH_RELEASE_ANIMATION_DURATION = 200;
-
public static final int INVALID_RECENTS_GROW_TARGET = -1;
private static final int LOG_VALUE_RESIZE_50_50 = 0;
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 d5db0cc..69d8db2 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
@@ -32,6 +32,7 @@
import android.os.SystemProperties;
import android.provider.Settings;
import android.util.Slog;
+import android.view.accessibility.AccessibilityManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -75,6 +76,7 @@
private final Handler mMainHandler = new Handler(Looper.getMainLooper());
private OneHandedDisplayAreaOrganizer mDisplayAreaOrganizer;
+ private final AccessibilityManager mAccessibilityManager;
/**
* Handle rotation based on OnDisplayChangingListener callback
@@ -164,6 +166,26 @@
}
};
+ private AccessibilityManager.AccessibilityStateChangeListener
+ mAccessibilityStateChangeListener =
+ new AccessibilityManager.AccessibilityStateChangeListener() {
+ @Override
+ public void onAccessibilityStateChanged(boolean enabled) {
+ if (enabled) {
+ final int mOneHandedTimeout = OneHandedSettingsUtil
+ .getSettingsOneHandedModeTimeout(mContext.getContentResolver());
+ final int timeout = mAccessibilityManager
+ .getRecommendedTimeoutMillis(mOneHandedTimeout * 1000
+ /* align with A11y timeout millis */,
+ AccessibilityManager.FLAG_CONTENT_CONTROLS);
+ mTimeoutHandler.setTimeout(timeout / 1000);
+ } else {
+ mTimeoutHandler.setTimeout(OneHandedSettingsUtil
+ .getSettingsOneHandedModeTimeout(mContext.getContentResolver()));
+ }
+ }
+ };
+
/**
* Creates {@link OneHandedController}, returns {@code null} if the feature is not supported.
*/
@@ -239,6 +261,11 @@
stopOneHanded(OneHandedEvents.EVENT_ONE_HANDED_TRIGGER_APP_TAPS_OUT);
}
});
+
+ mAccessibilityManager = (AccessibilityManager)
+ context.getSystemService(Context.ACCESSIBILITY_SERVICE);
+ mAccessibilityManager.addAccessibilityStateChangeListener(
+ mAccessibilityStateChangeListener);
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java
index 4d66f29..f8217c6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java
@@ -126,7 +126,7 @@
*/
public static boolean getSettingsSwipeToNotificationEnabled(ContentResolver resolver) {
return Settings.Secure.getInt(resolver,
- Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, 0) == 1;
+ Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, 1) == 1;
}
protected static void dump(PrintWriter pw, String prefix, ContentResolver resolver) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
index fe01811..3362d2a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
@@ -22,6 +22,7 @@
import android.animation.ValueAnimator;
import android.annotation.IntDef;
import android.graphics.Rect;
+import android.view.Choreographer;
import android.view.SurfaceControl;
import com.android.internal.annotations.VisibleForTesting;
@@ -327,8 +328,14 @@
mEndValue = endValue;
}
- SurfaceControl.Transaction newSurfaceControlTransaction() {
- return mSurfaceControlTransactionFactory.getTransaction();
+ /**
+ * @return {@link SurfaceControl.Transaction} instance with vsync-id.
+ */
+ protected SurfaceControl.Transaction newSurfaceControlTransaction() {
+ final SurfaceControl.Transaction tx =
+ mSurfaceControlTransactionFactory.getTransaction();
+ tx.setFrameTimelineVsync(Choreographer.getSfInstance().getVsyncId());
+ return tx;
}
@VisibleForTesting
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java
index 484592e..f839727 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsAlgorithm.java
@@ -129,10 +129,9 @@
: getDefaultBounds();
final boolean useCurrentSize = reentryState != null && reentryState.getSize() != null;
- final Rect r = transformBoundsToAspectRatioIfValid(destinationBounds,
+ return transformBoundsToAspectRatioIfValid(destinationBounds,
mPipBoundsState.getAspectRatio(), false /* useCurrentMinEdgeSize */,
useCurrentSize);
- return r;
}
/** Returns the current bounds adjusted to the new aspect ratio, if valid. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
index 4493d38..d0d9b26 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
@@ -26,6 +26,7 @@
import android.view.DisplayInfo;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.function.TriConsumer;
import com.android.wm.shell.R;
import com.android.wm.shell.common.DisplayLayout;
@@ -33,7 +34,6 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
-import java.util.function.BiConsumer;
/**
* Singleton source of truth for the current state of PIP bounds.
@@ -80,7 +80,7 @@
private boolean mHasUserResizedPip;
private @Nullable Runnable mOnMinimalSizeChangeCallback;
- private @Nullable BiConsumer<Boolean, Integer> mOnShelfVisibilityChangeCallback;
+ private @Nullable TriConsumer<Boolean, Integer, Boolean> mOnShelfVisibilityChangeCallback;
public PipBoundsState(@NonNull Context context) {
mContext = context;
@@ -310,6 +310,11 @@
/** Set whether the shelf is showing and its height. */
public void setShelfVisibility(boolean showing, int height) {
+ setShelfVisibility(showing, height, true);
+ }
+
+ /** Set whether the shelf is showing and its height. */
+ public void setShelfVisibility(boolean showing, int height, boolean updateMovementBounds) {
final boolean shelfShowing = showing && height > 0;
if (shelfShowing == mIsShelfShowing && height == mShelfHeight) {
return;
@@ -318,7 +323,8 @@
mIsShelfShowing = showing;
mShelfHeight = height;
if (mOnShelfVisibilityChangeCallback != null) {
- mOnShelfVisibilityChangeCallback.accept(mIsShelfShowing, mShelfHeight);
+ mOnShelfVisibilityChangeCallback.accept(mIsShelfShowing, mShelfHeight,
+ updateMovementBounds);
}
}
@@ -351,7 +357,7 @@
/** Set a callback to be notified when the shelf visibility changes. */
public void setOnShelfVisibilityChangeCallback(
- @Nullable BiConsumer<Boolean, Integer> onShelfVisibilityChangeCallback) {
+ @Nullable TriConsumer<Boolean, Integer, Boolean> onShelfVisibilityChangeCallback) {
mOnShelfVisibilityChangeCallback = onShelfVisibilityChangeCallback;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
index 4d27602..fa88084 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
@@ -114,14 +114,14 @@
// the bounds for the next orientation using the destination bounds of the animation
// TODO: Technically this should account for movement animation bounds as well
Rect currentBounds = mPipTaskOrganizer.getCurrentOrAnimatingBounds();
- final boolean changed = onDisplayRotationChanged(mContext,
- mPipBoundsState.getNormalBounds(), currentBounds, mTmpInsetBounds, displayId,
- fromRotation, toRotation, t);
+ final Rect outBounds = new Rect();
+ final boolean changed = onDisplayRotationChanged(mContext, outBounds, currentBounds,
+ mTmpInsetBounds, displayId, fromRotation, toRotation, t);
if (changed) {
// If the pip was in the offset zone earlier, adjust the new bounds to the bottom of the
// movement bounds
- mTouchHandler.adjustBoundsForRotation(mPipBoundsState.getNormalBounds(),
- mPipBoundsState.getBounds(), mTmpInsetBounds);
+ mTouchHandler.adjustBoundsForRotation(outBounds, mPipBoundsState.getBounds(),
+ mTmpInsetBounds);
// The bounds are being applied to a specific snap fraction, so reset any known offsets
// for the previous orientation before updating the movement bounds.
@@ -129,14 +129,18 @@
// not during the fixed rotation. In fixed rotation case, app is about to enter PiP
// and we need the offsets preserved to calculate the destination bounds.
if (!mIsInFixedRotation) {
- mPipBoundsState.setShelfVisibility(false /* showing */, 0 /* height */);
+ // Update the shelf visibility without updating the movement bounds. We're already
+ // updating them below with the |fromRotation| flag set, which is more accurate
+ // than using the |fromShelfAdjustment|.
+ mPipBoundsState.setShelfVisibility(false /* showing */, 0 /* height */,
+ false /* updateMovementBounds */);
mPipBoundsState.setImeVisibility(false /* showing */, 0 /* height */);
mTouchHandler.onShelfVisibilityChanged(false, 0);
mTouchHandler.onImeVisibilityChanged(false, 0);
}
- updateMovementBounds(mPipBoundsState.getNormalBounds(), true /* fromRotation */,
- false /* fromImeAdjustment */, false /* fromShelfAdjustment */, t);
+ updateMovementBounds(outBounds, true /* fromRotation */, false /* fromImeAdjustment */,
+ false /* fromShelfAdjustment */, t);
}
};
@@ -248,12 +252,16 @@
false /* fromImeAdjustment */, false /* fromShelfAdjustment */,
null /* wct */);
});
- mPipBoundsState.setOnShelfVisibilityChangeCallback((isShowing, height) -> {
- mTouchHandler.onShelfVisibilityChanged(isShowing, height);
- updateMovementBounds(mPipBoundsState.getBounds(),
- false /* fromRotation */, false /* fromImeAdjustment */,
- true /* fromShelfAdjustment */, null /* windowContainerTransaction */);
- });
+ mPipBoundsState.setOnShelfVisibilityChangeCallback(
+ (isShowing, height, updateMovementBounds) -> {
+ mTouchHandler.onShelfVisibilityChanged(isShowing, height);
+ if (updateMovementBounds) {
+ updateMovementBounds(mPipBoundsState.getBounds(),
+ false /* fromRotation */, false /* fromImeAdjustment */,
+ true /* fromShelfAdjustment */,
+ null /* windowContainerTransaction */);
+ }
+ });
if (mTouchHandler != null) {
// Register the listener for input consumer touch events. Only for Phone
mPipInputConsumer.setInputListener(mTouchHandler::handleTouchEvent);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
index ee79824..e144ca3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
@@ -16,11 +16,18 @@
package com.android.wm.shell.startingsurface;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.content.Context.CONTEXT_RESTRICTED;
import static android.content.res.Configuration.EMPTY;
import static android.view.Display.DEFAULT_DISPLAY;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_CREATED;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_NEW_TASK;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_PROCESS_RUNNING;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_TASK_SWITCH;
-import android.app.ActivityManager;
+import android.app.ActivityManager.RunningTaskInfo;
+import android.app.ActivityTaskManager;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
@@ -30,18 +37,20 @@
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.hardware.display.DisplayManager;
-import android.os.Handler;
import android.os.IBinder;
-import android.os.Looper;
+import android.os.RemoteException;
import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;
+import android.window.StartingWindowInfo;
import android.window.TaskOrganizer;
+import android.window.TaskSnapshot;
import com.android.internal.R;
import com.android.internal.policy.PhoneWindow;
+import com.android.wm.shell.common.ShellExecutor;
import java.util.function.Consumer;
@@ -56,22 +65,24 @@
* @hide
*/
public class StartingSurfaceDrawer {
- private static final String TAG = StartingSurfaceDrawer.class.getSimpleName();
- private static final boolean DEBUG_SPLASH_SCREEN = false;
+ static final String TAG = StartingSurfaceDrawer.class.getSimpleName();
+ static final boolean DEBUG_SPLASH_SCREEN = false;
+ static final boolean DEBUG_TASK_SNAPSHOT = false;
private final Context mContext;
private final DisplayManager mDisplayManager;
+ final ShellExecutor mMainExecutor;
// TODO(b/131727939) remove this when clearing ActivityRecord
private static final int REMOVE_WHEN_TIMEOUT = 2000;
- public StartingSurfaceDrawer(Context context) {
+ public StartingSurfaceDrawer(Context context, ShellExecutor mainExecutor) {
mContext = context;
mDisplayManager = mContext.getSystemService(DisplayManager.class);
+ mMainExecutor = mainExecutor;
}
- private final Handler mHandler = new Handler(Looper.getMainLooper());
- private final SparseArray<TaskScreenView> mTaskScreenViews = new SparseArray<>();
+ private final SparseArray<StartingWindowRecord> mStartingWindowRecords = new SparseArray<>();
/** Obtain proper context for showing splash screen on the provided display. */
private Context getDisplayContext(Context context, int displayId) {
@@ -90,12 +101,111 @@
return context.createDisplayContext(targetDisplay);
}
+ private static class PreferredStartingTypeHelper {
+ private static final int STARTING_TYPE_NO = 0;
+ private static final int STARTING_TYPE_SPLASH_SCREEN = 1;
+ private static final int STARTING_TYPE_SNAPSHOT = 2;
+
+ TaskSnapshot mSnapshot;
+ int mPreferredType;
+
+ PreferredStartingTypeHelper(StartingWindowInfo taskInfo) {
+ final int parameter = taskInfo.startingWindowTypeParameter;
+ final boolean newTask = (parameter & TYPE_PARAMETER_NEW_TASK) != 0;
+ final boolean taskSwitch = (parameter & TYPE_PARAMETER_TASK_SWITCH) != 0;
+ final boolean processRunning = (parameter & TYPE_PARAMETER_PROCESS_RUNNING) != 0;
+ final boolean allowTaskSnapshot = (parameter & TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT) != 0;
+ final boolean activityCreated = (parameter & TYPE_PARAMETER_ACTIVITY_CREATED) != 0;
+ mPreferredType = preferredStartingWindowType(taskInfo, newTask, taskSwitch,
+ processRunning, allowTaskSnapshot, activityCreated);
+ }
+
+ // reference from ActivityRecord#getStartingWindowType
+ private int preferredStartingWindowType(StartingWindowInfo windowInfo,
+ boolean newTask, boolean taskSwitch, boolean processRunning,
+ boolean allowTaskSnapshot, boolean activityCreated) {
+ if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
+ Slog.d(TAG, "preferredStartingWindowType newTask " + newTask
+ + " taskSwitch " + taskSwitch
+ + " processRunning " + processRunning
+ + " allowTaskSnapshot " + allowTaskSnapshot
+ + " activityCreated " + activityCreated);
+ }
+
+ if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
+ return STARTING_TYPE_SPLASH_SCREEN;
+ } else if (taskSwitch && allowTaskSnapshot) {
+ final TaskSnapshot snapshot = getTaskSnapshot(windowInfo.taskInfo.taskId);
+ if (isSnapshotCompatible(windowInfo, snapshot)) {
+ return STARTING_TYPE_SNAPSHOT;
+ }
+ if (windowInfo.taskInfo.topActivityType != ACTIVITY_TYPE_HOME) {
+ return STARTING_TYPE_SPLASH_SCREEN;
+ }
+ return STARTING_TYPE_NO;
+ } else {
+ return STARTING_TYPE_NO;
+ }
+ }
+
+ /**
+ * Returns {@code true} if the task snapshot is compatible with this activity (at least the
+ * rotation must be the same).
+ */
+ private boolean isSnapshotCompatible(StartingWindowInfo windowInfo, TaskSnapshot snapshot) {
+ if (snapshot == null) {
+ if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
+ Slog.d(TAG, "isSnapshotCompatible no snapshot " + windowInfo.taskInfo.taskId);
+ }
+ return false;
+ }
+
+ final int taskRotation = windowInfo.taskInfo.configuration
+ .windowConfiguration.getRotation();
+ final int snapshotRotation = snapshot.getRotation();
+ if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
+ Slog.d(TAG, "isSnapshotCompatible rotation " + taskRotation
+ + " snapshot " + snapshotRotation);
+ }
+ return taskRotation == snapshotRotation;
+ }
+
+ private TaskSnapshot getTaskSnapshot(int taskId) {
+ if (mSnapshot != null) {
+ return mSnapshot;
+ }
+ try {
+ mSnapshot = ActivityTaskManager.getService().getTaskSnapshot(taskId,
+ false/* isLowResolution */);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to get snapshot for task: " + taskId + ", from: " + e);
+ return null;
+ }
+ return mSnapshot;
+ }
+ }
+
/**
* Called when a task need a starting window.
*/
- public void addStartingWindow(ActivityManager.RunningTaskInfo taskInfo, IBinder appToken) {
+ public void addStartingWindow(StartingWindowInfo windowInfo, IBinder appToken) {
+ final PreferredStartingTypeHelper helper =
+ new PreferredStartingTypeHelper(windowInfo);
+ final RunningTaskInfo runningTaskInfo = windowInfo.taskInfo;
+ if (helper.mPreferredType == PreferredStartingTypeHelper.STARTING_TYPE_SPLASH_SCREEN) {
+ addSplashScreenStartingWindow(runningTaskInfo, appToken);
+ } else if (helper.mPreferredType == PreferredStartingTypeHelper.STARTING_TYPE_SNAPSHOT) {
+ final TaskSnapshot snapshot = helper.mSnapshot;
+ makeTaskSnapshotWindow(windowInfo, appToken, snapshot);
+ }
+ // If prefer don't show, then don't show!
+ }
+ private void addSplashScreenStartingWindow(RunningTaskInfo taskInfo, IBinder appToken) {
final ActivityInfo activityInfo = taskInfo.topActivityInfo;
+ if (activityInfo == null) {
+ return;
+ }
final int displayId = taskInfo.displayId;
if (activityInfo.packageName == null) {
return;
@@ -250,18 +360,34 @@
}
/**
+ * Called when a task need a snapshot starting window.
+ */
+ private void makeTaskSnapshotWindow(StartingWindowInfo startingWindowInfo,
+ IBinder appToken, TaskSnapshot snapshot) {
+ final int taskId = startingWindowInfo.taskInfo.taskId;
+ final TaskSnapshotWindow surface = TaskSnapshotWindow.create(startingWindowInfo, appToken,
+ snapshot, mMainExecutor, () -> removeWindowSynced(taskId) /* clearWindow */);
+ mMainExecutor.execute(() -> {
+ mMainExecutor.executeDelayed(() -> removeWindowSynced(taskId), REMOVE_WHEN_TIMEOUT);
+ final StartingWindowRecord tView =
+ new StartingWindowRecord(null/* decorView */, surface);
+ mStartingWindowRecords.put(taskId, tView);
+ });
+ }
+
+ /**
* Called when the content of a task is ready to show, starting window can be removed.
*/
- public void removeStartingWindow(ActivityManager.RunningTaskInfo taskInfo) {
- if (DEBUG_SPLASH_SCREEN) {
- Slog.d(TAG, "Task start finish, remove starting surface for task " + taskInfo.taskId);
+ public void removeStartingWindow(int taskId) {
+ if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
+ Slog.d(TAG, "Task start finish, remove starting surface for task " + taskId);
}
- mHandler.post(() -> removeWindowSynced(taskInfo.taskId));
+ mMainExecutor.execute(() -> removeWindowSynced(taskId));
}
protected void postAddWindow(int taskId, IBinder appToken,
View view, WindowManager wm, WindowManager.LayoutParams params) {
- mHandler.post(() -> {
+ mMainExecutor.execute(() -> {
boolean shouldSaveView = true;
try {
wm.addView(view, params);
@@ -286,25 +412,32 @@
if (shouldSaveView) {
removeWindowSynced(taskId);
- mHandler.postDelayed(() -> removeWindowSynced(taskId), REMOVE_WHEN_TIMEOUT);
- final TaskScreenView tView = new TaskScreenView(view);
- mTaskScreenViews.put(taskId, tView);
+ mMainExecutor.executeDelayed(() -> removeWindowSynced(taskId), REMOVE_WHEN_TIMEOUT);
+ final StartingWindowRecord tView =
+ new StartingWindowRecord(view, null /* TaskSnapshotWindow */);
+ mStartingWindowRecords.put(taskId, tView);
}
});
}
protected void removeWindowSynced(int taskId) {
- final TaskScreenView preView = mTaskScreenViews.get(taskId);
- if (preView != null) {
- if (preView.mDecorView != null) {
+ final StartingWindowRecord record = mStartingWindowRecords.get(taskId);
+ if (record != null) {
+ if (record.mDecorView != null) {
if (DEBUG_SPLASH_SCREEN) {
Slog.v(TAG, "Removing splash screen window for task: " + taskId);
}
- final WindowManager wm = preView.mDecorView.getContext()
+ final WindowManager wm = record.mDecorView.getContext()
.getSystemService(WindowManager.class);
- wm.removeView(preView.mDecorView);
+ wm.removeView(record.mDecorView);
}
- mTaskScreenViews.remove(taskId);
+ if (record.mTaskSnapshotWindow != null) {
+ if (DEBUG_TASK_SNAPSHOT) {
+ Slog.v(TAG, "Removing task snapshot window for " + taskId);
+ }
+ record.mTaskSnapshotWindow.remove(mMainExecutor);
+ }
+ mStartingWindowRecords.remove(taskId);
}
}
@@ -315,13 +448,15 @@
}
/**
- * Record the views in a starting window.
+ * Record the view or surface for a starting window.
*/
- private static class TaskScreenView {
+ private static class StartingWindowRecord {
private final View mDecorView;
+ private final TaskSnapshotWindow mTaskSnapshotWindow;
- TaskScreenView(View decorView) {
+ StartingWindowRecord(View decorView, TaskSnapshotWindow taskSnapshotWindow) {
mDecorView = decorView;
+ mTaskSnapshotWindow = taskSnapshotWindow;
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
new file mode 100644
index 0000000..e66d85f
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
@@ -0,0 +1,622 @@
+/*
+ * 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.startingsurface;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.graphics.Color.WHITE;
+import static android.graphics.Color.alpha;
+import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
+import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
+import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+import static android.view.WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES;
+import static android.view.WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
+import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
+import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY;
+import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
+import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
+import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
+import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+
+import static com.android.internal.policy.DecorView.NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES;
+import static com.android.internal.policy.DecorView.STATUS_BAR_COLOR_VIEW_ATTRIBUTES;
+import static com.android.internal.policy.DecorView.getNavigationBarRect;
+
+import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.ActivityManager.TaskDescription;
+import android.app.ActivityThread;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.hardware.HardwareBuffer;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.util.MergedConfiguration;
+import android.util.Slog;
+import android.view.IWindowSession;
+import android.view.InputChannel;
+import android.view.InsetsSourceControl;
+import android.view.InsetsState;
+import android.view.Surface;
+import android.view.SurfaceControl;
+import android.view.SurfaceSession;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowInsets;
+import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
+import android.window.ClientWindowFrames;
+import android.window.StartingWindowInfo;
+import android.window.TaskSnapshot;
+
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.policy.DecorView;
+import com.android.internal.view.BaseIWindow;
+import com.android.wm.shell.common.ShellExecutor;
+
+/**
+ * This class represents a starting window that shows a snapshot.
+ *
+ * @hide
+ */
+public class TaskSnapshotWindow {
+
+ private static final long SIZE_MISMATCH_MINIMUM_TIME_MS = 450;
+
+ /**
+ * When creating the starting window, we use the exact same layout flags such that we end up
+ * with a window with the exact same dimensions etc. However, these flags are not used in layout
+ * and might cause other side effects so we exclude them.
+ */
+ static final int FLAG_INHERIT_EXCLUDES = FLAG_NOT_FOCUSABLE
+ | FLAG_NOT_TOUCHABLE
+ | FLAG_NOT_TOUCH_MODAL
+ | FLAG_ALT_FOCUSABLE_IM
+ | FLAG_NOT_FOCUSABLE
+ | FLAG_HARDWARE_ACCELERATED
+ | FLAG_IGNORE_CHEEK_PRESSES
+ | FLAG_LOCAL_FOCUS_MODE
+ | FLAG_SLIPPERY
+ | FLAG_WATCH_OUTSIDE_TOUCH
+ | FLAG_SPLIT_TOUCH
+ | FLAG_SCALED
+ | FLAG_SECURE;
+
+ private static final String TAG = StartingSurfaceDrawer.TAG;
+ private static final boolean DEBUG = StartingSurfaceDrawer.DEBUG_TASK_SNAPSHOT;
+ private static final String TITLE_FORMAT = "SnapshotStartingWindow for taskId=%s";
+
+ //tmp vars for unused relayout params
+ private static final Point TMP_SURFACE_SIZE = new Point();
+
+ private final Window mWindow;
+ private final Surface mSurface;
+ private final Runnable mClearWindowHandler;
+ private SurfaceControl mSurfaceControl;
+ private SurfaceControl mChildSurfaceControl;
+ private final IWindowSession mSession;
+ private final Rect mTaskBounds;
+ private final Rect mFrame = new Rect();
+ private final Rect mSystemBarInsets = new Rect();
+ private TaskSnapshot mSnapshot;
+ private final RectF mTmpSnapshotSize = new RectF();
+ private final RectF mTmpDstFrame = new RectF();
+ private final CharSequence mTitle;
+ private boolean mHasDrawn;
+ private long mShownTime;
+ private boolean mSizeMismatch;
+ private final Paint mBackgroundPaint = new Paint();
+ private final int mActivityType;
+ private final int mStatusBarColor;
+ private final SystemBarBackgroundPainter mSystemBarBackgroundPainter;
+ private final int mOrientationOnCreation;
+ private final SurfaceControl.Transaction mTransaction;
+ private final Matrix mSnapshotMatrix = new Matrix();
+ private final float[] mTmpFloat9 = new float[9];
+
+ static TaskSnapshotWindow create(StartingWindowInfo info, IBinder appToken,
+ TaskSnapshot snapshot, ShellExecutor mainExecutor, Runnable clearWindowHandler) {
+ final ActivityManager.RunningTaskInfo runningTaskInfo = info.taskInfo;
+ final int taskId = runningTaskInfo.taskId;
+ if (DEBUG) {
+ Slog.d(TAG, "create taskSnapshot surface for task: " + taskId);
+ }
+
+ final WindowManager.LayoutParams attrs = info.topOpaqueWindowLayoutParams;
+ final WindowManager.LayoutParams mainWindowParams = info.mainWindowLayoutParams;
+ final InsetsState topWindowInsetsState = info.topOpaqueWindowInsetsState;
+ if (attrs == null || mainWindowParams == null || topWindowInsetsState == null) {
+ Slog.w(TAG, "unable to create taskSnapshot surface for task: " + taskId);
+ return null;
+ }
+ final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
+
+ final int appearance = attrs.insetsFlags.appearance;
+ final int windowFlags = attrs.flags;
+ final int windowPrivateFlags = attrs.privateFlags;
+
+ layoutParams.packageName = mainWindowParams.packageName;
+ layoutParams.windowAnimations = mainWindowParams.windowAnimations;
+ layoutParams.dimAmount = mainWindowParams.dimAmount;
+ layoutParams.type = TYPE_APPLICATION_STARTING;
+ layoutParams.format = snapshot.getHardwareBuffer().getFormat();
+ layoutParams.flags = (windowFlags & ~FLAG_INHERIT_EXCLUDES)
+ | FLAG_NOT_FOCUSABLE
+ | FLAG_NOT_TOUCHABLE;
+ // Setting as trusted overlay to let touches pass through. This is safe because this
+ // window is controlled by the system.
+ layoutParams.privateFlags = (windowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS)
+ | PRIVATE_FLAG_TRUSTED_OVERLAY;
+ layoutParams.token = appToken;
+ layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
+ layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
+ layoutParams.insetsFlags.appearance = appearance;
+ layoutParams.insetsFlags.behavior = attrs.insetsFlags.behavior;
+ layoutParams.layoutInDisplayCutoutMode = attrs.layoutInDisplayCutoutMode;
+ layoutParams.setFitInsetsTypes(attrs.getFitInsetsTypes());
+ layoutParams.setFitInsetsSides(attrs.getFitInsetsSides());
+ layoutParams.setFitInsetsIgnoringVisibility(attrs.isFitInsetsIgnoringVisibility());
+
+ layoutParams.setTitle(String.format(TITLE_FORMAT, taskId));
+
+ final Point taskSize = snapshot.getTaskSize();
+ final Rect taskBounds = new Rect(0, 0, taskSize.x, taskSize.y);
+ final int orientation = snapshot.getOrientation();
+
+ final int activityType = runningTaskInfo.topActivityType;
+ final int displayId = runningTaskInfo.displayId;
+
+ final IWindowSession session = WindowManagerGlobal.getWindowSession();
+ final SurfaceControl surfaceControl = new SurfaceControl();
+ final ClientWindowFrames tmpFrames = new ClientWindowFrames();
+
+ final InsetsSourceControl[] mTempControls = new InsetsSourceControl[0];
+ final MergedConfiguration tmpMergedConfiguration = new MergedConfiguration();
+
+ final TaskDescription taskDescription;
+ if (runningTaskInfo.taskDescription != null) {
+ taskDescription = runningTaskInfo.taskDescription;
+ } else {
+ taskDescription = new TaskDescription();
+ taskDescription.setBackgroundColor(WHITE);
+ }
+
+ final TaskSnapshotWindow snapshotSurface = new TaskSnapshotWindow(
+ surfaceControl, snapshot, layoutParams.getTitle(), taskDescription, appearance,
+ windowFlags, windowPrivateFlags, taskBounds, orientation, activityType,
+ topWindowInsetsState, clearWindowHandler);
+ final Window window = snapshotSurface.mWindow;
+
+ final InsetsState mTmpInsetsState = new InsetsState();
+ final InputChannel tmpInputChannel = new InputChannel();
+ mainExecutor.execute(() -> {
+ try {
+ final int res = session.addToDisplay(window, layoutParams, View.GONE,
+ displayId, mTmpInsetsState, tmpFrames.frame,
+ tmpFrames.displayCutout, tmpInputChannel/* outInputChannel */,
+ mTmpInsetsState, mTempControls);
+ if (res < 0) {
+ Slog.w(TAG, "Failed to add snapshot starting window res=" + res);
+ return;
+ }
+ } catch (RemoteException e) {
+ snapshotSurface.clearWindowSynced();
+ }
+ window.setOuter(snapshotSurface, mainExecutor);
+ try {
+ session.relayout(window, layoutParams, -1, -1, View.VISIBLE, 0, -1,
+ tmpFrames, tmpMergedConfiguration, surfaceControl, mTmpInsetsState,
+ mTempControls, TMP_SURFACE_SIZE);
+ } catch (RemoteException e) {
+ snapshotSurface.clearWindowSynced();
+ }
+
+ final Rect systemBarInsets = getSystemBarInsets(tmpFrames.frame, topWindowInsetsState);
+ snapshotSurface.setFrames(tmpFrames.frame, systemBarInsets);
+ snapshotSurface.drawSnapshot();
+ });
+ return snapshotSurface;
+ }
+
+ public TaskSnapshotWindow(SurfaceControl surfaceControl,
+ TaskSnapshot snapshot, CharSequence title, TaskDescription taskDescription,
+ int appearance, int windowFlags, int windowPrivateFlags, Rect taskBounds,
+ int currentOrientation, int activityType, InsetsState topWindowInsetsState,
+ Runnable clearWindowHandler) {
+ mSurface = new Surface();
+ mSession = WindowManagerGlobal.getWindowSession();
+ mWindow = new Window();
+ mWindow.setSession(mSession);
+ mSurfaceControl = surfaceControl;
+ mSnapshot = snapshot;
+ mTitle = title;
+ int backgroundColor = taskDescription.getBackgroundColor();
+ mBackgroundPaint.setColor(backgroundColor != 0 ? backgroundColor : WHITE);
+ mTaskBounds = taskBounds;
+ mSystemBarBackgroundPainter = new SystemBarBackgroundPainter(windowFlags,
+ windowPrivateFlags, appearance, taskDescription, 1f, topWindowInsetsState);
+ mStatusBarColor = taskDescription.getStatusBarColor();
+ mOrientationOnCreation = currentOrientation;
+ mActivityType = activityType;
+ mTransaction = new SurfaceControl.Transaction();
+ mClearWindowHandler = clearWindowHandler;
+ }
+
+ /**
+ * Ask system bar background painter to draw status bar background.
+ * @hide
+ */
+ public void drawStatusBarBackground(Canvas c, @Nullable Rect alreadyDrawnFrame) {
+ mSystemBarBackgroundPainter.drawStatusBarBackground(c, alreadyDrawnFrame,
+ mSystemBarBackgroundPainter.getStatusBarColorViewHeight());
+ }
+
+ /**
+ * Ask system bar background painter to draw navigation bar background.
+ * @hide
+ */
+ public void drawNavigationBarBackground(Canvas c) {
+ mSystemBarBackgroundPainter.drawNavigationBarBackground(c);
+ }
+
+ void remove(ShellExecutor mainExecutor) {
+ final long now = SystemClock.uptimeMillis();
+ if (mSizeMismatch && now - mShownTime < SIZE_MISMATCH_MINIMUM_TIME_MS
+ // Show the latest content as soon as possible for unlocking to home.
+ && mActivityType != ACTIVITY_TYPE_HOME) {
+ final long delayTime = mShownTime + SIZE_MISMATCH_MINIMUM_TIME_MS - now;
+ mainExecutor.executeDelayed(() -> remove(mainExecutor), delayTime);
+ if (DEBUG) {
+ Slog.d(TAG, "Defer removing snapshot surface in " + delayTime);
+ }
+ return;
+ }
+ mainExecutor.execute(() -> {
+ try {
+ if (DEBUG) {
+ Slog.d(TAG, "Removing snapshot surface, mHasDrawn: " + mHasDrawn);
+ }
+ mSession.remove(mWindow);
+ } catch (RemoteException e) {
+ // nothing
+ }
+ });
+ }
+
+ /**
+ * Set frame size.
+ * @hide
+ */
+ public void setFrames(Rect frame, Rect systemBarInsets) {
+ mFrame.set(frame);
+ mSystemBarInsets.set(systemBarInsets);
+ final HardwareBuffer snapshot = mSnapshot.getHardwareBuffer();
+ mSizeMismatch = (mFrame.width() != snapshot.getWidth()
+ || mFrame.height() != snapshot.getHeight());
+ mSystemBarBackgroundPainter.setInsets(systemBarInsets);
+ }
+
+ static Rect getSystemBarInsets(Rect frame, InsetsState state) {
+ return state.calculateInsets(frame, WindowInsets.Type.systemBars(),
+ false /* ignoreVisibility */);
+ }
+
+ private void drawSnapshot() {
+ mSurface.copyFrom(mSurfaceControl);
+ if (DEBUG) {
+ Slog.d(TAG, "Drawing snapshot surface sizeMismatch= " + mSizeMismatch);
+ }
+ if (mSizeMismatch) {
+ // The dimensions of the buffer and the window don't match, so attaching the buffer
+ // will fail. Better create a child window with the exact dimensions and fill the parent
+ // window with the background color!
+ drawSizeMismatchSnapshot();
+ } else {
+ drawSizeMatchSnapshot();
+ }
+ mShownTime = SystemClock.uptimeMillis();
+ mHasDrawn = true;
+ reportDrawn();
+
+ // In case window manager leaks us, make sure we don't retain the snapshot.
+ mSnapshot = null;
+ }
+
+ private void drawSizeMatchSnapshot() {
+ mSurface.attachAndQueueBufferWithColorSpace(mSnapshot.getHardwareBuffer(),
+ mSnapshot.getColorSpace());
+ mSurface.release();
+ }
+
+ private void drawSizeMismatchSnapshot() {
+ if (!mSurface.isValid()) {
+ throw new IllegalStateException("mSurface does not hold a valid surface.");
+ }
+ final HardwareBuffer buffer = mSnapshot.getHardwareBuffer();
+ final SurfaceSession session = new SurfaceSession();
+
+ // We consider nearly matched dimensions as there can be rounding errors and the user won't
+ // notice very minute differences from scaling one dimension more than the other
+ final boolean aspectRatioMismatch = Math.abs(
+ ((float) buffer.getWidth() / buffer.getHeight())
+ - ((float) mFrame.width() / mFrame.height())) > 0.01f;
+
+ // Keep a reference to it such that it doesn't get destroyed when finalized.
+ mChildSurfaceControl = new SurfaceControl.Builder(session)
+ .setName(mTitle + " - task-snapshot-surface")
+ .setBufferSize(buffer.getWidth(), buffer.getHeight())
+ .setFormat(buffer.getFormat())
+ .setParent(mSurfaceControl)
+ .setCallsite("TaskSnapshotWindow.drawSizeMismatchSnapshot")
+ .build();
+ Surface surface = new Surface();
+ surface.copyFrom(mChildSurfaceControl);
+
+ final Rect frame;
+ // We can just show the surface here as it will still be hidden as the parent is
+ // still hidden.
+ mTransaction.show(mChildSurfaceControl);
+ if (aspectRatioMismatch) {
+ // Clip off ugly navigation bar.
+ final Rect crop = calculateSnapshotCrop();
+ frame = calculateSnapshotFrame(crop);
+ mTransaction.setWindowCrop(mChildSurfaceControl, crop);
+ mTransaction.setPosition(mChildSurfaceControl, frame.left, frame.top);
+ mTmpSnapshotSize.set(crop);
+ mTmpDstFrame.set(frame);
+ } else {
+ frame = null;
+ mTmpSnapshotSize.set(0, 0, buffer.getWidth(), buffer.getHeight());
+ mTmpDstFrame.set(mFrame);
+ mTmpDstFrame.offsetTo(0, 0);
+ }
+
+ // Scale the mismatch dimensions to fill the task bounds
+ mSnapshotMatrix.setRectToRect(mTmpSnapshotSize, mTmpDstFrame, Matrix.ScaleToFit.FILL);
+ mTransaction.setMatrix(mChildSurfaceControl, mSnapshotMatrix, mTmpFloat9);
+
+ mTransaction.apply();
+ surface.attachAndQueueBufferWithColorSpace(buffer, mSnapshot.getColorSpace());
+ surface.release();
+
+ if (aspectRatioMismatch) {
+ final Canvas c = mSurface.lockCanvas(null);
+ drawBackgroundAndBars(c, frame);
+ mSurface.unlockCanvasAndPost(c);
+ mSurface.release();
+ }
+ }
+
+ /**
+ * Calculates the snapshot crop in snapshot coordinate space.
+ *
+ * @return crop rect in snapshot coordinate space.
+ */
+ public Rect calculateSnapshotCrop() {
+ final Rect rect = new Rect();
+ final HardwareBuffer snapshot = mSnapshot.getHardwareBuffer();
+ rect.set(0, 0, snapshot.getWidth(), snapshot.getHeight());
+ final Rect insets = mSnapshot.getContentInsets();
+
+ final float scaleX = (float) snapshot.getWidth() / mSnapshot.getTaskSize().x;
+ final float scaleY = (float) snapshot.getHeight() / mSnapshot.getTaskSize().y;
+
+ // Let's remove all system decorations except the status bar, but only if the task is at the
+ // very top of the screen.
+ final boolean isTop = mTaskBounds.top == 0 && mFrame.top == 0;
+ rect.inset((int) (insets.left * scaleX),
+ isTop ? 0 : (int) (insets.top * scaleY),
+ (int) (insets.right * scaleX),
+ (int) (insets.bottom * scaleY));
+ return rect;
+ }
+
+ /**
+ * Calculates the snapshot frame in window coordinate space from crop.
+ *
+ * @param crop rect that is in snapshot coordinate space.
+ */
+ public Rect calculateSnapshotFrame(Rect crop) {
+ final HardwareBuffer snapshot = mSnapshot.getHardwareBuffer();
+ final float scaleX = (float) snapshot.getWidth() / mSnapshot.getTaskSize().x;
+ final float scaleY = (float) snapshot.getHeight() / mSnapshot.getTaskSize().y;
+
+ // Rescale the frame from snapshot to window coordinate space
+ final Rect frame = new Rect(0, 0,
+ (int) (crop.width() / scaleX + 0.5f),
+ (int) (crop.height() / scaleY + 0.5f)
+ );
+
+ // However, we also need to make space for the navigation bar on the left side.
+ frame.offset(mSystemBarInsets.left, 0);
+ return frame;
+ }
+
+ /**
+ * Draw status bar and navigation bar background.
+ * @hide
+ */
+ public void drawBackgroundAndBars(Canvas c, Rect frame) {
+ final int statusBarHeight = mSystemBarBackgroundPainter.getStatusBarColorViewHeight();
+ final boolean fillHorizontally = c.getWidth() > frame.right;
+ final boolean fillVertically = c.getHeight() > frame.bottom;
+ if (fillHorizontally) {
+ c.drawRect(frame.right, alpha(mStatusBarColor) == 0xFF ? statusBarHeight : 0,
+ c.getWidth(), fillVertically
+ ? frame.bottom
+ : c.getHeight(),
+ mBackgroundPaint);
+ }
+ if (fillVertically) {
+ c.drawRect(0, frame.bottom, c.getWidth(), c.getHeight(), mBackgroundPaint);
+ }
+ mSystemBarBackgroundPainter.drawDecors(c, frame);
+ }
+
+ /**
+ * Clear window from drawer, must be post on main executor.
+ */
+ private void clearWindowSynced() {
+ if (mClearWindowHandler != null) {
+ mClearWindowHandler.run();
+ }
+ }
+
+ private void reportDrawn() {
+ try {
+ mSession.finishDrawing(mWindow, null /* postDrawTransaction */);
+ } catch (RemoteException e) {
+ clearWindowSynced();
+ }
+ }
+
+ static class Window extends BaseIWindow {
+ private TaskSnapshotWindow mOuter;
+ private ShellExecutor mMainExecutor;
+
+ public void setOuter(TaskSnapshotWindow outer, ShellExecutor mainExecutor) {
+ mOuter = outer;
+ mMainExecutor = mainExecutor;
+ }
+
+ @Override
+ public void resized(ClientWindowFrames frames, boolean reportDraw,
+ MergedConfiguration mergedConfiguration, boolean forceLayout,
+ boolean alwaysConsumeSystemBars, int displayId) {
+ if (mOuter != null) {
+ if (mergedConfiguration != null
+ && mOuter.mOrientationOnCreation
+ != mergedConfiguration.getMergedConfiguration().orientation) {
+ // The orientation of the screen is changing. We better remove the snapshot ASAP
+ // as we are going to wait on the new window in any case to unfreeze the screen,
+ // and the starting window is not needed anymore.
+ mMainExecutor.execute(() -> {
+ mOuter.clearWindowSynced();
+ });
+ } else if (reportDraw) {
+ mMainExecutor.execute(() -> {
+ if (mOuter.mHasDrawn) {
+ mOuter.reportDrawn();
+ }
+ });
+ }
+ }
+ }
+ }
+
+ /**
+ * Helper class to draw the background of the system bars in regions the task snapshot isn't
+ * filling the window.
+ */
+ static class SystemBarBackgroundPainter {
+ private final Paint mStatusBarPaint = new Paint();
+ private final Paint mNavigationBarPaint = new Paint();
+ private final int mStatusBarColor;
+ private final int mNavigationBarColor;
+ private final int mWindowFlags;
+ private final int mWindowPrivateFlags;
+ private final float mScale;
+ private final InsetsState mInsetsState;
+ private final Rect mSystemBarInsets = new Rect();
+
+ SystemBarBackgroundPainter(int windowFlags, int windowPrivateFlags, int appearance,
+ TaskDescription taskDescription, float scale, InsetsState insetsState) {
+ mWindowFlags = windowFlags;
+ mWindowPrivateFlags = windowPrivateFlags;
+ mScale = scale;
+ final Context context = ActivityThread.currentActivityThread().getSystemUiContext();
+ final int semiTransparent = context.getColor(
+ R.color.system_bar_background_semi_transparent);
+ mStatusBarColor = DecorView.calculateBarColor(windowFlags, FLAG_TRANSLUCENT_STATUS,
+ semiTransparent, taskDescription.getStatusBarColor(), appearance,
+ APPEARANCE_LIGHT_STATUS_BARS,
+ taskDescription.getEnsureStatusBarContrastWhenTransparent());
+ mNavigationBarColor = DecorView.calculateBarColor(windowFlags,
+ FLAG_TRANSLUCENT_NAVIGATION, semiTransparent,
+ taskDescription.getNavigationBarColor(), appearance,
+ APPEARANCE_LIGHT_NAVIGATION_BARS,
+ taskDescription.getEnsureNavigationBarContrastWhenTransparent()
+ && context.getResources().getBoolean(R.bool.config_navBarNeedsScrim));
+ mStatusBarPaint.setColor(mStatusBarColor);
+ mNavigationBarPaint.setColor(mNavigationBarColor);
+ mInsetsState = insetsState;
+ }
+
+ void setInsets(Rect systemBarInsets) {
+ mSystemBarInsets.set(systemBarInsets);
+ }
+
+ int getStatusBarColorViewHeight() {
+ final boolean forceBarBackground =
+ (mWindowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0;
+ if (STATUS_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
+ mInsetsState, mStatusBarColor, mWindowFlags, forceBarBackground)) {
+ return (int) (mSystemBarInsets.top * mScale);
+ } else {
+ return 0;
+ }
+ }
+
+ private boolean isNavigationBarColorViewVisible() {
+ final boolean forceBarBackground =
+ (mWindowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0;
+ return NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
+ mInsetsState, mNavigationBarColor, mWindowFlags, forceBarBackground);
+ }
+
+ void drawDecors(Canvas c, @Nullable Rect alreadyDrawnFrame) {
+ drawStatusBarBackground(c, alreadyDrawnFrame, getStatusBarColorViewHeight());
+ drawNavigationBarBackground(c);
+ }
+
+ void drawStatusBarBackground(Canvas c, @Nullable Rect alreadyDrawnFrame,
+ int statusBarHeight) {
+ if (statusBarHeight > 0 && Color.alpha(mStatusBarColor) != 0
+ && (alreadyDrawnFrame == null || c.getWidth() > alreadyDrawnFrame.right)) {
+ final int rightInset = (int) (mSystemBarInsets.right * mScale);
+ final int left = alreadyDrawnFrame != null ? alreadyDrawnFrame.right : 0;
+ c.drawRect(left, 0, c.getWidth() - rightInset, statusBarHeight, mStatusBarPaint);
+ }
+ }
+
+ @VisibleForTesting
+ void drawNavigationBarBackground(Canvas c) {
+ final Rect navigationBarRect = new Rect();
+ getNavigationBarRect(c.getWidth(), c.getHeight(), mSystemBarInsets, navigationBarRect,
+ mScale);
+ final boolean visible = isNavigationBarColorViewVisible();
+ if (visible && Color.alpha(mNavigationBarColor) != 0 && !navigationBarRect.isEmpty()) {
+ c.drawRect(navigationBarRect, mNavigationBarPaint);
+ }
+ }
+ }
+}
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 c5b54bc..e3ac3f0 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
@@ -17,6 +17,7 @@
package com.android.wm.shell.flicker
import android.graphics.Region
+import com.android.server.wm.flicker.DOCKED_STACK_DIVIDER
import com.android.server.wm.flicker.dsl.EventLogAssertion
import com.android.server.wm.flicker.dsl.LayersAssertion
import com.android.server.wm.flicker.helpers.WindowUtils
@@ -52,6 +53,30 @@
}
@JvmOverloads
+fun LayersAssertion.dockedStackDividerBecomesVisible(
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all("dividerLayerBecomesVisible") {
+ this.hidesLayer(DOCKED_STACK_DIVIDER)
+ .then()
+ .showsLayer(DOCKED_STACK_DIVIDER)
+ }
+}
+
+@JvmOverloads
+fun LayersAssertion.dockedStackDividerBecomesInvisible(
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all("dividerLayerBecomesInvisible") {
+ this.showsLayer(DOCKED_STACK_DIVIDER)
+ .then()
+ .hidesLayer(DOCKED_STACK_DIVIDER)
+ }
+}
+
+@JvmOverloads
fun LayersAssertion.dockedStackDividerIsInvisible(
bugId: Int = 0,
enabled: Boolean = bugId == 0
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/ImeAppHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/ImeAppHelper.kt
index d580104..c546a4d 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/ImeAppHelper.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/ImeAppHelper.kt
@@ -20,7 +20,6 @@
import androidx.test.uiautomator.By
import androidx.test.uiautomator.Until
import com.android.server.wm.flicker.helpers.FIND_TIMEOUT
-import com.android.server.wm.flicker.helpers.waitForIME
import com.android.wm.shell.flicker.TEST_APP_IME_ACTIVITY_LABEL
import com.android.wm.shell.flicker.testapp.Components
import org.junit.Assert
@@ -39,14 +38,9 @@
Assert.assertNotNull("Text field not found, this usually happens when the device " +
"was left in an unknown state (e.g. in split screen)", editText)
editText.click()
- if (!uiDevice.waitForIME()) {
- Assert.fail("IME did not appear")
- }
}
fun closeIME() {
uiDevice.pressBack()
- // Using only the AccessibilityInfo it is not possible to identify if the IME is active
- uiDevice.waitForIdle(1000)
}
}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt
index ed5f8a4..bc74daf 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt
@@ -20,20 +20,17 @@
import android.media.session.MediaController
import android.media.session.MediaSessionManager
import android.os.SystemClock
-import android.view.KeyEvent.KEYCODE_WINDOW
import androidx.test.uiautomator.By
-import androidx.test.uiautomator.Until
+import androidx.test.uiautomator.BySelector
import com.android.server.wm.flicker.helpers.closePipWindow
import com.android.server.wm.flicker.helpers.hasPipWindow
-import com.android.wm.shell.flicker.SYSTEM_UI_PACKAGE_NAME
import com.android.wm.shell.flicker.TEST_APP_PIP_ACTIVITY_LABEL
+import com.android.wm.shell.flicker.pip.tv.closeTvPipWindow
+import com.android.wm.shell.flicker.pip.tv.isFocusedOrHasFocusedChild
import com.android.wm.shell.flicker.testapp.Components
-import org.junit.Assert.assertNotNull
import org.junit.Assert.fail
-class PipAppHelper(
- instrumentation: Instrumentation
-) : BaseAppHelper(
+class PipAppHelper(instrumentation: Instrumentation) : BaseAppHelper(
instrumentation,
TEST_APP_PIP_ACTIVITY_LABEL,
Components.PipActivity()
@@ -47,12 +44,34 @@
it.packageName == packageName
}
- fun clickButton(resourceId: String) =
- uiDevice.findObject(By.res(packageName, resourceId))?.click()
- ?: fail("$resourceId button is not found")
+ fun clickObject(resId: String) {
+ val selector = By.res(packageName, resId)
+ val obj = uiDevice.findObject(selector) ?: error("Could not find `$resId` object")
+
+ if (!isTelevision) {
+ obj.click()
+ } else {
+ focusOnObject(selector) || error("Could not focus on `$resId` object")
+ uiDevice.pressDPadCenter()
+ }
+ }
+
+ private fun focusOnObject(selector: BySelector): Boolean {
+ // We expect all the focusable UI elements to be arranged in a way so that it is possible
+ // to "cycle" over all them by clicking the D-Pad DOWN button, going back up to "the top"
+ // from "the bottom".
+ repeat(FOCUS_ATTEMPTS) {
+ uiDevice.findObject(selector)?.apply { if (isFocusedOrHasFocusedChild) return true }
+ ?: error("The object we try to focus on is gone.")
+
+ uiDevice.pressDPadDown()
+ uiDevice.waitForIdle()
+ }
+ return false
+ }
fun clickEnterPipButton() {
- clickButton("enter_pip")
+ clickObject(ENTER_PIP_BUTTON_ID)
// TODO(b/172321238): remove this check once hasPipWindow is fixed on TVs
if (!isTelevision) {
@@ -64,17 +83,14 @@
}
fun clickStartMediaSessionButton() {
- val startButton = uiDevice.findObject(By.res(packageName, "media_session_start"))
- assertNotNull("Start button not found, this usually happens when the device " +
- "was left in an unknown state (e.g. in split screen)", startButton)
- startButton.click()
+ clickObject(MEDIA_SESSION_START_RADIO_BUTTON_ID)
}
fun checkWithCustomActionsCheckbox() = uiDevice
- .findObject(By.res(packageName, "with_custom_actions"))
- ?.takeIf { it.isCheckable }
- ?.apply { if (!isChecked) click() }
- ?: error("'With custom actions' checkbox not found")
+ .findObject(By.res(packageName, WITH_CUSTOM_ACTIONS_BUTTON_ID))
+ ?.takeIf { it.isCheckable }
+ ?.apply { if (!isChecked) clickObject(WITH_CUSTOM_ACTIONS_BUTTON_ID) }
+ ?: error("'With custom actions' checkbox not found")
fun pauseMedia() = mediaController?.transportControls?.pause()
?: error("No active media session found")
@@ -83,21 +99,21 @@
?: error("No active media session found")
fun closePipWindow() {
- // TODO(b/172321238): remove this check once and simply call closePipWindow once the TV
- // logic is integrated there.
- if (!isTelevision) {
- uiDevice.closePipWindow()
+ if (isTelevision) {
+ uiDevice.closeTvPipWindow()
} else {
- // Bring up Pip menu
- uiDevice.pressKeyCode(KEYCODE_WINDOW)
-
- // Wait for the menu to come up and render the close button
- val closeButton = uiDevice.wait(
- Until.findObject(By.res(SYSTEM_UI_PACKAGE_NAME, "close_button")), 3_000)
- assertNotNull("Pip menu close button is not found", closeButton)
- closeButton.click()
-
- waitUntilClosed()
+ uiDevice.closePipWindow()
}
+
+ if (!waitUntilClosed()) {
+ fail("Couldn't close Pip")
+ }
+ }
+
+ companion object {
+ private const val FOCUS_ATTEMPTS = 20
+ private const val ENTER_PIP_BUTTON_ID = "enter_pip"
+ private const val WITH_CUSTOM_ACTIONS_BUTTON_ID = "with_custom_actions"
+ private const val MEDIA_SESSION_START_RADIO_BUTTON_ID = "media_session_start"
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterLegacySplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterLegacySplitScreenTest.kt
index 02f6f8c..b33fa55 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterLegacySplitScreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterLegacySplitScreenTest.kt
@@ -27,9 +27,9 @@
import com.android.server.wm.flicker.helpers.isInSplitScreen
import com.android.server.wm.flicker.helpers.launchSplitScreen
import com.android.server.wm.flicker.helpers.openQuickstep
+import com.android.server.wm.flicker.helpers.openQuickStepAndClearRecentAppsFromOverview
import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
import com.android.wm.shell.flicker.dockedStackDividerIsInvisible
-import com.android.wm.shell.flicker.dockedStackDividerIsVisible
import com.android.wm.shell.flicker.helpers.SplitScreenHelper.Companion.TEST_REPETITIONS
import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
@@ -38,6 +38,9 @@
import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisible
import com.android.wm.shell.flicker.dockedStackSecondaryBoundsIsVisible
import org.junit.Assert
+import com.android.wm.shell.flicker.dockedStackDividerBecomesVisible
+import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -46,7 +49,7 @@
/**
* Test SplitScreen launch.
- * To run this test: `atest WMShellFlickerTests:EnterSplitScreenTest`
+ * To run this test: `atest WMShellFlickerTests:EnterLegacySplitScreenTest`
*/
@Presubmit
@RequiresDevice
@@ -56,6 +59,8 @@
rotationName: String,
rotation: Int
) : SplitScreenTestBase(rotationName, rotation) {
+ private val letterBox = "Letterbox"
+
private val splitScreenSetup: FlickerBuilder
get() = FlickerBuilder(instrumentation).apply {
val testLaunchActivity = "launch_splitScreen_test_activity"
@@ -65,6 +70,7 @@
setup {
eachRun {
uiDevice.wakeUpAndGoToHomeScreen()
+ uiDevice.openQuickStepAndClearRecentAppsFromOverview()
}
}
teardown {
@@ -85,6 +91,7 @@
windowManagerTrace {
navBarWindowIsAlwaysVisible()
statusBarWindowIsAlwaysVisible()
+ visibleWindowsShownMoreThanOneConsecutiveEntry(listOf(launcherPackageName))
}
}
}
@@ -103,9 +110,12 @@
}
assertions {
layersTrace {
- dockedStackDividerIsVisible()
dockedStackPrimaryBoundsIsVisible(
rotation, splitScreenApp.defaultWindowName, 169271943)
+ dockedStackDividerBecomesVisible()
+ visibleLayersShownMoreThanOneConsecutiveEntry(
+ listOf(launcherPackageName, splitScreenApp.defaultWindowName)
+ )
}
windowManagerTrace {
end {
@@ -132,11 +142,15 @@
}
assertions {
layersTrace {
- dockedStackDividerIsVisible()
dockedStackPrimaryBoundsIsVisible(
rotation, splitScreenApp.defaultWindowName, 169271943)
dockedStackSecondaryBoundsIsVisible(
rotation, secondaryApp.defaultWindowName, 169271943)
+ dockedStackDividerBecomesVisible()
+ visibleLayersShownMoreThanOneConsecutiveEntry(
+ listOf(launcherPackageName, splitScreenApp.defaultWindowName,
+ secondaryApp.defaultWindowName)
+ )
}
windowManagerTrace {
end {
@@ -166,6 +180,9 @@
assertions {
layersTrace {
dockedStackDividerIsInvisible()
+ visibleLayersShownMoreThanOneConsecutiveEntry(
+ listOf(launcherPackageName, nonResizeableApp.defaultWindowName)
+ )
}
windowManagerTrace {
end {
@@ -197,6 +214,10 @@
val displayBounds = WindowUtils.getDisplayBounds(rotation)
this.hasVisibleRegion(nonResizeableApp.defaultWindowName, displayBounds)
}
+ visibleLayersShownMoreThanOneConsecutiveEntry(
+ listOf(launcherPackageName, splitScreenApp.defaultWindowName,
+ nonResizeableApp.defaultWindowName, letterBox)
+ )
}
windowManagerTrace {
end {
@@ -229,6 +250,10 @@
val displayBounds = WindowUtils.getDisplayBounds(rotation)
this.hasVisibleRegion(nonResizeableApp.defaultWindowName, displayBounds)
}
+ visibleLayersShownMoreThanOneConsecutiveEntry(
+ listOf(launcherPackageName, splitScreenApp.defaultWindowName,
+ nonResizeableApp.defaultWindowName, letterBox)
+ )
}
windowManagerTrace {
end {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottomTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottomTest.kt
new file mode 100644
index 0000000..573ffc6
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottomTest.kt
@@ -0,0 +1,94 @@
+/*
+ * 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 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.endRotation
+import com.android.server.wm.flicker.helpers.buildTestTag
+import com.android.server.wm.flicker.helpers.exitSplitScreen
+import com.android.server.wm.flicker.helpers.exitSplitScreenFromBottom
+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:ExitLegacySplitScreenFromBottomTest`
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class ExitLegacySplitScreenFromBottomTest(
+ 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")
+
+ // b/161435597 causes the test not to work on 90 degrees
+ return FlickerTestRunnerFactory(instrumentation, listOf(Surface.ROTATION_0))
+ .buildTest { configuration ->
+ withTestName {
+ buildTestTag("exitSplitScreenFromBottom", testApp,
+ configuration)
+ }
+ repeat { configuration.repetitions }
+ setup {
+ test {
+ device.wakeUpAndGoToHomeScreen()
+ }
+ eachRun {
+ testApp.open()
+ device.launchSplitScreen()
+ device.waitForIdle()
+ this.setRotation(configuration.endRotation)
+ }
+ }
+ teardown {
+ eachRun {
+ testApp.exit()
+ }
+ test {
+ if (device.isInSplitScreen()) {
+ device.exitSplitScreen()
+ }
+ }
+ }
+ transitions {
+ device.exitSplitScreenFromBottom()
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenTest.kt
index 33306bf..c51c73a 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenTest.kt
@@ -21,16 +21,22 @@
import android.view.Surface
import androidx.test.filters.FlakyTest
import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.layerBecomesInvisible
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.launchSplitScreen
+import com.android.server.wm.flicker.helpers.openQuickStepAndClearRecentAppsFromOverview
import com.android.server.wm.flicker.helpers.resizeSplitScreen
import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
-import com.android.wm.shell.flicker.dockedStackDividerIsInvisible
-import com.android.wm.shell.flicker.helpers.SplitScreenHelper.Companion.TEST_REPETITIONS
import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import com.android.wm.shell.flicker.dockedStackDividerIsInvisible
+import com.android.wm.shell.flicker.helpers.SplitScreenHelper.Companion.TEST_REPETITIONS
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -39,7 +45,7 @@
/**
* Test exit SplitScreen mode.
- * To run this test: `atest WMShellFlickerTests:ExitSplitScreenTest`
+ * To run this test: `atest WMShellFlickerTests:ExitLegacySplitScreenTest`
*/
@Presubmit
@RequiresDevice
@@ -58,10 +64,9 @@
setup {
eachRun {
uiDevice.wakeUpAndGoToHomeScreen()
- secondaryApp.open()
- uiDevice.pressHome()
- splitScreenApp.open()
- uiDevice.pressHome()
+ uiDevice.openQuickStepAndClearRecentAppsFromOverview()
+ secondaryApp.launchViaIntent()
+ splitScreenApp.launchViaIntent()
uiDevice.launchSplitScreen()
}
}
@@ -71,6 +76,15 @@
secondaryApp.exit()
}
}
+ assertions {
+ windowManagerTrace {
+ visibleWindowsShownMoreThanOneConsecutiveEntry()
+ }
+ layersTrace {
+ visibleLayersShownMoreThanOneConsecutiveEntry(
+ listOf(launcherPackageName))
+ }
+ }
}
@Test
@@ -87,6 +101,7 @@
assertions {
layersTrace {
dockedStackDividerIsInvisible()
+ layerBecomesInvisible(splitScreenApp.defaultWindowName)
}
windowManagerTrace {
navBarWindowIsAlwaysVisible()
@@ -137,4 +152,4 @@
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/LegacySplitScreenToLauncherTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncherTest.kt
index cc02aa3..629c71f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncherTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncherTest.kt
@@ -17,10 +17,10 @@
package com.android.wm.shell.flicker.legacysplitscreen
import android.platform.test.annotations.Presubmit
+import android.support.test.launcherhelper.LauncherStrategyFactory
import android.view.Surface
import androidx.test.filters.RequiresDevice
import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.DOCKED_STACK_DIVIDER
import com.android.server.wm.flicker.Flicker
import com.android.server.wm.flicker.FlickerTestRunner
import com.android.server.wm.flicker.FlickerTestRunnerFactory
@@ -31,16 +31,21 @@
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.openQuickStepAndClearRecentAppsFromOverview
import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
import com.android.server.wm.flicker.navBarLayerRotatesAndScales
+import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.flicker.layerBecomesInvisible
import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
import com.android.server.wm.flicker.noUncoveredRegions
import com.android.server.wm.flicker.repetitions
import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
import com.android.server.wm.flicker.statusBarLayerRotatesScales
import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import com.android.wm.shell.flicker.dockedStackDividerBecomesInvisible
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@@ -48,7 +53,7 @@
/**
* Test open app to split screen.
- * To run this test: `atest WMShellFlickerTests:SplitScreenToLauncherTest`
+ * To run this test: `atest WMShellFlickerTests:LegacySplitScreenToLauncherTest`
*/
@Presubmit
@RequiresDevice
@@ -63,6 +68,8 @@
@JvmStatic
fun getParams(): Collection<Array<Any>> {
val instrumentation = InstrumentationRegistry.getInstrumentation()
+ val launcherPackageName = LauncherStrategyFactory.getInstance(instrumentation)
+ .launcherStrategy.supportedLauncherPackage
val testApp = StandardAppHelper(instrumentation,
"com.android.wm.shell.flicker.testapp", "SimpleApp")
@@ -76,6 +83,7 @@
setup {
test {
device.wakeUpAndGoToHomeScreen()
+ device.openQuickStepAndClearRecentAppsFromOverview()
}
eachRun {
testApp.open()
@@ -101,6 +109,7 @@
windowManagerTrace {
navBarWindowIsAlwaysVisible()
statusBarWindowIsAlwaysVisible()
+ visibleWindowsShownMoreThanOneConsecutiveEntry()
}
layersTrace {
@@ -109,19 +118,13 @@
noUncoveredRegions(configuration.endRotation)
navBarLayerRotatesAndScales(configuration.endRotation)
statusBarLayerRotatesScales(configuration.endRotation)
+ visibleLayersShownMoreThanOneConsecutiveEntry(
+ listOf(launcherPackageName))
// b/161435597 causes the test not to work on 90 degrees
- all("dividerLayerBecomesInvisible") {
- this.showsLayer(DOCKED_STACK_DIVIDER)
- .then()
- .hidesLayer(DOCKED_STACK_DIVIDER)
- }
+ dockedStackDividerBecomesInvisible()
- all("appLayerBecomesInvisible") {
- this.showsLayer(testApp.getPackage())
- .then()
- .hidesLayer(testApp.getPackage())
- }
+ layerBecomesInvisible(testApp.getPackage())
}
eventLog {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OpenAppToLegacySplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OpenAppToLegacySplitScreenTest.kt
index bb80726..af03869 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OpenAppToLegacySplitScreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OpenAppToLegacySplitScreenTest.kt
@@ -17,30 +17,36 @@
package com.android.wm.shell.flicker.legacysplitscreen
import android.platform.test.annotations.Presubmit
+import android.support.test.launcherhelper.LauncherStrategyFactory
import android.view.Surface
import androidx.test.filters.RequiresDevice
import androidx.test.platform.app.InstrumentationRegistry
-import com.android.server.wm.flicker.DOCKED_STACK_DIVIDER
import com.android.server.wm.flicker.Flicker
import com.android.server.wm.flicker.FlickerTestRunner
import com.android.server.wm.flicker.FlickerTestRunnerFactory
-import com.android.server.wm.flicker.endRotation
import com.android.server.wm.flicker.helpers.StandardAppHelper
+import com.android.server.wm.flicker.endRotation
import com.android.server.wm.flicker.focusChanges
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.openQuickStepAndClearRecentAppsFromOverview
import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
import com.android.server.wm.flicker.navBarLayerRotatesAndScales
+import com.android.server.wm.flicker.appWindowBecomesVisible
+import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.flicker.layerBecomesVisible
import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
import com.android.server.wm.flicker.noUncoveredRegions
import com.android.server.wm.flicker.repetitions
import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
import com.android.server.wm.flicker.statusBarLayerRotatesScales
import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import com.android.wm.shell.flicker.dockedStackDividerBecomesVisible
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@@ -48,7 +54,7 @@
/**
* Test open app to split screen.
- * To run this test: `atest WMShellFlickerTests:OpenAppToSplitScreenTest`
+ * To run this test: `atest WMShellFlickerTests:OpenAppToLegacySplitScreenTest`
*/
@Presubmit
@RequiresDevice
@@ -63,6 +69,8 @@
@JvmStatic
fun getParams(): Collection<Array<Any>> {
val instrumentation = InstrumentationRegistry.getInstrumentation()
+ val launcherPackageName = LauncherStrategyFactory.getInstance(instrumentation)
+ .launcherStrategy.supportedLauncherPackage
val testApp = StandardAppHelper(instrumentation,
"com.android.wm.shell.flicker.testapp", "SimpleApp")
@@ -76,9 +84,11 @@
setup {
test {
device.wakeUpAndGoToHomeScreen()
+ device.openQuickStepAndClearRecentAppsFromOverview()
}
eachRun {
testApp.open()
+ device.pressHome()
this.setRotation(configuration.endRotation)
}
}
@@ -99,6 +109,9 @@
windowManagerTrace {
navBarWindowIsAlwaysVisible()
statusBarWindowIsAlwaysVisible()
+ visibleWindowsShownMoreThanOneConsecutiveEntry()
+
+ appWindowBecomesVisible(testApp.getPackage())
}
layersTrace {
@@ -108,12 +121,11 @@
navBarLayerRotatesAndScales(configuration.endRotation,
bugId = 140855415)
statusBarLayerRotatesScales(configuration.endRotation)
+ visibleLayersShownMoreThanOneConsecutiveEntry(
+ listOf(launcherPackageName))
- all("dividerLayerBecomesVisible") {
- this.hidesLayer(DOCKED_STACK_DIVIDER)
- .then()
- .showsLayer(DOCKED_STACK_DIVIDER)
- }
+ dockedStackDividerBecomesVisible()
+ layerBecomesVisible(testApp.getPackage())
}
eventLog {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreenTest.kt
index e3beb41..391cb2a 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreenTest.kt
@@ -47,6 +47,8 @@
import com.android.server.wm.flicker.startRotation
import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
@@ -55,7 +57,7 @@
/**
* Test split screen resizing window transitions.
- * To run this test: `atest WMShellFlickerTests:ResizeSplitScreenTest`
+ * To run this test: `atest WMShellFlickerTests:ResizeLegacySplitScreenTest`
*
* Currently it runs only in 0 degrees because of b/156100803
*/
@@ -131,6 +133,7 @@
windowManagerTrace {
navBarWindowIsAlwaysVisible()
statusBarWindowIsAlwaysVisible()
+ visibleWindowsShownMoreThanOneConsecutiveEntry()
all("topAppWindowIsAlwaysVisible", bugId = 156223549) {
this.showsAppWindow(sSimpleActivity)
@@ -147,6 +150,7 @@
noUncoveredRegions(configuration.endRotation)
navBarLayerRotatesAndScales(configuration.endRotation)
statusBarLayerRotatesScales(configuration.endRotation)
+ visibleLayersShownMoreThanOneConsecutiveEntry()
all("topAppLayerIsAlwaysVisible") {
this.showsLayer(sSimpleActivity)
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
index ae2200c..923f2a4 100644
--- 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
@@ -23,6 +23,7 @@
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.openQuickStepAndClearRecentAppsFromOverview
import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
import com.android.server.wm.flicker.navBarLayerRotatesAndScales
import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
@@ -56,7 +57,8 @@
}
setup {
test {
- device.wakeUpAndGoToHomeScreen()
+ uiDevice.wakeUpAndGoToHomeScreen()
+ uiDevice.openQuickStepAndClearRecentAppsFromOverview()
}
}
teardown {
@@ -81,7 +83,7 @@
}
transitions {
splitScreenApp.launchViaIntent()
- device.launchSplitScreen()
+ uiDevice.launchSplitScreen()
setRotation(rotation)
}
assertions {
@@ -114,7 +116,7 @@
transitions {
splitScreenApp.launchViaIntent()
setRotation(rotation)
- device.launchSplitScreen()
+ uiDevice.launchSplitScreen()
}
assertions {
layersTrace {
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
index a1b44f0..4578f68 100644
--- 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
@@ -23,6 +23,7 @@
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.openQuickStepAndClearRecentAppsFromOverview
import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
import com.android.server.wm.flicker.navBarLayerRotatesAndScales
import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
@@ -57,7 +58,8 @@
}
setup {
test {
- device.wakeUpAndGoToHomeScreen()
+ uiDevice.wakeUpAndGoToHomeScreen()
+ uiDevice.openQuickStepAndClearRecentAppsFromOverview()
}
}
teardown {
@@ -83,7 +85,7 @@
transitions {
secondaryApp.launchViaIntent()
splitScreenApp.launchViaIntent()
- device.launchSplitScreen()
+ uiDevice.launchSplitScreen()
splitScreenApp.reopenAppFromOverview()
setRotation(rotation)
}
@@ -121,7 +123,7 @@
secondaryApp.launchViaIntent()
splitScreenApp.launchViaIntent()
setRotation(rotation)
- device.launchSplitScreen()
+ uiDevice.launchSplitScreen()
splitScreenApp.reopenAppFromOverview()
}
assertions {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/SplitScreenTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/SplitScreenTestBase.kt
index a2e325e..a536ec8 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/SplitScreenTestBase.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/SplitScreenTestBase.kt
@@ -16,6 +16,7 @@
package com.android.wm.shell.flicker.legacysplitscreen
+import android.support.test.launcherhelper.LauncherStrategyFactory
import com.android.wm.shell.flicker.NonRotationTestBase
import com.android.wm.shell.flicker.TEST_APP_NONRESIZEABLE_LABEL
import com.android.wm.shell.flicker.TEST_APP_SPLITSCREEN_PRIMARY_LABEL
@@ -36,4 +37,6 @@
protected val nonResizeableApp = SplitScreenHelper(instrumentation,
TEST_APP_NONRESIZEABLE_LABEL,
Components.NonResizeableActivity())
+ protected val launcherPackageName = LauncherStrategyFactory.getInstance(instrumentation)
+ .launcherStrategy.supportedLauncherPackage
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
index 6b44ce6..866d654 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
@@ -25,8 +25,10 @@
import com.android.server.wm.flicker.helpers.closePipWindow
import com.android.server.wm.flicker.helpers.hasPipWindow
import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
import com.android.wm.shell.flicker.IME_WINDOW_NAME
import com.android.wm.shell.flicker.helpers.ImeAppHelper
+import com.android.wm.shell.flicker.testapp.Components
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -46,6 +48,8 @@
rotation: Int
) : PipTestBase(rotationName, rotation) {
private val keyboardApp = ImeAppHelper(instrumentation)
+ private val keyboardComponent = Components.ImeActivity().componentName
+ private val helper = WindowManagerStateHelper()
private val keyboardScenario: FlickerBuilder
get() = FlickerBuilder(instrumentation).apply {
@@ -64,6 +68,8 @@
// UiAutomator doesn't support to launch the multiple Activities in a task.
// So use launchActivity() for the Keyboard Activity.
keyboardApp.launchViaIntent()
+ helper.waitForAppTransitionIdle()
+ helper.waitForFullScreenApp(keyboardComponent)
}
}
teardown {
@@ -88,9 +94,11 @@
transitions {
// open the soft keyboard
keyboardApp.openIME()
+ helper.waitImeWindowShown()
// then close it again
keyboardApp.closeIME()
+ helper.waitImeWindowGone()
}
assertions {
windowManagerTrace {
@@ -112,11 +120,13 @@
transitions {
// open the soft keyboard
keyboardApp.openIME()
+ helper.waitImeWindowShown()
}
teardown {
eachRun {
// close the keyboard
keyboardApp.closeIME()
+ helper.waitImeWindowGone()
}
}
assertions {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
index 81cdbf0..9eae179 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
@@ -41,7 +41,7 @@
/**
* Test Pip with split-screen.
- * To run this test: `atest WMShellFlickerTests:PipSplitScreenTest`
+ * To run this test: `atest WMShellFlickerTests:PipLegacySplitScreenTest`
*/
@RequiresDevice
@RunWith(Parameterized::class)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipBasicTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipBasicTest.kt
index 70425a3..49094e6 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipBasicTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipBasicTest.kt
@@ -42,7 +42,7 @@
testApp.launchViaIntent()
// Set up ratio and enter Pip
- testApp.clickButton(radioButtonId)
+ testApp.clickObject(radioButtonId)
testApp.clickEnterPipButton()
val actualRatio: Float = testApp.ui?.visibleBounds?.ratio
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipMenuTests.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipMenuTests.kt
index 4cb6447..66efb5a 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipMenuTests.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipMenuTests.kt
@@ -59,17 +59,24 @@
@Test
fun pipMenu_correctPosition() {
- val pipMenu = enterPip_openMenu_assertShown()
-
- // Make sure it's fullscreen
- assertTrue("Pip menu should be shown fullscreen", pipMenu.isFullscreen(uiDevice))
+ enterPip_openMenu_assertShown()
// Make sure the PiP task is positioned where it should be.
val activityBounds: Rect = testApp.ui?.visibleBounds
- ?: error("Could not retrieve PiP Activity bounds")
+ ?: error("Could not retrieve Pip Activity bounds")
assertTrue("Pip Activity is positioned correctly while Pip menu is shown",
pipBoundsWhileInMenu == activityBounds)
+ // Make sure the Pip Menu Actions are positioned correctly.
+ uiDevice.findTvPipMenuControls()?.visibleBounds?.run {
+ assertTrue("Pip Menu Actions should be positioned below the Activity in Pip",
+ top >= activityBounds.bottom)
+ assertTrue("Pip Menu Actions should be positioned central horizontally",
+ centerX() == uiDevice.displayWidth / 2)
+ assertTrue("Pip Menu Actions should be fully shown on the screen",
+ left >= 0 && right <= uiDevice.displayWidth && bottom <= uiDevice.displayHeight)
+ } ?: error("Could not retrieve Pip Menu Actions bounds")
+
testApp.closePipWindow()
}
@@ -100,11 +107,11 @@
enterPip_openMenu_assertShown()
// PiP menu should contain the Close button
- val closeButton = uiDevice.findTvPipMenuCloseButton()
+ uiDevice.findTvPipMenuCloseButton()
?: fail("\"Close PIP\" button should be shown in Pip menu")
// Clicking on the Close button should close the app
- closeButton.click()
+ uiDevice.clickTvPipMenuCloseButton()
assertTrue("\"Close PIP\" button should close the PiP", testApp.waitUntilClosed())
}
@@ -113,12 +120,12 @@
enterPip_openMenu_assertShown()
// PiP menu should contain the Fullscreen button
- val fullscreenButton = uiDevice.findTvPipMenuFullscreenButton()
+ uiDevice.findTvPipMenuFullscreenButton()
?: fail("\"Full screen\" button should be shown in Pip menu")
// Clicking on the fullscreen button should return app to the fullscreen mode.
// Click, wait for the app to go fullscreen
- fullscreenButton.click()
+ uiDevice.clickTvPipMenuFullscreenButton()
assertTrue("\"Full screen\" button should open the app fullscreen",
wait { testApp.ui?.isFullscreen(uiDevice) ?: false })
@@ -136,12 +143,12 @@
assertFullscreenAndCloseButtonsAreShown()
// PiP menu should contain the Pause button
- val pauseButton = uiDevice.findTvPipMenuElementWithDescription(pauseButtonDescription)
+ uiDevice.findTvPipMenuElementWithDescription(pauseButtonDescription)
?: fail("\"Pause\" button should be shown in Pip menu if there is an active " +
"playing media session.")
// When we pause media, the button should change from Pause to Play
- pauseButton.click()
+ uiDevice.clickTvPipMenuElementWithDescription(pauseButtonDescription)
assertFullscreenAndCloseButtonsAreShown()
// PiP menu should contain the Play button now
@@ -161,27 +168,26 @@
// PiP menu should contain "No-Op", "Off" and "Clear" buttons...
uiDevice.findTvPipMenuElementWithDescription(TEST_APP_PIP_MENU_ACTION_NO_OP)
?: fail("\"No-Op\" button should be shown in Pip menu")
- val offButton = uiDevice.findTvPipMenuElementWithDescription(TEST_APP_PIP_MENU_ACTION_OFF)
+ uiDevice.findTvPipMenuElementWithDescription(TEST_APP_PIP_MENU_ACTION_OFF)
?: fail("\"Off\" button should be shown in Pip menu")
uiDevice.findTvPipMenuElementWithDescription(TEST_APP_PIP_MENU_ACTION_CLEAR)
?: fail("\"Clear\" button should be shown in Pip menu")
// ... and should also contain the "Full screen" and "Close" buttons.
assertFullscreenAndCloseButtonsAreShown()
- offButton.click()
+ uiDevice.clickTvPipMenuElementWithDescription(TEST_APP_PIP_MENU_ACTION_OFF)
// Invoking the "Off" action should replace it with the "On" action/button and should
// remove the "No-Op" action/button. "Clear" action/button should remain in the menu ...
uiDevice.waitForTvPipMenuElementWithDescription(TEST_APP_PIP_MENU_ACTION_ON)
?: fail("\"On\" button should be shown in Pip for a corresponding custom action")
assertNull("\"No-Op\" button should not be shown in Pip menu",
uiDevice.findTvPipMenuElementWithDescription(TEST_APP_PIP_MENU_ACTION_NO_OP))
- val clearButton =
- uiDevice.findTvPipMenuElementWithDescription(TEST_APP_PIP_MENU_ACTION_CLEAR)
+ uiDevice.findTvPipMenuElementWithDescription(TEST_APP_PIP_MENU_ACTION_CLEAR)
?: fail("\"Clear\" button should be shown in Pip menu")
// ... as well as the "Full screen" and "Close" buttons.
assertFullscreenAndCloseButtonsAreShown()
- clearButton.click()
+ uiDevice.clickTvPipMenuElementWithDescription(TEST_APP_PIP_MENU_ACTION_CLEAR)
// Invoking the "Clear" action should remove all the custom actions and their corresponding
// buttons, ...
uiDevice.waitUntilTvPipMenuElementWithDescriptionIsGone(TEST_APP_PIP_MENU_ACTION_ON)?.also {
@@ -211,9 +217,8 @@
?: fail("\"No-Op\" button should be shown in Pip menu")
uiDevice.findTvPipMenuElementWithDescription(TEST_APP_PIP_MENU_ACTION_OFF)
?: fail("\"Off\" button should be shown in Pip menu")
- val clearButton =
- uiDevice.findTvPipMenuElementWithDescription(TEST_APP_PIP_MENU_ACTION_CLEAR)
- ?: fail("\"Clear\" button should be shown in Pip menu")
+ uiDevice.findTvPipMenuElementWithDescription(TEST_APP_PIP_MENU_ACTION_CLEAR)
+ ?: fail("\"Clear\" button should be shown in Pip menu")
// ... should also contain the "Full screen" and "Close" buttons, ...
assertFullscreenAndCloseButtonsAreShown()
// ... but should not contain media buttons.
@@ -222,7 +227,7 @@
assertNull("\"Pause\" button should not be shown in menu when there are custom actions",
uiDevice.findTvPipMenuElementWithDescription(pauseButtonDescription))
- clearButton.click()
+ uiDevice.clickTvPipMenuElementWithDescription(TEST_APP_PIP_MENU_ACTION_CLEAR)
// Invoking the "Clear" action should remove all the custom actions, which should bring up
// media buttons...
uiDevice.waitForTvPipMenuElementWithDescription(pauseButtonDescription)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvUtils.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvUtils.kt
index 0732794..587b551 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvUtils.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvUtils.kt
@@ -18,6 +18,7 @@
import android.view.KeyEvent
import androidx.test.uiautomator.By
+import androidx.test.uiautomator.BySelector
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.UiObject2
import androidx.test.uiautomator.Until
@@ -25,11 +26,18 @@
/** Id of the root view in the com.android.wm.shell.pip.tv.PipMenuActivity */
private const val TV_PIP_MENU_ROOT_ID = "tv_pip_menu"
+private const val TV_PIP_MENU_CONTROLS_ID = "pip_controls"
private const val TV_PIP_MENU_CLOSE_BUTTON_ID = "close_button"
private const val TV_PIP_MENU_FULLSCREEN_BUTTON_ID = "full_button"
+private const val FOCUS_ATTEMPTS = 10
private const val WAIT_TIME_MS = 3_000L
+private val TV_PIP_MENU_CLOSE_BUTTON_SELECTOR =
+ By.res(SYSTEM_UI_PACKAGE_NAME, TV_PIP_MENU_CLOSE_BUTTON_ID)
+private val TV_PIP_MENU_FULLSCREEN_BUTTON_SELECTOR =
+ By.res(SYSTEM_UI_PACKAGE_NAME, TV_PIP_MENU_FULLSCREEN_BUTTON_ID)
+
private val tvPipMenuSelector = By.res(SYSTEM_UI_PACKAGE_NAME, TV_PIP_MENU_ROOT_ID)
fun UiDevice.pressWindowKey() = pressKeyCode(KeyEvent.KEYCODE_WINDOW)
@@ -39,16 +47,35 @@
fun UiDevice.waitForTvPipMenuToClose(): Boolean = wait(Until.gone(tvPipMenuSelector), WAIT_TIME_MS)
-fun UiDevice.findTvPipMenuCloseButton(): UiObject2? = findObject(
- By.res(SYSTEM_UI_PACKAGE_NAME, TV_PIP_MENU_CLOSE_BUTTON_ID))
+fun UiDevice.findTvPipMenuControls(): UiObject2? =
+ findObject(tvPipMenuSelector)
+ ?.findObject(By.res(SYSTEM_UI_PACKAGE_NAME, TV_PIP_MENU_CONTROLS_ID))
-fun UiDevice.findTvPipMenuFullscreenButton(): UiObject2? = findObject(
- By.res(SYSTEM_UI_PACKAGE_NAME, TV_PIP_MENU_FULLSCREEN_BUTTON_ID))
+fun UiDevice.findTvPipMenuCloseButton(): UiObject2? =
+ findObject(tvPipMenuSelector)?.findObject(TV_PIP_MENU_CLOSE_BUTTON_SELECTOR)
-fun UiDevice.findTvPipMenuElementWithDescription(desc: String): UiObject2? {
- val buttonSelector = By.desc(desc)
- val menuWithButtonSelector = By.copy(tvPipMenuSelector).hasDescendant(buttonSelector)
- return findObject(menuWithButtonSelector)?.findObject(buttonSelector)
+fun UiDevice.clickTvPipMenuCloseButton() {
+ focusOnObjectInTvPipMenu(TV_PIP_MENU_CLOSE_BUTTON_SELECTOR) ||
+ error("Could not focus on the Close button")
+ pressDPadCenter()
+}
+
+fun UiDevice.findTvPipMenuFullscreenButton(): UiObject2? =
+ findObject(tvPipMenuSelector)?.findObject(TV_PIP_MENU_FULLSCREEN_BUTTON_SELECTOR)
+
+fun UiDevice.clickTvPipMenuFullscreenButton() {
+ focusOnObjectInTvPipMenu(TV_PIP_MENU_FULLSCREEN_BUTTON_SELECTOR) ||
+ error("Could not focus on the Fullscreen button")
+ pressDPadCenter()
+}
+
+fun UiDevice.findTvPipMenuElementWithDescription(desc: String): UiObject2? =
+ findObject(tvPipMenuSelector)?.findObject(By.desc(desc).pkg(SYSTEM_UI_PACKAGE_NAME))
+
+fun UiDevice.clickTvPipMenuElementWithDescription(desc: String) {
+ focusOnObjectInTvPipMenu(By.desc(desc).pkg(SYSTEM_UI_PACKAGE_NAME)) ||
+ error("Could not focus on the Pip menu object with \"$desc\" description")
+ pressDPadCenter()
}
fun UiDevice.waitForTvPipMenuElementWithDescription(desc: String): UiObject2? {
@@ -63,4 +90,33 @@
fun UiObject2.isFullscreen(uiDevice: UiDevice): Boolean = visibleBounds.run {
height() == uiDevice.displayHeight && width() == uiDevice.displayWidth
+}
+
+val UiObject2.isFocusedOrHasFocusedChild: Boolean
+ get() = isFocused || findObject(By.focused(true)) != null
+
+fun UiDevice.closeTvPipWindow() {
+ // Check if Pip menu is Open. If it's not, open it.
+ if (findObject(tvPipMenuSelector) == null) {
+ pressWindowKey()
+ waitForTvPipMenu() ?: error("Could not open Pip menu")
+ }
+
+ clickTvPipMenuCloseButton()
+ waitForTvPipMenuToClose()
+}
+
+private fun UiDevice.focusOnObjectInTvPipMenu(objectSelector: BySelector): Boolean {
+ repeat(FOCUS_ATTEMPTS) {
+ val menu = findObject(tvPipMenuSelector) ?: error("Pip Menu is now shown")
+ val objectToFocus = menu.findObject(objectSelector)
+ .apply { if (isFocusedOrHasFocusedChild) return true }
+ ?: error("The object we try to focus on is gone.")
+ val currentlyFocused = menu.findObject(By.focused(true))
+ ?: error("Pip menu does not contain a focused element")
+ if (objectToFocus.visibleCenter.x < currentlyFocused.visibleCenter.x)
+ pressDPadLeft() else pressDPadRight()
+ waitForIdle()
+ }
+ return false
}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/layout/activity_pip.xml b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/layout/activity_pip.xml
index e5d2f82..909b77c 100644
--- a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/layout/activity_pip.xml
+++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/layout/activity_pip.xml
@@ -21,6 +21,12 @@
android:orientation="vertical"
android:background="@android:color/holo_blue_bright">
+ <!-- All the buttons (and other clickable elements) should be arranged in a way so that it is
+ possible to "cycle" over all them by clicking on the D-Pad DOWN button. The way we do it
+ here is by arranging them this vertical LL and by relying on the nextFocusDown attribute
+ where things are arranged differently and to circle back up to the top once we reach the
+ bottom. -->
+
<Button
android:id="@+id/enter_pip"
android:layout_width="wrap_content"
@@ -87,12 +93,14 @@
android:id="@+id/media_session_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:nextFocusDown="@id/media_session_stop"
android:text="Start"/>
<Button
android:id="@+id/media_session_stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:nextFocusDown="@id/enter_pip"
android:text="Stop"/>
</LinearLayout>
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TaskViewTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TaskViewTest.java
index 11bf4ff..01b5204 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TaskViewTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TaskViewTest.java
@@ -215,4 +215,19 @@
verify(mViewListener).onBackPressedOnTaskRoot(eq(mTaskInfo.taskId));
}
+
+ @Test
+ public void testSetOnBackPressedOnTaskRoot() {
+ mTaskView.onTaskAppeared(mTaskInfo, mLeash);
+ verify(mOrganizer).setInterceptBackPressedOnTaskRoot(eq(mTaskInfo.token), eq(true));
+ }
+
+ @Test
+ public void testUnsetOnBackPressedOnTaskRoot() {
+ mTaskView.onTaskAppeared(mTaskInfo, mLeash);
+ verify(mOrganizer).setInterceptBackPressedOnTaskRoot(eq(mTaskInfo.token), eq(true));
+
+ mTaskView.onTaskVanished(mTaskInfo);
+ verify(mOrganizer).setInterceptBackPressedOnTaskRoot(eq(mTaskInfo.token), eq(false));
+ }
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/TaskStackListenerImplTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/TaskStackListenerImplTest.java
index 8842872..495be41 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/TaskStackListenerImplTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/TaskStackListenerImplTest.java
@@ -32,6 +32,7 @@
import android.os.RemoteException;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import android.window.TaskSnapshot;
import androidx.test.filters.SmallTest;
@@ -153,7 +154,7 @@
@Test
public void testOnTaskSnapshotChanged() {
- ActivityManager.TaskSnapshot snapshot = mock(ActivityManager.TaskSnapshot.class);
+ TaskSnapshot snapshot = mock(TaskSnapshot.class);
mImpl.onTaskSnapshotChanged(123, snapshot);
verify(mCallback).onTaskSnapshotChanged(eq(123), eq(snapshot));
verify(mOtherCallback).onTaskSnapshotChanged(eq(123), eq(snapshot));
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 708a6c5..cd46816 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
@@ -75,15 +75,16 @@
}
@Test
- @UiThreadTest
- public void testSnapToTarget() {
- DividerSnapAlgorithm.SnapTarget snapTarget = getSnapTarget(0 /* position */,
- DividerSnapAlgorithm.SnapTarget.FLAG_NONE);
- mSplitLayout.snapToTarget(0 /* currentPosition */, snapTarget);
- verify(mLayoutChangeListener).onBoundsChanging(any(SplitLayout.class));
+ public void testSetDividePosition() {
+ mSplitLayout.setDividePosition(anyInt());
+ verify(mLayoutChangeListener).onBoundsChanged(any(SplitLayout.class));
+ }
+ @Test
+ @UiThreadTest
+ public void testSnapToDismissTarget() {
// verify it callbacks properly when the snap target indicates dismissing split.
- snapTarget = getSnapTarget(0 /* position */,
+ DividerSnapAlgorithm.SnapTarget snapTarget = getSnapTarget(0 /* position */,
DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_START);
mSplitLayout.snapToTarget(0 /* currentPosition */, snapTarget);
verify(mLayoutChangeListener).onSnappedToDismiss(eq(false));
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java
index 7f280cd..d30fa38 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java
@@ -197,6 +197,11 @@
}
@Override
+ public SurfaceControl.Transaction setFrameTimelineVsync(long frameTimelineVsyncId) {
+ return this;
+ }
+
+ @Override
public void apply() {}
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java
index 8ba301a..dea24d3 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java
@@ -31,14 +31,13 @@
import androidx.test.filters.SmallTest;
+import com.android.internal.util.function.TriConsumer;
import com.android.wm.shell.ShellTestCase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.util.function.BiConsumer;
-
/**
* Tests for {@link PipBoundsState}.
*/
@@ -117,23 +116,33 @@
@Test
public void testSetShelfVisibility_changed_callbackInvoked() {
- final BiConsumer<Boolean, Integer> callback = mock(BiConsumer.class);
+ final TriConsumer<Boolean, Integer, Boolean> callback = mock(TriConsumer.class);
mPipBoundsState.setOnShelfVisibilityChangeCallback(callback);
mPipBoundsState.setShelfVisibility(true, 100);
- verify(callback).accept(true, 100);
+ verify(callback).accept(true, 100, true);
+ }
+
+ @Test
+ public void testSetShelfVisibility_changedWithoutUpdateMovBounds_callbackInvoked() {
+ final TriConsumer<Boolean, Integer, Boolean> callback = mock(TriConsumer.class);
+ mPipBoundsState.setOnShelfVisibilityChangeCallback(callback);
+
+ mPipBoundsState.setShelfVisibility(true, 100, false);
+
+ verify(callback).accept(true, 100, false);
}
@Test
public void testSetShelfVisibility_notChanged_callbackNotInvoked() {
- final BiConsumer<Boolean, Integer> callback = mock(BiConsumer.class);
+ final TriConsumer<Boolean, Integer, Boolean> callback = mock(TriConsumer.class);
mPipBoundsState.setShelfVisibility(true, 100);
mPipBoundsState.setOnShelfVisibilityChangeCallback(callback);
mPipBoundsState.setShelfVisibility(true, 100);
- verify(callback, never()).accept(true, 100);
+ verify(callback, never()).accept(true, 100, true);
}
@Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
index f5628ab..07115c2 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
@@ -41,11 +41,14 @@
import android.view.View;
import android.view.WindowManager;
import android.view.WindowMetrics;
+import android.window.StartingWindowInfo;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.wm.shell.common.HandlerExecutor;
+import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.startingsurface.StartingSurfaceDrawer;
import org.junit.Before;
@@ -70,8 +73,8 @@
static final class TestStartingSurfaceDrawer extends StartingSurfaceDrawer{
int mAddWindowForTask = 0;
- TestStartingSurfaceDrawer(Context context) {
- super(context);
+ TestStartingSurfaceDrawer(Context context, ShellExecutor executor) {
+ super(context, executor);
}
@Override
@@ -109,36 +112,38 @@
doReturn(metrics).when(mMockWindowManager).getMaximumWindowMetrics();
doNothing().when(mMockWindowManager).addView(any(), any());
- mStartingSurfaceDrawer = spy(new TestStartingSurfaceDrawer(context));
+ mStartingSurfaceDrawer = spy(new TestStartingSurfaceDrawer(context,
+ new HandlerExecutor(new Handler(Looper.getMainLooper()))));
}
@Test
public void testAddSplashScreenSurface() {
final int taskId = 1;
final Handler mainLoop = new Handler(Looper.getMainLooper());
- final ActivityManager.RunningTaskInfo taskInfo =
- createTaskInfo(taskId, WINDOWING_MODE_FULLSCREEN);
- mStartingSurfaceDrawer.addStartingWindow(taskInfo, mBinder);
+ final StartingWindowInfo windowInfo =
+ createWindowInfo(taskId, WINDOWING_MODE_FULLSCREEN);
+ mStartingSurfaceDrawer.addStartingWindow(windowInfo, mBinder);
waitHandlerIdle(mainLoop);
verify(mStartingSurfaceDrawer).postAddWindow(eq(taskId), eq(mBinder), any(), any(), any());
assertEquals(mStartingSurfaceDrawer.mAddWindowForTask, taskId);
- mStartingSurfaceDrawer.removeStartingWindow(taskInfo);
+ mStartingSurfaceDrawer.removeStartingWindow(windowInfo.taskInfo.taskId);
waitHandlerIdle(mainLoop);
verify(mStartingSurfaceDrawer).removeWindowSynced(eq(taskId));
assertEquals(mStartingSurfaceDrawer.mAddWindowForTask, 0);
}
- private ActivityManager.RunningTaskInfo createTaskInfo(int taskId, int windowingMode) {
- ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo();
+ private StartingWindowInfo createWindowInfo(int taskId, int windowingMode) {
+ StartingWindowInfo windowInfo = new StartingWindowInfo();
final ActivityInfo info = new ActivityInfo();
info.applicationInfo = new ApplicationInfo();
info.packageName = "test";
info.theme = android.R.style.Theme;
+ final ActivityManager.RunningTaskInfo taskInfo = new ActivityManager.RunningTaskInfo();
taskInfo.topActivityInfo = info;
taskInfo.taskId = taskId;
- taskInfo.configuration.windowConfiguration.setWindowingMode(windowingMode);
- return taskInfo;
+ windowInfo.taskInfo = taskInfo;
+ return windowInfo;
}
private static void waitHandlerIdle(Handler handler) {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/TaskSnapshotWindowTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/TaskSnapshotWindowTest.java
new file mode 100644
index 0000000..94af329
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/TaskSnapshotWindowTest.java
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package unittest.src.com.android.wm.shell.startingsurface;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
+
+import android.app.ActivityManager.TaskDescription;
+import android.content.ComponentName;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorSpace;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.hardware.HardwareBuffer;
+import android.view.InsetsState;
+import android.view.Surface;
+import android.view.SurfaceControl;
+import android.window.TaskSnapshot;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.wm.shell.startingsurface.TaskSnapshotWindow;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test class for {@link TaskSnapshotWindow}.
+ *
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class TaskSnapshotWindowTest {
+
+ private TaskSnapshotWindow mWindow;
+
+ private void setupSurface(int width, int height) {
+ setupSurface(width, height, new Rect(), 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
+ new Rect(0, 0, width, height));
+ }
+
+ private void setupSurface(int width, int height, Rect contentInsets, int sysuiVis,
+ int windowFlags, Rect taskBounds) {
+ // Previously when constructing TaskSnapshots for this test, scale was 1.0f, so to mimic
+ // this behavior set the taskSize to be the same as the taskBounds width and height. The
+ // taskBounds passed here are assumed to be the same task bounds as when the snapshot was
+ // taken. We assume there is no aspect ratio mismatch between the screenshot and the
+ // taskBounds
+ assertEquals(width, taskBounds.width());
+ assertEquals(height, taskBounds.height());
+ Point taskSize = new Point(taskBounds.width(), taskBounds.height());
+
+ final TaskSnapshot snapshot = createTaskSnapshot(width, height, taskSize, contentInsets);
+ mWindow = new TaskSnapshotWindow(new SurfaceControl(), snapshot, "Test",
+ createTaskDescription(Color.WHITE, Color.RED, Color.BLUE),
+ 0 /* appearance */, windowFlags /* windowFlags */, 0 /* privateWindowFlags */,
+ taskBounds, ORIENTATION_PORTRAIT, ACTIVITY_TYPE_STANDARD, new InsetsState(),
+ null /* clearWindow */);
+ }
+
+ private TaskSnapshot createTaskSnapshot(int width, int height, Point taskSize,
+ Rect contentInsets) {
+ final HardwareBuffer buffer = HardwareBuffer.create(width, height, HardwareBuffer.RGBA_8888,
+ 1, HardwareBuffer.USAGE_CPU_READ_RARELY);
+ return new TaskSnapshot(
+ System.currentTimeMillis(),
+ new ComponentName("", ""), buffer,
+ ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT,
+ Surface.ROTATION_0, taskSize, contentInsets, false,
+ true /* isRealSnapshot */, WINDOWING_MODE_FULLSCREEN,
+ 0 /* systemUiVisibility */, false /* isTranslucent */);
+ }
+
+ private static TaskDescription createTaskDescription(int background, int statusBar,
+ int navigationBar) {
+ final TaskDescription td = new TaskDescription();
+ td.setBackgroundColor(background);
+ td.setStatusBarColor(statusBar);
+ td.setNavigationBarColor(navigationBar);
+ return td;
+ }
+
+ @Test
+ public void fillEmptyBackground_fillHorizontally() {
+ setupSurface(200, 100);
+ final Canvas mockCanvas = mock(Canvas.class);
+ when(mockCanvas.getWidth()).thenReturn(200);
+ when(mockCanvas.getHeight()).thenReturn(100);
+ mWindow.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 100, 200));
+ verify(mockCanvas).drawRect(eq(100.0f), eq(0.0f), eq(200.0f), eq(100.0f), any());
+ }
+
+ @Test
+ public void fillEmptyBackground_fillVertically() {
+ setupSurface(100, 200);
+ final Canvas mockCanvas = mock(Canvas.class);
+ when(mockCanvas.getWidth()).thenReturn(100);
+ when(mockCanvas.getHeight()).thenReturn(200);
+ mWindow.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 200, 100));
+ verify(mockCanvas).drawRect(eq(0.0f), eq(100.0f), eq(100.0f), eq(200.0f), any());
+ }
+
+ @Test
+ public void fillEmptyBackground_fillBoth() {
+ setupSurface(200, 200);
+ final Canvas mockCanvas = mock(Canvas.class);
+ when(mockCanvas.getWidth()).thenReturn(200);
+ when(mockCanvas.getHeight()).thenReturn(200);
+ mWindow.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 100, 100));
+ verify(mockCanvas).drawRect(eq(100.0f), eq(0.0f), eq(200.0f), eq(100.0f), any());
+ verify(mockCanvas).drawRect(eq(0.0f), eq(100.0f), eq(200.0f), eq(200.0f), any());
+ }
+
+ @Test
+ public void fillEmptyBackground_dontFill_sameSize() {
+ setupSurface(100, 100);
+ final Canvas mockCanvas = mock(Canvas.class);
+ when(mockCanvas.getWidth()).thenReturn(100);
+ when(mockCanvas.getHeight()).thenReturn(100);
+ mWindow.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 100, 100));
+ verify(mockCanvas, never()).drawRect(anyInt(), anyInt(), anyInt(), anyInt(), any());
+ }
+
+ @Test
+ public void fillEmptyBackground_dontFill_bitmapLarger() {
+ setupSurface(100, 100);
+ final Canvas mockCanvas = mock(Canvas.class);
+ when(mockCanvas.getWidth()).thenReturn(100);
+ when(mockCanvas.getHeight()).thenReturn(100);
+ mWindow.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 200, 200));
+ verify(mockCanvas, never()).drawRect(anyInt(), anyInt(), anyInt(), anyInt(), any());
+ }
+
+ @Test
+ public void testCalculateSnapshotCrop() {
+ setupSurface(100, 100, new Rect(0, 10, 0, 10), 0, 0, new Rect(0, 0, 100, 100));
+ assertEquals(new Rect(0, 0, 100, 90), mWindow.calculateSnapshotCrop());
+ }
+
+ @Test
+ public void testCalculateSnapshotCrop_taskNotOnTop() {
+ setupSurface(100, 100, new Rect(0, 10, 0, 10), 0, 0, new Rect(0, 50, 100, 150));
+ assertEquals(new Rect(0, 10, 100, 90), mWindow.calculateSnapshotCrop());
+ }
+
+ @Test
+ public void testCalculateSnapshotCrop_navBarLeft() {
+ setupSurface(100, 100, new Rect(10, 10, 0, 0), 0, 0, new Rect(0, 0, 100, 100));
+ assertEquals(new Rect(10, 0, 100, 100), mWindow.calculateSnapshotCrop());
+ }
+
+ @Test
+ public void testCalculateSnapshotCrop_navBarRight() {
+ setupSurface(100, 100, new Rect(0, 10, 10, 0), 0, 0, new Rect(0, 0, 100, 100));
+ assertEquals(new Rect(0, 0, 90, 100), mWindow.calculateSnapshotCrop());
+ }
+
+ @Test
+ public void testCalculateSnapshotCrop_waterfall() {
+ setupSurface(100, 100, new Rect(5, 10, 5, 10), 0, 0, new Rect(0, 0, 100, 100));
+ assertEquals(new Rect(5, 0, 95, 90), mWindow.calculateSnapshotCrop());
+ }
+
+ @Test
+ public void testCalculateSnapshotFrame() {
+ setupSurface(100, 100);
+ final Rect insets = new Rect(0, 10, 0, 10);
+ mWindow.setFrames(new Rect(0, 0, 100, 100), insets);
+ assertEquals(new Rect(0, 0, 100, 80),
+ mWindow.calculateSnapshotFrame(new Rect(0, 10, 100, 90)));
+ }
+
+ @Test
+ public void testCalculateSnapshotFrame_navBarLeft() {
+ setupSurface(100, 100);
+ final Rect insets = new Rect(10, 10, 0, 0);
+ mWindow.setFrames(new Rect(0, 0, 100, 100), insets);
+ assertEquals(new Rect(10, 0, 100, 90),
+ mWindow.calculateSnapshotFrame(new Rect(10, 10, 100, 100)));
+ }
+
+ @Test
+ public void testCalculateSnapshotFrame_waterfall() {
+ setupSurface(100, 100, new Rect(5, 10, 5, 10), 0, 0, new Rect(0, 0, 100, 100));
+ final Rect insets = new Rect(0, 10, 0, 10);
+ mWindow.setFrames(new Rect(5, 0, 95, 100), insets);
+ assertEquals(new Rect(0, 0, 90, 90),
+ mWindow.calculateSnapshotFrame(new Rect(5, 0, 95, 90)));
+ }
+
+ @Test
+ public void testDrawStatusBarBackground() {
+ setupSurface(100, 100);
+ final Rect insets = new Rect(0, 10, 10, 0);
+ mWindow.setFrames(new Rect(0, 0, 100, 100), insets);
+ final Canvas mockCanvas = mock(Canvas.class);
+ when(mockCanvas.getWidth()).thenReturn(100);
+ when(mockCanvas.getHeight()).thenReturn(100);
+ mWindow.drawStatusBarBackground(mockCanvas, new Rect(0, 0, 50, 100));
+ verify(mockCanvas).drawRect(eq(50.0f), eq(0.0f), eq(90.0f), eq(10.0f), any());
+ }
+
+ @Test
+ public void testDrawStatusBarBackground_nullFrame() {
+ setupSurface(100, 100);
+ final Rect insets = new Rect(0, 10, 10, 0);
+ mWindow.setFrames(new Rect(0, 0, 100, 100), insets);
+ final Canvas mockCanvas = mock(Canvas.class);
+ when(mockCanvas.getWidth()).thenReturn(100);
+ when(mockCanvas.getHeight()).thenReturn(100);
+ mWindow.drawStatusBarBackground(mockCanvas, null);
+ verify(mockCanvas).drawRect(eq(0.0f), eq(0.0f), eq(90.0f), eq(10.0f), any());
+ }
+
+ @Test
+ public void testDrawStatusBarBackground_nope() {
+ setupSurface(100, 100);
+ final Rect insets = new Rect(0, 10, 10, 0);
+ mWindow.setFrames(new Rect(0, 0, 100, 100), insets);
+ final Canvas mockCanvas = mock(Canvas.class);
+ when(mockCanvas.getWidth()).thenReturn(100);
+ when(mockCanvas.getHeight()).thenReturn(100);
+ mWindow.drawStatusBarBackground(mockCanvas, new Rect(0, 0, 100, 100));
+ verify(mockCanvas, never()).drawRect(anyInt(), anyInt(), anyInt(), anyInt(), any());
+ }
+
+ @Test
+ public void testDrawNavigationBarBackground() {
+ final Rect insets = new Rect(0, 10, 0, 10);
+ setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
+ new Rect(0, 0, 100, 100));
+ mWindow.setFrames(new Rect(0, 0, 100, 100), insets);
+ final Canvas mockCanvas = mock(Canvas.class);
+ when(mockCanvas.getWidth()).thenReturn(100);
+ when(mockCanvas.getHeight()).thenReturn(100);
+ mWindow.drawNavigationBarBackground(mockCanvas);
+ verify(mockCanvas).drawRect(eq(new Rect(0, 90, 100, 100)), any());
+ }
+
+ @Test
+ public void testDrawNavigationBarBackground_left() {
+ final Rect insets = new Rect(10, 10, 0, 0);
+ setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
+ new Rect(0, 0, 100, 100));
+ mWindow.setFrames(new Rect(0, 0, 100, 100), insets);
+ final Canvas mockCanvas = mock(Canvas.class);
+ when(mockCanvas.getWidth()).thenReturn(100);
+ when(mockCanvas.getHeight()).thenReturn(100);
+ mWindow.drawNavigationBarBackground(mockCanvas);
+ verify(mockCanvas).drawRect(eq(new Rect(0, 0, 10, 100)), any());
+ }
+
+ @Test
+ public void testDrawNavigationBarBackground_right() {
+ final Rect insets = new Rect(0, 10, 10, 0);
+ setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
+ new Rect(0, 0, 100, 100));
+ mWindow.setFrames(new Rect(0, 0, 100, 100), insets);
+ final Canvas mockCanvas = mock(Canvas.class);
+ when(mockCanvas.getWidth()).thenReturn(100);
+ when(mockCanvas.getHeight()).thenReturn(100);
+ mWindow.drawNavigationBarBackground(mockCanvas);
+ verify(mockCanvas).drawRect(eq(new Rect(90, 0, 100, 100)), any());
+ }
+}
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index a545b3d..bec80a7 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -670,7 +670,7 @@
}
auto entry_flags = type_spec->GetFlagsForEntryIndex(entry_idx);
- if (UNLIKELY(!entry_flags)) {
+ if (UNLIKELY(!entry_flags.has_value())) {
return base::unexpected(entry_flags.error());
}
type_flags |= entry_flags.value();
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 4010e4e..bce70e2 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -897,12 +897,12 @@
// Decode the UTF-16 length. This is not used if we're not
// converting to UTF-16 from UTF-8.
const base::expected<size_t, IOError> u16len = decodeLength(&str);
- if (UNLIKELY(!u16len)) {
+ if (UNLIKELY(!u16len.has_value())) {
return base::unexpected(u16len.error());
}
const base::expected<size_t, IOError> u8len = decodeLength(&str);
- if (UNLIKELY(!u8len)) {
+ if (UNLIKELY(!u8len.has_value())) {
return base::unexpected(u8len.error());
}
diff --git a/libs/androidfw/ResourceUtils.cpp b/libs/androidfw/ResourceUtils.cpp
index a34aa72..87fb2c0 100644
--- a/libs/androidfw/ResourceUtils.cpp
+++ b/libs/androidfw/ResourceUtils.cpp
@@ -56,7 +56,8 @@
.package_len = package_name.size(),
};
- if (base::expected<StringPiece, NullOrIOError> type_str = type_string_ref.string8()) {
+ if (base::expected<StringPiece, NullOrIOError> type_str = type_string_ref.string8();
+ type_str.ok()) {
name.type = type_str->data();
name.type_len = type_str->size();
} else if (UNLIKELY(IsIOError(type_str))) {
@@ -64,7 +65,8 @@
}
if (name.type == nullptr) {
- if (base::expected<StringPiece16, NullOrIOError> type16_str = type_string_ref.string16()) {
+ if (base::expected<StringPiece16, NullOrIOError> type16_str = type_string_ref.string16();
+ type16_str.ok()) {
name.type16 = type16_str->data();
name.type_len = type16_str->size();
} else if (!type16_str.has_value()) {
@@ -72,7 +74,8 @@
}
}
- if (base::expected<StringPiece, NullOrIOError> entry_str = entry_string_ref.string8()) {
+ if (base::expected<StringPiece, NullOrIOError> entry_str = entry_string_ref.string8();
+ entry_str.ok()) {
name.entry = entry_str->data();
name.entry_len = entry_str->size();
} else if (UNLIKELY(IsIOError(entry_str))) {
@@ -80,7 +83,8 @@
}
if (name.entry == nullptr) {
- if (base::expected<StringPiece16, NullOrIOError> entry16_str = entry_string_ref.string16()) {
+ if (base::expected<StringPiece16, NullOrIOError> entry16_str = entry_string_ref.string16();
+ entry16_str.ok()) {
name.entry16 = entry16_str->data();
name.entry_len = entry16_str->size();
} else if (!entry16_str.has_value()) {
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 0533aa6..9d82f63 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -618,6 +618,7 @@
"tests/unit/LayerUpdateQueueTests.cpp",
"tests/unit/LinearAllocatorTests.cpp",
"tests/unit/MatrixTests.cpp",
+ "tests/unit/OpBufferTests.cpp",
"tests/unit/PathInterpolatorTests.cpp",
"tests/unit/RenderNodeDrawableTests.cpp",
"tests/unit/RenderNodeTests.cpp",
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 9a4ed81..acb74f4 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -669,7 +669,10 @@
if (paint) {
pnt = *paint;
}
- pnt.setShader(bitmap.makeImage()->makeShader());
+ SkSamplingOptions sampling(pnt.isFilterBitmap() ? SkFilterMode::kLinear
+ : SkFilterMode::kNearest,
+ SkMipmapMode::kNone);
+ pnt.setShader(bitmap.makeImage()->makeShader(sampling));
auto v = builder.detach();
apply_looper(&pnt, [&](const SkPaint& p) {
mCanvas->drawVertices(v, SkBlendMode::kModulate, p);
diff --git a/libs/hwui/canvas/OpBuffer.h b/libs/hwui/canvas/OpBuffer.h
index 6dc29d9..1237d69 100644
--- a/libs/hwui/canvas/OpBuffer.h
+++ b/libs/hwui/canvas/OpBuffer.h
@@ -144,7 +144,86 @@
ItemHeader* last() const { return isEmpty() ? nullptr : itemAt(mBuffer->endOffset); }
+ class sentinal {
+ public:
+ explicit sentinal(const uint8_t* end) : end(end) {}
+ private:
+ const uint8_t* const end;
+ };
+
+ sentinal end() const {
+ return sentinal{end_ptr()};
+ }
+
+ template <ItemTypes T>
+ class filtered_iterator {
+ public:
+ explicit filtered_iterator(uint8_t* start, const uint8_t* end)
+ : mCurrent(start), mEnd(end) {
+ ItemHeader* header = reinterpret_cast<ItemHeader*>(mCurrent);
+ if (header->type != T) {
+ advance();
+ }
+ }
+
+ filtered_iterator& operator++() {
+ advance();
+ return *this;
+ }
+
+ // Although this iterator self-terminates, we need a placeholder to compare against
+ // to make for-each loops happy
+ bool operator!=(const sentinal& other) const {
+ return mCurrent != mEnd;
+ }
+
+ ItemContainer<T>& operator*() {
+ return *reinterpret_cast<ItemContainer<T>*>(mCurrent);
+ }
+ private:
+ void advance() {
+ ItemHeader* header = reinterpret_cast<ItemHeader*>(mCurrent);
+ do {
+ mCurrent += header->size;
+ header = reinterpret_cast<ItemHeader*>(mCurrent);
+ } while (mCurrent != mEnd && header->type != T);
+ }
+ uint8_t* mCurrent;
+ const uint8_t* const mEnd;
+ };
+
+ template <ItemTypes T>
+ class filtered_view {
+ public:
+ explicit filtered_view(uint8_t* start, const uint8_t* end) : mStart(start), mEnd(end) {}
+
+ filtered_iterator<T> begin() const {
+ return filtered_iterator<T>{mStart, mEnd};
+ }
+
+ sentinal end() const {
+ return sentinal{mEnd};
+ }
+ private:
+ uint8_t* mStart;
+ const uint8_t* const mEnd;
+ };
+
+ template <ItemTypes T>
+ filtered_view<T> filter() const {
+ return filtered_view<T>{start_ptr(), end_ptr()};
+ }
+
private:
+
+ uint8_t* start_ptr() const {
+ return reinterpret_cast<uint8_t*>(mBuffer) + mBuffer->startOffset;
+ }
+
+ const uint8_t* end_ptr() const {
+ return reinterpret_cast<uint8_t*>(mBuffer) + mBuffer->used;
+ }
+
template <typename F, std::size_t... I>
void for_each(F&& f, std::index_sequence<I...>) const {
// Validate we're not empty
@@ -159,8 +238,8 @@
}...};
// Do the actual iteration of each item
- uint8_t* current = reinterpret_cast<uint8_t*>(mBuffer) + mBuffer->startOffset;
- uint8_t* end = reinterpret_cast<uint8_t*>(mBuffer) + mBuffer->used;
+ uint8_t* current = start_ptr();
+ const uint8_t* end = end_ptr();
while (current != end) {
auto header = reinterpret_cast<ItemHeader*>(current);
// `f` could be a destructor, so ensure all accesses to the OP happen prior to invoking
diff --git a/libs/hwui/hwui/Paint.h b/libs/hwui/hwui/Paint.h
index e75e9e7..05bae5c 100644
--- a/libs/hwui/hwui/Paint.h
+++ b/libs/hwui/hwui/Paint.h
@@ -137,6 +137,9 @@
bool isDevKern() const { return mDevKern; }
void setDevKern(bool d) { mDevKern = d; }
+ // Deprecated -- bitmapshaders will be taking this flag explicitly
+ bool isFilterBitmap() const { return this->getFilterQuality() != kNone_SkFilterQuality; }
+
// The Java flags (Paint.java) no longer fit into the native apis directly.
// These methods handle converting to and from them and the native representations
// in android::Paint.
@@ -149,7 +152,7 @@
// The only respected flags are : [ antialias, dither, filterBitmap ]
static uint32_t GetSkPaintJavaFlags(const SkPaint&);
static void SetSkPaintJavaFlags(SkPaint*, uint32_t flags);
-
+
private:
SkFont mFont;
sk_sp<SkDrawLooper> mLooper;
diff --git a/libs/hwui/jni/Shader.cpp b/libs/hwui/jni/Shader.cpp
index 45795ff..aaec60b 100644
--- a/libs/hwui/jni/Shader.cpp
+++ b/libs/hwui/jni/Shader.cpp
@@ -61,7 +61,7 @@
///////////////////////////////////////////////////////////////////////////////////////////////
static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong matrixPtr, jlong bitmapHandle,
- jint tileModeX, jint tileModeY) {
+ jint tileModeX, jint tileModeY, bool filter) {
const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
sk_sp<SkImage> image;
if (bitmapHandle) {
@@ -74,8 +74,10 @@
SkBitmap bitmap;
image = SkMakeImageFromRasterBitmap(bitmap, kNever_SkCopyPixelsMode);
}
+ SkSamplingOptions sampling(filter ? SkFilterMode::kLinear : SkFilterMode::kNearest,
+ SkMipmapMode::kNone);
sk_sp<SkShader> shader = image->makeShader(
- (SkTileMode)tileModeX, (SkTileMode)tileModeY);
+ (SkTileMode)tileModeX, (SkTileMode)tileModeY, sampling);
ThrowIAE_IfNull(env, shader.get());
if (matrix) {
@@ -291,7 +293,7 @@
};
static const JNINativeMethod gBitmapShaderMethods[] = {
- { "nativeCreate", "(JJII)J", (void*)BitmapShader_constructor },
+ { "nativeCreate", "(JJIIZ)J", (void*)BitmapShader_constructor },
};
static const JNINativeMethod gLinearGradientMethods[] = {
diff --git a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
index bfbdc5c..c6c9e9d 100644
--- a/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
+++ b/libs/hwui/pipeline/skia/GLFunctorDrawable.cpp
@@ -19,8 +19,6 @@
#include <private/hwui/DrawGlInfo.h>
#include "FunctorDrawable.h"
#include "GrBackendSurface.h"
-#include "GrRenderTarget.h"
-#include "GrRenderTargetContext.h"
#include "RenderNode.h"
#include "SkAndroidFrameworkUtils.h"
#include "SkClipStack.h"
@@ -40,19 +38,13 @@
}
static void GetFboDetails(SkCanvas* canvas, GLuint* outFboID, SkISize* outFboSize) {
- GrRenderTargetContext* renderTargetContext =
- canvas->internal_private_accessTopLayerRenderTargetContext();
- LOG_ALWAYS_FATAL_IF(!renderTargetContext, "Failed to retrieve GrRenderTargetContext");
-
- GrRenderTarget* renderTarget = renderTargetContext->accessRenderTarget();
- LOG_ALWAYS_FATAL_IF(!renderTarget, "accessRenderTarget failed");
-
+ GrBackendRenderTarget renderTarget = canvas->topLayerBackendRenderTarget();
GrGLFramebufferInfo fboInfo;
- LOG_ALWAYS_FATAL_IF(!renderTarget->getBackendRenderTarget().getGLFramebufferInfo(&fboInfo),
+ LOG_ALWAYS_FATAL_IF(!renderTarget.getGLFramebufferInfo(&fboInfo),
"getGLFrameBufferInfo failed");
*outFboID = fboInfo.fFBOID;
- *outFboSize = SkISize::Make(renderTargetContext->width(), renderTargetContext->height());
+ *outFboSize = renderTarget.dimensions();
}
void GLFunctorDrawable::onDraw(SkCanvas* canvas) {
@@ -75,7 +67,7 @@
SkISize fboSize;
GetFboDetails(canvas, &fboID, &fboSize);
- SkIRect surfaceBounds = canvas->internal_private_getTopLayerBounds();
+ SkIRect surfaceBounds = canvas->topLayerBounds();
SkIRect clipBounds = canvas->getDeviceClipBounds();
SkM44 mat4(canvas->getLocalToDevice());
SkRegion clipRegion;
diff --git a/libs/hwui/tests/common/scenes/BitmapShaders.cpp b/libs/hwui/tests/common/scenes/BitmapShaders.cpp
index c4067af..03aeb55 100644
--- a/libs/hwui/tests/common/scenes/BitmapShaders.cpp
+++ b/libs/hwui/tests/common/scenes/BitmapShaders.cpp
@@ -44,15 +44,16 @@
skCanvas.drawRect(SkRect::MakeXYWH(100, 100, 100, 100), skPaint);
});
+ SkSamplingOptions sampling;
Paint paint;
sk_sp<SkImage> image = hwuiBitmap->makeImage();
sk_sp<SkShader> repeatShader =
- image->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat);
+ image->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, sampling);
paint.setShader(std::move(repeatShader));
canvas.drawRoundRect(0, 0, 500, 500, 50.0f, 50.0f, paint);
sk_sp<SkShader> mirrorShader =
- image->makeShader(SkTileMode::kMirror, SkTileMode::kMirror);
+ image->makeShader(SkTileMode::kMirror, SkTileMode::kMirror, sampling);
paint.setShader(std::move(mirrorShader));
canvas.drawRoundRect(0, 600, 500, 1100, 50.0f, 50.0f, paint);
}
diff --git a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
index 5886ea3..564354f 100644
--- a/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
+++ b/libs/hwui/tests/common/scenes/HwBitmapInCompositeShader.cpp
@@ -74,6 +74,6 @@
sk_sp<SkShader> createBitmapShader(Bitmap& bitmap) {
sk_sp<SkImage> image = bitmap.makeImage();
- return image->makeShader();
+ return image->makeShader(SkSamplingOptions());
}
};
diff --git a/libs/hwui/tests/unit/CanvasOpTests.cpp b/libs/hwui/tests/unit/CanvasOpTests.cpp
index 033a587..a09e742 100644
--- a/libs/hwui/tests/unit/CanvasOpTests.cpp
+++ b/libs/hwui/tests/unit/CanvasOpTests.cpp
@@ -36,50 +36,6 @@
// We lazy
using Op = CanvasOpType;
-enum MockTypes {
- Lifecycle,
- COUNT
-};
-
-template<MockTypes T>
-struct MockOp;
-
-template<MockTypes T>
-struct MockOpContainer {
- OpBufferItemHeader<MockTypes> header;
- MockOp<T> impl;
-};
-
-struct LifecycleTracker {
- int ctor_count = 0;
- int dtor_count = 0;
-
- int alive() { return ctor_count - dtor_count; }
-};
-
-template<>
-struct MockOp<MockTypes::Lifecycle> {
- MockOp() = delete;
- void operator=(const MockOp&) = delete;
-
- MockOp(LifecycleTracker* tracker) : tracker(tracker) {
- tracker->ctor_count += 1;
- }
-
- MockOp(const MockOp& other) {
- tracker = other.tracker;
- tracker->ctor_count += 1;
- }
-
- ~MockOp() {
- tracker->dtor_count += 1;
- }
-
- LifecycleTracker* tracker = nullptr;
-};
-
-using MockBuffer = OpBuffer<MockTypes, MockOpContainer>;
-
class CanvasOpCountingReceiver {
public:
template <CanvasOpType T>
@@ -104,62 +60,6 @@
return count;
}
-TEST(CanvasOp, lifecycleCheck) {
- LifecycleTracker tracker;
- {
- MockBuffer buffer;
- buffer.push_container(MockOpContainer<MockTypes::Lifecycle> {
- .impl = MockOp<MockTypes::Lifecycle>{&tracker}
- });
- EXPECT_EQ(tracker.alive(), 1);
- buffer.clear();
- EXPECT_EQ(tracker.alive(), 0);
- }
- EXPECT_EQ(tracker.alive(), 0);
-}
-
-TEST(CanvasOp, lifecycleCheckMove) {
- LifecycleTracker tracker;
- {
- MockBuffer buffer;
- buffer.push_container(MockOpContainer<MockTypes::Lifecycle> {
- .impl = MockOp<MockTypes::Lifecycle>{&tracker}
- });
- EXPECT_EQ(tracker.alive(), 1);
- {
- MockBuffer other(std::move(buffer));
- EXPECT_EQ(tracker.alive(), 1);
- EXPECT_EQ(buffer.size(), 0);
- EXPECT_GT(other.size(), 0);
- EXPECT_EQ(1, countItems(other));
- EXPECT_EQ(0, countItems(buffer));
-
- other.push_container(MockOpContainer<MockTypes::Lifecycle> {
- .impl = MockOp<MockTypes::Lifecycle>{&tracker}
- });
-
- EXPECT_EQ(2, countItems(other));
- EXPECT_EQ(2, tracker.alive());
-
- buffer.push_container(MockOpContainer<MockTypes::Lifecycle> {
- .impl = MockOp<MockTypes::Lifecycle>{&tracker}
- });
- EXPECT_EQ(1, countItems(buffer));
- EXPECT_EQ(3, tracker.alive());
-
- buffer = std::move(other);
- EXPECT_EQ(2, countItems(buffer));
- EXPECT_EQ(2, tracker.alive());
- }
- EXPECT_EQ(2, countItems(buffer));
- EXPECT_EQ(2, tracker.alive());
- buffer.clear();
- EXPECT_EQ(0, countItems(buffer));
- EXPECT_EQ(0, tracker.alive());
- }
- EXPECT_EQ(tracker.alive(), 0);
-}
-
TEST(CanvasOp, verifyConst) {
CanvasOpBuffer buffer;
buffer.push<Op::DrawColor>({
@@ -708,7 +608,3 @@
EXPECT_EQ(1, receiver[Op::Save]);
EXPECT_EQ(1, receiver[Op::Restore]);
}
-
-TEST(CanvasOp, frontendTransform) {
-
-}
\ No newline at end of file
diff --git a/libs/hwui/tests/unit/OpBufferTests.cpp b/libs/hwui/tests/unit/OpBufferTests.cpp
new file mode 100644
index 0000000..c0ae943
--- /dev/null
+++ b/libs/hwui/tests/unit/OpBufferTests.cpp
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <canvas/OpBuffer.h>
+
+using namespace android;
+using namespace android::uirenderer;
+
+enum MockTypes {
+ Lifecycle,
+ NoOp,
+ IntHolder,
+ COUNT
+};
+
+using Op = MockTypes;
+
+template<MockTypes T>
+struct MockOp;
+
+template<MockTypes T>
+struct MockOpContainer {
+ OpBufferItemHeader<MockTypes> header;
+ MockOp<T> impl;
+
+ MockOpContainer(MockOp<T>&& impl) : impl(std::move(impl)) {}
+};
+
+struct LifecycleTracker {
+ int ctor_count = 0;
+ int dtor_count = 0;
+
+ int alive() { return ctor_count - dtor_count; }
+};
+
+template<>
+struct MockOp<MockTypes::Lifecycle> {
+ MockOp() = delete;
+ void operator=(const MockOp&) = delete;
+
+ MockOp(LifecycleTracker* tracker) : tracker(tracker) {
+ tracker->ctor_count += 1;
+ }
+
+ MockOp(const MockOp& other) {
+ tracker = other.tracker;
+ tracker->ctor_count += 1;
+ }
+
+ ~MockOp() {
+ tracker->dtor_count += 1;
+ }
+
+ LifecycleTracker* tracker = nullptr;
+};
+
+template<>
+struct MockOp<MockTypes::NoOp> {};
+
+template<>
+struct MockOp<MockTypes::IntHolder> {
+ int value = -1;
+};
+
+struct MockBuffer : public OpBuffer<MockTypes, MockOpContainer> {
+ template <MockTypes T>
+ void push(MockOp<T>&& op) {
+ push_container(MockOpContainer<T>{std::move(op)});
+ }
+};
+
+template<typename T>
+static int countItems(const T& t) {
+ int count = 0;
+ t.for_each([&](auto i) {
+ count++;
+ });
+ return count;
+}
+
+TEST(OpBuffer, lifecycleCheck) {
+ LifecycleTracker tracker;
+ {
+ MockBuffer buffer;
+ buffer.push_container(MockOpContainer<Op::Lifecycle> {
+ MockOp<MockTypes::Lifecycle>{&tracker}
+ });
+ EXPECT_EQ(tracker.alive(), 1);
+ buffer.clear();
+ EXPECT_EQ(tracker.alive(), 0);
+ }
+ EXPECT_EQ(tracker.alive(), 0);
+}
+
+TEST(OpBuffer, lifecycleCheckMove) {
+ LifecycleTracker tracker;
+ {
+ MockBuffer buffer;
+ buffer.push_container(MockOpContainer<Op::Lifecycle> {
+ MockOp<MockTypes::Lifecycle>{&tracker}
+ });
+ EXPECT_EQ(tracker.alive(), 1);
+ {
+ MockBuffer other(std::move(buffer));
+ EXPECT_EQ(tracker.alive(), 1);
+ EXPECT_EQ(buffer.size(), 0);
+ EXPECT_GT(other.size(), 0);
+ EXPECT_EQ(1, countItems(other));
+ EXPECT_EQ(0, countItems(buffer));
+
+ other.push_container(MockOpContainer<MockTypes::Lifecycle> {
+ MockOp<MockTypes::Lifecycle>{&tracker}
+ });
+
+ EXPECT_EQ(2, countItems(other));
+ EXPECT_EQ(2, tracker.alive());
+
+ buffer.push_container(MockOpContainer<MockTypes::Lifecycle> {
+ MockOp<MockTypes::Lifecycle>{&tracker}
+ });
+ EXPECT_EQ(1, countItems(buffer));
+ EXPECT_EQ(3, tracker.alive());
+
+ buffer = std::move(other);
+ EXPECT_EQ(2, countItems(buffer));
+ EXPECT_EQ(2, tracker.alive());
+ }
+ EXPECT_EQ(2, countItems(buffer));
+ EXPECT_EQ(2, tracker.alive());
+ buffer.clear();
+ EXPECT_EQ(0, countItems(buffer));
+ EXPECT_EQ(0, tracker.alive());
+ }
+ EXPECT_EQ(tracker.alive(), 0);
+}
+
+TEST(OpBuffer, verifyConst) {
+ MockBuffer buffer;
+ buffer.push<Op::IntHolder>({42});
+ buffer.for_each([](auto op) {
+ static_assert(std::is_const_v<std::remove_reference_t<decltype(*op)>>,
+ "Expected container to be const");
+ });
+}
+
+TEST(OpBuffer, filterView) {
+ MockBuffer buffer;
+ buffer.push<Op::NoOp>({});
+ buffer.push<Op::IntHolder>({0});
+ buffer.push<Op::IntHolder>({1});
+ buffer.push<Op::NoOp>({});
+ buffer.push<Op::NoOp>({});
+ buffer.push<Op::IntHolder>({2});
+ buffer.push<Op::NoOp>({});
+ buffer.push<Op::NoOp>({});
+ buffer.push<Op::NoOp>({});
+ buffer.push<Op::NoOp>({});
+
+
+ int index = 0;
+ for (const auto& it : buffer.filter<Op::IntHolder>()) {
+ ASSERT_EQ(Op::IntHolder, it.header.type);
+ EXPECT_EQ(index, it.impl.value);
+ index++;
+ }
+ EXPECT_EQ(index, 3);
+
+ int count = 0;
+ for (const auto& it : buffer.filter<Op::NoOp>()) {
+ ASSERT_EQ(Op::NoOp, it.header.type);
+ count++;
+ }
+ EXPECT_EQ(count, 7);
+}
+
diff --git a/location/java/android/location/GnssMeasurementRequest.aidl b/location/java/android/location/GnssMeasurementRequest.aidl
new file mode 100644
index 0000000..7e50728
--- /dev/null
+++ b/location/java/android/location/GnssMeasurementRequest.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.location;
+
+parcelable GnssMeasurementRequest;
diff --git a/location/java/android/location/GnssMeasurementRequest.java b/location/java/android/location/GnssMeasurementRequest.java
new file mode 100644
index 0000000..613f591
--- /dev/null
+++ b/location/java/android/location/GnssMeasurementRequest.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.location;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * This class contains extra parameters to pass in a GNSS measurement request.
+ */
+public final class GnssMeasurementRequest implements Parcelable {
+ private final boolean mFullTracking;
+
+ /**
+ * Creates a {@link GnssMeasurementRequest} with a full list of parameters.
+ */
+ private GnssMeasurementRequest(boolean fullTracking) {
+ mFullTracking = fullTracking;
+ }
+
+ /**
+ * Represents whether to enable full GNSS tracking.
+ *
+ * <p>If true, GNSS chipset switches off duty cycling. In such a mode, no clock
+ * discontinuities are expected, and when supported, carrier phase should be continuous in
+ * good signal conditions. All non-blocklisted, healthy constellations, satellites and
+ * frequency bands that the chipset supports must be reported in this mode. The GNSS chipset
+ * will consume more power in full tracking mode than in duty cycling mode. If false, GNSS
+ * chipset optimizes power via duty cycling, constellations and frequency limits, etc.
+ *
+ * <p>Full GNSS tracking mode affects GnssMeasurement and other GNSS functionalities
+ * including GNSS location.
+ */
+ public boolean isFullTracking() {
+ return mFullTracking;
+ }
+
+ @NonNull
+ public static final Creator<GnssMeasurementRequest> CREATOR =
+ new Creator<GnssMeasurementRequest>() {
+ @Override
+ @NonNull
+ public GnssMeasurementRequest createFromParcel(@NonNull Parcel parcel) {
+ return new GnssMeasurementRequest(parcel.readBoolean());
+ }
+
+ @Override
+ public GnssMeasurementRequest[] newArray(int i) {
+ return new GnssMeasurementRequest[i];
+ }
+ };
+
+ @Override
+ public void writeToParcel(@NonNull Parcel parcel, int flags) {
+ parcel.writeBoolean(mFullTracking);
+ }
+
+ @NonNull
+ @Override
+ public String toString() {
+ StringBuilder s = new StringBuilder();
+ s.append("GnssMeasurementRequest[");
+ if (mFullTracking) {
+ s.append("FullTracking");
+ }
+ s.append(']');
+ return s.toString();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null) return false;
+ if (!(obj instanceof GnssMeasurementRequest)) return false;
+
+ GnssMeasurementRequest other = (GnssMeasurementRequest) obj;
+ if (mFullTracking != other.mFullTracking) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return mFullTracking ? 1 : 0;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Builder for {@link GnssMeasurementRequest} */
+ public static final class Builder {
+ private boolean mFullTracking;
+
+ /**
+ * Constructs a {@link Builder} instance.
+ */
+ public Builder() {
+ }
+
+ /**
+ * Constructs a {@link Builder} instance by copying a {@link GnssMeasurementRequest}.
+ */
+ public Builder(@NonNull GnssMeasurementRequest request) {
+ mFullTracking = request.isFullTracking();
+ }
+
+ /**
+ * Set the value of whether to enable full GNSS tracking, which is false by default.
+ *
+ * <p>If true, GNSS chipset switches off duty cycling. In such a mode, no clock
+ * discontinuities are expected, and when supported, carrier phase should be continuous in
+ * good signal conditions. All non-blocklisted, healthy constellations, satellites and
+ * frequency bands that the chipset supports must be reported in this mode. The GNSS chipset
+ * will consume more power in full tracking mode than in duty cycling mode. If false,
+ * GNSS chipset optimizes power via duty cycling, constellations and frequency limits, etc.
+ *
+ * <p>Full GNSS tracking mode affects GnssMeasurement and other GNSS functionalities
+ * including GNSS location.
+ *
+ * <p>Full tracking requests always override non-full tracking requests. If any full
+ * tracking request occurs, all listeners on the device will receive full tracking GNSS
+ * measurements.
+ */
+ @NonNull public Builder setFullTracking(boolean value) {
+ mFullTracking = value;
+ return this;
+ }
+
+ /** Builds a {@link GnssMeasurementRequest} instance as specified by this builder. */
+ @NonNull
+ public GnssMeasurementRequest build() {
+ return new GnssMeasurementRequest(mFullTracking);
+ }
+ }
+}
diff --git a/location/java/android/location/GnssRequest.java b/location/java/android/location/GnssRequest.java
index 5fc9161..9c9766f 100644
--- a/location/java/android/location/GnssRequest.java
+++ b/location/java/android/location/GnssRequest.java
@@ -45,11 +45,23 @@
* frequency bands that the chipset supports must be reported in this mode. The GNSS chipset
* is allowed to consume more power in this mode. If false, GNSS chipset optimizes power via
* duty cycling, constellations and frequency limits, etc.
+ *
+ * <p>Full GNSS tracking mode affects GnssMeasurement and other GNSS functionalities
+ * including GNSS location.
*/
public boolean isFullTracking() {
return mFullTracking;
}
+ /**
+ * Converts the {@link GnssRequest} into a {@link GnssMeasurementRequest}.
+ * @hide
+ */
+ @NonNull
+ public GnssMeasurementRequest toGnssMeasurementRequest() {
+ return new GnssMeasurementRequest.Builder().setFullTracking(isFullTracking()).build();
+ }
+
@NonNull
public static final Creator<GnssRequest> CREATOR =
new Creator<GnssRequest>() {
@@ -131,6 +143,9 @@
* is allowed to consume more power in this mode. If false, GNSS chipset optimizes power via
* duty cycling, constellations and frequency limits, etc.
*
+ * <p>Full GNSS tracking mode affects GnssMeasurement and other GNSS functionalities
+ * including GNSS location.
+ *
* <p>Full tracking requests always override non-full tracking requests. If any full
* tracking request occurs, all listeners on the device will receive full tracking GNSS
* measurements.
diff --git a/location/java/android/location/GnssSignalQuality.java b/location/java/android/location/GnssSignalQuality.java
new file mode 100644
index 0000000..7945f3e
--- /dev/null
+++ b/location/java/android/location/GnssSignalQuality.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.location;
+
+import android.server.location.ServerLocationProtoEnums;
+
+/**
+ * Gnss signal quality information.
+ *
+ * @hide
+ */
+public interface GnssSignalQuality {
+
+ int GNSS_SIGNAL_QUALITY_UNKNOWN =
+ ServerLocationProtoEnums.GPS_SIGNAL_QUALITY_UNKNOWN; // -1
+
+ int GNSS_SIGNAL_QUALITY_POOR =
+ ServerLocationProtoEnums.GPS_SIGNAL_QUALITY_POOR; // 0
+
+ int GNSS_SIGNAL_QUALITY_GOOD =
+ ServerLocationProtoEnums.GPS_SIGNAL_QUALITY_GOOD; // 1
+
+ int NUM_GNSS_SIGNAL_QUALITY_LEVELS = GNSS_SIGNAL_QUALITY_GOOD + 1;
+}
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 92e2136..a666eb4 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -22,7 +22,7 @@
import android.location.GeocoderParams;
import android.location.Geofence;
import android.location.GnssMeasurementCorrections;
-import android.location.GnssRequest;
+import android.location.GnssMeasurementRequest;
import android.location.IGeocodeListener;
import android.location.IGnssAntennaInfoListener;
import android.location.IGnssMeasurementsListener;
@@ -78,7 +78,7 @@
void registerGnssStatusCallback(in IGnssStatusListener callback, String packageName, String attributionTag);
void unregisterGnssStatusCallback(in IGnssStatusListener callback);
- void addGnssMeasurementsListener(in GnssRequest request, in IGnssMeasurementsListener listener, String packageName, String attributionTag);
+ void addGnssMeasurementsListener(in GnssMeasurementRequest request, in IGnssMeasurementsListener listener, String packageName, String attributionTag);
void removeGnssMeasurementsListener(in IGnssMeasurementsListener listener);
void injectGnssMeasurementCorrections(in GnssMeasurementCorrections corrections);
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 914beaf..ecdba1f 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -2371,7 +2371,7 @@
handler = new Handler();
}
- return registerGnssMeasurementsCallback(new GnssRequest.Builder().build(),
+ return registerGnssMeasurementsCallback(new GnssMeasurementRequest.Builder().build(),
new HandlerExecutor(handler), callback);
}
@@ -2390,8 +2390,8 @@
public boolean registerGnssMeasurementsCallback(
@NonNull @CallbackExecutor Executor executor,
@NonNull GnssMeasurementsEvent.Callback callback) {
- return registerGnssMeasurementsCallback(new GnssRequest.Builder().build(), executor,
- callback);
+ return registerGnssMeasurementsCallback(new GnssMeasurementRequest.Builder().build(),
+ executor, callback);
}
/**
@@ -2408,14 +2408,42 @@
* @throws IllegalArgumentException if callback is null
* @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
* @hide
+ * @deprecated Use {@link #registerGnssMeasurementsCallback(GnssMeasurementRequest, Executor,
+ * GnssMeasurementsEvent.Callback)} instead.
*/
+ @Deprecated
@SystemApi
- @RequiresPermission(allOf = {ACCESS_FINE_LOCATION, LOCATION_HARDWARE})
+ @RequiresPermission(ACCESS_FINE_LOCATION)
public boolean registerGnssMeasurementsCallback(
@NonNull GnssRequest request,
@NonNull @CallbackExecutor Executor executor,
@NonNull GnssMeasurementsEvent.Callback callback) {
Preconditions.checkArgument(request != null, "invalid null request");
+ getGnssMeasurementsTransportMultiplexer().addListener(request.toGnssMeasurementRequest(),
+ callback, executor);
+ return true;
+ }
+
+ /**
+ * Registers a GNSS measurement callback.
+ *
+ * @param request extra parameters to pass to GNSS measurement provider. For example, if {@link
+ * GnssMeasurementRequest#isFullTracking()} is true, GNSS chipset switches off
+ * duty cycling.
+ * @param executor the executor that the callback runs on
+ * @param callback a {@link GnssMeasurementsEvent.Callback} object to register.
+ * @return {@code true} always if the callback was added successfully, {@code false} otherwise.
+ * @throws IllegalArgumentException if request is null
+ * @throws IllegalArgumentException if executor is null
+ * @throws IllegalArgumentException if callback is null
+ * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
+ */
+ @RequiresPermission(ACCESS_FINE_LOCATION)
+ public boolean registerGnssMeasurementsCallback(
+ @NonNull GnssMeasurementRequest request,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull GnssMeasurementsEvent.Callback callback) {
+ Preconditions.checkArgument(request != null, "invalid null request");
getGnssMeasurementsTransportMultiplexer().addListener(request, callback, executor);
return true;
}
@@ -2907,14 +2935,14 @@
}
private class GnssMeasurementsTransportMultiplexer extends
- ListenerTransportMultiplexer<GnssRequest, GnssMeasurementsEvent.Callback> {
+ ListenerTransportMultiplexer<GnssMeasurementRequest, GnssMeasurementsEvent.Callback> {
private @Nullable IGnssMeasurementsListener mListenerTransport;
GnssMeasurementsTransportMultiplexer() {}
@Override
- protected void registerWithServer(GnssRequest request) throws RemoteException {
+ protected void registerWithServer(GnssMeasurementRequest request) throws RemoteException {
IGnssMeasurementsListener transport = mListenerTransport;
if (transport == null) {
transport = new GnssMeasurementsListener();
@@ -2937,9 +2965,10 @@
}
@Override
- protected GnssRequest mergeRequests(Collection<GnssRequest> requests) {
- GnssRequest.Builder builder = new GnssRequest.Builder();
- for (GnssRequest request : requests) {
+ protected GnssMeasurementRequest mergeRequests(
+ Collection<GnssMeasurementRequest> requests) {
+ GnssMeasurementRequest.Builder builder = new GnssMeasurementRequest.Builder();
+ for (GnssMeasurementRequest request : requests) {
if (request.isFullTracking()) {
builder.setFullTracking(true);
break;
diff --git a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
index 0822cda..dd8a8c3 100644
--- a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
+++ b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
@@ -16,6 +16,11 @@
package com.android.internal.location.gnssmetrics;
+import static android.location.GnssSignalQuality.GNSS_SIGNAL_QUALITY_GOOD;
+import static android.location.GnssSignalQuality.GNSS_SIGNAL_QUALITY_POOR;
+import static android.location.GnssSignalQuality.GNSS_SIGNAL_QUALITY_UNKNOWN;
+import static android.location.GnssSignalQuality.NUM_GNSS_SIGNAL_QUALITY_LEVELS;
+
import android.app.StatsManager;
import android.content.Context;
import android.location.GnssStatus;
@@ -23,7 +28,6 @@
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.connectivity.GpsBatteryStats;
-import android.server.location.ServerLocationProtoEnums;
import android.text.format.DateUtils;
import android.util.Base64;
import android.util.Log;
@@ -50,17 +54,6 @@
private static final String TAG = "GnssMetrics";
- private static final int GPS_SIGNAL_QUALITY_UNKNOWN =
- ServerLocationProtoEnums.GPS_SIGNAL_QUALITY_UNKNOWN; // -1
-
- private static final int GPS_SIGNAL_QUALITY_POOR =
- ServerLocationProtoEnums.GPS_SIGNAL_QUALITY_POOR; // 0
-
- private static final int GPS_SIGNAL_QUALITY_GOOD =
- ServerLocationProtoEnums.GPS_SIGNAL_QUALITY_GOOD; // 1
-
- public static final int NUM_GPS_SIGNAL_QUALITY_LEVELS = GPS_SIGNAL_QUALITY_GOOD + 1;
-
/** Default time between location fixes (in millisecs) */
private static final int DEFAULT_TIME_BETWEEN_FIXES_MILLISECS = 1000;
@@ -397,7 +390,7 @@
stats.getLoggingDurationMs() / ((double) DateUtils.MINUTE_IN_MILLIS)).append(
"\n");
long[] t = stats.getTimeInGpsSignalQualityLevel();
- if (t != null && t.length == NUM_GPS_SIGNAL_QUALITY_LEVELS) {
+ if (t != null && t.length == NUM_GNSS_SIGNAL_QUALITY_LEVELS) {
s.append(" Amount of time (while on battery) Top 4 Avg CN0 > "
+ GnssPowerMetrics.POOR_TOP_FOUR_AVG_CN0_THRESHOLD_DB_HZ
+ " dB-Hz (min): ").append(
@@ -512,7 +505,7 @@
// so that
// the first CNO report will trigger an update to BatteryStats
mLastAverageCn0 = -100.0;
- mLastSignalLevel = GPS_SIGNAL_QUALITY_UNKNOWN;
+ mLastSignalLevel = GNSS_SIGNAL_QUALITY_UNKNOWN;
}
/**
@@ -584,9 +577,9 @@
*/
private int getSignalLevel(double cn0) {
if (cn0 > POOR_TOP_FOUR_AVG_CN0_THRESHOLD_DB_HZ) {
- return GnssMetrics.GPS_SIGNAL_QUALITY_GOOD;
+ return GNSS_SIGNAL_QUALITY_GOOD;
}
- return GnssMetrics.GPS_SIGNAL_QUALITY_POOR;
+ return GNSS_SIGNAL_QUALITY_POOR;
}
}
diff --git a/media/java/android/media/AudioDeviceAttributes.java b/media/java/android/media/AudioDeviceAttributes.java
index 6c8b500..7caac89 100644
--- a/media/java/android/media/AudioDeviceAttributes.java
+++ b/media/java/android/media/AudioDeviceAttributes.java
@@ -120,7 +120,13 @@
mAddress = address;
}
- /*package*/ AudioDeviceAttributes(int nativeType, @NonNull String address) {
+ /**
+ * @hide
+ * Constructor from internal device type and address
+ * @param type the internal device type, as defined in {@link AudioSystem}
+ * @param address the address of the device, or an empty string for devices without one
+ */
+ public AudioDeviceAttributes(int nativeType, @NonNull String address) {
mRole = (nativeType & AudioSystem.DEVICE_BIT_IN) != 0 ? ROLE_INPUT : ROLE_OUTPUT;
mType = AudioDeviceInfo.convertInternalDeviceToDeviceType(nativeType);
mAddress = address;
@@ -191,10 +197,8 @@
public String toString() {
return new String("AudioDeviceAttributes:"
+ " role:" + roleToString(mRole)
- + " type:" + (mRole == ROLE_OUTPUT ? AudioSystem.getOutputDeviceName(
- AudioDeviceInfo.convertDeviceTypeToInternalDevice(mType))
- : AudioSystem.getInputDeviceName(
- AudioDeviceInfo.convertDeviceTypeToInternalDevice(mType)))
+ + " type:" + (mRole == ROLE_OUTPUT ? AudioSystem.getOutputDeviceName(mNativeType)
+ : AudioSystem.getInputDeviceName(mNativeType))
+ " addr:" + mAddress);
}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 3bd68d8..367b784 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2931,7 +2931,7 @@
public boolean isMusicActive() {
final IAudioService service = getService();
try {
- return service.isMusicActive();
+ return service.isMusicActive(false /*remotely*/);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2945,7 +2945,12 @@
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public boolean isMusicActiveRemotely() {
- return AudioSystem.isStreamActiveRemotely(STREAM_MUSIC, 0);
+ final IAudioService service = getService();
+ try {
+ return service.isMusicActive(true /*remotely*/);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
@@ -5108,7 +5113,12 @@
case STREAM_NOTIFICATION:
case STREAM_DTMF:
case STREAM_ACCESSIBILITY:
- return AudioSystem.getDevicesForStream(streamType);
+ final IAudioService service = getService();
+ try {
+ return service.getDevicesForStream(streamType);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
default:
return 0;
}
@@ -6173,6 +6183,29 @@
}
/**
+ * Returns an {@link AudioDeviceInfo} corresponding to the specified {@link AudioPort} ID.
+ * @param portId The audio port ID to look up for.
+ * @param flags A set of bitflags specifying the criteria to test.
+ * @see #GET_DEVICES_OUTPUTS
+ * @see #GET_DEVICES_INPUTS
+ * @see #GET_DEVICES_ALL
+ * @return An AudioDeviceInfo or null if no device with matching port ID is found.
+ * @hide
+ */
+ public static AudioDeviceInfo getDeviceForPortId(int portId, int flags) {
+ if (portId == 0) {
+ return null;
+ }
+ AudioDeviceInfo[] devices = getDevicesStatic(flags);
+ for (AudioDeviceInfo device : devices) {
+ if (device.getId() == portId) {
+ return device;
+ }
+ }
+ return null;
+ }
+
+ /**
* Registers an {@link AudioDeviceCallback} object to receive notifications of changes
* to the set of connected audio devices.
* @param callback The {@link AudioDeviceCallback} object to receive connect/disconnect
@@ -6859,6 +6892,297 @@
return hwSyncId;
}
+ /**
+ * Selects the audio device that should be used for communication use cases, for instance voice
+ * or video calls. This method can be used by voice or video chat applications to select a
+ * different audio device than the one selected by default by the platform.
+ * <p>The device selection is expressed as an {@link AudioDeviceInfo}, of role sink
+ * ({@link AudioDeviceInfo#isSink()} is <code>true</code>) and of one of the following types:
+ * <ul>
+ * <li> {@link AudioDeviceInfo#TYPE_BUILTIN_EARPIECE}
+ * <li> {@link AudioDeviceInfo#TYPE_BUILTIN_SPEAKER}
+ * <li> {@link AudioDeviceInfo#TYPE_WIRED_HEADSET}
+ * <li> {@link AudioDeviceInfo#TYPE_BLUETOOTH_SCO}
+ * <li> {@link AudioDeviceInfo#TYPE_USB_HEADSET}
+ * <li> {@link AudioDeviceInfo#TYPE_BLE_HEADSET}
+ * </ul>
+ * The selection is active as long as the requesting application lives, until
+ * {@link #clearDeviceForCommunication} is called or until the device is disconnected.
+ * It is therefore important for applications to clear the request when a call ends or the
+ * application is paused.
+ * <p>In case of simultaneous requests by multiple applications the priority is given to the
+ * application currently controlling the audio mode (see {@link #setMode(int)}). This is the
+ * latest application having selected mode {@link #MODE_IN_COMMUNICATION} or mode
+ * {@link #MODE_IN_CALL}. Note that <code>MODE_IN_CALL</code> can only be selected by the main
+ * telephony application with permission
+ * {@link android.Manifest.permission#MODIFY_PHONE_STATE}.
+ * <p> If the requested devices is not currently available, the request will be rejected and
+ * the method will return false.
+ * <p>This API replaces the following deprecated APIs:
+ * <ul>
+ * <li> {@link #startBluetoothSco()}
+ * <li> {@link #stopBluetoothSco()}
+ * <li> {@link #setSpeakerphoneOn(boolean)}
+ * </ul>
+ * <h4>Example</h4>
+ * <p>The example below shows how to enable and disable speakerphone mode.
+ * <pre class="prettyprint">
+ * // Get an AudioManager instance
+ * AudioManager audioManager = Context.getSystemService(AudioManager.class);
+ * try {
+ * AudioDeviceInfo speakerDevice = null;
+ * AudioDeviceInfo[] devices = audioManager.getDevices(GET_DEVICES_OUTPUTS);
+ * for (AudioDeviceInfo device : devices) {
+ * if (device.getType() == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER) {
+ * speakerDevice = device;
+ * break;
+ * }
+ * }
+ * if (speakerDevice != null) {
+ * // Turn speakerphone ON.
+ * boolean result = audioManager.setDeviceForCommunication(speakerDevice);
+ * if (!result) {
+ * // Handle error.
+ * }
+ * // Turn speakerphone OFF.
+ * audioManager.clearDeviceForCommunication();
+ * }
+ * } catch (IllegalArgumentException e) {
+ * // Handle exception.
+ * }
+ * </pre>
+ * @param device the requested audio device.
+ * @return <code>true</code> if the request was accepted, <code>false</code> otherwise.
+ * @throws IllegalArgumentException If an invalid device is specified.
+ */
+ public boolean setDeviceForCommunication(@NonNull AudioDeviceInfo device) {
+ Objects.requireNonNull(device);
+ try {
+ if (device.getId() == 0) {
+ throw new IllegalArgumentException("In valid device: " + device);
+ }
+ return getService().setDeviceForCommunication(mICallBack, device.getId());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Cancels previous communication device selection made with
+ * {@link #setDeviceForCommunication(AudioDeviceInfo)}.
+ */
+ public void clearDeviceForCommunication() {
+ try {
+ getService().setDeviceForCommunication(mICallBack, 0);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns currently selected audio device for communication.
+ * <p>This API replaces the following deprecated APIs:
+ * <ul>
+ * <li> {@link #isBluetoothScoOn()}
+ * <li> {@link #isSpeakerphoneOn()}
+ * </ul>
+ * @return an {@link AudioDeviceInfo} indicating which audio device is
+ * currently selected or communication use cases or null if default selection
+ * is used.
+ */
+ @Nullable
+ public AudioDeviceInfo getDeviceForCommunication() {
+ try {
+ return getDeviceForPortId(
+ getService().getDeviceForCommunication(), GET_DEVICES_OUTPUTS);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * @hide
+ * Returns an {@link AudioDeviceInfo} corresponding to a connected device of the type provided.
+ * The type must be a valid output type defined in <code>AudioDeviceInfo</code> class,
+ * for instance {@link AudioDeviceInfo#TYPE_BUILTIN_SPEAKER}.
+ * The method will return null if no device of the provided type is connected.
+ * If more than one device of the provided type is connected, an object corresponding to the
+ * first device encountered in the enumeration list will be returned.
+ * @param deviceType The device device for which an <code>AudioDeviceInfo</code>
+ * object is queried.
+ * @return An AudioDeviceInfo object or null if no device with the requested type is connected.
+ * @throws IllegalArgumentException If an invalid device type is specified.
+ */
+ @TestApi
+ @Nullable
+ public static AudioDeviceInfo getDeviceInfoFromType(
+ @AudioDeviceInfo.AudioDeviceTypeOut int deviceType) {
+ AudioDeviceInfo[] devices = getDevicesStatic(GET_DEVICES_OUTPUTS);
+ for (AudioDeviceInfo device : devices) {
+ if (device.getType() == deviceType) {
+ return device;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Listener registered by client to be notified upon communication audio device change.
+ * See {@link #setDeviceForCommunication(AudioDeviceInfo)}.
+ */
+ public interface OnCommunicationDeviceChangedListener {
+ /**
+ * Callback method called upon communication audio device change.
+ * @param device the audio device selected for communication use cases
+ */
+ void onCommunicationDeviceChanged(@Nullable AudioDeviceInfo device);
+ }
+
+ /**
+ * Adds a listener for being notified of changes to the communication audio device.
+ * See {@link #setDeviceForCommunication(AudioDeviceInfo)}.
+ * @param executor
+ * @param listener
+ */
+ public void addOnCommunicationDeviceChangedListener(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull OnCommunicationDeviceChangedListener listener) {
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(listener);
+ synchronized (mCommDevListenerLock) {
+ if (hasCommDevListener(listener)) {
+ throw new IllegalArgumentException(
+ "attempt to call addOnCommunicationDeviceChangedListener() "
+ + "on a previously registered listener");
+ }
+ // lazy initialization of the list of strategy-preferred device listener
+ if (mCommDevListeners == null) {
+ mCommDevListeners = new ArrayList<>();
+ }
+ final int oldCbCount = mCommDevListeners.size();
+ mCommDevListeners.add(new CommDevListenerInfo(listener, executor));
+ if (oldCbCount == 0 && mCommDevListeners.size() > 0) {
+ // register binder for callbacks
+ if (mCommDevDispatcherStub == null) {
+ mCommDevDispatcherStub = new CommunicationDeviceDispatcherStub();
+ }
+ try {
+ getService().registerCommunicationDeviceDispatcher(mCommDevDispatcherStub);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+ }
+
+ /**
+ * Removes a previously added listener of changes to the communication audio device.
+ * See {@link #setDeviceForCommunication(AudioDeviceInfo)}.
+ * @param listener
+ */
+ public void removeOnCommunicationDeviceChangedListener(
+ @NonNull OnCommunicationDeviceChangedListener listener) {
+ Objects.requireNonNull(listener);
+ synchronized (mCommDevListenerLock) {
+ if (!removeCommDevListener(listener)) {
+ throw new IllegalArgumentException(
+ "attempt to call removeOnCommunicationDeviceChangedListener() "
+ + "on an unregistered listener");
+ }
+ if (mCommDevListeners.size() == 0) {
+ // unregister binder for callbacks
+ try {
+ getService().unregisterCommunicationDeviceDispatcher(
+ mCommDevDispatcherStub);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ } finally {
+ mCommDevDispatcherStub = null;
+ mCommDevListeners = null;
+ }
+ }
+ }
+ }
+
+ private final Object mCommDevListenerLock = new Object();
+ /**
+ * List of listeners for preferred device for strategy and their associated Executor.
+ * List is lazy-initialized on first registration
+ */
+ @GuardedBy("mCommDevListenerLock")
+ private @Nullable ArrayList<CommDevListenerInfo> mCommDevListeners;
+
+ private static class CommDevListenerInfo {
+ final @NonNull OnCommunicationDeviceChangedListener mListener;
+ final @NonNull Executor mExecutor;
+
+ CommDevListenerInfo(OnCommunicationDeviceChangedListener listener, Executor exe) {
+ mListener = listener;
+ mExecutor = exe;
+ }
+ }
+
+ @GuardedBy("mCommDevListenerLock")
+ private CommunicationDeviceDispatcherStub mCommDevDispatcherStub;
+
+ private final class CommunicationDeviceDispatcherStub
+ extends ICommunicationDeviceDispatcher.Stub {
+
+ @Override
+ public void dispatchCommunicationDeviceChanged(int portId) {
+ // make a shallow copy of listeners so callback is not executed under lock
+ final ArrayList<CommDevListenerInfo> commDevListeners;
+ synchronized (mCommDevListenerLock) {
+ if (mCommDevListeners == null || mCommDevListeners.size() == 0) {
+ return;
+ }
+ commDevListeners = (ArrayList<CommDevListenerInfo>) mCommDevListeners.clone();
+ }
+ AudioDeviceInfo device = getDeviceForPortId(portId, GET_DEVICES_OUTPUTS);
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ for (CommDevListenerInfo info : commDevListeners) {
+ info.mExecutor.execute(() ->
+ info.mListener.onCommunicationDeviceChanged(device));
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+ }
+
+ @GuardedBy("mCommDevListenerLock")
+ private @Nullable CommDevListenerInfo getCommDevListenerInfo(
+ OnCommunicationDeviceChangedListener listener) {
+ if (mCommDevListeners == null) {
+ return null;
+ }
+ for (CommDevListenerInfo info : mCommDevListeners) {
+ if (info.mListener == listener) {
+ return info;
+ }
+ }
+ return null;
+ }
+
+ @GuardedBy("mCommDevListenerLock")
+ private boolean hasCommDevListener(OnCommunicationDeviceChangedListener listener) {
+ return getCommDevListenerInfo(listener) != null;
+ }
+
+ @GuardedBy("mCommDevListenerLock")
+ /**
+ * @return true if the listener was removed from the list
+ */
+ private boolean removeCommDevListener(OnCommunicationDeviceChangedListener listener) {
+ final CommDevListenerInfo infoToRemove = getCommDevListenerInfo(listener);
+ if (infoToRemove != null) {
+ mCommDevListeners.remove(infoToRemove);
+ return true;
+ }
+ return false;
+ }
+
//---------------------------------------------------------
// Inner classes
//--------------------
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 8987a71..164b194 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -1730,7 +1730,7 @@
int[] types = new int[devices.size()];
String[] addresses = new String[devices.size()];
for (int i = 0; i < devices.size(); ++i) {
- types[i] = AudioDeviceInfo.convertDeviceTypeToInternalDevice(devices.get(i).getType());
+ types[i] = devices.get(i).getInternalType();
addresses[i] = devices.get(i).getAddress();
}
return setDevicesRoleForStrategy(strategy, role, types, addresses);
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index de885f49..8ea380a 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -83,6 +83,10 @@
* <p>
* Supported for writing: JPEG, PNG, WebP.
* <p>
+ * Note: JPEG and HEIF files may contain XMP data either inside the Exif data chunk or outside of
+ * it. This class will search both locations for XMP data, but if XMP data exist both inside and
+ * outside Exif, will favor the XMP data inside Exif over the one outside.
+ * <p>
* Note: It is recommended to use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
* <a href="{@docRoot}reference/androidx/exifinterface/media/ExifInterface.html">ExifInterface
* Library</a> since it is a superset of this class. In addition to the functionalities of this
@@ -3185,6 +3189,24 @@
readExifSegment(bytes, IFD_TYPE_PRIMARY);
}
+ String xmpOffsetStr = retriever.extractMetadata(
+ MediaMetadataRetriever.METADATA_KEY_XMP_OFFSET);
+ String xmpLengthStr = retriever.extractMetadata(
+ MediaMetadataRetriever.METADATA_KEY_XMP_LENGTH);
+ if (xmpOffsetStr != null && xmpLengthStr != null) {
+ int offset = Integer.parseInt(xmpOffsetStr);
+ int length = Integer.parseInt(xmpLengthStr);
+ in.seek(offset);
+ byte[] xmpBytes = new byte[length];
+ if (in.read(xmpBytes) != length) {
+ throw new IOException("Failed to read XMP from HEIF");
+ }
+ if (getAttribute(TAG_XMP) == null) {
+ mAttributes[IFD_TYPE_PRIMARY].put(TAG_XMP, new ExifAttribute(
+ IFD_FORMAT_BYTE, xmpBytes.length, offset, xmpBytes));
+ }
+ }
+
if (DEBUG) {
Log.d(TAG, "Heif meta: " + width + "x" + height + ", rotation " + rotation);
}
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 2ac5b50..bad0d19 100755
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -28,6 +28,7 @@
import android.media.IAudioRoutesObserver;
import android.media.IAudioServerStateDispatcher;
import android.media.ICapturePresetDevicesRoleDispatcher;
+import android.media.ICommunicationDeviceDispatcher;
import android.media.IPlaybackConfigDispatcher;
import android.media.IRecordingConfigDispatcher;
import android.media.IRingtonePlayer;
@@ -335,5 +336,16 @@
in String packageName, int uid, int pid, in UserHandle userHandle,
int targetSdkVersion);
- boolean isMusicActive();
+ boolean isMusicActive(in boolean remotely);
+
+ int getDevicesForStream(in int streamType);
+
+ boolean setDeviceForCommunication(IBinder cb, int portId);
+
+ int getDeviceForCommunication();
+
+ void registerCommunicationDeviceDispatcher(ICommunicationDeviceDispatcher dispatcher);
+
+ oneway void unregisterCommunicationDeviceDispatcher(
+ ICommunicationDeviceDispatcher dispatcher);
}
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java b/media/java/android/media/ICommunicationDeviceDispatcher.aidl
similarity index 63%
copy from media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java
copy to media/java/android/media/ICommunicationDeviceDispatcher.aidl
index 52f2787..429f934 100644
--- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java
+++ b/media/java/android/media/ICommunicationDeviceDispatcher.aidl
@@ -14,19 +14,15 @@
* limitations under the License.
*/
-package com.android.mediatranscodingtest;
+package android.media;
/**
+ * AIDL for AudioService to signal audio communication device updates.
*
- * This class has the names of the all the activity name and variables in the
- * instrumentation test.
- *
+ * {@hide}
*/
-public class MediaConstants {
- /*
- * Source test files.
- */
- public static final String[] SOURCE_HEVC_VIDEO_ONLY_TEST_FILES = {
- "/sdcard/media_api/video/VideoOnlyHEVC.mp4",
- };
+oneway interface ICommunicationDeviceDispatcher {
+
+ void dispatchCommunicationDeviceChanged(int portId);
+
}
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index e7e83eb..9657b25 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -1865,10 +1865,6 @@
&& 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,
@@ -2010,8 +2006,11 @@
* 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.
+ * 32-bit processes will not support resolutions larger than 4096x4096 due to
+ * the limited address space, but performance points will be presented as is.
+ * In other words, even though a component publishes a performance point for
+ * a resolution higher than 4096x4096, it does not mean that the resolution is supported
+ * for 32-bit processes.
*/
@Nullable
public List<PerformancePoint> getSupportedPerformancePoints() {
@@ -2215,28 +2214,6 @@
(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/MediaFrameworkInitializer.java b/media/java/android/media/MediaFrameworkPlatformInitializer.java
similarity index 87%
rename from media/java/android/media/MediaFrameworkInitializer.java
rename to media/java/android/media/MediaFrameworkPlatformInitializer.java
index 577442e..e703669 100644
--- a/media/java/android/media/MediaFrameworkInitializer.java
+++ b/media/java/android/media/MediaFrameworkPlatformInitializer.java
@@ -28,11 +28,15 @@
/**
* Class for performing registration for all media services
*
- * TODO (b/160513103): Move this class when moving media service code to APEX
+ * TODO (b/160513103): This class is still needed on platform side until
+ * MEDIA_SESSION_SERVICE is moved onto com.android.media apex.
+ * Once that's done, we can move the code that registers the service onto the
+ * MediaFrameworkInitializer class on the apex.
+ *
* @hide
*/
-public class MediaFrameworkInitializer {
- private MediaFrameworkInitializer() {
+public class MediaFrameworkPlatformInitializer {
+ private MediaFrameworkPlatformInitializer() {
}
private static volatile MediaServiceManager sMediaServiceManager;
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index 86d1d15..32a9168 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -1313,14 +1313,14 @@
public static final int METADATA_KEY_VIDEO_FRAME_COUNT = 32;
/**
- * If the media contains EXIF data, this key retrieves the offset value
+ * If the media contains EXIF data, this key retrieves the offset (in bytes)
* of the data.
*/
public static final int METADATA_KEY_EXIF_OFFSET = 33;
/**
- * If the media contains EXIF data, this key retrieves the length of the
- * data.
+ * If the media contains EXIF data, this key retrieves the length (in bytes)
+ * of the data.
*/
public static final int METADATA_KEY_EXIF_LENGTH = 34;
@@ -1371,5 +1371,21 @@
@SystemApi(client = MODULE_LIBRARIES)
public static final int METADATA_KEY_VIDEO_CODEC_MIME_TYPE = 40;
+ /**
+ * If the media contains XMP data, this key retrieves the offset (in bytes)
+ * of the data.
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ public static final int METADATA_KEY_XMP_OFFSET = 41;
+
+ /**
+ * If the media contains XMP data, this key retrieves the length (in bytes)
+ * of the data.
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ public static final int METADATA_KEY_XMP_LENGTH = 42;
+
// Add more here...
}
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index 4940c76..36f7bed 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -43,6 +43,7 @@
import android.os.ServiceManager;
import android.os.UserHandle;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.Log;
import android.view.Display;
import android.view.DisplayAddress;
@@ -54,6 +55,7 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -111,6 +113,8 @@
IMediaRouterClient mClient;
MediaRouterClientState mClientState;
+ Map<Integer, Integer> mStreamVolume = new ArrayMap<>();
+
final IAudioRoutesObserver.Stub mAudioRoutesObserver = new IAudioRoutesObserver.Stub() {
@Override
public void dispatchAudioRoutesChanged(final AudioRoutesInfo newRoutes) {
@@ -262,6 +266,17 @@
mCurAudioRoutesInfo.bluetoothName = newRoutes.bluetoothName;
}
+ int getStreamVolume(int streamType) {
+ if (!mStreamVolume.containsKey(streamType)) {
+ try {
+ mStreamVolume.put(streamType, mAudioService.getStreamVolume(streamType));
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error getting local stream volume", e);
+ }
+ }
+ return mStreamVolume.get(streamType);
+ }
+
boolean isBluetoothA2dpOn() {
try {
return mBluetoothA2dpRoute != null && mAudioService.isBluetoothA2dpOn();
@@ -1976,13 +1991,7 @@
*/
public int getVolume() {
if (mPlaybackType == PLAYBACK_TYPE_LOCAL) {
- int vol = 0;
- try {
- vol = sStatic.mAudioService.getStreamVolume(mPlaybackStream);
- } catch (RemoteException e) {
- Log.e(TAG, "Error getting local stream volume", e);
- }
- return vol;
+ return sStatic.getStreamVolume(mPlaybackStream);
} else {
return mVolume;
}
@@ -3139,11 +3148,12 @@
if (intent.getAction().equals(AudioManager.VOLUME_CHANGED_ACTION)) {
final int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE,
-1);
+ final int newVolume = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, 0);
+ sStatic.mStreamVolume.put(streamType, newVolume);
if (streamType != AudioManager.STREAM_MUSIC) {
return;
}
- final int newVolume = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, 0);
final int oldVolume = intent.getIntExtra(
AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, 0);
if (newVolume != oldVolume) {
diff --git a/media/java/android/media/MediaServiceManager.java b/media/java/android/media/MediaServiceManager.java
index 21e2d84..96bff4f 100644
--- a/media/java/android/media/MediaServiceManager.java
+++ b/media/java/android/media/MediaServiceManager.java
@@ -17,6 +17,8 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.annotation.SystemApi.Client;
import android.os.IBinder;
import android.os.ServiceManager;
@@ -27,7 +29,11 @@
* <p> Only the media mainline module will be able to access an instance of this class.
* @hide
*/
+@SystemApi(client = Client.MODULE_LIBRARIES)
public class MediaServiceManager {
+ private static final String MEDIA_SESSION_SERVICE = "media_session";
+ private static final String MEDIA_TRANSCODING_SERVICE = "media.transcoding";
+
/**
* @hide
*/
@@ -59,10 +65,18 @@
}
/**
- * Returns {@link ServiceRegisterer} for the "media_session" service.
+ * Returns {@link ServiceRegisterer} for MEDIA_SESSION_SERVICE.
*/
@NonNull
public ServiceRegisterer getMediaSessionServiceRegisterer() {
- return new ServiceRegisterer("media_session");
+ return new ServiceRegisterer(MEDIA_SESSION_SERVICE);
+ }
+
+ /**
+ * Returns {@link ServiceRegisterer} for MEDIA_TRANSCODING_SERVICE.
+ */
+ @NonNull
+ public ServiceRegisterer getMediaTranscodingServiceRegisterer() {
+ return new ServiceRegisterer(MEDIA_TRANSCODING_SERVICE);
}
}
diff --git a/media/java/android/media/OWNERS b/media/java/android/media/OWNERS
index cbc9ab7..cf06fad 100644
--- a/media/java/android/media/OWNERS
+++ b/media/java/android/media/OWNERS
@@ -6,3 +6,4 @@
olly@google.com
andrewlewis@google.com
sungsoo@google.com
+jmtrivi@google.com
diff --git a/media/java/android/media/SoundPool.java b/media/java/android/media/SoundPool.java
index 1bf2863..3f685a4 100644
--- a/media/java/android/media/SoundPool.java
+++ b/media/java/android/media/SoundPool.java
@@ -149,7 +149,8 @@
super(attributes, AudioPlaybackConfiguration.PLAYER_TYPE_JAM_SOUNDPOOL);
// do native setup
- if (native_setup(new WeakReference<SoundPool>(this), maxStreams, attributes) != 0) {
+ if (native_setup(new WeakReference<SoundPool>(this),
+ maxStreams, attributes, getCurrentOpPackageName()) != 0) {
throw new RuntimeException("Native setup failed");
}
mAttributes = attributes;
@@ -501,7 +502,7 @@
private native final int _load(FileDescriptor fd, long offset, long length, int priority);
private native final int native_setup(Object weakRef, int maxStreams,
- Object/*AudioAttributes*/ attributes);
+ @NonNull Object/*AudioAttributes*/ attributes, @NonNull String opPackageName);
private native final int _play(int soundID, float leftVolume, float rightVolume,
int priority, int loop, float rate);
diff --git a/media/java/android/media/ToneGenerator.java b/media/java/android/media/ToneGenerator.java
index 140e70d..6a695e6 100644
--- a/media/java/android/media/ToneGenerator.java
+++ b/media/java/android/media/ToneGenerator.java
@@ -16,9 +16,11 @@
package android.media;
+import android.annotation.NonNull;
+import android.app.ActivityThread;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
-
+import android.text.TextUtils;
/**
@@ -746,7 +748,7 @@
*
*/
public ToneGenerator(int streamType, int volume) {
- native_setup(streamType, volume);
+ native_setup(streamType, volume, getCurrentOpPackageName());
}
/**
@@ -880,7 +882,8 @@
*/
public native void release();
- private native final void native_setup(int streamType, int volume);
+ private native void native_setup(
+ int streamType, int volume, @NonNull String opPackageName);
private native final void native_finalize();
@@ -895,6 +898,10 @@
@Override
protected void finalize() { native_finalize(); }
+ private String getCurrentOpPackageName() {
+ return TextUtils.emptyIfNull(ActivityThread.currentOpPackageName());
+ }
+
@SuppressWarnings("unused")
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private long mNativeContext; // accessed by native methods
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index 6af39f8..00ee914 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -28,7 +28,7 @@
import android.content.pm.ParceledListSlice;
import android.media.AudioManager;
import android.media.IRemoteVolumeControllerCallback;
-import android.media.MediaFrameworkInitializer;
+import android.media.MediaFrameworkPlatformInitializer;
import android.media.MediaSession2;
import android.media.Session2Token;
import android.os.Bundle;
@@ -122,7 +122,7 @@
// Consider rewriting like DisplayManagerGlobal
// Decide if we need context
mContext = context;
- mService = ISessionManager.Stub.asInterface(MediaFrameworkInitializer
+ mService = ISessionManager.Stub.asInterface(MediaFrameworkPlatformInitializer
.getMediaServiceManager()
.getMediaSessionServiceRegisterer()
.get());
@@ -180,7 +180,7 @@
* be provided in priority order with the most important controller at index
* 0.
* <p>
- * This requires the android.Manifest.permission.MEDIA_CONTENT_CONTROL
+ * This requires the {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL}
* permission be held by the calling app. You may also retrieve this list if
* your app is an enabled notification listener using the
* {@link NotificationListenerService} APIs, in which case you must pass the
@@ -196,14 +196,18 @@
}
/**
- * Get active sessions for a specific user. To retrieve actions for a user
- * other than your own you must hold the
- * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission
- * in addition to any other requirements. If you are an enabled notification
- * listener you may only get sessions for the users you are enabled for.
+ * Get active sessions for the given user.
+ * <p>
+ * This requires the {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission be
+ * held by the calling app. You may also retrieve this list if your app is an enabled
+ * notification listener using the {@link NotificationListenerService} APIs, in which case you
+ * must pass the {@link ComponentName} of your enabled listener.
+ * <p>
+ * The calling application needs to hold the
+ * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission in order to
+ * retrieve sessions for user ids that do not belong to current process.
*
- * @param notificationListener The enabled notification listener component.
- * May be null.
+ * @param notificationListener The enabled notification listener component. May be null.
* @param userId The user id to fetch sessions for.
* @return A list of controllers for ongoing sessions.
* @hide
@@ -248,8 +252,9 @@
* Gets a list of {@link Session2Token} with type {@link Session2Token#TYPE_SESSION} for the
* given user.
* <p>
- * If you want to get tokens for another user, you must hold the
- * android.Manifest.permission#INTERACT_ACROSS_USERS_FULL permission.
+ * The calling application needs to hold the
+ * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission in order to
+ * retrieve session tokens for user ids that do not belong to current process.
*
* @param userId The user id to fetch sessions for.
* @return A list of {@link Session2Token}
@@ -267,11 +272,12 @@
}
/**
- * Add a listener to be notified when the list of active sessions changes. This requires the
- * {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission be held by the calling
- * app. You may also retrieve this list if your app is an enabled notification listener using
- * the {@link NotificationListenerService} APIs, in which case you must pass the
- * {@link ComponentName} of your enabled listener.
+ * Add a listener to be notified when the list of active sessions changes.
+ * <p>
+ * This requires the {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission be
+ * held by the calling app. You may also retrieve this list if your app is an enabled
+ * notificationlistener using the {@link NotificationListenerService} APIs, in which case you
+ * must pass the {@link ComponentName} of your enabled listener.
*
* @param sessionListener The listener to add.
* @param notificationListener The enabled notification listener component. May be null.
@@ -283,12 +289,13 @@
}
/**
- * Add a listener to be notified when the list of active sessions changes. This requires the
- * {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission be held by the calling
- * app. You may also retrieve this list if your app is an enabled notification listener using
- * the {@link NotificationListenerService} APIs, in which case you must pass the
- * {@link ComponentName} of your enabled listener. Updates will be posted to the handler
- * specified or to the caller's thread if the handler is null.
+ * Add a listener to be notified when the list of active sessions changes.
+ * <p>
+ * This requires the {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission be
+ * held by the calling app. You may also retrieve this list if your app is an enabled
+ * notification listener using the {@link NotificationListenerService} APIs, in which case you
+ * must pass the {@link ComponentName} of your enabled listener. Updates will be posted to the
+ * handler specified or to the caller's thread if the handler is null.
*
* @param sessionListener The listener to add.
* @param notificationListener The enabled notification listener component. May be null.
@@ -302,15 +309,17 @@
}
/**
- * Add a listener to be notified when the list of active sessions changes for the given user.
- * The calling app must have the {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL}
- * permission if it wants to call this method for a user that is not running the app.
+ * Add a listener to be notified when the list of active sessions changes.
* <p>
* This requires the {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission be
* held by the calling app. You may also retrieve this list if your app is an enabled
* notification listener using the {@link NotificationListenerService} APIs, in which case you
* must pass the {@link ComponentName} of your enabled listener. Updates will be posted to the
* handler specified or to the caller's thread if the handler is null.
+ * <p>
+ * The calling application needs to hold the
+ * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission in order to
+ * add listeners for user ids that do not belong to current process.
*
* @param sessionListener The listener to add.
* @param notificationListener The enabled notification listener component. May be null.
@@ -407,6 +416,10 @@
* Library</a> for consistent behavior across all devices.
* <p>
* Adds a listener to be notified when the {@link #getSession2Tokens()} changes.
+ * <p>
+ * The calling application needs to hold the
+ * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission in order to
+ * add listeners for user ids that do not belong to current process.
*
* @param userId The userId to listen for changes on
* @param listener The listener to add
@@ -705,8 +718,9 @@
/**
* Checks whether the remote user is a trusted app.
* <p>
- * An app is trusted if the app holds the android.Manifest.permission.MEDIA_CONTENT_CONTROL
- * permission or has an enabled notification listener.
+ * An app is trusted if the app holds the
+ * {@link android.Manifest.permission#MEDIA_CONTENT_CONTROL} permission or has an enabled
+ * notification listener.
*
* @param userInfo The remote user info from either
* {@link MediaSession#getCurrentControllerInfo()} or
diff --git a/media/java/android/media/tv/tuner/dvr/DvrRecorder.java b/media/java/android/media/tv/tuner/dvr/DvrRecorder.java
index 8871167..c4b622d 100644
--- a/media/java/android/media/tv/tuner/dvr/DvrRecorder.java
+++ b/media/java/android/media/tv/tuner/dvr/DvrRecorder.java
@@ -47,6 +47,7 @@
private static int sInstantId = 0;
private int mSegmentId = 0;
private int mOverflow;
+ private Boolean mIsStopped = null;
private native int nativeAttachFilter(Filter filter);
private native int nativeDetachFilter(Filter filter);
@@ -135,7 +136,13 @@
.write(FrameworkStatsLog.TV_TUNER_DVR_STATUS, mUserId,
FrameworkStatsLog.TV_TUNER_DVR_STATUS__TYPE__RECORD,
FrameworkStatsLog.TV_TUNER_DVR_STATUS__STATE__STARTED, mSegmentId, 0);
- return nativeStartDvr();
+ synchronized (mIsStopped) {
+ int result = nativeStartDvr();
+ if (result == Tuner.RESULT_SUCCESS) {
+ mIsStopped = false;
+ }
+ return result;
+ }
}
/**
@@ -152,7 +159,13 @@
.write(FrameworkStatsLog.TV_TUNER_DVR_STATUS, mUserId,
FrameworkStatsLog.TV_TUNER_DVR_STATUS__TYPE__RECORD,
FrameworkStatsLog.TV_TUNER_DVR_STATUS__STATE__STOPPED, mSegmentId, mOverflow);
- return nativeStopDvr();
+ synchronized (mIsStopped) {
+ int result = nativeStopDvr();
+ if (result == Tuner.RESULT_SUCCESS) {
+ mIsStopped = true;
+ }
+ return result;
+ }
}
/**
@@ -164,7 +177,13 @@
*/
@Result
public int flush() {
- return nativeFlushDvr();
+ synchronized (mIsStopped) {
+ if (mIsStopped) {
+ return nativeFlushDvr();
+ }
+ Log.w(TAG, "Cannot flush non-stopped Record DVR.");
+ return Tuner.RESULT_INVALID_STATE;
+ }
}
/**
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 440d5bc..6fa94f1 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -337,8 +337,8 @@
/////////////// MediaEvent ///////////////////////
-MediaEvent::MediaEvent(sp<Filter> filter, hidl_handle avHandle,
- uint64_t dataId, uint64_t dataSize, jobject obj) : mFilter(filter),
+MediaEvent::MediaEvent(sp<FilterClient> filterClient, hidl_handle avHandle,
+ uint64_t dataId, uint64_t dataSize, jobject obj) : mFilterClient(filterClient),
mDataId(dataId), mDataSize(dataSize), mBuffer(nullptr),
mDataIdRefCnt(0), mAvHandleRefCnt(0), mIonHandle(nullptr) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
@@ -359,12 +359,13 @@
if (pC2Buffer != NULL) {
pC2Buffer->unregisterOnDestroyNotify(&DestroyCallback, this);
}
+ mFilterClient = NULL;
}
void MediaEvent::finalize() {
- if (mAvHandleRefCnt == 0) {
- mFilter->mFilterSp->releaseAvHandle(
- hidl_handle(mAvHandle), mDataIdRefCnt == 0 ? mDataId : 0);
+ if (mAvHandleRefCnt == 0 && mFilterClient != NULL) {
+ mFilterClient->releaseAvHandle(
+ mAvHandle, mDataIdRefCnt == 0 ? mDataId : 0);
native_handle_close(mAvHandle);
}
}
@@ -382,21 +383,25 @@
int numInts = 0;
int memIndex;
int dataSize;
+ SharedHandleInfo info = mFilterClient->getAvSharedHandleInfo();
+ native_handle_t* avSharedHandle = info.sharedHandle;
+ uint64_t avSharedMemSize = info.size;
+
if (mAvHandle->numFds == 0) {
- if (mFilter->mAvSharedHandle == NULL) {
+ if (avSharedHandle == NULL) {
ALOGE("Shared AV memory handle is not initialized.");
return NULL;
}
- if (mFilter->mAvSharedHandle->numFds == 0) {
+ if (avSharedHandle->numFds == 0) {
ALOGE("Shared AV memory handle is empty.");
return NULL;
}
- fd = mFilter->mAvSharedHandle->data[0];
- dataSize = mFilter->mAvSharedMemSize;
- numInts = mFilter->mAvSharedHandle->numInts;
+ fd = avSharedHandle->data[0];
+ dataSize = avSharedMemSize;
+ numInts = avSharedHandle->numInts;
if (numInts > 0) {
// If the first int in the shared native handle has value, use it as the index
- memIndex = mFilter->mAvSharedHandle->data[mFilter->mAvSharedHandle->numFds];
+ memIndex = avSharedHandle->data[avSharedHandle->numFds];
}
} else {
fd = mAvHandle->data[0];
@@ -407,11 +412,11 @@
// event has value, use it as the index
memIndex = mAvHandle->data[mAvHandle->numFds];
} else {
- if (mFilter->mAvSharedHandle != NULL) {
- numInts = mFilter->mAvSharedHandle->numInts;
+ if (avSharedHandle != NULL) {
+ numInts = avSharedHandle->numInts;
if (numInts > 0) {
// If the first int in the shared native handle has value, use it as the index
- memIndex = mFilter->mAvSharedHandle->data[mFilter->mAvSharedHandle->numFds];
+ memIndex = avSharedHandle->data[avSharedHandle->numFds];
}
}
}
@@ -462,9 +467,9 @@
return mDataId;
}
-/////////////// FilterCallback ///////////////////////
+/////////////// FilterClientCallbackImpl ///////////////////////
-jobjectArray FilterCallback::getSectionEvent(
+jobjectArray FilterClientCallbackImpl::getSectionEvent(
jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/SectionEvent");
@@ -486,7 +491,7 @@
return arr;
}
-jobjectArray FilterCallback::getMediaEvent(
+jobjectArray FilterClientCallbackImpl::getMediaEvent(
jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/MediaEvent");
@@ -537,7 +542,7 @@
if (mediaEvent.avMemory.getNativeHandle() != NULL || mediaEvent.avDataId != 0) {
sp<MediaEvent> mediaEventSp =
- new MediaEvent(mFilter, mediaEvent.avMemory,
+ new MediaEvent(mFilterClient, mediaEvent.avMemory,
mediaEvent.avDataId, dataLength + offset, obj);
mediaEventSp->mAvHandleRefCnt++;
env->SetLongField(obj, eventContext, (jlong) mediaEventSp.get());
@@ -549,7 +554,7 @@
return arr;
}
-jobjectArray FilterCallback::getPesEvent(
+jobjectArray FilterClientCallbackImpl::getPesEvent(
jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/PesEvent");
@@ -570,7 +575,7 @@
return arr;
}
-jobjectArray FilterCallback::getTsRecordEvent(
+jobjectArray FilterClientCallbackImpl::getTsRecordEvent(
jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events,
const std::vector<DemuxFilterEventExt::Event>& eventsExt) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
@@ -623,7 +628,7 @@
return arr;
}
-jobjectArray FilterCallback::getMmtpRecordEvent(
+jobjectArray FilterClientCallbackImpl::getMmtpRecordEvent(
jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events,
const std::vector<DemuxFilterEventExt::Event>& eventsExt) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
@@ -665,7 +670,7 @@
return arr;
}
-jobjectArray FilterCallback::getDownloadEvent(
+jobjectArray FilterClientCallbackImpl::getDownloadEvent(
jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/DownloadEvent");
@@ -689,7 +694,7 @@
return arr;
}
-jobjectArray FilterCallback::getIpPayloadEvent(
+jobjectArray FilterClientCallbackImpl::getIpPayloadEvent(
jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/IpPayloadEvent");
@@ -705,7 +710,7 @@
return arr;
}
-jobjectArray FilterCallback::getTemiEvent(
+jobjectArray FilterClientCallbackImpl::getTemiEvent(
jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/TemiEvent");
@@ -728,7 +733,7 @@
return arr;
}
-jobjectArray FilterCallback::getScramblingStatusEvent(
+jobjectArray FilterClientCallbackImpl::getScramblingStatusEvent(
jobjectArray& arr, const std::vector<DemuxFilterEventExt::Event>& eventsExt) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/ScramblingStatusEvent");
@@ -740,7 +745,7 @@
return arr;
}
-jobjectArray FilterCallback::getIpCidChangeEvent(
+jobjectArray FilterClientCallbackImpl::getIpCidChangeEvent(
jobjectArray& arr, const std::vector<DemuxFilterEventExt::Event>& eventsExt) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/IpCidChangeEvent");
@@ -752,7 +757,7 @@
return arr;
}
-jobjectArray FilterCallback::getRestartEvent(
+jobjectArray FilterClientCallbackImpl::getRestartEvent(
jobjectArray& arr, const std::vector<DemuxFilterEventExt::Event>& eventsExt) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
jclass eventClazz = env->FindClass("android/media/tv/tuner/filter/RestartEvent");
@@ -764,9 +769,9 @@
return arr;
}
-Return<void> FilterCallback::onFilterEvent_1_1(const DemuxFilterEvent& filterEvent,
+void FilterClientCallbackImpl::onFilterEvent_1_1(const DemuxFilterEvent& filterEvent,
const DemuxFilterEventExt& filterEventExt) {
- ALOGD("FilterCallback::onFilterEvent_1_1");
+ ALOGD("FilterClientCallbackImpl::onFilterEvent_1_1");
JNIEnv *env = AndroidRuntime::getJNIEnv();
jobjectArray array;
@@ -848,14 +853,13 @@
}
}
env->CallVoidMethod(
- mFilter->mFilterObj,
+ mFilterObj,
gFields.onFilterEventID,
array);
- return Void();
}
-Return<void> FilterCallback::onFilterEvent(const DemuxFilterEvent& filterEvent) {
- ALOGD("FilterCallback::onFilterEvent");
+void FilterClientCallbackImpl::onFilterEvent(const DemuxFilterEvent& filterEvent) {
+ ALOGD("FilterClientCallbackImpl::onFilterEvent");
std::vector<DemuxFilterEventExt::Event> emptyEventsExt;
DemuxFilterEventExt emptyFilterEventExt {
.events = emptyEventsExt,
@@ -863,49 +867,20 @@
return onFilterEvent_1_1(filterEvent, emptyFilterEventExt);
}
-Return<void> FilterCallback::onFilterStatus(const DemuxFilterStatus status) {
- ALOGD("FilterCallback::onFilterStatus");
+void FilterClientCallbackImpl::onFilterStatus(const DemuxFilterStatus status) {
+ ALOGD("FilterClientCallbackImpl::onFilterStatus");
JNIEnv *env = AndroidRuntime::getJNIEnv();
env->CallVoidMethod(
- mFilter->mFilterObj,
+ mFilterObj,
gFields.onFilterStatusID,
(jint)status);
- return Void();
}
-void FilterCallback::setFilter(const sp<Filter> filter) {
- ALOGD("FilterCallback::setFilter");
- // JNI Object
- mFilter = filter;
-}
-
-FilterCallback::~FilterCallback() {}
-
-/////////////// Filter ///////////////////////
-
-Filter::Filter(sp<IFilter> sp, jobject obj) : mFilterSp(sp) {
- JNIEnv *env = AndroidRuntime::getJNIEnv();
- mFilterObj = env->NewWeakGlobalRef(obj);
-}
-
-Filter::~Filter() {
- JNIEnv *env = AndroidRuntime::getJNIEnv();
-
- env->DeleteWeakGlobalRef(mFilterObj);
- mFilterObj = NULL;
- EventFlag::deleteEventFlag(&mFilterMQEventFlag);
-}
-
-int Filter::close() {
- Result r = mFilterSp->close();
- if (r == Result::SUCCESS) {
- EventFlag::deleteEventFlag(&mFilterMQEventFlag);
- }
- return (int)r;
-}
-
-sp<IFilter> Filter::getIFilter() {
- return mFilterSp;
+void FilterClientCallbackImpl::setFilter(jweak filterObj, sp<FilterClient> filterClient) {
+ ALOGD("FilterClientCallbackImpl::setFilter");
+ // Java Object
+ mFilterObj = filterObj;
+ mFilterClient = filterClient;
}
/////////////// TimeFilter ///////////////////////
@@ -927,22 +902,23 @@
return mTimeFilterSp;
}
-/////////////// FrontendCallback ///////////////////////
+/////////////// FrontendClientCallbackImpl ///////////////////////
-FrontendCallback::FrontendCallback(jweak tunerObj, FrontendId id) : mObject(tunerObj), mId(id) {}
+FrontendClientCallbackImpl::FrontendClientCallbackImpl(
+ jweak tunerObj, FrontendId id) : mObject(tunerObj), mId(id) {}
-Return<void> FrontendCallback::onEvent(FrontendEventType frontendEventType) {
- ALOGD("FrontendCallback::onEvent, type=%d", frontendEventType);
+void FrontendClientCallbackImpl::onEvent(FrontendEventType frontendEventType) {
+ ALOGD("FrontendClientCallbackImpl::onEvent, type=%d", frontendEventType);
JNIEnv *env = AndroidRuntime::getJNIEnv();
env->CallVoidMethod(
mObject,
gFields.onFrontendEventID,
(jint)frontendEventType);
- return Void();
}
-Return<void> FrontendCallback::onScanMessage(FrontendScanMessageType type, const FrontendScanMessage& message) {
- ALOGD("FrontendCallback::onScanMessage, type=%d", type);
+void FrontendClientCallbackImpl::onScanMessage(
+ FrontendScanMessageType type, const FrontendScanMessage& message) {
+ ALOGD("FrontendClientCallbackImpl::onScanMessage, type=%d", type);
JNIEnv *env = AndroidRuntime::getJNIEnv();
jclass clazz = env->FindClass("android/media/tv/tuner/Tuner");
switch(type) {
@@ -1050,13 +1026,15 @@
mObject,
env->GetMethodID(clazz, "onDvbsStandard", "(I)V"),
standard);
- } else if (std.getDiscriminator() == FrontendScanMessage::Standard::hidl_discriminator::tStd) {
+ } else if (std.getDiscriminator() ==
+ FrontendScanMessage::Standard::hidl_discriminator::tStd) {
standard = (jint) std.tStd();
env->CallVoidMethod(
mObject,
env->GetMethodID(clazz, "onDvbtStandard", "(I)V"),
standard);
- } else if (std.getDiscriminator() == FrontendScanMessage::Standard::hidl_discriminator::sifStd) {
+ } else if (std.getDiscriminator() ==
+ FrontendScanMessage::Standard::hidl_discriminator::sifStd) {
standard = (jint) std.sifStd();
env->CallVoidMethod(
mObject,
@@ -1081,17 +1059,17 @@
}
env->CallVoidMethod(
mObject,
- env->GetMethodID(clazz, "onAtsc3PlpInfos", "([Landroid/media/tv/tuner/frontend/Atsc3PlpInfo;)V"),
+ env->GetMethodID(clazz, "onAtsc3PlpInfos",
+ "([Landroid/media/tv/tuner/frontend/Atsc3PlpInfo;)V"),
array);
break;
}
}
- return Void();
}
-Return<void> FrontendCallback::onScanMessageExt1_1(FrontendScanMessageTypeExt1_1 type,
+void FrontendClientCallbackImpl::onScanMessageExt1_1(FrontendScanMessageTypeExt1_1 type,
const FrontendScanMessageExt1_1& message) {
- ALOGD("FrontendCallback::onScanMessageExt1_1, type=%d", type);
+ ALOGD("FrontendClientCallbackImpl::onScanMessageExt1_1, type=%d", type);
JNIEnv *env = AndroidRuntime::getJNIEnv();
jclass clazz = env->FindClass("android/media/tv/tuner/Tuner");
switch(type) {
@@ -1165,7 +1143,6 @@
default:
break;
}
- return Void();
}
/////////////// Tuner ///////////////////////
@@ -1202,7 +1179,11 @@
env->DeleteWeakGlobalRef(mObject);
env->DeleteGlobalRef(mClass);
mTuner = NULL;
+ mFe = NULL;
+ mDemux = NULL;
mTunerClient = NULL;
+ mFeClient = NULL;
+ mDemuxClient = NULL;
mClass = NULL;
mObject = NULL;
}
@@ -1252,9 +1233,11 @@
return obj;
}
-jobject JTuner::openFrontendById(int id) {
+jobject JTuner::openFrontendByHandle(int feHandle) {
sp<IFrontend> fe;
Result res;
+ uint32_t id = getResourceIdFromHandle(feHandle);
+
mTuner->openFrontendById(id, [&](Result r, const sp<IFrontend>& frontend) {
fe = frontend;
res = r;
@@ -1269,11 +1252,25 @@
if (mDemux != NULL) {
mDemux->setFrontendDataSource(mFeId);
}
- sp<FrontendCallback> feCb = new FrontendCallback(mObject, id);
- fe->setCallback(feCb);
jint jId = (jint) id;
+ // TODO: Handle reopening frontend with different handle
+ sp<FrontendClient> feClient = mTunerClient->openFrontend(feHandle);
+ if (feClient == NULL) {
+ ALOGE("Failed to open frontend");
+ return NULL;
+ }
+ mFeClient = feClient;
+
+ mFeId = mFeClient->getId();
+ jId = (jint) id;
+ if (mDemuxClient != NULL) {
+ mDemuxClient->setFrontendDataSource(mFeClient);
+ }
+ sp<FrontendClientCallbackImpl> feClientCb = new FrontendClientCallbackImpl(mObject, id);
+ mFeClient->setCallback(feClientCb);
+
JNIEnv *env = AndroidRuntime::getJNIEnv();
// TODO: add more fields to frontend
return env->NewObject(
@@ -1589,30 +1586,19 @@
}
int JTuner::tune(const FrontendSettings& settings, const FrontendSettingsExt1_1& settingsExt1_1) {
- if (mFe == NULL) {
+ if (mFeClient == nullptr) {
ALOGE("frontend is not initialized");
return (int)Result::INVALID_STATE;
}
- Result result;
- sp<::android::hardware::tv::tuner::V1_1::IFrontend> fe_1_1 =
- ::android::hardware::tv::tuner::V1_1::IFrontend::castFrom(mFe);
- if (fe_1_1 == NULL) {
- ALOGD("1.1 frontend is not found. Using 1.0 instead.");
- result = mFe->tune(settings);
- return (int)result;
- }
-
- result = fe_1_1->tune_1_1(settings, settingsExt1_1);
- return (int)result;
+ return (int) mFeClient->tune(settings,settingsExt1_1);
}
int JTuner::stopTune() {
- if (mFe == NULL) {
+ if (mFeClient == nullptr) {
ALOGE("frontend is not initialized");
return (int)Result::INVALID_STATE;
}
- Result result = mFe->stopTune();
- return (int)result;
+ return (int) mFeClient->stopTune();
}
int JTuner::scan(const FrontendSettings& settings, FrontendScanType scanType,
@@ -1662,28 +1648,47 @@
}
Result JTuner::openDemux() {
- if (mTuner == nullptr) {
+ if (mTuner == nullptr || mTunerClient == nullptr) {
return Result::NOT_INITIALIZED;
}
- if (mDemux != nullptr) {
- return Result::SUCCESS;
- }
- Result res;
- uint32_t id;
- sp<IDemux> demuxSp;
- mTuner->openDemux([&](Result r, uint32_t demuxId, const sp<IDemux>& demux) {
- demuxSp = demux;
- id = demuxId;
- res = r;
- ALOGD("open demux, id = %d", demuxId);
- });
- if (res == Result::SUCCESS) {
- mDemux = demuxSp;
- mDemuxId = id;
- if (mFe != NULL) {
- mDemux->setFrontendDataSource(mFeId);
+
+ Result res = Result::SUCCESS;
+
+ if (mDemux == nullptr) {
+ uint32_t id;
+ sp<IDemux> demuxSp;
+ mTuner->openDemux([&](Result r, uint32_t demuxId, const sp<IDemux>& demux) {
+ demuxSp = demux;
+ id = demuxId;
+ res = r;
+ ALOGD("open demux, id = %d", demuxId);
+ });
+ if (res == Result::SUCCESS) {
+ mDemux = demuxSp;
+ mDemuxId = id;
+ if (mFe != NULL) {
+ mDemux->setFrontendDataSource(mFeId);
+ }
+ } else {
+ return res;
}
}
+
+ // TODO: replace demux opening with mTunerClient->openDemux(handle)
+ // when DemuxClient is fully ready
+ if (mDemuxClient == nullptr) {
+ sp<DemuxClient> demuxClient = new DemuxClient();
+ if (demuxClient == NULL) {
+ ALOGE("Failed to open demux");
+ return Result::UNKNOWN_ERROR;
+ }
+ mDemuxClient = demuxClient;
+ mDemuxClient->setHidlDemux(mDemux);
+ if (mFeClient != NULL) {
+ mDemuxClient->setFrontendDataSource(mFeClient);
+ }
+ }
+
return res;
}
@@ -1701,23 +1706,31 @@
return (jint) res;
}
}
+
+ if (mFeClient != NULL) {
+ res = mFeClient->close();
+ if (res != Result::SUCCESS) {
+ return (jint) res;
+ }
+ mFeClient = NULL;
+ }
+ if (mDemuxClient != NULL) {
+ res = mDemuxClient->close();
+ if (res != Result::SUCCESS) {
+ return (jint) res;
+ }
+ mDemuxClient = NULL;
+ }
return (jint) res;
}
-jobject JTuner::getAvSyncHwId(sp<Filter> filter) {
- if (mDemux == NULL) {
+jobject JTuner::getAvSyncHwId(sp<FilterClient> filterClient) {
+ if (mDemuxClient == NULL) {
return NULL;
}
- uint32_t avSyncHwId;
- Result res;
- sp<IFilter> iFilterSp = filter->getIFilter();
- mDemux->getAvSyncHwId(iFilterSp,
- [&](Result r, uint32_t id) {
- res = r;
- avSyncHwId = id;
- });
- if (res == Result::SUCCESS) {
+ int avSyncHwId = mDemuxClient->getAvSyncHwId(filterClient);
+ if (avSyncHwId >= 0) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
jclass integerClazz = env->FindClass("java/lang/Integer");
jmethodID intInit = env->GetMethodID(integerClazz, "<init>", "(I)V");
@@ -1727,17 +1740,11 @@
}
jobject JTuner::getAvSyncTime(jint id) {
- if (mDemux == NULL) {
+ if (mDemuxClient == NULL) {
return NULL;
}
- uint64_t time;
- Result res;
- mDemux->getAvSyncTime(static_cast<uint32_t>(id),
- [&](Result r, uint64_t ts) {
- res = r;
- time = ts;
- });
- if (res == Result::SUCCESS) {
+ long time = mDemuxClient->getAvSyncTime((int)id);
+ if (time >= 0) {
JNIEnv *env = AndroidRuntime::getJNIEnv();
jclass longClazz = env->FindClass("java/lang/Long");
jmethodID longInit = env->GetMethodID(longClazz, "<init>", "(J)V");
@@ -1747,13 +1754,13 @@
}
int JTuner::connectCiCam(jint id) {
- if (mDemux == NULL) {
+ if (mDemuxClient == NULL) {
Result r = openDemux();
if (r != Result::SUCCESS) {
return (int) r;
}
}
- Result r = mDemux->connectCiCam(static_cast<uint32_t>(id));
+ Result r = mDemuxClient->connectCiCam((int)id);
return (int) r;
}
@@ -1779,13 +1786,13 @@
}
int JTuner::disconnectCiCam() {
- if (mDemux == NULL) {
+ if (mDemuxClient == NULL) {
Result r = openDemux();
if (r != Result::SUCCESS) {
return (int) r;
}
}
- Result r = mDemux->disconnectCiCam();
+ Result r = mDemuxClient->disconnectCiCam();
return (int) r;
}
@@ -1832,34 +1839,25 @@
}
jobject JTuner::openFilter(DemuxFilterType type, int bufferSize) {
- if (mDemux == NULL) {
+ if (mDemux == NULL || mDemuxClient == NULL) {
if (openDemux() != Result::SUCCESS) {
return NULL;
}
}
- sp<IFilter> iFilterSp;
- sp<::android::hardware::tv::tuner::V1_1::IFilter> iFilterSp_1_1;
- sp<FilterCallback> callback = new FilterCallback();
- Result res;
- mDemux->openFilter(type, bufferSize, callback,
- [&](Result r, const sp<IFilter>& filter) {
- iFilterSp = filter;
- res = r;
- });
- if (res != Result::SUCCESS || iFilterSp == NULL) {
+ sp<FilterClient> filterClient;
+ sp<FilterClientCallbackImpl> callback = new FilterClientCallbackImpl();
+ filterClient = mDemuxClient->openFilter(type, bufferSize, callback);
+ if (filterClient == NULL) {
ALOGD("Failed to open filter, type = %d", type.mainType);
return NULL;
}
uint64_t fId;
- iFilterSp->getId([&](Result, uint32_t filterId) {
- fId = filterId;
- });
- iFilterSp_1_1 = ::android::hardware::tv::tuner::V1_1::IFilter::castFrom(iFilterSp);
- if (iFilterSp_1_1 != NULL) {
- iFilterSp_1_1->getId64Bit([&](Result, uint64_t filterId64Bit) {
- fId = filterId64Bit;
- });
+ Result res = filterClient->getId64Bit(fId);
+ if (res != Result::SUCCESS) {
+ uint32_t id;
+ filterClient->getId(id);
+ fId = static_cast<uint64_t>(id);
}
JNIEnv *env = AndroidRuntime::getJNIEnv();
@@ -1869,35 +1867,9 @@
gFields.filterInitID,
(jlong) fId);
- sp<Filter> filterSp = new Filter(iFilterSp, filterObj);
- filterSp->incStrong(filterObj);
- env->SetLongField(filterObj, gFields.filterContext, (jlong)filterSp.get());
- filterSp->mIsMediaFilter = false;
- filterSp->mAvSharedHandle = NULL;
- callback->setFilter(filterSp);
-
- if (type.mainType == DemuxFilterMainType::MMTP) {
- if (type.subType.mmtpFilterType() == DemuxMmtpFilterType::AUDIO ||
- type.subType.mmtpFilterType() == DemuxMmtpFilterType::VIDEO) {
- filterSp->mIsMediaFilter = true;
- }
- }
-
- if (type.mainType == DemuxFilterMainType::TS) {
- if (type.subType.tsFilterType() == DemuxTsFilterType::AUDIO ||
- type.subType.tsFilterType() == DemuxTsFilterType::VIDEO) {
- filterSp->mIsMediaFilter = true;
- }
- }
-
- if (iFilterSp_1_1 != NULL && filterSp->mIsMediaFilter) {
- iFilterSp_1_1->getAvSharedHandle([&](Result r, hidl_handle avMemory, uint64_t avMemSize) {
- if (r == Result::SUCCESS) {
- filterSp->mAvSharedHandle = native_handle_clone(avMemory.getNativeHandle());
- filterSp->mAvSharedMemSize = avMemSize;
- }
- });
- }
+ filterClient->incStrong(filterObj);
+ env->SetLongField(filterObj, gFields.filterContext, (jlong)filterClient.get());
+ callback->setFilter(env->NewWeakGlobalRef(filterObj), filterClient);
return filterObj;
}
@@ -2616,6 +2588,15 @@
if (r == Result::SUCCESS) {
mFe = NULL;
mFe_1_1 = NULL;
+ } else {
+ return (jint) r;
+ }
+
+ if (mFeClient != NULL) {
+ r = mFeClient->close();
+ }
+ if (r == Result::SUCCESS) {
+ mFeClient = NULL;
}
return (jint) r;
}
@@ -2627,10 +2608,18 @@
}
if (r == Result::SUCCESS) {
mDemux = NULL;
+ } else {
+ return (jint) r;
+ }
+
+ if (mDemuxClient != NULL) {
+ r = mDemuxClient->close();
+ }
+ if (r == Result::SUCCESS) {
+ mDemuxClient = NULL;
}
return (jint) r;
}
-
} // namespace android
////////////////////////////////////////////////////////////////////////////////
@@ -3271,8 +3260,8 @@
return settingsExt1_1;
}
-static sp<Filter> getFilter(JNIEnv *env, jobject filter) {
- return (Filter *)env->GetLongField(filter, gFields.filterContext);
+static sp<FilterClient> getFilterClient(JNIEnv *env, jobject filter) {
+ return (FilterClient *)env->GetLongField(filter, gFields.filterContext);
}
static DvrSettings getDvrSettings(JNIEnv *env, jobject settings, bool isRecorder) {
@@ -3383,7 +3372,7 @@
static void android_media_tv_Tuner_native_setup(JNIEnv *env, jobject thiz) {
sp<JTuner> tuner = new JTuner(env, thiz);
- setTuner(env,thiz, tuner);
+ setTuner(env, thiz, tuner);
}
static jint android_media_tv_Tuner_native_get_tuner_version(JNIEnv *env, jobject thiz) {
@@ -3399,8 +3388,7 @@
static jobject android_media_tv_Tuner_open_frontend_by_handle(
JNIEnv *env, jobject thiz, jint handle) {
sp<JTuner> tuner = getTuner(env, thiz);
- uint32_t id = getResourceIdFromHandle(handle);
- return tuner->openFrontendById(id);
+ return tuner->openFrontendByHandle(handle);
}
static int android_media_tv_Tuner_tune(JNIEnv *env, jobject thiz, jint type, jobject settings) {
@@ -3446,13 +3434,13 @@
static jobject android_media_tv_Tuner_get_av_sync_hw_id(
JNIEnv *env, jobject thiz, jobject filter) {
- sp<Filter> filterSp = getFilter(env, filter);
- if (filterSp == NULL) {
- ALOGD("Failed to get sync ID. Filter not found");
+ sp<FilterClient> filterClient = getFilterClient(env, filter);
+ if (filterClient == NULL) {
+ ALOGD("Failed to get sync ID. Filter client not found");
return NULL;
}
sp<JTuner> tuner = getTuner(env, thiz);
- return tuner->getAvSyncHwId(filterSp);
+ return tuner->getAvSyncHwId(filterClient);
}
static jobject android_media_tv_Tuner_get_av_sync_time(JNIEnv *env, jobject thiz, jint id) {
@@ -3913,26 +3901,13 @@
}
static Result configureIpFilterContextId(
- JNIEnv *env, sp<IFilter> iFilterSp, jobject ipFilterConfigObj) {
+ JNIEnv *env, sp<FilterClient> filterClient, jobject ipFilterConfigObj) {
jclass clazz = env->FindClass(
"android/media/tv/tuner/filter/IpFilterConfiguration");
uint32_t cid = env->GetIntField(ipFilterConfigObj, env->GetFieldID(
clazz, "mIpFilterContextId", "I"));
- Result res = Result::SUCCESS;
- if (cid != static_cast<uint32_t>(Constant::INVALID_IP_FILTER_CONTEXT_ID)) {
- sp<::android::hardware::tv::tuner::V1_1::IFilter> iFilterSp_1_1;
- iFilterSp_1_1 = ::android::hardware::tv::tuner::V1_1::IFilter::castFrom(iFilterSp);
- if (iFilterSp_1_1 != NULL) {
- res = iFilterSp_1_1->configureIpCid(cid);
- if (res != Result::SUCCESS) {
- return res;
- }
- } else {
- ALOGW("configureIpCid is not supported with the current HAL implementation.");
- }
- }
- return res;
+ return filterClient->configureIpFilterContextId(cid);
}
static jint copyData(JNIEnv *env, std::unique_ptr<MQ>& mq, EventFlag* flag, jbyteArray buffer,
@@ -3975,21 +3950,20 @@
static jint android_media_tv_Tuner_configure_filter(
JNIEnv *env, jobject filter, int type, int subtype, jobject settings) {
ALOGD("configure filter type=%d, subtype=%d", type, subtype);
- sp<Filter> filterSp = getFilter(env, filter);
- sp<IFilter> iFilterSp = filterSp->getIFilter();
- if (iFilterSp == NULL) {
+ sp<FilterClient> filterClient = getFilterClient(env, filter);
+ if (filterClient == NULL) {
ALOGD("Failed to configure filter: filter not found");
return (jint) Result::NOT_INITIALIZED;
}
DemuxFilterSettings filterSettings = getFilterConfiguration(env, type, subtype, settings);
- Result res = iFilterSp->configure(filterSettings);
+ Result res = filterClient->configure(filterSettings);
if (res != Result::SUCCESS) {
return (jint) res;
}
if (static_cast<DemuxFilterMainType>(type) == DemuxFilterMainType::IP) {
- res = configureIpFilterContextId(env, iFilterSp, settings);
+ res = configureIpFilterContextId(env, filterClient, settings);
if (res != Result::SUCCESS) {
return (jint) res;
}
@@ -3997,49 +3971,19 @@
AvStreamType streamType;
if (isAvFilterSettings(filterSettings) && getAvStreamType(env, settings, streamType)) {
- sp<::android::hardware::tv::tuner::V1_1::IFilter> iFilterSp_1_1;
- iFilterSp_1_1 = ::android::hardware::tv::tuner::V1_1::IFilter::castFrom(iFilterSp);
- if (iFilterSp_1_1 != NULL) {
- res = iFilterSp_1_1->configureAvStreamType(streamType);
- } else {
- ALOGW("configureAvStreamType is not supported with the current HAL implementation.");
- }
- if (res != Result::SUCCESS) {
- return (jint) res;
- }
+ res = filterClient->configureAvStreamType(streamType);
}
-
- MQDescriptorSync<uint8_t> filterMQDesc;
- Result getQueueDescResult = Result::UNKNOWN_ERROR;
- if (filterSp->mFilterMQ == NULL) {
- iFilterSp->getQueueDesc(
- [&](Result r, const MQDescriptorSync<uint8_t>& desc) {
- filterMQDesc = desc;
- getQueueDescResult = r;
- ALOGD("getFilterQueueDesc");
- });
- if (getQueueDescResult == Result::SUCCESS) {
- filterSp->mFilterMQ = std::make_unique<MQ>(filterMQDesc, true);
- EventFlag::createEventFlag(
- filterSp->mFilterMQ->getEventFlagWord(), &(filterSp->mFilterMQEventFlag));
- }
- }
- return (jint) getQueueDescResult;
+ return (jint) res;
}
static jint android_media_tv_Tuner_get_filter_id(JNIEnv* env, jobject filter) {
- sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
- if (iFilterSp == NULL) {
- ALOGD("Failed to get filter ID: filter not found");
+ sp<FilterClient> filterClient = getFilterClient(env, filter);
+ if (filterClient == NULL) {
+ ALOGD("Failed to get filter ID: filter client not found");
return (int) Result::NOT_INITIALIZED;
}
- Result res;
uint32_t id;
- iFilterSp->getId(
- [&](Result r, uint32_t filterId) {
- res = r;
- id = filterId;
- });
+ Result res = filterClient->getId(id);
if (res != Result::SUCCESS) {
return (jint) Constant::INVALID_FILTER_ID;
}
@@ -4047,30 +3991,13 @@
}
static jlong android_media_tv_Tuner_get_filter_64bit_id(JNIEnv* env, jobject filter) {
- sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
- if (iFilterSp == NULL) {
- ALOGD("Failed to get filter ID: filter not found");
- return static_cast<jlong>(
- ::android::hardware::tv::tuner::V1_1::Constant64Bit::INVALID_FILTER_ID_64BIT);
+ sp<FilterClient> filterClient = getFilterClient(env, filter);
+ if (filterClient == NULL) {
+ ALOGD("Failed to get filter ID 64 bit: filter client not found");
+ return (int) Result::NOT_INITIALIZED;
}
-
- sp<::android::hardware::tv::tuner::V1_1::IFilter> iFilterSp_1_1;
- iFilterSp_1_1 = ::android::hardware::tv::tuner::V1_1::IFilter::castFrom(iFilterSp);
- Result res;
uint64_t id;
-
- if (iFilterSp_1_1 != NULL) {
- iFilterSp_1_1->getId64Bit(
- [&](Result r, uint64_t filterId64Bit) {
- res = r;
- id = filterId64Bit;
- });
- } else {
- ALOGW("getId64Bit is not supported with the current HAL implementation.");
- return static_cast<jlong>(
- ::android::hardware::tv::tuner::V1_1::Constant64Bit::INVALID_FILTER_ID_64BIT);
- }
-
+ Result res = filterClient->getId64Bit(id);
return (res == Result::SUCCESS) ?
static_cast<jlong>(id) : static_cast<jlong>(
::android::hardware::tv::tuner::V1_1::Constant64Bit::INVALID_FILTER_ID_64BIT);
@@ -4078,96 +4005,96 @@
static jint android_media_tv_Tuner_configure_monitor_event(
JNIEnv* env, jobject filter, int monitorEventType) {
- sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
- if (iFilterSp == NULL) {
- ALOGD("Failed to configure scrambling event: filter not found");
- return (jint) Result::NOT_INITIALIZED;
+ sp<FilterClient> filterClient = getFilterClient(env, filter);
+ if (filterClient == NULL) {
+ ALOGD("Failed to configure scrambling event: filter client not found");
+ return (int) Result::NOT_INITIALIZED;
}
-
- sp<::android::hardware::tv::tuner::V1_1::IFilter> iFilterSp_1_1;
- iFilterSp_1_1 = ::android::hardware::tv::tuner::V1_1::IFilter::castFrom(iFilterSp);
- Result res;
-
- if (iFilterSp_1_1 != NULL) {
- res = iFilterSp_1_1->configureMonitorEvent(monitorEventType);
- } else {
- ALOGW("configureScramblingEvent is not supported with the current HAL implementation.");
- return (jint) Result::INVALID_STATE;
- }
-
+ Result res = filterClient->configureMonitorEvent(monitorEventType);
return (jint) res;
}
static jint android_media_tv_Tuner_set_filter_data_source(
JNIEnv* env, jobject filter, jobject srcFilter) {
- sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
- if (iFilterSp == NULL) {
- ALOGD("Failed to set filter data source: filter not found");
- return (jint) Result::NOT_INITIALIZED;
+ sp<FilterClient> filterClient = getFilterClient(env, filter);
+ if (filterClient == NULL) {
+ ALOGD("Failed to set filter data source: filter client not found");
+ return (int) Result::NOT_INITIALIZED;
}
- Result r;
+ Result res;
if (srcFilter == NULL) {
- r = iFilterSp->setDataSource(NULL);
+ res = filterClient->setDataSource(NULL);
} else {
- sp<IFilter> srcSp = getFilter(env, srcFilter)->getIFilter();
- if (iFilterSp == NULL) {
+ sp<FilterClient> srcClient = getFilterClient(env, srcFilter);
+ if (srcClient == NULL) {
ALOGD("Failed to set filter data source: src filter not found");
return (jint) Result::INVALID_ARGUMENT;
}
- r = iFilterSp->setDataSource(srcSp);
+ res = filterClient->setDataSource(srcClient);
}
- return (jint) r;
+ return (jint) res;
}
static jint android_media_tv_Tuner_start_filter(JNIEnv *env, jobject filter) {
- sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
- if (iFilterSp == NULL) {
- ALOGD("Failed to start filter: filter not found");
- return (jint) Result::NOT_INITIALIZED;
+ sp<FilterClient> filterClient = getFilterClient(env, filter);
+ if (filterClient == NULL) {
+ ALOGD("Failed to start filter: filter client not found");
+ return (int) Result::NOT_INITIALIZED;
}
- Result r = iFilterSp->start();
- return (jint) r;
+ return (jint) filterClient->start();
}
static jint android_media_tv_Tuner_stop_filter(JNIEnv *env, jobject filter) {
- sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
- if (iFilterSp == NULL) {
- ALOGD("Failed to stop filter: filter not found");
- return (jint) Result::NOT_INITIALIZED;
+ sp<FilterClient> filterClient = getFilterClient(env, filter);
+ if (filterClient == NULL) {
+ ALOGD("Failed to stop filter: filter client not found");
+ return (int) Result::NOT_INITIALIZED;
}
- Result r = iFilterSp->stop();
- return (jint) r;
+ return (jint) filterClient->stop();
}
static jint android_media_tv_Tuner_flush_filter(JNIEnv *env, jobject filter) {
- sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
- if (iFilterSp == NULL) {
- ALOGD("Failed to flush filter: filter not found");
- return (jint) Result::NOT_INITIALIZED;
+ sp<FilterClient> filterClient = getFilterClient(env, filter);
+ if (filterClient == NULL) {
+ ALOGD("Failed to flush filter: filter client not found");
+ return (int) Result::NOT_INITIALIZED;
}
- Result r = iFilterSp->flush();
- return (jint) r;
+ return (jint) filterClient->flush();
}
static jint android_media_tv_Tuner_read_filter_fmq(
JNIEnv *env, jobject filter, jbyteArray buffer, jlong offset, jlong size) {
- sp<Filter> filterSp = getFilter(env, filter);
- if (filterSp == NULL) {
+ sp<FilterClient> filterClient = getFilterClient(env, filter);
+ if (filterClient == NULL) {
jniThrowException(env, "java/lang/IllegalStateException",
- "Failed to read filter FMQ: filter not found");
+ "Failed to read filter FMQ: filter client not found");
return 0;
}
- return copyData(env, filterSp->mFilterMQ, filterSp->mFilterMQEventFlag, buffer, offset, size);
+
+ jboolean isCopy;
+ jbyte *dst = env->GetByteArrayElements(buffer, &isCopy);
+ ALOGD("copyData, isCopy=%d", isCopy);
+ if (dst == nullptr) {
+ jniThrowRuntimeException(env, "Failed to GetByteArrayElements");
+ return 0;
+ }
+ int realReadSize = filterClient->read(reinterpret_cast<uint8_t*>(dst) + offset, size);
+ env->ReleaseByteArrayElements(buffer, dst, 0);
+ if (realReadSize < 0) {
+ return (jint) Result::UNKNOWN_ERROR;
+ }
+ return (jint) Result::SUCCESS;
}
static jint android_media_tv_Tuner_close_filter(JNIEnv *env, jobject filter) {
- sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
- if (iFilterSp == NULL) {
- ALOGD("Failed to close filter: filter not found");
- return (jint) Result::NOT_INITIALIZED;
+ sp<FilterClient> filterClient = getFilterClient(env, filter);
+ if (filterClient == NULL) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Failed to close filter: filter client not found");
+ return 0;
}
- Result r = iFilterSp->close();
- return (jint) r;
+
+ return (jint) filterClient->close();
}
static sp<TimeFilter> getTimeFilter(JNIEnv *env, jobject filter) {
@@ -4275,7 +4202,8 @@
if (descramblerSp == NULL) {
return (jint) Result::NOT_INITIALIZED;
}
- sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
+ // TODO: use filter client once descramblerClient is ready
+ sp<IFilter> iFilterSp = getFilterClient(env, filter)->getHalFilter();
Result result = descramblerSp->addPid(getDemuxPid((int)pidType, (int)pid), iFilterSp);
return (jint) result;
}
@@ -4286,7 +4214,8 @@
if (descramblerSp == NULL) {
return (jint) Result::NOT_INITIALIZED;
}
- sp<IFilter> iFilterSp = getFilter(env, filter)->getIFilter();
+ // TODO: use filter client once descramblerClient is ready
+ sp<IFilter> iFilterSp = getFilterClient(env, filter)->getHalFilter();
Result result = descramblerSp->removePid(getDemuxPid((int)pidType, (int)pid), iFilterSp);
return (jint) result;
}
@@ -4358,12 +4287,13 @@
if (dvrSp == NULL) {
return (jint) Result::NOT_INITIALIZED;
}
- sp<Filter> filterSp = getFilter(env, filter);
- if (filterSp == NULL) {
+ sp<FilterClient> filterClient = getFilterClient(env, filter);
+ if (filterClient == NULL) {
return (jint) Result::INVALID_ARGUMENT;
}
sp<IDvr> iDvrSp = dvrSp->getIDvr();
- sp<IFilter> iFilterSp = filterSp->getIFilter();
+ // TODO: use filter client once dvrClient is ready
+ sp<IFilter> iFilterSp = filterClient->getHalFilter();
Result result = iDvrSp->attachFilter(iFilterSp);
return (jint) result;
}
@@ -4373,12 +4303,13 @@
if (dvrSp == NULL) {
return (jint) Result::NOT_INITIALIZED;
}
- sp<Filter> filterSp = getFilter(env, filter);
- if (filterSp == NULL) {
+ sp<FilterClient> filterClient = getFilterClient(env, filter);
+ if (filterClient == NULL) {
return (jint) Result::INVALID_ARGUMENT;
}
sp<IDvr> iDvrSp = dvrSp->getIDvr();
- sp<IFilter> iFilterSp = filterSp->getIFilter();
+ // TODO: use filter client once dvrClient is ready
+ sp<IFilter> iFilterSp = filterClient->getHalFilter();
Result result = iDvrSp->detachFilter(iFilterSp);
return (jint) result;
}
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index bec834c..4149228 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -34,6 +34,11 @@
#include <utils/Mutex.h>
#include <utils/RefBase.h>
+#include "tuner/DemuxClient.h"
+#include "tuner/FilterClient.h"
+#include "tuner/FilterClientCallback.h"
+#include "tuner/FrontendClient.h"
+#include "tuner/FrontendClientCallback.h"
#include "tuner/TunerClient.h"
#include "jni.h"
@@ -95,6 +100,7 @@
Lnb(sp<ILnb> sp, jobject obj);
~Lnb();
sp<ILnb> getILnb();
+ // TODO: remove after migrate to client lib
sp<ILnb> mLnbSp;
jweak mLnbObj;
};
@@ -115,6 +121,7 @@
jint close();
MQ& getDvrMQ();
sp<IDvr> getIDvr();
+ // TODO: remove after migrate to client lib
sp<IDvr> mDvrSp;
jweak mDvrObj;
std::unique_ptr<MQ> mDvrMQ;
@@ -123,29 +130,15 @@
int mFd;
};
-struct Filter : public RefBase {
- Filter(sp<IFilter> sp, jobject obj);
- ~Filter();
- int close();
- sp<IFilter> getIFilter();
- sp<IFilter> mFilterSp;
- std::unique_ptr<MQ> mFilterMQ;
- EventFlag* mFilterMQEventFlag;
- jweak mFilterObj;
- native_handle_t* mAvSharedHandle;
- uint64_t mAvSharedMemSize;
- bool mIsMediaFilter;
-};
-
struct MediaEvent : public RefBase {
- MediaEvent(sp<Filter> filter, hidl_handle avHandle, uint64_t dataId,
+ MediaEvent(sp<FilterClient> filterClient, hidl_handle avHandle, uint64_t dataId,
uint64_t dataSize, jobject obj);
~MediaEvent();
jobject getLinearBlock();
uint64_t getAudioHandle();
void finalize();
- sp<Filter> mFilter;
+ sp<FilterClient> mFilterClient;
native_handle_t* mAvHandle;
uint64_t mDataId;
uint64_t mDataSize;
@@ -159,16 +152,16 @@
std::weak_ptr<C2Buffer> mC2Buffer;
};
-struct FilterCallback : public IFilterCallback {
- ~FilterCallback();
- virtual Return<void> onFilterEvent_1_1(const DemuxFilterEvent& filterEvent,
+struct FilterClientCallbackImpl : public FilterClientCallback {
+ virtual void onFilterEvent_1_1(const DemuxFilterEvent& filterEvent,
const DemuxFilterEventExt& filterEventExt);
- virtual Return<void> onFilterEvent(const DemuxFilterEvent& filterEvent);
- virtual Return<void> onFilterStatus(const DemuxFilterStatus status);
+ virtual void onFilterEvent(const DemuxFilterEvent& filterEvent);
+ virtual void onFilterStatus(const DemuxFilterStatus status);
- void setFilter(const sp<Filter> filter);
+ void setFilter(jweak filterObj, sp<FilterClient> filterClient);
private:
- sp<Filter> mFilter;
+ jweak mFilterObj;
+ sp<FilterClient> mFilterClient;
jobjectArray getSectionEvent(
jobjectArray& arr, const std::vector<DemuxFilterEvent::Event>& events);
jobjectArray getMediaEvent(
@@ -195,13 +188,13 @@
jobjectArray& arr, const std::vector<DemuxFilterEventExt::Event>& eventsExt);
};
-struct FrontendCallback : public IFrontendCallback {
- FrontendCallback(jweak tunerObj, FrontendId id);
+struct FrontendClientCallbackImpl : public FrontendClientCallback {
+ FrontendClientCallbackImpl(jweak tunerObj, FrontendId id);
- virtual Return<void> onEvent(FrontendEventType frontendEventType);
- virtual Return<void> onScanMessage(
+ virtual void onEvent(FrontendEventType frontendEventType);
+ virtual void onScanMessage(
FrontendScanMessageType type, const FrontendScanMessage& message);
- virtual Return<void> onScanMessageExt1_1(
+ virtual void onScanMessageExt1_1(
FrontendScanMessageTypeExt1_1 type, const FrontendScanMessageExt1_1& messageExt);
jweak mObject;
@@ -212,22 +205,24 @@
TimeFilter(sp<ITimeFilter> sp, jweak obj);
~TimeFilter();
sp<ITimeFilter> getITimeFilter();
+ // TODO: remove after migrate to client lib
sp<ITimeFilter> mTimeFilterSp;
jweak mTimeFilterObj;
};
struct JTuner : public RefBase {
JTuner(JNIEnv *env, jobject thiz);
+ // TODO: modify after migrate to client lib
sp<ITuner> getTunerService();
int getTunerVersion();
- jobject getAvSyncHwId(sp<Filter> filter);
+ jobject getAvSyncHwId(sp<FilterClient> filter);
jobject getAvSyncTime(jint id);
int connectCiCam(jint id);
int linkCiCam(jint id);
int disconnectCiCam();
int unlinkCiCam(jint id);
jobject getFrontendIds();
- jobject openFrontendById(int id);
+ jobject openFrontendByHandle(int feHandle);
jint closeFrontendById(int id);
jobject getFrontendInfo(int id);
int tune(const FrontendSettings& settings, const FrontendSettingsExt1_1& settingsExt1_1);
@@ -257,15 +252,22 @@
private:
jclass mClass;
jweak mObject;
+ // TODO: remove after migrate to client lib
static sp<ITuner> mTuner;
static sp<::android::hardware::tv::tuner::V1_1::ITuner> mTuner_1_1;
static sp<TunerClient> mTunerClient;
+ // TODO: remove after migrate to client lib
sp<IFrontend> mFe;
+ // TODO: remove after migrate to client lib
sp<::android::hardware::tv::tuner::V1_1::IFrontend> mFe_1_1;
+ sp<FrontendClient> mFeClient;
int mFeId;
hidl_vec<LnbId> mLnbIds;
+ // TODO: remove after migrate to client lib
sp<ILnb> mLnb;
+ // TODO: remove after migrate to client lib
sp<IDemux> mDemux;
+ sp<DemuxClient> mDemuxClient;
uint32_t mDemuxId;
static jobject getAnalogFrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps);
static jobject getAtsc3FrontendCaps(JNIEnv *env, FrontendInfo::FrontendCapabilities& caps);
@@ -279,6 +281,9 @@
static jobject getDtmbFrontendCaps(JNIEnv *env, int id);
bool isV1_1ExtendedStatusType(jint type);
+ static uint32_t getResourceIdFromHandle(jint handle) {
+ return (handle & 0x00ff0000) >> 16;
+ }
};
class C2DataIdInfo : public C2Param {
diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp
index ac44843..253b4e3 100644
--- a/media/jni/soundpool/SoundPool.cpp
+++ b/media/jni/soundpool/SoundPool.cpp
@@ -84,8 +84,9 @@
} // namespace
-SoundPool::SoundPool(int32_t maxStreams, const audio_attributes_t* attributes)
- : mStreamManager(maxStreams, kStreamManagerThreads, attributes)
+SoundPool::SoundPool(
+ int32_t maxStreams, const audio_attributes_t* attributes, const std::string& opPackageName)
+ : mStreamManager(maxStreams, kStreamManagerThreads, attributes, opPackageName)
{
ALOGV("%s(maxStreams=%d, attr={ content_type=%d, usage=%d, flags=0x%x, tags=%s })",
__func__, maxStreams,
diff --git a/media/jni/soundpool/SoundPool.h b/media/jni/soundpool/SoundPool.h
index d5b16ef..ffb1c99 100644
--- a/media/jni/soundpool/SoundPool.h
+++ b/media/jni/soundpool/SoundPool.h
@@ -19,6 +19,8 @@
#include "SoundManager.h"
#include "StreamManager.h"
+#include <string>
+
namespace android {
/**
@@ -29,7 +31,8 @@
*/
class SoundPool {
public:
- SoundPool(int32_t maxStreams, const audio_attributes_t* attributes);
+ SoundPool(int32_t maxStreams, const audio_attributes_t* attributes,
+ const std::string& opPackageName = {});
~SoundPool();
// SoundPool Java API support
diff --git a/media/jni/soundpool/Stream.cpp b/media/jni/soundpool/Stream.cpp
index e7042d0..73e319a 100644
--- a/media/jni/soundpool/Stream.cpp
+++ b/media/jni/soundpool/Stream.cpp
@@ -332,7 +332,9 @@
0 /*default notification frames*/, AUDIO_SESSION_ALLOCATE,
AudioTrack::TRANSFER_DEFAULT,
nullptr /*offloadInfo*/, -1 /*uid*/, -1 /*pid*/,
- mStreamManager->getAttributes());
+ mStreamManager->getAttributes(),
+ false /*doNotReconnect*/, 1.0f /*maxRequiredSpeed*/,
+ mStreamManager->getOpPackageName());
// Set caller name so it can be logged in destructor.
// MediaMetricsConstants.h: AMEDIAMETRICS_PROP_CALLERNAME_VALUE_SOUNDPOOL
newTrack->setCallerName("soundpool");
diff --git a/media/jni/soundpool/StreamManager.cpp b/media/jni/soundpool/StreamManager.cpp
index 5b6494d..502ee00 100644
--- a/media/jni/soundpool/StreamManager.cpp
+++ b/media/jni/soundpool/StreamManager.cpp
@@ -98,9 +98,11 @@
#pragma clang diagnostic ignored "-Wthread-safety-analysis"
StreamManager::StreamManager(
- int32_t streams, size_t threads, const audio_attributes_t* attributes)
+ int32_t streams, size_t threads, const audio_attributes_t* attributes,
+ std::string opPackageName)
: StreamMap(streams)
, mAttributes(*attributes)
+ , mOpPackageName(std::move(opPackageName))
{
ALOGV("%s(%d, %zu, ...)", __func__, streams, threads);
forEach([this](Stream *stream) {
diff --git a/media/jni/soundpool/StreamManager.h b/media/jni/soundpool/StreamManager.h
index 59ae2f9..81ac69e 100644
--- a/media/jni/soundpool/StreamManager.h
+++ b/media/jni/soundpool/StreamManager.h
@@ -24,6 +24,7 @@
#include <map>
#include <memory>
#include <mutex>
+#include <string>
#include <unordered_set>
#include <vector>
@@ -386,7 +387,8 @@
public:
// Note: the SoundPool pointer is only used for stream initialization.
// It is not stored in StreamManager.
- StreamManager(int32_t streams, size_t threads, const audio_attributes_t* attributes);
+ StreamManager(int32_t streams, size_t threads, const audio_attributes_t* attributes,
+ std::string opPackageName);
~StreamManager();
// Returns positive streamID on success, 0 on failure. This is locked.
@@ -400,6 +402,8 @@
const audio_attributes_t* getAttributes() const { return &mAttributes; }
+ const std::string& getOpPackageName() const { return mOpPackageName; }
+
// Moves the stream to the restart queue (called upon BUFFER_END of the static track)
// this is locked internally.
// If activeStreamIDToMatch is nonzero, it will only move to the restart queue
@@ -473,6 +477,8 @@
// The paired stream may be active or restarting.
// No particular order.
std::unordered_set<Stream*> mProcessingStreams GUARDED_BY(mStreamManagerLock);
+
+ const std::string mOpPackageName;
};
} // namespace android::soundpool
diff --git a/media/jni/soundpool/android_media_SoundPool.cpp b/media/jni/soundpool/android_media_SoundPool.cpp
index 26725f8..357cc63 100644
--- a/media/jni/soundpool/android_media_SoundPool.cpp
+++ b/media/jni/soundpool/android_media_SoundPool.cpp
@@ -22,6 +22,7 @@
#include <utils/Log.h>
#include <jni.h>
#include <nativehelper/JNIPlatformHelp.h>
+#include <nativehelper/ScopedUtfChars.h>
#include <android_runtime/AndroidRuntime.h>
#include "SoundPool.h"
@@ -181,7 +182,7 @@
static jint
android_media_SoundPool_native_setup(JNIEnv *env, jobject thiz, jobject weakRef,
- jint maxChannels, jobject jaa)
+ jint maxChannels, jobject jaa, jstring opPackageName)
{
if (jaa == nullptr) {
ALOGE("Error creating SoundPool: invalid audio attributes");
@@ -203,7 +204,8 @@
paa->flags = (audio_flags_mask_t) env->GetIntField(jaa, javaAudioAttrFields.fieldFlags);
ALOGV("android_media_SoundPool_native_setup");
- auto *ap = new SoundPool(maxChannels, paa);
+ ScopedUtfChars opPackageNameStr(env, opPackageName);
+ auto *ap = new SoundPool(maxChannels, paa, opPackageNameStr.c_str());
if (ap == nullptr) {
return -1;
}
@@ -298,7 +300,7 @@
(void *)android_media_SoundPool_setRate
},
{ "native_setup",
- "(Ljava/lang/Object;ILjava/lang/Object;)I",
+ "(Ljava/lang/Object;ILjava/lang/Object;Ljava/lang/String;)I",
(void*)android_media_SoundPool_native_setup
},
{ "native_release",
diff --git a/media/jni/tuner/DemuxClient.cpp b/media/jni/tuner/DemuxClient.cpp
index 11acb5e..b237a24 100644
--- a/media/jni/tuner/DemuxClient.cpp
+++ b/media/jni/tuner/DemuxClient.cpp
@@ -68,14 +68,12 @@
sp<HidlFilterCallback> callback = new HidlFilterCallback(cb);
sp<IFilter> hidlFilter = openHidlFilter(type, bufferSize, callback);
if (hidlFilter != NULL) {
- sp<FilterClient> filterClient = new FilterClient();
+ sp<FilterClient> filterClient = new FilterClient(type);
filterClient->setHidlFilter(hidlFilter);
return filterClient;
}
}
- // TODO: handle share av memory handle
-
return NULL;
}
@@ -141,7 +139,7 @@
}
Result DemuxClient::close() {
- // pending aidl interface
+ // TODO: pending aidl interface
if (mDemux != NULL) {
Result res = mDemux->close();
diff --git a/media/jni/tuner/FilterClient.cpp b/media/jni/tuner/FilterClient.cpp
index a71cae6..0aab5fe 100644
--- a/media/jni/tuner/FilterClient.cpp
+++ b/media/jni/tuner/FilterClient.cpp
@@ -22,6 +22,9 @@
#include "FilterClient.h"
using ::android::hardware::tv::tuner::V1_0::DemuxQueueNotifyBits;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
+using ::android::hardware::tv::tuner::V1_0::DemuxMmtpFilterType;
+using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
namespace android {
@@ -29,20 +32,25 @@
// TODO: pending aidl interface
// TODO: add filter callback
-FilterClient::FilterClient() {
+FilterClient::FilterClient(DemuxFilterType type) {
//mTunerFilter = tunerFilter;
+ mAvSharedHandle = NULL;
+ checkIsMediaFilter(type);
}
FilterClient::~FilterClient() {
//mTunerFilter = NULL;
mFilter = NULL;
mFilter_1_1 = NULL;
+ mAvSharedHandle = NULL;
+ mAvSharedMemSize = 0;
}
// TODO: remove after migration to Tuner Service is done.
void FilterClient::setHidlFilter(sp<IFilter> filter) {
mFilter = filter;
mFilter_1_1 = ::android::hardware::tv::tuner::V1_1::IFilter::castFrom(mFilter);
+ handleAvShareMemory();
}
int FilterClient::read(uint8_t* buffer, int size) {
@@ -59,6 +67,22 @@
return -1;
}
+SharedHandleInfo FilterClient::getAvSharedHandleInfo() {
+ SharedHandleInfo info{
+ .sharedHandle = NULL,
+ .size = 0,
+ };
+
+ // TODO: pending aidl interface
+
+ if (mFilter_1_1 != NULL) {
+ info.sharedHandle = mAvSharedHandle;
+ info.size = mAvSharedMemSize;
+ }
+
+ return info;
+}
+
Result FilterClient::configure(DemuxFilterSettings configure) {
// TODO: pending aidl interface
@@ -187,7 +211,11 @@
// TODO: pending aidl interface
if (mFilter != NULL) {
- return mFilter->close();
+ Result res = mFilter->close();
+ if (res == Result::SUCCESS) {
+ mFilter = NULL;
+ }
+ return res;
}
return Result::INVALID_STATE;
@@ -261,4 +289,31 @@
return size;
}
+
+void FilterClient::checkIsMediaFilter(DemuxFilterType type) {
+ if (type.mainType == DemuxFilterMainType::MMTP) {
+ if (type.subType.mmtpFilterType() == DemuxMmtpFilterType::AUDIO ||
+ type.subType.mmtpFilterType() == DemuxMmtpFilterType::VIDEO) {
+ mIsMediaFilter = true;
+ }
+ }
+
+ if (type.mainType == DemuxFilterMainType::TS) {
+ if (type.subType.tsFilterType() == DemuxTsFilterType::AUDIO ||
+ type.subType.tsFilterType() == DemuxTsFilterType::VIDEO) {
+ mIsMediaFilter = true;
+ }
+ }
+}
+
+void FilterClient::handleAvShareMemory() {
+ if (mFilter_1_1 != NULL && mIsMediaFilter) {
+ mFilter_1_1->getAvSharedHandle([&](Result r, hidl_handle avMemory, uint64_t avMemSize) {
+ if (r == Result::SUCCESS) {
+ mAvSharedHandle = native_handle_clone(avMemory.getNativeHandle());
+ mAvSharedMemSize = avMemSize;
+ }
+ });
+ }
+}
} // namespace android
diff --git a/media/jni/tuner/FilterClient.h b/media/jni/tuner/FilterClient.h
index 4af74b0..976b2f5 100644
--- a/media/jni/tuner/FilterClient.h
+++ b/media/jni/tuner/FilterClient.h
@@ -34,6 +34,7 @@
using ::android::hardware::Void;
using ::android::hardware::hidl_handle;
using ::android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterType;
using ::android::hardware::tv::tuner::V1_0::IFilter;
using ::android::hardware::tv::tuner::V1_0::Result;
using ::android::hardware::tv::tuner::V1_1::AvStreamType;
@@ -45,6 +46,11 @@
namespace android {
+struct SharedHandleInfo {
+ native_handle_t* sharedHandle;
+ uint64_t size;
+};
+
// TODO: pending aidl interface
/*class TunerFilterCallback : public BnTunerFilterCallback {
@@ -75,7 +81,7 @@
public:
// TODO: pending aidl interface
- FilterClient();
+ FilterClient(DemuxFilterType type);
~FilterClient();
// TODO: remove after migration to Tuner Service is done.
@@ -89,6 +95,11 @@
int read(uint8_t* buffer, int size);
/**
+ * Get the a/v shared memory handle information
+ */
+ SharedHandleInfo getAvSharedHandleInfo();
+
+ /**
* Configure the filter.
*/
Result configure(DemuxFilterSettings configure);
@@ -161,6 +172,8 @@
private:
Result getFilterMq();
int copyData(uint8_t* buffer, int size);
+ void checkIsMediaFilter(DemuxFilterType type);
+ void handleAvShareMemory();
/**
* An AIDL Tuner Filter Singleton assigned at the first time when the Tuner Client
@@ -189,6 +202,10 @@
sp<FilterClientCallback> mCallback;
//shared_ptr<TunerFilterCallback> mAidlCallback;
sp<HidlFilterCallback> mHidlCallback;
+
+ native_handle_t* mAvSharedHandle;
+ uint64_t mAvSharedMemSize;
+ bool mIsMediaFilter;
};
} // namespace android
diff --git a/media/tests/MediaTranscodingTest/Android.bp b/media/tests/MediaTranscodingTest/Android.bp
deleted file mode 100644
index bd687a1..0000000
--- a/media/tests/MediaTranscodingTest/Android.bp
+++ /dev/null
@@ -1,16 +0,0 @@
-android_test {
- name: "mediatranscodingtest",
- srcs: ["**/*.java"],
- libs: [
- "android.test.runner",
- "android.test.base",
- ],
- static_libs: [
- "androidx.test.ext.junit",
- "androidx.test.rules",
- "androidx.test.uiautomator_uiautomator",
- "androidx.test.rules",
- "testng"
- ],
- platform_apis: true,
-}
diff --git a/media/tests/MediaTranscodingTest/AndroidManifest.xml b/media/tests/MediaTranscodingTest/AndroidManifest.xml
deleted file mode 100644
index 07674da..0000000
--- a/media/tests/MediaTranscodingTest/AndroidManifest.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.mediatranscodingtest">
-
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
- <uses-permission android:name="android.permission.WAKE_LOCK"/>
-
- <application android:label="@string/app_name">
- <uses-library android:name="android.test.runner"/>
- <activity android:label="@string/app_name"
- android:name="MediaTranscodingTest"
- android:screenOrientation="landscape"
- android:exported="true">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.LAUNCHER"/>
- </intent-filter>
- </activity>
- </application>
-
- <instrumentation android:name=".MediaTranscodingTestRunner"
- android:targetPackage="com.android.mediatranscodingtest"
- android:label="MediaTranscoding tests InstrumentationRunner">
- </instrumentation>
-</manifest>
diff --git a/media/tests/MediaTranscodingTest/Readme.txt b/media/tests/MediaTranscodingTest/Readme.txt
deleted file mode 100644
index e3b835b..0000000
--- a/media/tests/MediaTranscodingTest/Readme.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-MediaTranscodingTest/
- Uses instrumentation and so can be run with runtest.
- It assumes /sdcard/media_api/ has been populated.
-
-contents/media_api/
- Push to /sdcard/media_api/ for use with MediaTranscodingTest:
- adb shell mkdir /sdcard/media_api
- adb push contents/media_api/ /sdcard/media_api/
diff --git a/media/tests/MediaTranscodingTest/assets/ConflictSupportedValue.xml b/media/tests/MediaTranscodingTest/assets/ConflictSupportedValue.xml
deleted file mode 100644
index 9b2fa3b..0000000
--- a/media/tests/MediaTranscodingTest/assets/ConflictSupportedValue.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<media-capabilities xmlns:android="http://schemas.android.com/apk/res/android">
- <format android:name="HEVC" supported="true"/>
- <format android:name="HEVC" supported="false"/>
-</media-capabilities>
diff --git a/media/tests/MediaTranscodingTest/assets/EmptyFormat.xml b/media/tests/MediaTranscodingTest/assets/EmptyFormat.xml
deleted file mode 100644
index 5ef5e51..0000000
--- a/media/tests/MediaTranscodingTest/assets/EmptyFormat.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<media-capabilities xmlns:android="http://schemas.android.com/apk/res/android">
- <format />
-</media-capabilities>
diff --git a/media/tests/MediaTranscodingTest/assets/FormatWithoutSupported.xml b/media/tests/MediaTranscodingTest/assets/FormatWithoutSupported.xml
deleted file mode 100644
index e50c212..0000000
--- a/media/tests/MediaTranscodingTest/assets/FormatWithoutSupported.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<media-capabilities xmlns:android="http://schemas.android.com/apk/res/android">
- <format android:name="HEVC"/>
-</media-capabilities>
diff --git a/media/tests/MediaTranscodingTest/assets/MediaCapabilities.xml b/media/tests/MediaTranscodingTest/assets/MediaCapabilities.xml
deleted file mode 100644
index 3bff61e..0000000
--- a/media/tests/MediaTranscodingTest/assets/MediaCapabilities.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<media-capabilities xmlns:android="http://schemas.android.com/apk/res/android">
- <format android:name="HEVC" supported="true"/>
- <format android:name="HDR10" supported="false"/>
- <format android:name="SlowMotion" supported="false"/>
-</media-capabilities>
diff --git a/media/tests/MediaTranscodingTest/assets/SupportAllHdr.xml b/media/tests/MediaTranscodingTest/assets/SupportAllHdr.xml
deleted file mode 100644
index 5cf66b0..0000000
--- a/media/tests/MediaTranscodingTest/assets/SupportAllHdr.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<media-capabilities xmlns:android="http://schemas.android.com/apk/res/android">
- <format android:name="HEVC" supported="true"/>
- <format android:name="HDR10" supported="true"/>
- <format android:name="HDR10Plus" supported="true"/>
- <format android:name="Dolby-Vision" supported="true"/>
- <format android:name="HLG" supported="true"/>
- <format android:name="SlowMotion" supported="true"/>
-</media-capabilities>
diff --git a/media/tests/MediaTranscodingTest/assets/SupportHdrWithoutHevc.xml b/media/tests/MediaTranscodingTest/assets/SupportHdrWithoutHevc.xml
deleted file mode 100644
index 309aa1d..0000000
--- a/media/tests/MediaTranscodingTest/assets/SupportHdrWithoutHevc.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<media-capabilities xmlns:android="http://schemas.android.com/apk/res/android">
- <format android:name="HDR10" supported="true"/>
- <format android:name="SlowMotion" supported="false"/>
-</media-capabilities>
diff --git a/media/tests/MediaTranscodingTest/assets/SupportedWithoutFormat.xml b/media/tests/MediaTranscodingTest/assets/SupportedWithoutFormat.xml
deleted file mode 100644
index 29454fc..0000000
--- a/media/tests/MediaTranscodingTest/assets/SupportedWithoutFormat.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<media-capabilities xmlns:android="http://schemas.android.com/apk/res/android">
- <format supported="true"/>
-</media-capabilities>
diff --git a/media/tests/MediaTranscodingTest/assets/WrongBooleanValue.xml b/media/tests/MediaTranscodingTest/assets/WrongBooleanValue.xml
deleted file mode 100644
index 62de6cd..0000000
--- a/media/tests/MediaTranscodingTest/assets/WrongBooleanValue.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<media-capabilities xmlns:android="http://schemas.android.com/apk/res/android">
- <format android:name="HEVC" supported="yes"/>
- <format android:name="HDR10" supported="false"/>
- <format android:name="SlowMotion" supported="false"/>
-</media-capabilities>
diff --git a/media/tests/MediaTranscodingTest/assets/WrongMediaCapabilityTag.xml b/media/tests/MediaTranscodingTest/assets/WrongMediaCapabilityTag.xml
deleted file mode 100644
index 5db42e5..0000000
--- a/media/tests/MediaTranscodingTest/assets/WrongMediaCapabilityTag.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<media-capability xmlns:android="http://schemas.android.com/apk/res/android">
- <format android:name="HEVC" supported="true"/>
- <format android:name="HDR10" supported="true"/>
- <format android:name="SlowMotion" supported="true"/>
-</media-capabilities>
diff --git a/media/tests/MediaTranscodingTest/assets/WrongMediaCapabilityTag2.xml b/media/tests/MediaTranscodingTest/assets/WrongMediaCapabilityTag2.xml
deleted file mode 100644
index e924c48..0000000
--- a/media/tests/MediaTranscodingTest/assets/WrongMediaCapabilityTag2.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<MediaCapability xmlns:android="http://schemas.android.com/apk/res/android">
- <format android:name="HEVC" supported="true"/>
- <format android:name="HDR10" supported="true"/>
- <format android:name="SlowMotion" supported="true"/>
-</MediaCapability>
diff --git a/media/tests/MediaTranscodingTest/build_and_run_unit_tests.sh b/media/tests/MediaTranscodingTest/build_and_run_unit_tests.sh
deleted file mode 100644
index c8fb3a6..0000000
--- a/media/tests/MediaTranscodingTest/build_and_run_unit_tests.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/bash
-#
-# Run tests in this directory.
-#
-
-if [ -z "$ANDROID_BUILD_TOP" ]; then
- echo "Android build environment not set"
- exit -1
-fi
-
-# ensure we have mm
-. $ANDROID_BUILD_TOP/build/envsetup.sh
-
-mm
-
-echo "[==========] waiting for device"
-adb root && adb wait-for-device remount
-
-echo "[==========] set to use real transcoder"
-adb shell setprop debug.transcoding.simulated_transcoder false;
-adb shell kill -9 `pid media.transcoding`
-
-echo "[==========] build test apk"
-mmm -j16 .
-adb install -r -g ${OUT}/testcases/mediatranscodingtest/arm64/mediatranscodingtest.apk
-
-# Push the files into app's cache directory/
-FILES=$ANDROID_BUILD_TOP/frameworks/av/media/libmediatranscoding/tests/assets/*
-for file in $FILES
-do
-adb push --sync $file /data/user/0/com.android.mediatranscodingtest/cache/
-done
-
-echo "[==========] running MediaTranscodeManagerTest"
-adb shell am instrument -e class com.android.mediatranscodingtest.MediaTranscodeManagerTest -w com.android.mediatranscodingtest/.MediaTranscodingTestRunner
-
-echo "[==========] running MediaTranscodeManagerDiedTest"
-adb shell am instrument -e class com.android.mediatranscodingtest.MediaTranscodeManagerDiedTest -w com.android.mediatranscodingtest/.MediaTranscodingTestRunner
-
diff --git a/media/tests/MediaTranscodingTest/res/drawable-hdpi/icon.png b/media/tests/MediaTranscodingTest/res/drawable-hdpi/icon.png
deleted file mode 100644
index a02138e..0000000
--- a/media/tests/MediaTranscodingTest/res/drawable-hdpi/icon.png
+++ /dev/null
Binary files differ
diff --git a/media/tests/MediaTranscodingTest/res/drawable-mdpi/icon.png b/media/tests/MediaTranscodingTest/res/drawable-mdpi/icon.png
deleted file mode 100644
index 64e3601..0000000
--- a/media/tests/MediaTranscodingTest/res/drawable-mdpi/icon.png
+++ /dev/null
Binary files differ
diff --git a/media/tests/MediaTranscodingTest/res/layout/surface_view.xml b/media/tests/MediaTranscodingTest/res/layout/surface_view.xml
deleted file mode 100644
index 3b49db0..0000000
--- a/media/tests/MediaTranscodingTest/res/layout/surface_view.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
-
- <FrameLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <SurfaceView
- android:id="@+id/surface_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_centerInParent="true"
- />
-
- </FrameLayout>
-
-</LinearLayout>
diff --git a/media/tests/MediaTranscodingTest/res/raw/VideoOnlyAVC.mp4 b/media/tests/MediaTranscodingTest/res/raw/VideoOnlyAVC.mp4
deleted file mode 100644
index 2033a3f..0000000
--- a/media/tests/MediaTranscodingTest/res/raw/VideoOnlyAVC.mp4
+++ /dev/null
Binary files differ
diff --git a/media/tests/MediaTranscodingTest/res/raw/VideoOnlyHEVC.mp4 b/media/tests/MediaTranscodingTest/res/raw/VideoOnlyHEVC.mp4
deleted file mode 100644
index 7ac0024..0000000
--- a/media/tests/MediaTranscodingTest/res/raw/VideoOnlyHEVC.mp4
+++ /dev/null
Binary files differ
diff --git a/media/tests/MediaTranscodingTest/res/raw/cubicle_avc_480x240_aac_24KHz.mp4 b/media/tests/MediaTranscodingTest/res/raw/cubicle_avc_480x240_aac_24KHz.mp4
deleted file mode 100644
index ef7e1b7..0000000
--- a/media/tests/MediaTranscodingTest/res/raw/cubicle_avc_480x240_aac_24KHz.mp4
+++ /dev/null
Binary files differ
diff --git a/media/tests/MediaTranscodingTest/res/values/strings.xml b/media/tests/MediaTranscodingTest/res/values/strings.xml
deleted file mode 100644
index 0e1f8eb..0000000
--- a/media/tests/MediaTranscodingTest/res/values/strings.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <!-- Test application name [CHAR LIMIT=32] -->
- <string name="app_name">MediaTranscodingTest</string>
-</resources>
diff --git a/media/tests/MediaTranscodingTest/res/xml/mediacapabilities.xml b/media/tests/MediaTranscodingTest/res/xml/mediacapabilities.xml
deleted file mode 100644
index 3bff61e..0000000
--- a/media/tests/MediaTranscodingTest/res/xml/mediacapabilities.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<media-capabilities xmlns:android="http://schemas.android.com/apk/res/android">
- <format android:name="HEVC" supported="true"/>
- <format android:name="HDR10" supported="false"/>
- <format android:name="SlowMotion" supported="false"/>
-</media-capabilities>
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/ApplicationMediaCapabilitiesTest.java b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/ApplicationMediaCapabilitiesTest.java
deleted file mode 100644
index 74552a5..0000000
--- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/ApplicationMediaCapabilitiesTest.java
+++ /dev/null
@@ -1,306 +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.mediatranscodingtest;
-
-/*
- * Test for ApplicationMediaCapabilities in the media framework.
- *
- * To run this test suite:
- make frameworks/base/media/tests/MediaTranscodingTest
- make mediatranscodingtest
-
- adb install -r testcases/mediatranscodingtest/arm64/mediatranscodingtest.apk
-
- adb shell am instrument -e class \
- com.android.mediatranscodingtest.ApplicationMediaCapabilitiesTest \
- -w com.android.mediatranscodingtest/.MediaTranscodingTestRunner
- *
- */
-
-import static org.testng.Assert.assertThrows;
-
-import android.content.Context;
-import android.content.res.XmlResourceParser;
-import android.media.ApplicationMediaCapabilities;
-import android.media.MediaFeature;
-import android.media.MediaFormat;
-import android.test.ActivityInstrumentationTestCase2;
-import android.util.Log;
-import android.util.Xml;
-
-import org.junit.Test;
-import org.xmlpull.v1.XmlPullParser;
-
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-
-public class ApplicationMediaCapabilitiesTest extends
- ActivityInstrumentationTestCase2<MediaTranscodingTest> {
- private static final String TAG = "MediaCapabilityTest";
-
- private Context mContext;
-
- public ApplicationMediaCapabilitiesTest() {
- super("com.android.MediaCapabilityTest", MediaTranscodingTest.class);
- }
-
- public void setUp() throws Exception {
- Log.d(TAG, "setUp");
- super.setUp();
-
- mContext = getInstrumentation().getContext();
- }
-
-
- @Test
- public void testSetSupportHevc() throws Exception {
- ApplicationMediaCapabilities capability =
- new ApplicationMediaCapabilities.Builder().addSupportedVideoMimeType(
- MediaFormat.MIMETYPE_VIDEO_HEVC).build();
- assertTrue(capability.isVideoMimeTypeSupported(MediaFormat.MIMETYPE_VIDEO_HEVC));
-
- ApplicationMediaCapabilities capability2 =
- new ApplicationMediaCapabilities.Builder().build();
- assertFalse(capability2.isVideoMimeTypeSupported(MediaFormat.MIMETYPE_VIDEO_HEVC));
- }
-
- @Test
- public void testSetSupportHdr() throws Exception {
- ApplicationMediaCapabilities capability =
- new ApplicationMediaCapabilities.Builder().addSupportedHdrType(
- MediaFeature.HdrType.HDR10_PLUS).addSupportedVideoMimeType(
- MediaFormat.MIMETYPE_VIDEO_HEVC).build();
- assertEquals(true, capability.isHdrTypeSupported(MediaFeature.HdrType.HDR10_PLUS));
- }
-
- @Test
- public void testSetSupportSlowMotion() throws Exception {
- ApplicationMediaCapabilities capability =
- new ApplicationMediaCapabilities.Builder().setSlowMotionSupported(true).build();
- assertTrue(capability.isSlowMotionSupported());
- }
-
- @Test
- public void testBuilder() throws Exception {
- ApplicationMediaCapabilities capability =
- new ApplicationMediaCapabilities.Builder().addSupportedVideoMimeType(
- MediaFormat.MIMETYPE_VIDEO_HEVC).addSupportedHdrType(
- MediaFeature.HdrType.HDR10_PLUS).setSlowMotionSupported(true).build();
- assertTrue(capability.isVideoMimeTypeSupported(MediaFormat.MIMETYPE_VIDEO_HEVC));
- assertTrue(capability.isHdrTypeSupported(MediaFeature.HdrType.HDR10_PLUS));
- assertTrue(capability.isSlowMotionSupported());
- }
-
- @Test
- public void testSupportHdrWithoutSupportHevc() throws Exception {
- assertThrows(UnsupportedOperationException.class, () -> {
- ApplicationMediaCapabilities capability =
- new ApplicationMediaCapabilities.Builder().addSupportedHdrType(
- MediaFeature.HdrType.HDR10_PLUS).build();
- });
- }
-
- // Test read the application's xml from res/xml folder using the XmlResourceParser.
- // <format android:name="HEVC" supported="true"/>
- // <format android:name="HDR10" supported="false"/>
- // <format android:name="SlowMotion" supported="false"/>
- @Test
- public void testReadMediaCapabilitiesXml() throws Exception {
- XmlResourceParser parser = mContext.getResources().getXml(R.xml.mediacapabilities);
- ApplicationMediaCapabilities capability = ApplicationMediaCapabilities.createFromXml(
- parser);
- assertFalse(capability.isHdrTypeSupported(MediaFeature.HdrType.HDR10));
- assertFalse(capability.isSlowMotionSupported());
- assertTrue(capability.isVideoMimeTypeSupported(MediaFormat.MIMETYPE_VIDEO_HEVC));
- }
-
- // Test read the application's xml from res/xml folder using the XmlResourceParser.
- // <format android:name="HEVC" supported="true"/>
- // <format android:name="HDR10" supported="true"/>
- // <format android:name="HDR10Plus" supported="true"/>
- // <format android:name="Dolby-Vision" supported="true"/>
- // <format android:name="HLG" supported="true"/>
- // <format android:name="SlowMotion" supported="true"/>
- @Test
- public void testReadMediaCapabilitiesXmlWithSupportAllHdr() throws Exception {
- InputStream xmlIs = mContext.getAssets().open("SupportAllHdr.xml");
- final XmlPullParser parser = Xml.newPullParser();
- parser.setInput(xmlIs, StandardCharsets.UTF_8.name());
-
- ApplicationMediaCapabilities capability = ApplicationMediaCapabilities.createFromXml(
- parser);
- assertTrue(capability.isHdrTypeSupported(MediaFeature.HdrType.HDR10));
- assertTrue(capability.isHdrTypeSupported(MediaFeature.HdrType.HDR10_PLUS));
- assertTrue(capability.isHdrTypeSupported(MediaFeature.HdrType.DOLBY_VISION));
- assertTrue(capability.isHdrTypeSupported(MediaFeature.HdrType.HLG));
- assertTrue(capability.isSlowMotionSupported());
- assertTrue(capability.isVideoMimeTypeSupported(MediaFormat.MIMETYPE_VIDEO_HEVC));
- }
-
- // Test read the xml from res/assets folder using the InputStream.
- // <format android:name="HEVC" supported="true"/>
- // <format android:name="HDR10" supported="false"/>
- // <format android:name="SlowMotion" supported="false"/>
- @Test
- public void testReadFromCorrectXmlWithInputStreamInAssets() throws Exception {
- InputStream xmlIs = mContext.getAssets().open("MediaCapabilities.xml");
- final XmlPullParser parser = Xml.newPullParser();
- parser.setInput(xmlIs, StandardCharsets.UTF_8.name());
-
- ApplicationMediaCapabilities capability = ApplicationMediaCapabilities.createFromXml(
- parser);
- assertFalse(capability.isHdrTypeSupported(MediaFeature.HdrType.HDR10));
- assertFalse(capability.isSlowMotionSupported());
- assertTrue(capability.isVideoMimeTypeSupported(MediaFormat.MIMETYPE_VIDEO_HEVC));
- }
-
- // Test parsing invalid xml with wrong tag expect UnsupportedOperationException
- // MediaCapability does not match MediaCapabilities at the end which will lead to
- // exception with "Ill-formatted xml file"
- // <MediaCapability xmlns:android="http://schemas.android.com/apk/res/android">
- // <format android:name="HEVC" supported="true"/>
- // <format android:name="HDR10" supported="true"/>
- // <format android:name="SlowMotion" supported="true"/>
- // </MediaCapabilities>
- @Test
- public void testReadFromWrongMediaCapabilityXml() throws Exception {
- assertThrows(UnsupportedOperationException.class, () -> {
- InputStream xmlIs = mContext.getAssets().open("WrongMediaCapabilityTag.xml");
- final XmlPullParser parser = Xml.newPullParser();
- parser.setInput(xmlIs, StandardCharsets.UTF_8.name());
- ApplicationMediaCapabilities capability = ApplicationMediaCapabilities.createFromXml(
- parser);
- });
- }
-
- // Test invalid xml with wrong tag expect UnsupportedOperationException
- // MediaCapability is wrong tag.
- // <MediaCapability xmlns:android="http://schemas.android.com/apk/res/android">
- // <format android:name="HEVC" supported="true"/>
- // <format android:name="HDR10" supported="true"/>
- // <format android:name="SlowMotion" supported="true"/>
- // </MediaCapability>
- @Test
- public void testReadFromWrongMediaCapabilityXml2() throws Exception {
- assertThrows(UnsupportedOperationException.class, () -> {
- InputStream xmlIs = mContext.getAssets().open("WrongMediaCapabilityTag2.xml");
- final XmlPullParser parser = Xml.newPullParser();
- parser.setInput(xmlIs, StandardCharsets.UTF_8.name());
- ApplicationMediaCapabilities capability = ApplicationMediaCapabilities.createFromXml(
- parser);
- });
- }
-
- // Test invalid attribute value of "support" with true->yes expect UnsupportedOperationException
- // <MediaCapabilities xmlns:android="http://schemas.android.com/apk/res/android">
- // <format android:name="HEVC" supported="yes"/>
- // <format android:name="HDR10" supported="false"/>
- // <format android:name="SlowMotion" supported="false"/>
- // </MediaCapabilities>
- @Test
- public void testReadFromXmlWithWrongBoolean() throws Exception {
- assertThrows(UnsupportedOperationException.class, () -> {
- InputStream xmlIs = mContext.getAssets().open("WrongBooleanValue.xml");
- final XmlPullParser parser = Xml.newPullParser();
- parser.setInput(xmlIs, StandardCharsets.UTF_8.name());
- ApplicationMediaCapabilities capability = ApplicationMediaCapabilities.createFromXml(
- parser);
- });
- }
-
- // Test parsing capabilities that support HDR10 but not support HEVC.
- // Expect UnsupportedOperationException
- // <MediaCapability xmlns:android="http://schemas.android.com/apk/res/android">
- // <format android:name="HDR10" supported="true"/>
- // <format android:name="SlowMotion" supported="false"/>
- // </MediaCapabilities>
- @Test
- public void testReadXmlSupportHdrWithoutSupportHevc() throws Exception {
- assertThrows(UnsupportedOperationException.class, () -> {
- InputStream xmlIs = mContext.getAssets().open("SupportHdrWithoutHevc.xml");
- final XmlPullParser parser = Xml.newPullParser();
- parser.setInput(xmlIs, StandardCharsets.UTF_8.name());
- ApplicationMediaCapabilities capability = ApplicationMediaCapabilities.createFromXml(
- parser);
- });
- }
-
- // Test parsing capabilities that has conflicted supported value.
- // Expect UnsupportedOperationException
- // <media-capabilities xmlns:android="http://schemas.android.com/apk/res/android">
- // <format android:name="HEVC" supported="true"/>
- // <format android:name="HEVC" supported="false"/>
- // </media-capabilities>
- @Test
- public void testReadXmlConflictSupportedValue() throws Exception {
- assertThrows(UnsupportedOperationException.class, () -> {
- InputStream xmlIs = mContext.getAssets().open("ConflictSupportedValue.xml");
- final XmlPullParser parser = Xml.newPullParser();
- parser.setInput(xmlIs, StandardCharsets.UTF_8.name());
- ApplicationMediaCapabilities capability = ApplicationMediaCapabilities.createFromXml(
- parser);
- });
- }
-
- // Test parsing capabilities that has empty format.
- // Expect UnsupportedOperationException
- // <media-capabilities xmlns:android="http://schemas.android.com/apk/res/android">
- // <format/>
- // </media-capabilities>
- @Test
- public void testReadXmlWithEmptyFormat() throws Exception {
- assertThrows(UnsupportedOperationException.class, () -> {
- InputStream xmlIs = mContext.getAssets().open("EmptyFormat.xml");
- final XmlPullParser parser = Xml.newPullParser();
- parser.setInput(xmlIs, StandardCharsets.UTF_8.name());
- ApplicationMediaCapabilities capability = ApplicationMediaCapabilities.createFromXml(
- parser);
- });
- }
-
- // Test parsing capabilities that has empty format.
- // Expect UnsupportedOperationException
- // <media-capabilities xmlns:android="http://schemas.android.com/apk/res/android">
- // <format android:name="HEVC"/>
- // </media-capabilities>
- @Test
- public void testReadXmlFormatWithoutSupported() throws Exception {
- assertThrows(UnsupportedOperationException.class, () -> {
- InputStream xmlIs = mContext.getAssets().open("FormatWithoutSupported.xml");
- final XmlPullParser parser = Xml.newPullParser();
- parser.setInput(xmlIs, StandardCharsets.UTF_8.name());
- ApplicationMediaCapabilities capability = ApplicationMediaCapabilities.createFromXml(
- parser);
- });
- }
-
- // Test parsing capabilities that has supported without the format name.
- // Expect UnsupportedOperationException
- // <media-capabilities xmlns:android="http://schemas.android.com/apk/res/android">
- // <format supported="true"/>
- // </media-capabilities>
- @Test
- public void testReadXmlSupportedWithoutFormat() throws Exception {
- assertThrows(UnsupportedOperationException.class, () -> {
- InputStream xmlIs = mContext.getAssets().open("SupportedWithoutFormat.xml");
- final XmlPullParser parser = Xml.newPullParser();
- parser.setInput(xmlIs, StandardCharsets.UTF_8.name());
- ApplicationMediaCapabilities capability = ApplicationMediaCapabilities.createFromXml(
- parser);
- });
- }
-}
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerDiedTest.java b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerDiedTest.java
deleted file mode 100644
index 7c9842b..0000000
--- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerDiedTest.java
+++ /dev/null
@@ -1,284 +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.mediatranscodingtest;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.media.MediaFormat;
-import android.media.MediaTranscodeManager;
-import android.media.MediaTranscodeManager.TranscodingRequest;
-import android.media.MediaTranscodeManager.TranscodingSession;
-import android.media.MediaTranscodingException;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.FileUtils;
-import android.os.ParcelFileDescriptor;
-import android.test.ActivityInstrumentationTestCase2;
-import android.util.Log;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.uiautomator.UiDevice;
-
-import org.junit.Test;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/*
- * Service died tests for MediaTranscodeManager in the media framework.
- *
- * To run this test suite:
- make frameworks/base/media/tests/MediaTranscodingTest
- make mediatranscodingtest
-
- adb install -r testcases/mediatranscodingtest/arm64/mediatranscodingtest.apk
-
- adb shell am instrument -e class \
- com.android.mediatranscodingtest.MediaTranscodeManagerDiedTest \
- -w com.android.mediatranscodingtest/.MediaTranscodingTestRunner
- *
- */
-public class MediaTranscodeManagerDiedTest
- extends ActivityInstrumentationTestCase2<MediaTranscodingTest> {
- private static final String TAG = "MediaTranscodeManagerDiedTest";
- /** The time to wait for the transcode operation to complete before failing the test. */
- private static final int TRANSCODE_TIMEOUT_SECONDS = 10;
-
- /** Maximum number of retry to connect to the service. */
- private static final int CONNECT_SERVICE_RETRY_COUNT = 100;
-
- /** Interval between trying to reconnect to the service. */
- private static final int INTERVAL_CONNECT_SERVICE_RETRY_MS = 40;
-
- private Context mContext;
- private MediaTranscodeManager mMediaTranscodeManager = null;
- private Uri mSourceHEVCVideoUri = null;
- private Uri mSourceAVCVideoUri = null;
- private Uri mDestinationUri = null;
-
- // Setting for transcoding to H.264.
- private static final String MIME_TYPE = MediaFormat.MIMETYPE_VIDEO_AVC;
- private static final int BIT_RATE = 20000000; // 20Mbps
- private static final int WIDTH = 1920;
- private static final int HEIGHT = 1080;
-
- public MediaTranscodeManagerDiedTest() {
- super("com.android.MediaTranscodeManagerTest", MediaTranscodingTest.class);
- }
-
- // Copy the resource to cache.
- private Uri resourceToUri(Context context, int resId, String name) throws IOException {
- Uri resUri = new Uri.Builder()
- .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
- .authority(context.getResources().getResourcePackageName(resId))
- .appendPath(context.getResources().getResourceTypeName(resId))
- .appendPath(context.getResources().getResourceEntryName(resId))
- .build();
-
- Uri cacheUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
- + mContext.getCacheDir().getAbsolutePath() + "/" + name);
-
- InputStream is = mContext.getResources().openRawResource(resId);
- OutputStream os = mContext.getContentResolver().openOutputStream(cacheUri);
-
- FileUtils.copy(is, os);
-
- return cacheUri;
- }
-
- private static Uri generateNewUri(Context context, String filename) {
- File outFile = new File(context.getExternalCacheDir(), filename);
- return Uri.fromFile(outFile);
- }
-
- /**
- * Creates a MediaFormat with the basic set of values.
- */
- private static MediaFormat createMediaFormat() {
- MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, WIDTH, HEIGHT);
- format.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE);
- return format;
- }
-
- private MediaTranscodeManager getManager() {
- for (int count = 1; count <= CONNECT_SERVICE_RETRY_COUNT; count++) {
- Log.d(TAG, "Trying to connect to service. Try count: " + count);
- MediaTranscodeManager manager = mContext.getSystemService(MediaTranscodeManager.class);
- if (manager != null) {
- return manager;
- }
- try {
- // Sleep a bit before retry.
- Thread.sleep(INTERVAL_CONNECT_SERVICE_RETRY_MS);
- } catch (InterruptedException ie) {
- /* ignore */
- }
- }
-
- throw new UnsupportedOperationException("Failed to acquire MediaTranscodeManager");
- }
-
- @Override
- public void setUp() throws Exception {
- Log.d(TAG, "setUp");
- super.setUp();
-
- mContext = getInstrumentation().getContext();
- mMediaTranscodeManager = getManager();
- assertNotNull(mMediaTranscodeManager);
- androidx.test.InstrumentationRegistry.registerInstance(getInstrumentation(), new Bundle());
-
- // Setup source HEVC file uri.
- mSourceHEVCVideoUri = resourceToUri(mContext, R.raw.VideoOnlyHEVC, "VideoOnlyHEVC.mp4");
-
- // Setup source AVC file uri.
- mSourceAVCVideoUri = resourceToUri(mContext, R.raw.VideoOnlyAVC,
- "VideoOnlyAVC.mp4");
-
- // Setup destination file.
- mDestinationUri = generateNewUri(mContext, "transcoded.mp4");
- }
-
- @Override
- public void tearDown() throws Exception {
- super.tearDown();
- }
-
- // [[ $(adb shell whoami) == "root" ]]
- private boolean checkIfRoot() {
- try (ParcelFileDescriptor result = getInstrumentation().getUiAutomation()
- .executeShellCommand("whoami");
- BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
- new FileInputStream(result.getFileDescriptor())))) {
- String line;
- while ((line = bufferedReader.readLine()) != null) {
- if (line.contains("root")) {
- return true;
- }
- }
- } catch (IOException ie) {
- return false;
- }
- return false;
- }
-
- private String executeShellCommand(String cmd) throws Exception {
- return UiDevice.getInstance(
- InstrumentationRegistry.getInstrumentation()).executeShellCommand(cmd);
- }
-
- @Test
- public void testHandleTranscoderServiceDied() throws Exception {
- if (!checkIfRoot()) {
- throw new AssertionError("must be root to run this test; try adb root?");
- }
-
- Semaphore transcodeCompleteSemaphore = new Semaphore(0);
- Semaphore sessionStartedSemaphore = new Semaphore(0);
-
- // Transcode a 15 seconds video, so that the transcoding is not finished when we kill the
- // service.
- Uri srcUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
- + mContext.getCacheDir().getAbsolutePath() + "/longtest_15s.mp4");
- Uri destinationUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
- + mContext.getCacheDir().getAbsolutePath() + "/HevcTranscode.mp4");
-
- TranscodingRequest request =
- new TranscodingRequest.Builder()
- .setSourceUri(mSourceHEVCVideoUri)
- .setDestinationUri(destinationUri)
- .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
- .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
- .setVideoTrackFormat(createMediaFormat())
- .build();
- Executor listenerExecutor = Executors.newSingleThreadExecutor();
-
- Log.i(TAG, "transcoding to " + createMediaFormat());
-
- TranscodingSession session = mMediaTranscodeManager.enqueueRequest(request,
- listenerExecutor,
- TranscodingSession -> {
- Log.d(TAG,
- "Transcoding completed with result: " + TranscodingSession.getResult());
- transcodeCompleteSemaphore.release();
- });
- assertNotNull(session);
-
- AtomicInteger progressUpdateCount = new AtomicInteger(0);
-
- // Set progress update executor and use the same executor as result listener.
- session.setOnProgressUpdateListener(listenerExecutor,
- new TranscodingSession.OnProgressUpdateListener() {
- @Override
- public void onProgressUpdate(TranscodingSession session, int newProgress) {
- if (newProgress > 0) {
- sessionStartedSemaphore.release();
- }
- }
- });
-
- // Wait for progress update so the session is in running state.
- sessionStartedSemaphore.tryAcquire(TRANSCODE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
- assertTrue("session is not running",
- session.getStatus() == TranscodingSession.STATUS_RUNNING);
-
- // Kills the service and expects receiving failure of the session.
- executeShellCommand("pkill -f media.transcoding");
-
- Log.d(TAG, "testMediaTranscodeManager - Waiting for transcode result.");
- boolean finishedOnTime = transcodeCompleteSemaphore.tryAcquire(
- TRANSCODE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
- assertTrue("Invalid session status",
- session.getStatus() == TranscodingSession.STATUS_FINISHED);
- assertTrue("Invalid session result",
- session.getResult() == TranscodingSession.RESULT_ERROR);
-
-
- boolean retrysession = false;
- // Wait till service is available again.
- Log.d(TAG, "Retry the failed transcoding session");
- while (!retrysession) {
- try {
- session.retry();
- // Break out when session retry succeeds.
- break;
- } catch (MediaTranscodingException.ServiceNotAvailableException ex) {
- // Sleep for 10 milliseconds to wait.
- Thread.sleep(10);
- }
- }
-
- finishedOnTime = transcodeCompleteSemaphore.tryAcquire(
- TRANSCODE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
- // Check the make sure session is successfully finished after retry.
- assertTrue("Invalid session status",
- session.getStatus() == TranscodingSession.STATUS_FINISHED);
- assertTrue("Invalid session result",
- session.getResult() == TranscodingSession.RESULT_SUCCESS);
- }
-}
-
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java
deleted file mode 100644
index 8231988..0000000
--- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodeManagerTest.java
+++ /dev/null
@@ -1,649 +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.mediatranscodingtest;
-
-import static org.testng.Assert.assertThrows;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.media.ApplicationMediaCapabilities;
-import android.media.MediaFormat;
-import android.media.MediaTranscodeManager;
-import android.media.MediaTranscodeManager.TranscodingRequest;
-import android.media.MediaTranscodeManager.TranscodingRequest.MediaFormatResolver;
-import android.media.MediaTranscodeManager.TranscodingSession;
-import android.media.TranscodingTestConfig;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.FileUtils;
-import android.os.ParcelFileDescriptor;
-import android.test.ActivityInstrumentationTestCase2;
-import android.util.Log;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.uiautomator.UiDevice;
-
-import org.junit.Test;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/*
- * Functional tests for MediaTranscodeManager in the media framework.
- * The test uses actual media.Transcoding service as backend to fully
- * test the API functionality.
- *
- * To run this test suite:
- make frameworks/base/media/tests/MediaTranscodingTest
- make mediatranscodingtest
-
- adb install -r testcases/mediatranscodingtest/arm64/mediatranscodingtest.apk
-
- adb shell am instrument -e class \
- com.android.mediatranscodingtest.MediaTranscodeManagerTest \
- -w com.android.mediatranscodingtest/.MediaTranscodingTestRunner
- *
- */
-public class MediaTranscodeManagerTest
- extends ActivityInstrumentationTestCase2<MediaTranscodingTest> {
- private static final String TAG = "MediaTranscodeManagerTest";
- /** The time to wait for the transcode operation to complete before failing the test. */
- private static final int TRANSCODE_TIMEOUT_SECONDS = 10;
-
- /** Maximum number of retry to connect to the service. */
- private static final int CONNECT_SERVICE_RETRY_COUNT = 100;
-
- /** Interval between trying to reconnect to the service. */
- private static final int INTERVAL_CONNECT_SERVICE_RETRY_MS = 40;
-
- private Context mContext;
- private MediaTranscodeManager mMediaTranscodeManager = null;
- private Uri mSourceHEVCVideoUri = null;
- private Uri mSourceAVCVideoUri = null;
- private Uri mDestinationUri = null;
-
- // Setting for transcoding to H.264.
- private static final String MIME_TYPE = MediaFormat.MIMETYPE_VIDEO_AVC;
- private static final int BIT_RATE = 20000000; // 20Mbps
- private static final int WIDTH = 1920;
- private static final int HEIGHT = 1080;
-
- // Threshold for the psnr to make sure the transcoded video is sane.
- private static final int PSNR_THRESHOLD = 20;
-
- public MediaTranscodeManagerTest() {
- super("com.android.MediaTranscodeManagerTest", MediaTranscodingTest.class);
- }
-
-
- // Copy the resource to cache.
- private Uri resourceToUri(Context context, int resId, String name) throws IOException {
- Uri resUri = new Uri.Builder()
- .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
- .authority(context.getResources().getResourcePackageName(resId))
- .appendPath(context.getResources().getResourceTypeName(resId))
- .appendPath(context.getResources().getResourceEntryName(resId))
- .build();
-
- Uri cacheUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
- + mContext.getCacheDir().getAbsolutePath() + "/" + name);
-
- InputStream is = mContext.getResources().openRawResource(resId);
- OutputStream os = mContext.getContentResolver().openOutputStream(cacheUri);
-
- FileUtils.copy(is, os);
-
- return cacheUri;
- }
-
- private static Uri generateNewUri(Context context, String filename) {
- File outFile = new File(context.getExternalCacheDir(), filename);
- return Uri.fromFile(outFile);
- }
-
- // Generates a invalid uri which will let the mock service return transcoding failure.
- private static Uri generateInvalidTranscodingUri(Context context) {
- File outFile = new File(context.getExternalCacheDir(), "InvalidUri.mp4");
- return Uri.fromFile(outFile);
- }
-
- /**
- * Creates a MediaFormat with the basic set of values.
- */
- private static MediaFormat createMediaFormat() {
- MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, WIDTH, HEIGHT);
- format.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE);
- return format;
- }
-
- private MediaTranscodeManager getManager() {
- for (int count = 1; count <= CONNECT_SERVICE_RETRY_COUNT; count++) {
- Log.d(TAG, "Trying to connect to service. Try count: " + count);
- MediaTranscodeManager manager = mContext.getSystemService(MediaTranscodeManager.class);
- if (manager != null) {
- return manager;
- }
- try {
- // Sleep a bit before retry.
- Thread.sleep(INTERVAL_CONNECT_SERVICE_RETRY_MS);
- } catch (InterruptedException ie) {
- /* ignore */
- }
- }
-
- throw new UnsupportedOperationException("Failed to acquire MediaTranscodeManager");
- }
-
- @Override
- public void setUp() throws Exception {
- Log.d(TAG, "setUp");
- super.setUp();
-
- mContext = getInstrumentation().getContext();
- mMediaTranscodeManager = getManager();
- assertNotNull(mMediaTranscodeManager);
- androidx.test.InstrumentationRegistry.registerInstance(getInstrumentation(), new Bundle());
-
- // Setup source HEVC file uri.
- mSourceHEVCVideoUri = resourceToUri(mContext, R.raw.VideoOnlyHEVC, "VideoOnlyHEVC.mp4");
-
- // Setup source AVC file uri.
- mSourceAVCVideoUri = resourceToUri(mContext, R.raw.VideoOnlyAVC,
- "VideoOnlyAVC.mp4");
-
- // Setup destination file.
- mDestinationUri = generateNewUri(mContext, "transcoded.mp4");
- }
-
- @Override
- public void tearDown() throws Exception {
- super.tearDown();
- }
-
-
- /**
- * Verify that setting null destination uri will throw exception.
- */
- @Test
- public void testCreateTranscodingRequestWithNullDestinationUri() throws Exception {
- assertThrows(IllegalArgumentException.class, () -> {
- TranscodingRequest request =
- new TranscodingRequest.Builder()
- .setSourceUri(mSourceHEVCVideoUri)
- .setDestinationUri(null)
- .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
- .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
- .setVideoTrackFormat(createMediaFormat())
- .build();
- });
- }
-
- /**
- * Verify that setting invalid pid will throw exception.
- */
- @Test
- public void testCreateTranscodingWithInvalidClientPid() throws Exception {
- assertThrows(IllegalArgumentException.class, () -> {
- TranscodingRequest request =
- new TranscodingRequest.Builder()
- .setSourceUri(mSourceHEVCVideoUri)
- .setDestinationUri(mDestinationUri)
- .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
- .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
- .setClientPid(-1)
- .setVideoTrackFormat(createMediaFormat())
- .build();
- });
- }
-
- /**
- * Verify that setting invalid uid will throw exception.
- */
- @Test
- public void testCreateTranscodingWithInvalidClientUid() throws Exception {
- assertThrows(IllegalArgumentException.class, () -> {
- TranscodingRequest request =
- new TranscodingRequest.Builder()
- .setSourceUri(mSourceHEVCVideoUri)
- .setDestinationUri(mDestinationUri)
- .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
- .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
- .setClientUid(-1)
- .setVideoTrackFormat(createMediaFormat())
- .build();
- });
- }
-
- /**
- * Verify that setting null source uri will throw exception.
- */
- @Test
- public void testCreateTranscodingRequestWithNullSourceUri() throws Exception {
- assertThrows(IllegalArgumentException.class, () -> {
- TranscodingRequest request =
- new TranscodingRequest.Builder()
- .setSourceUri(null)
- .setDestinationUri(mDestinationUri)
- .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
- .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
- .build();
- });
- }
-
- /**
- * Verify that not setting source uri will throw exception.
- */
- @Test
- public void testCreateTranscodingRequestWithoutSourceUri() throws Exception {
- assertThrows(UnsupportedOperationException.class, () -> {
- TranscodingRequest request =
- new TranscodingRequest.Builder()
- .setDestinationUri(mDestinationUri)
- .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
- .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
- .setVideoTrackFormat(createMediaFormat())
- .build();
- });
- }
-
- /**
- * Verify that not setting destination uri will throw exception.
- */
- @Test
- public void testCreateTranscodingRequestWithoutDestinationUri() throws Exception {
- assertThrows(UnsupportedOperationException.class, () -> {
- TranscodingRequest request =
- new TranscodingRequest.Builder()
- .setSourceUri(mSourceHEVCVideoUri)
- .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
- .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
- .setVideoTrackFormat(createMediaFormat())
- .build();
- });
- }
-
- /**
- * Verify that setting image transcoding mode will throw exception.
- */
- @Test
- public void testCreateTranscodingRequestWithUnsupportedMode() throws Exception {
- assertThrows(UnsupportedOperationException.class, () -> {
- TranscodingRequest request =
- new TranscodingRequest.Builder()
- .setSourceUri(mSourceHEVCVideoUri)
- .setDestinationUri(mDestinationUri)
- .setType(MediaTranscodeManager.TRANSCODING_TYPE_IMAGE)
- .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
- .setVideoTrackFormat(createMediaFormat())
- .build();
- });
- }
-
- /**
- * Verify that setting video transcoding without setting video format will throw exception.
- */
- @Test
- public void testCreateTranscodingRequestWithoutVideoFormat() throws Exception {
- assertThrows(UnsupportedOperationException.class, () -> {
- TranscodingRequest request =
- new TranscodingRequest.Builder()
- .setSourceUri(mSourceHEVCVideoUri)
- .setDestinationUri(mDestinationUri)
- .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
- .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
- .build();
- });
- }
-
- void testTranscodingWithExpectResult(Uri srcUri, Uri dstUri, int expectedResult)
- throws Exception {
- Semaphore transcodeCompleteSemaphore = new Semaphore(0);
- TranscodingTestConfig testConfig = new TranscodingTestConfig();
- testConfig.passThroughMode = true;
- testConfig.processingTotalTimeMs = 300; // minimum time spent on transcoding.
-
- TranscodingRequest request =
- new TranscodingRequest.Builder()
- .setSourceUri(srcUri)
- .setDestinationUri(dstUri)
- .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
- .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
- .setVideoTrackFormat(createMediaFormat())
- .setTestConfig(testConfig)
- .build();
- Executor listenerExecutor = Executors.newSingleThreadExecutor();
-
- TranscodingSession session = mMediaTranscodeManager.enqueueRequest(request,
- listenerExecutor,
- TranscodingSession -> {
- Log.d(TAG,
- "Transcoding completed with result: " + TranscodingSession.getResult());
- assertTrue("Transcoding should failed.",
- TranscodingSession.getResult() == expectedResult);
- transcodeCompleteSemaphore.release();
- });
- assertNotNull(session);
-
- if (session != null) {
- Log.d(TAG, "testMediaTranscodeManager - Waiting for transcode to complete.");
- boolean finishedOnTime = transcodeCompleteSemaphore.tryAcquire(
- TRANSCODE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
- assertTrue("Transcode failed to complete in time.", finishedOnTime);
- }
-
- if (expectedResult == TranscodingSession.RESULT_SUCCESS) {
- // Checks the destination file get generated.
- File file = new File(dstUri.getPath());
- assertTrue("Failed to create destination file", file.exists());
-
- // Removes the file.
- file.delete();
- }
- }
-
- // Tests transcoding from invalid a invalid and expects failure.
- @Test
- public void testTranscodingInvalidSrcUri() throws Exception {
- Log.d(TAG, "Starting: testMediaTranscodeManager");
-
- Uri invalidSrcUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://"
- + mContext.getPackageName() + "/source.mp4");
- Log.d(TAG, "Transcoding from source: " + invalidSrcUri);
-
- // Create a file Uri: file:///data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
- // The full path of this file is:
- // /data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
- Uri destinationUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://"
- + mContext.getPackageName() + "/temp.mp4");
- Log.d(TAG, "Transcoding to destination: " + destinationUri);
-
- testTranscodingWithExpectResult(invalidSrcUri, destinationUri,
- TranscodingSession.RESULT_ERROR);
- }
-
- // Tests transcoding to a uri in res folder and expects failure as we could not write to res
- // folder.
- @Test
- public void testTranscodingToResFolder() throws Exception {
- Log.d(TAG, "Starting: testMediaTranscodeManager");
-
- // Create a file Uri: file:///data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
- // The full path of this file is:
- // /data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
- Uri destinationUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://"
- + mContext.getPackageName() + "/temp.mp4");
- Log.d(TAG, "Transcoding to destination: " + destinationUri);
-
- testTranscodingWithExpectResult(mSourceHEVCVideoUri, destinationUri,
- TranscodingSession.RESULT_ERROR);
- }
-
- // Tests transcoding to a uri in internal storage folder and expects success.
- @Test
- public void testTranscodingToCacheDir() throws Exception {
- Log.d(TAG, "Starting: testMediaTranscodeManager");
-
- // Create a file Uri: file:///data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
- // The full path of this file is:
- // /data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
- Uri destinationUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
- + mContext.getCacheDir().getAbsolutePath() + "/temp.mp4");
-
- testTranscodingWithExpectResult(mSourceHEVCVideoUri, destinationUri,
- TranscodingSession.RESULT_SUCCESS);
- }
-
- // Tests transcoding to a uri in internal files directory and expects success.
- @Test
- public void testTranscodingToInternalFilesDir() throws Exception {
- Log.d(TAG, "Starting: testMediaTranscodeManager");
-
- // Create a file Uri:
- // file:///storage/emulated/0/Android/data/com.android.mediatranscodingtest/files/temp.mp4
- Uri destinationUri = Uri.fromFile(new File(mContext.getFilesDir(), "temp.mp4"));
- Log.i(TAG, "Transcoding to files dir: " + destinationUri);
-
- testTranscodingWithExpectResult(mSourceHEVCVideoUri, destinationUri,
- TranscodingSession.RESULT_SUCCESS);
- }
-
- // Tests transcoding to a uri in external files directory and expects success.
- @Test
- public void testTranscodingToExternalFilesDir() throws Exception {
- Log.d(TAG, "Starting: testMediaTranscodeManager");
-
- // Create a file Uri: file:///data/user/0/com.android.mediatranscodingtest/files/temp.mp4
- Uri destinationUri = Uri.fromFile(new File(mContext.getExternalFilesDir(null), "temp.mp4"));
- Log.i(TAG, "Transcoding to files dir: " + destinationUri);
-
- testTranscodingWithExpectResult(mSourceHEVCVideoUri, destinationUri,
- TranscodingSession.RESULT_SUCCESS);
- }
-
- @Test
- public void testTranscodingFromHevcToAvc() throws Exception {
- Semaphore transcodeCompleteSemaphore = new Semaphore(0);
-
- // Create a file Uri: file:///data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
- // The full path of this file is:
- // /data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
- Uri destinationUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
- + mContext.getCacheDir().getAbsolutePath() + "/HevcTranscode.mp4");
-
- ApplicationMediaCapabilities clientCaps =
- new ApplicationMediaCapabilities.Builder().build();
- MediaFormatResolver resolver = new MediaFormatResolver()
- .setSourceVideoFormatHint(MediaFormat.createVideoFormat(
- MediaFormat.MIMETYPE_VIDEO_HEVC, WIDTH, HEIGHT))
- .setClientCapabilities(clientCaps);
- assertTrue(resolver.shouldTranscode());
- MediaFormat videoTrackFormat = resolver.resolveVideoFormat();
- assertNotNull(videoTrackFormat);
-
- int pid = android.os.Process.myPid();
- int uid = android.os.Process.myUid();
-
- TranscodingRequest request =
- new TranscodingRequest.Builder()
- .setSourceUri(mSourceHEVCVideoUri)
- .setDestinationUri(destinationUri)
- .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
- .setClientPid(pid)
- .setClientUid(uid)
- .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
- .setVideoTrackFormat(videoTrackFormat)
- .build();
- Executor listenerExecutor = Executors.newSingleThreadExecutor();
-
- assertEquals(pid, request.getClientPid());
- assertEquals(uid, request.getClientUid());
-
- Log.i(TAG, "transcoding to " + videoTrackFormat);
-
- TranscodingSession session = mMediaTranscodeManager.enqueueRequest(request,
- listenerExecutor,
- TranscodingSession -> {
- Log.d(TAG,
- "Transcoding completed with result: " + TranscodingSession.getResult());
- assertEquals(TranscodingSession.getResult(), TranscodingSession.RESULT_SUCCESS);
- transcodeCompleteSemaphore.release();
- });
- assertNotNull(session);
-
- if (session != null) {
- Log.d(TAG, "testMediaTranscodeManager - Waiting for transcode to cancel.");
- boolean finishedOnTime = transcodeCompleteSemaphore.tryAcquire(
- TRANSCODE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
- assertTrue("Transcode failed to complete in time.", finishedOnTime);
- }
-
- // TODO(hkuang): Validate the transcoded video's width and height, framerate.
-
- // Validates the transcoded video's psnr.
- MediaTranscodingTestUtil.VideoTranscodingStatistics stats =
- MediaTranscodingTestUtil.computeStats(mContext, mSourceAVCVideoUri, destinationUri);
- assertTrue("PSNR: " + stats.mAveragePSNR + " is too low",
- stats.mAveragePSNR >= PSNR_THRESHOLD);
- }
-
-
- @Test
- public void testCancelTranscoding() throws Exception {
- Log.d(TAG, "Starting: testMediaTranscodeManager");
- Semaphore transcodeCompleteSemaphore = new Semaphore(0);
-
- // Transcode a 15 seconds video, so that the transcoding is not finished when we cancel.
- Uri srcUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
- + mContext.getCacheDir().getAbsolutePath() + "/longtest_15s.mp4");
- Uri destinationUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
- + mContext.getCacheDir().getAbsolutePath() + "/HevcTranscode.mp4");
-
- TranscodingRequest request =
- new TranscodingRequest.Builder()
- .setSourceUri(srcUri)
- .setDestinationUri(destinationUri)
- .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
- .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
- .setVideoTrackFormat(createMediaFormat())
- .build();
- Executor listenerExecutor = Executors.newSingleThreadExecutor();
-
- TranscodingSession session = mMediaTranscodeManager.enqueueRequest(request,
- listenerExecutor,
- TranscodingSession -> {
- Log.d(TAG,
- "Transcoding completed with result: " + TranscodingSession.getResult());
- assertEquals(TranscodingSession.getResult(),
- TranscodingSession.RESULT_CANCELED);
- transcodeCompleteSemaphore.release();
- });
- assertNotNull(session);
-
- // TODO(hkuang): Wait for progress update before calling cancel to make sure transcoding is
- // started.
-
- session.cancel();
- Log.d(TAG, "testMediaTranscodeManager - Waiting for transcode to cancel.");
- boolean finishedOnTime = transcodeCompleteSemaphore.tryAcquire(
- 30, TimeUnit.MILLISECONDS);
- assertTrue("Fails to cancel transcoding", finishedOnTime);
- }
-
-
- @Test
- public void testTranscodingProgressUpdate() throws Exception {
- Log.d(TAG, "Starting: testMediaTranscodeManager");
-
- Semaphore transcodeCompleteSemaphore = new Semaphore(0);
- final CountDownLatch statusLatch = new CountDownLatch(1);
-
- // Create a file Uri: file:///data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
- // The full path of this file is:
- // /data/user/0/com.android.mediatranscodingtest/cache/temp.mp4
- Uri destinationUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
- + mContext.getCacheDir().getAbsolutePath() + "/HevcTranscode.mp4");
-
- TranscodingRequest request =
- new TranscodingRequest.Builder()
- .setSourceUri(mSourceHEVCVideoUri)
- .setDestinationUri(destinationUri)
- .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
- .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
- .setVideoTrackFormat(createMediaFormat())
- .build();
- Executor listenerExecutor = Executors.newSingleThreadExecutor();
-
- Log.i(TAG, "transcoding to " + createMediaFormat());
-
- TranscodingSession session = mMediaTranscodeManager.enqueueRequest(request,
- listenerExecutor,
- TranscodingSession -> {
- Log.d(TAG,
- "Transcoding completed with result: " + TranscodingSession.getResult());
- assertEquals(TranscodingSession.getResult(), TranscodingSession.RESULT_SUCCESS);
- transcodeCompleteSemaphore.release();
- });
- assertNotNull(session);
-
- AtomicInteger progressUpdateCount = new AtomicInteger(0);
-
- // Set progress update executor and use the same executor as result listener.
- session.setOnProgressUpdateListener(listenerExecutor,
- new TranscodingSession.OnProgressUpdateListener() {
- int mPreviousProgress = 0;
-
- @Override
- public void onProgressUpdate(TranscodingSession session, int newProgress) {
- assertTrue("Invalid proress update", newProgress > mPreviousProgress);
- assertTrue("Invalid proress update", newProgress <= 100);
- if (newProgress > 0) {
- statusLatch.countDown();
- }
- mPreviousProgress = newProgress;
- progressUpdateCount.getAndIncrement();
- Log.i(TAG, "Get progress update " + newProgress);
- }
- });
-
- try {
- statusLatch.await();
- // The transcoding should not be finished yet as the clip is long.
- assertTrue("Invalid status", session.getStatus() == TranscodingSession.STATUS_RUNNING);
- } catch (InterruptedException e) {
- }
-
- Log.d(TAG, "testMediaTranscodeManager - Waiting for transcode to cancel.");
- boolean finishedOnTime = transcodeCompleteSemaphore.tryAcquire(
- TRANSCODE_TIMEOUT_SECONDS, TimeUnit.SECONDS);
- assertTrue("Transcode failed to complete in time.", finishedOnTime);
- assertTrue("Failed to receive at least 10 progress updates",
- progressUpdateCount.get() > 10);
- }
-
- // [[ $(adb shell whoami) == "root" ]]
- private boolean checkIfRoot() throws IOException {
- try (ParcelFileDescriptor result = getInstrumentation().getUiAutomation()
- .executeShellCommand("whoami");
- BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(
- new FileInputStream(result.getFileDescriptor())))) {
- String line;
- while ((line = bufferedReader.readLine()) != null) {
- if (line.contains("root")) {
- return true;
- }
- }
- }
- return false;
- }
-
- private String executeShellCommand(String cmd) throws Exception {
- return UiDevice.getInstance(
- InstrumentationRegistry.getInstrumentation()).executeShellCommand(cmd);
- }
-}
-
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingBenchmark.java b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingBenchmark.java
deleted file mode 100644
index b152450..0000000
--- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingBenchmark.java
+++ /dev/null
@@ -1,324 +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.mediatranscodingtest;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.media.MediaFormat;
-import android.media.MediaTranscodeManager;
-import android.media.MediaTranscodeManager.TranscodingRequest;
-import android.media.MediaTranscodeManager.TranscodingSession;
-import android.media.MediaTranscodingException;
-import android.net.Uri;
-import android.test.ActivityInstrumentationTestCase2;
-import android.util.Log;
-
-import org.junit.Test;
-
-import java.io.IOException;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicLong;
-
-/*
- * Benchmarking for MediaTranscodeManager in the media framework.
- *
- * Note: This benchmarking requires to push all the files from http://go/transcodingbenchmark
- * to /data/user/0/com.android.mediatranscodingtest/cache/ directory after installing the apk.
- *
- * TODO(hkuang): Change it to download from server automatically instead of manually.
- *
- * To run this test suite:
- make frameworks/base/media/tests/MediaTranscodingTest
- make mediatranscodingtest
-
- adb install -r testcases/mediatranscodingtest/arm64/mediatranscodingtest.apk
- // Push the files to /data/user/0/com.android.mediatranscodingtest/cache/
- adb push $DOWNLOADPATH/*.mp4 /data/user/0/com.android.mediatranscodingtest/cache/
-
- adb shell am instrument -e class \
- com.android.mediatranscodingtest.MediaTranscodingBenchmark \
- -w com.android.mediatranscodingtest/.MediaTranscodingTestRunner
- *
- */
-public class MediaTranscodingBenchmark
- extends ActivityInstrumentationTestCase2<MediaTranscodingTest> {
- private static final String TAG = "MediaTranscodingBenchmark";
- // TODO(hkuang): Change this to query from MediaCodecInfo.CodecCapabilities for different
- // resolution.
- private static final int MINIMUM_TRANSCODING_FPS = 80;
- private static final int LOOP_COUNT = 3;
- // Default Setting for transcoding to H.264.
- private static final String MIME_TYPE = MediaFormat.MIMETYPE_VIDEO_AVC;
- private static final int BIT_RATE = 20000000; // 20Mbps
- private static final int WIDTH = 1920;
- private static final int HEIGHT = 1080;
- private Context mContext;
- private MediaTranscodeManager mMediaTranscodeManager = null;
-
- public MediaTranscodingBenchmark() {
- super("com.android.MediaTranscodingBenchmark", MediaTranscodingTest.class);
- }
-
- /**
- * Creates a MediaFormat with the basic set of values.
- */
- private static MediaFormat createMediaFormat() {
- MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, WIDTH, HEIGHT);
- format.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE);
- return format;
- }
-
- @Override
- public void setUp() throws Exception {
- Log.d(TAG, "setUp");
- super.setUp();
- mContext = getInstrumentation().getContext();
- mMediaTranscodeManager = mContext.getSystemService(MediaTranscodeManager.class);
- }
-
- @Override
- public void tearDown() throws Exception {
- super.tearDown();
- }
-
- /*
- * Transcode the sourceFileName to destinationFileName with LOOP_COUNT.
- */
- private void transcode(final String sourceFileName, final String destinationFileName)
- throws IOException, InterruptedException,
- MediaTranscodingException.ServiceNotAvailableException {
- AtomicLong totalTimeMs = new AtomicLong();
- AtomicLong transcodingTime = new AtomicLong();
- Uri srcUri = getUri(sourceFileName);
- Uri dstUri = getUri(destinationFileName);
-
- MediaTranscodingTestUtil.VideoFileInfo info =
- MediaTranscodingTestUtil.extractVideoFileInfo(mContext, getUri(sourceFileName));
-
- int timeoutSeconds = calMaxTranscodingWaitTimeSeconds(info.mNumVideoFrames,
- MINIMUM_TRANSCODING_FPS);
- Log.d(TAG, "Start Transcoding " + info.toString() + " " + timeoutSeconds);
-
- for (int loop = 0; loop < LOOP_COUNT; ++loop) {
- Semaphore transcodeCompleteSemaphore = new Semaphore(0);
- TranscodingRequest request =
- new TranscodingRequest.Builder()
- .setSourceUri(srcUri)
- .setDestinationUri(dstUri)
- .setType(MediaTranscodeManager.TRANSCODING_TYPE_VIDEO)
- .setPriority(MediaTranscodeManager.PRIORITY_REALTIME)
- .setVideoTrackFormat(createMediaFormat())
- .build();
- Executor listenerExecutor = Executors.newSingleThreadExecutor();
-
- long startTimeMs = System.currentTimeMillis();
- TranscodingSession session = mMediaTranscodeManager.enqueueRequest(request,
- listenerExecutor,
- TranscodingSession -> {
- Log.d(TAG,
- "Transcoding completed with result: "
- + TranscodingSession.getResult());
- assertEquals(TranscodingSession.getResult(),
- TranscodingSession.RESULT_SUCCESS);
- transcodingTime.set(System.currentTimeMillis() - startTimeMs);
- totalTimeMs.addAndGet(transcodingTime.get());
- transcodeCompleteSemaphore.release();
- });
-
- if (session != null) {
- Log.d(TAG, "testMediaTranscodeManager - Waiting for transcode to complete.");
- boolean finishedOnTime = transcodeCompleteSemaphore.tryAcquire(
- timeoutSeconds, TimeUnit.SECONDS);
- assertTrue("Transcode failed to complete in time.", finishedOnTime);
- }
- Log.i(TAG, "Loop: " + loop + " take " + transcodingTime.get() + " ms ");
- }
-
- float fps = info.mNumVideoFrames * 1000 * LOOP_COUNT / totalTimeMs.get();
- Log.i(TAG, "Transcoding " + info.toString() + " Transcoding fps: " + fps);
- }
-
- // Calculate the maximum wait time based on minimum transcoding throughput and frame number.
- private int calMaxTranscodingWaitTimeSeconds(int numberFrames, int minTranscodingFps) {
- float waitTime = (float) numberFrames / (float) minTranscodingFps;
- // If waitTimeSeconds is 0, wait for 1 second at least.
- int waitTimeSeconds = (int) Math.ceil(waitTime);
- return waitTimeSeconds == 0 ? 1 : waitTimeSeconds;
- }
-
- private Uri getUri(final String fileName) {
- String path = mContext.getCacheDir().getAbsolutePath();
- return new Uri.Builder().scheme(ContentResolver.SCHEME_FILE).appendPath(path).appendPath(
- fileName).build();
- }
-
- @Test
- public void testBenchmarkingAVCToAVCWith66FramesWithoutAudio() throws Exception {
- String videoNameWithoutExtension = "video_1920x1080_66frame_h264_22Mbps_30fps";
- String testVideoName = videoNameWithoutExtension + ".mp4";
- String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
- transcode(testVideoName, transcodedVideoName);
- }
-
- @Test
- public void testBenchmarkingAVCToAVCWith66FramesWithAudio() throws Exception {
- String videoNameWithoutExtension = "video_1920x1080_66frame_h264_22Mbps_30fps_aac";
- String testVideoName = videoNameWithoutExtension + ".mp4";
- String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
- transcode(testVideoName, transcodedVideoName);
- }
-
- @Test
- public void testBenchmarkingAVCToAVCWith361FramesWithoutAudio() throws Exception {
- String videoNameWithoutExtension = "video_1920x1080_361frame_h264_22Mbps_30fps";
- String testVideoName = videoNameWithoutExtension + ".mp4";
- String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
- transcode(testVideoName, transcodedVideoName);
- }
-
- @Test
- public void testBenchmarkingAVCToAVCWith361FramesWithAudio() throws Exception {
- String videoNameWithoutExtension = "video_1920x1080_361frame_h264_22Mbps_30fps_aac";
- String testVideoName = videoNameWithoutExtension + ".mp4";
- String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
- transcode(testVideoName, transcodedVideoName);
- }
-
- @Test
- public void testBenchmarkingAVCToAVCWith943FramesWithoutAudio() throws Exception {
- String videoNameWithoutExtension = "video_1920x1080_943frame_h264_22Mbps_30fps";
- String testVideoName = videoNameWithoutExtension + ".mp4";
- String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
- transcode(testVideoName, transcodedVideoName);
- }
-
- @Test
- public void testBenchmarkingAVCToAVCWith943FramesWithAudio() throws Exception {
- String videoNameWithoutExtension = "video_1920x1080_943frame_h264_22Mbps_30fps_aac";
- String testVideoName = videoNameWithoutExtension + ".mp4";
- String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
- transcode(testVideoName, transcodedVideoName);
- }
-
- @Test
- public void testBenchmarkingAVCToAVCWith1822FramesWithoutAudio() throws Exception {
- String videoNameWithoutExtension = "video_1920x1080_1822frame_h264_22Mbps_30fps";
- String testVideoName = videoNameWithoutExtension + ".mp4";
- String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
- transcode(testVideoName, transcodedVideoName);
- }
-
- @Test
- public void testBenchmarkingAVCToAVCWith1822FramesWithAudio() throws Exception {
- String videoNameWithoutExtension = "video_1920x1080_1822frame_h264_22Mbps_30fps_aac";
- String testVideoName = videoNameWithoutExtension + ".mp4";
- String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
- transcode(testVideoName, transcodedVideoName);
- }
-
- @Test
- public void testBenchmarkingAVCToAVCWith3648FramesWithoutAudio() throws Exception {
- String videoNameWithoutExtension = "video_1920x1080_3648frame_h264_22Mbps_30fps";
- String testVideoName = videoNameWithoutExtension + ".mp4";
- String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
- transcode(testVideoName, transcodedVideoName);
- }
-
- @Test
- public void testBenchmarkingAVCToAVCWith3648FramesWithAudio() throws Exception {
- String videoNameWithoutExtension = "video_1920x1080_3648frame_h264_22Mbps_30fps_aac";
- String testVideoName = videoNameWithoutExtension + ".mp4";
- String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
- transcode(testVideoName, transcodedVideoName);
- }
-
- @Test
- public void testBenchmarkingAVCToAVCWith11042FramesWithoutAudio() throws Exception {
- String videoNameWithoutExtension = "video_1920x1080_11042frame_h264_22Mbps_30fps";
- String testVideoName = videoNameWithoutExtension + ".mp4";
- String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
- transcode(testVideoName, transcodedVideoName);
- }
-
- @Test
- public void testBenchmarkingAVCToAVCWith11042FramesWithAudio() throws Exception {
- String videoNameWithoutExtension = "video_1920x1080_11042frame_h264_22Mbps_30fps_aac";
- String testVideoName = videoNameWithoutExtension + ".mp4";
- String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
- transcode(testVideoName, transcodedVideoName);
- }
-
- @Test
- public void testBenchmarkingHEVCToAVCWith107FramesWithoutAudio() throws Exception {
- String videoNameWithoutExtension = "video_1920x1080_107frame_hevc_4Mbps_30fps";
- String testVideoName = videoNameWithoutExtension + ".mp4";
- String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
- transcode(testVideoName, transcodedVideoName);
- }
-
- @Test
- public void testBenchmarkingHEVCToAVCWith928FramesWithoutAudio() throws Exception {
- String videoNameWithoutExtension = "video_1920x1080_928frame_hevc_4Mbps_30fps";
- String testVideoName = videoNameWithoutExtension + ".mp4";
- String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
- transcode(testVideoName, transcodedVideoName);
- }
-
- @Test
- public void testBenchmarkingHEVCToAVCWith1863FramesWithoutAudio() throws Exception {
- String videoNameWithoutExtension = "video_1920x1080_1863frame_hevc_4Mbps_30fps";
- String testVideoName = videoNameWithoutExtension + ".mp4";
- String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
- transcode(testVideoName, transcodedVideoName);
- }
-
- @Test
- public void testBenchmarkingHEVCToAVCWith3863FramesWithoutAudio() throws Exception {
- String videoNameWithoutExtension = "video_1920x1080_3863frame_hevc_4Mbps_30fps";
- String testVideoName = videoNameWithoutExtension + ".mp4";
- String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
- transcode(testVideoName, transcodedVideoName);
- }
-
- @Test
- public void testBenchmarkingHEVCToAVCWith9374FramesWithoutAudio() throws Exception {
- String videoNameWithoutExtension = "video_1920x1080_9374frame_hevc_4Mbps_30fps";
- String testVideoName = videoNameWithoutExtension + ".mp4";
- String transcodedVideoName = videoNameWithoutExtension + "_transcode.mp4";
-
- transcode(testVideoName, transcodedVideoName);
- }
-}
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingTest.java b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingTest.java
deleted file mode 100644
index 6f83bad..0000000
--- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingTest.java
+++ /dev/null
@@ -1,47 +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.mediatranscodingtest;
-
-import android.app.Activity;
-import android.content.Context;
-import android.os.Bundle;
-import android.os.PowerManager;
-
-public class MediaTranscodingTest extends Activity {
- private PowerManager.WakeLock mWakeLock = null;
-
- public MediaTranscodingTest() {
- }
-
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- setContentView(R.layout.surface_view);
-
- //Acquire the full wake lock to keep the device up
- PowerManager pm = (PowerManager) this.getSystemService(Context.POWER_SERVICE);
- mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, "MediaTranscodingTest");
- mWakeLock.acquire();
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- mWakeLock.release();
- }
-}
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingTestRunner.java b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingTestRunner.java
deleted file mode 100644
index 76050ac..0000000
--- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingTestRunner.java
+++ /dev/null
@@ -1,55 +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.mediatranscodingtest;
-
-import android.os.Bundle;
-import android.test.InstrumentationTestRunner;
-import android.test.InstrumentationTestSuite;
-
-import junit.framework.TestSuite;
-
-
-/**
- * Instrumentation Test Runner for all MediaTranscoding tests.
- *
- * Running all tests:
- *
- * adb shell am instrument \
- * -w com.android.mediatranscodingtest/.MediaTranscodingTestRunner
- */
-
-public class MediaTranscodingTestRunner extends InstrumentationTestRunner {
- @Override
- public TestSuite getAllTests() {
- TestSuite suite = new InstrumentationTestSuite(this);
- suite.addTestSuite(MediaTranscodeManagerDiedTest.class);
- suite.addTestSuite(ApplicationMediaCapabilitiesTest.class);
- suite.addTestSuite(MediaTranscodeManagerTest.class);
- suite.addTestSuite(MediaTranscodingBenchmark.class);
- return suite;
- }
-
- @Override
- public ClassLoader getLoader() {
- return MediaTranscodingTestRunner.class.getClassLoader();
- }
-
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- }
-}
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingTestUtil.java b/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingTestUtil.java
deleted file mode 100644
index 69f124f..0000000
--- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaTranscodingTestUtil.java
+++ /dev/null
@@ -1,480 +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.mediatranscodingtest;
-
-import static org.junit.Assert.assertTrue;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.res.AssetFileDescriptor;
-import android.graphics.ImageFormat;
-import android.media.Image;
-import android.media.MediaCodec;
-import android.media.MediaCodecInfo;
-import android.media.MediaExtractor;
-import android.media.MediaFormat;
-import android.media.MediaMetadataRetriever;
-import android.net.Uri;
-import android.util.Log;
-import android.util.Size;
-
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.ByteBuffer;
-import java.util.Locale;
-
-
-/* package */ class MediaTranscodingTestUtil {
- private static final String TAG = "MediaTranscodingTestUtil";
-
- // Helper class to extract the information from source file and transcoded file.
- static class VideoFileInfo {
- String mUri;
- int mNumVideoFrames = 0;
- int mWidth = 0;
- int mHeight = 0;
- float mVideoFrameRate = 0.0f;
- boolean mHasAudio = false;
-
- public String toString() {
- String str = mUri;
- str += " Width:" + mWidth;
- str += " Height:" + mHeight;
- str += " FrameRate:" + mWidth;
- str += " FrameCount:" + mNumVideoFrames;
- str += " HasAudio:" + (mHasAudio ? "Yes" : "No");
- return str;
- }
- }
-
- static VideoFileInfo extractVideoFileInfo(Context ctx, Uri videoUri) throws IOException {
- VideoFileInfo info = new VideoFileInfo();
- AssetFileDescriptor afd = null;
- MediaMetadataRetriever retriever = null;
-
- try {
- afd = ctx.getContentResolver().openAssetFileDescriptor(videoUri, "r");
- retriever = new MediaMetadataRetriever();
- retriever.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
-
- info.mUri = videoUri.getLastPathSegment();
- Log.i(TAG, "Trying to transcode to " + info.mUri);
- String width = retriever.extractMetadata(
- MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);
- String height = retriever.extractMetadata(
- MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);
- if (width != null && height != null) {
- info.mWidth = Integer.parseInt(width);
- info.mHeight = Integer.parseInt(height);
- }
-
- String frameRate = retriever.extractMetadata(
- MediaMetadataRetriever.METADATA_KEY_CAPTURE_FRAMERATE);
- if (frameRate != null) {
- info.mVideoFrameRate = Float.parseFloat(frameRate);
- }
-
- String frameCount = retriever.extractMetadata(
- MediaMetadataRetriever.METADATA_KEY_VIDEO_FRAME_COUNT);
- if (frameCount != null) {
- info.mNumVideoFrames = Integer.parseInt(frameCount);
- }
-
- String hasAudio = retriever.extractMetadata(
- MediaMetadataRetriever.METADATA_KEY_HAS_AUDIO);
- if (hasAudio != null) {
- info.mHasAudio = hasAudio.equals("yes");
- }
- } finally {
- if (retriever != null) {
- retriever.close();
- }
- if (afd != null) {
- afd.close();
- }
- }
- return info;
- }
-
- static VideoTranscodingStatistics computeStats(final Context ctx, final Uri sourceMp4,
- final Uri transcodedMp4)
- throws Exception {
- // First decode the sourceMp4 to a temp yuv in yuv420p format.
- Uri sourceYUV420PUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
- + ctx.getCacheDir().getAbsolutePath() + "/sourceYUV420P.yuv");
- Size sourceSize = decodeMp4ToYuv(ctx, sourceMp4, sourceYUV420PUri);
-
- // Second decode the transcodedMp4 to a temp yuv in yuv420p format.
- Uri transcodedYUV420PUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
- + ctx.getCacheDir().getAbsolutePath() + "/transcodedYUV420P.yuv");
- Size transcodedSize = decodeMp4ToYuv(ctx, transcodedMp4, transcodedYUV420PUri);
-
- assertTrue(sourceSize.equals(transcodedSize));
-
- // Then Compute the psnr of transcodedYUV420PUri against sourceYUV420PUri.
- return computePsnr(ctx, sourceYUV420PUri, transcodedYUV420PUri, sourceSize.getWidth(),
- transcodedSize.getHeight());
- }
-
- private static Size decodeMp4ToYuv(final Context ctx, final Uri fileUri, final Uri yuvUri)
- throws Exception {
- AssetFileDescriptor fileFd = null;
- MediaExtractor extractor = null;
- MediaCodec codec = null;
- AssetFileDescriptor yuvFd = null;
- FileOutputStream out = null;
- int width = 0;
- int height = 0;
-
- try {
- fileFd = ctx.getContentResolver().openAssetFileDescriptor(fileUri,"r");
- extractor = new MediaExtractor();
- extractor.setDataSource(fileFd.getFileDescriptor(), fileFd.getStartOffset(),
- fileFd.getLength());
-
- // Selects the video track.
- int trackCount = extractor.getTrackCount();
- if (trackCount <= 0) {
- throw new IllegalArgumentException("Invalid mp4 file");
- }
- int videoTrackIndex = -1;
- for (int i = 0; i < trackCount; i++) {
- extractor.selectTrack(i);
- MediaFormat format = extractor.getTrackFormat(i);
- if (format.getString(MediaFormat.KEY_MIME).startsWith("video/")) {
- videoTrackIndex = i;
- break;
- }
- }
- if (videoTrackIndex == -1) {
- throw new IllegalArgumentException("Can not find video track");
- }
-
- extractor.selectTrack(videoTrackIndex);
- MediaFormat format = extractor.getTrackFormat(videoTrackIndex);
- String mime = format.getString(MediaFormat.KEY_MIME);
- format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
- MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar);
-
- // Opens the yuv file uri.
- yuvFd = ctx.getContentResolver().openAssetFileDescriptor(yuvUri,
- "w");
- out = new FileOutputStream(yuvFd.getFileDescriptor());
-
- codec = MediaCodec.createDecoderByType(mime);
- codec.configure(format,
- null, // surface
- null, // crypto
- 0); // flags
- codec.start();
-
- ByteBuffer[] inputBuffers = codec.getInputBuffers();
- ByteBuffer[] outputBuffers = codec.getOutputBuffers();
- MediaFormat decoderOutputFormat = codec.getInputFormat();
-
- // start decode loop
- MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
-
- final long kTimeOutUs = 1000; // 1ms timeout
- long lastOutputTimeUs = 0;
- boolean sawInputEOS = false;
- boolean sawOutputEOS = false;
- int inputNum = 0;
- int outputNum = 0;
- boolean advanceDone = true;
-
- long start = System.currentTimeMillis();
- while (!sawOutputEOS) {
- // handle input
- if (!sawInputEOS) {
- int inputBufIndex = codec.dequeueInputBuffer(kTimeOutUs);
-
- if (inputBufIndex >= 0) {
- ByteBuffer dstBuf = inputBuffers[inputBufIndex];
- // sample contains the buffer and the PTS offset normalized to frame index
- int sampleSize =
- extractor.readSampleData(dstBuf, 0 /* offset */);
- long presentationTimeUs = extractor.getSampleTime();
- advanceDone = extractor.advance();
-
- if (sampleSize < 0) {
- Log.d(TAG, "saw input EOS.");
- sawInputEOS = true;
- sampleSize = 0;
- }
- codec.queueInputBuffer(
- inputBufIndex,
- 0 /* offset */,
- sampleSize,
- presentationTimeUs,
- sawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
- } else {
- Log.d(TAG, "codec.dequeueInputBuffer() unrecognized return value:");
- }
- }
-
- // handle output
- int outputBufIndex = codec.dequeueOutputBuffer(info, kTimeOutUs);
-
- if (outputBufIndex >= 0) {
- if (info.size > 0) { // Disregard 0-sized buffers at the end.
- outputNum++;
- Log.i(TAG, "Output frame numer " + outputNum);
- Image image = codec.getOutputImage(outputBufIndex);
- dumpYUV420PToFile(image, out);
- }
-
- codec.releaseOutputBuffer(outputBufIndex, false /* render */);
- if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
- Log.d(TAG, "saw output EOS.");
- sawOutputEOS = true;
- }
- } else if (outputBufIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
- outputBuffers = codec.getOutputBuffers();
- Log.d(TAG, "output buffers have changed.");
- } else if (outputBufIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
- decoderOutputFormat = codec.getOutputFormat();
- width = decoderOutputFormat.getInteger(MediaFormat.KEY_WIDTH);
- height = decoderOutputFormat.getInteger(MediaFormat.KEY_HEIGHT);
- Log.d(TAG, "output resolution " + width + "x" + height);
- } else {
- Log.w(TAG, "codec.dequeueOutputBuffer() unrecognized return index");
- }
- }
- } finally {
- codec.stop();
- codec.release();
- extractor.release();
- out.close();
- fileFd.close();
- yuvFd.close();
- }
- return new Size(width, height);
- }
-
- private static void dumpYUV420PToFile(Image image, FileOutputStream out) throws IOException {
- int format = image.getFormat();
-
- if (ImageFormat.YUV_420_888 != format) {
- throw new UnsupportedOperationException("Only supports YUV420P");
- }
-
- int imageWidth = image.getWidth();
- int imageHeight = image.getHeight();
- byte[] bb = new byte[imageWidth * imageHeight];
- byte[] lb = null;
- Image.Plane[] planes = image.getPlanes();
- for (int i = 0; i < planes.length; ++i) {
- ByteBuffer buf = planes[i].getBuffer();
-
- int width, height, rowStride, pixelStride, x, y;
- rowStride = planes[i].getRowStride();
- pixelStride = planes[i].getPixelStride();
- if (i == 0) {
- width = imageWidth;
- height = imageHeight;
- } else {
- width = imageWidth / 2;
- height = imageHeight / 2;
- }
-
- if (buf.hasArray()) {
- byte b[] = buf.array();
- int offs = buf.arrayOffset();
- if (pixelStride == 1) {
- for (y = 0; y < height; ++y) {
- System.arraycopy(bb, y * width, b, y * rowStride + offs, width);
- }
- } else {
- // do it pixel-by-pixel
- for (y = 0; y < height; ++y) {
- int lineOffset = offs + y * rowStride;
- for (x = 0; x < width; ++x) {
- bb[y * width + x] = b[lineOffset + x * pixelStride];
- }
- }
- }
- } else { // almost always ends up here due to direct buffers
- int pos = buf.position();
- if (pixelStride == 1) {
- for (y = 0; y < height; ++y) {
- buf.position(pos + y * rowStride);
- buf.get(bb, y * width, width);
- }
- } else {
- // Reallocate linebuffer if necessary.
- if (lb == null || lb.length < rowStride) {
- lb = new byte[rowStride];
- }
- // do it pixel-by-pixel
- for (y = 0; y < height; ++y) {
- buf.position(pos + y * rowStride);
- // we're only guaranteed to have pixelStride * (width - 1) + 1 bytes
- buf.get(lb, 0, pixelStride * (width - 1) + 1);
- for (x = 0; x < width; ++x) {
- bb[y * width + x] = lb[x * pixelStride];
- }
- }
- }
- buf.position(pos);
- }
- // Write out the buffer to the output.
- out.write(bb, 0, width * height);
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////////////////////////
- // The following psnr code is leveraged from the following file with minor modification:
- // cts/tests/tests/media/src/android/media/cts/VideoCodecTestBase.java
- ////////////////////////////////////////////////////////////////////////////////////////////////
-
- /**
- * Calculates PSNR value between two video frames.
- */
- private static double computePSNR(byte[] data0, byte[] data1) {
- long squareError = 0;
- assertTrue(data0.length == data1.length);
- int length = data0.length;
- for (int i = 0; i < length; i++) {
- int diff = ((int) data0[i] & 0xff) - ((int) data1[i] & 0xff);
- squareError += diff * diff;
- }
- double meanSquareError = (double) squareError / length;
- double psnr = 10 * Math.log10((double) 255 * 255 / meanSquareError);
- return psnr;
- }
-
- /**
- * Calculates average and minimum PSNR values between
- * set of reference and decoded video frames.
- * Runs PSNR calculation for the full duration of the decoded data.
- */
- private static VideoTranscodingStatistics computePsnr(
- Context ctx,
- Uri referenceYuvFileUri,
- Uri decodedYuvFileUri,
- int width,
- int height) throws Exception {
- VideoTranscodingStatistics statistics = new VideoTranscodingStatistics();
- AssetFileDescriptor referenceFd = ctx.getContentResolver().openAssetFileDescriptor(
- referenceYuvFileUri, "r");
- InputStream referenceStream = new FileInputStream(referenceFd.getFileDescriptor());
-
- AssetFileDescriptor decodedFd = ctx.getContentResolver().openAssetFileDescriptor(
- decodedYuvFileUri, "r");
- InputStream decodedStream = new FileInputStream(decodedFd.getFileDescriptor());
-
- int ySize = width * height;
- int uvSize = width * height / 4;
- byte[] yRef = new byte[ySize];
- byte[] yDec = new byte[ySize];
- byte[] uvRef = new byte[uvSize];
- byte[] uvDec = new byte[uvSize];
-
- int frames = 0;
- double averageYPSNR = 0;
- double averageUPSNR = 0;
- double averageVPSNR = 0;
- double minimumYPSNR = Integer.MAX_VALUE;
- double minimumUPSNR = Integer.MAX_VALUE;
- double minimumVPSNR = Integer.MAX_VALUE;
- int minimumPSNRFrameIndex = 0;
-
- while (true) {
- // Calculate Y PSNR.
- int bytesReadRef = referenceStream.read(yRef);
- int bytesReadDec = decodedStream.read(yDec);
- if (bytesReadDec == -1) {
- break;
- }
- if (bytesReadRef == -1) {
- // Reference file wrapping up
- referenceStream.close();
- break;
- }
- double curYPSNR = computePSNR(yRef, yDec);
- averageYPSNR += curYPSNR;
- minimumYPSNR = Math.min(minimumYPSNR, curYPSNR);
- double curMinimumPSNR = curYPSNR;
-
- // Calculate U PSNR.
- bytesReadRef = referenceStream.read(uvRef);
- bytesReadDec = decodedStream.read(uvDec);
- double curUPSNR = computePSNR(uvRef, uvDec);
- averageUPSNR += curUPSNR;
- minimumUPSNR = Math.min(minimumUPSNR, curUPSNR);
- curMinimumPSNR = Math.min(curMinimumPSNR, curUPSNR);
-
- // Calculate V PSNR.
- bytesReadRef = referenceStream.read(uvRef);
- bytesReadDec = decodedStream.read(uvDec);
- double curVPSNR = computePSNR(uvRef, uvDec);
- averageVPSNR += curVPSNR;
- minimumVPSNR = Math.min(minimumVPSNR, curVPSNR);
- curMinimumPSNR = Math.min(curMinimumPSNR, curVPSNR);
-
- // Frame index for minimum PSNR value - help to detect possible distortions
- if (curMinimumPSNR < statistics.mMinimumPSNR) {
- statistics.mMinimumPSNR = curMinimumPSNR;
- minimumPSNRFrameIndex = frames;
- }
-
- String logStr = String.format(Locale.US, "PSNR #%d: Y: %.2f. U: %.2f. V: %.2f",
- frames, curYPSNR, curUPSNR, curVPSNR);
- Log.v(TAG, logStr);
-
- frames++;
- }
-
- averageYPSNR /= frames;
- averageUPSNR /= frames;
- averageVPSNR /= frames;
- statistics.mAveragePSNR = (4 * averageYPSNR + averageUPSNR + averageVPSNR) / 6;
-
- Log.d(TAG, "PSNR statistics for " + frames + " frames.");
- String logStr = String.format(Locale.US,
- "Average PSNR: Y: %.1f. U: %.1f. V: %.1f. Average: %.1f",
- averageYPSNR, averageUPSNR, averageVPSNR, statistics.mAveragePSNR);
- Log.d(TAG, logStr);
- logStr = String.format(Locale.US,
- "Minimum PSNR: Y: %.1f. U: %.1f. V: %.1f. Overall: %.1f at frame %d",
- minimumYPSNR, minimumUPSNR, minimumVPSNR,
- statistics.mMinimumPSNR, minimumPSNRFrameIndex);
- Log.d(TAG, logStr);
-
- referenceStream.close();
- decodedStream.close();
- referenceFd.close();
- decodedFd.close();
- return statistics;
- }
-
- /**
- * Transcoding PSNR statistics.
- */
- protected static class VideoTranscodingStatistics {
- public double mAveragePSNR;
- public double mMinimumPSNR;
-
- VideoTranscodingStatistics() {
- mMinimumPSNR = Integer.MAX_VALUE;
- }
- }
-}
-
diff --git a/mime/OWNERS b/mime/OWNERS
index 6f9dbea..2357979 100644
--- a/mime/OWNERS
+++ b/mime/OWNERS
@@ -1 +1,2 @@
+include platform/libcore:/OWNERS
include /core/java/android/os/storage/OWNERS
diff --git a/native/android/Android.bp b/native/android/Android.bp
index 6db4da9..3daaf05 100644
--- a/native/android/Android.bp
+++ b/native/android/Android.bp
@@ -103,7 +103,7 @@
version_script: "libandroid.map.txt",
stubs: {
symbol_file: "libandroid.map.txt",
- versions: ["29"],
+ versions: ["29", "31"],
},
}
diff --git a/native/android/OWNERS b/native/android/OWNERS
index 266764a..ac5a895 100644
--- a/native/android/OWNERS
+++ b/native/android/OWNERS
@@ -1,4 +1,3 @@
-set noparent
-
+per-file libandroid_net.map.txt, net.c = set noparent
per-file libandroid_net.map.txt, net.c = codewiz@google.com, jchalard@google.com, junyulai@google.com
per-file libandroid_net.map.txt, net.c = lorenzo@google.com, reminv@google.com, satk@google.com
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 438e8b8..c2b26bc 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Ignoreer kodewisselingverstekke"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Aktiveer kodewisseling"</string>
<string name="transcode_default" msgid="3784803084573509491">"Aanvaar dat programme moderne formate steun"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Aktiveer kodewisseling vir programme"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Lopende dienste"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Sien en beheer dienste wat tans aktief is"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-implementering"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Bedraade oorfoon"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Aan"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Af"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Diensverskaffernetwerk verander tans"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobiele data is af"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Nie gestel om data te gebruik nie"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Geen foon nie."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Foon, een staaf."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Foon, twee stawe."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Foon, drie stawe."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Foonsein is vol."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Geen data nie."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data, een staaf."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Data, twee stawe."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Data, drie stawe."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Datasein vol."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet is ontkoppel."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet gekoppel."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index fd5777d..65ce6e0 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"የትራንስኮዲንግ ነባሪዎችን ሻር"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"ትራንስኮዲንግን ያንቁ"</string>
<string name="transcode_default" msgid="3784803084573509491">"መተግበሪያዎች ዘመናዊ ቅርጸቶችን እንደሚደግፉ አድርገው ይቁጠሩ"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"ለመተግበሪያዎች ትራንስኮዲንግን ያንቁ"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"አሂድ አገልግሎቶች"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"በአሁኑጊዜ እየሄዱ ያሉ አገልግሎቶችን ተቆጣጠር እና እይ"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"የWebView ትግበራ"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"ባለገመድ ጆሮ ማዳመጫ"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"አብራ"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"አጥፋ"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"የአገልግሎት አቅራቢ አውታረ መረብን በመቀየር ላይ"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3ጂ"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"ኤጅ"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"ጂፒአርኤስ"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"ሰ"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"ሰ+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4ጂ"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"የተንቀሳቃሽ ስልክ ውሂብ ጠፍቷል"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"ውሂብን ለመጠቀም አልተቀናበረም"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"ምንም ስልክ የለም።"</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"የስልክ አንድ አሞሌ"</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"የስልክ ሁለት አሞሌ"</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"የስልክ ሦስት አሞሌ"</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"የስልክ አመልካች ሙሉ ነው።"</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"ምንም ውሂብ የለም።"</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"የውሂብ አንድ አሞሌ"</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"የውሂብ ሁለት አሞሌዎች።"</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"የውሂብ ሦስት አሞሌዎች።"</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"የውሂብ አመልካች ሙሉ ነው።"</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ኤተርኔት ተነቅሏል።"</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"ኤተርኔት ተገናኝቷል።"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index b81031e..3ea96c7 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"إلغاء الإعدادات التلقائية لتحويل الترميز"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"تفعيل تحويل الترميز"</string>
<string name="transcode_default" msgid="3784803084573509491">"افتراض أن التطبيق يتوافق مع التنسيقات الحديثة"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"تفعيل تحويل الترميز للتطبيقات"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"الخدمات قيد التشغيل"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"عرض الخدمات قيد التشغيل في الوقت الحالي والتحكم فيها"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"تطبيق WebView"</string>
@@ -570,4 +569,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"سمّاعة سلكية"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"تفعيل"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"إيقاف"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"جارٍ تغيير شبكة مشغِّل شبكة الجوّال."</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"شبكة الجيل الثالث"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"شبكة EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"شبكة GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"شبكة الجيل الرابع"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"شبكة الجيل الرابع أو أحدث"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"تم إيقاف بيانات الجوال"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"لم يتم الضبط على استخدام البيانات"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"ليست هناك إشارة بالهاتف."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"إشارة الهاتف تتكون من شريط واحد."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"إشارة الهاتف تتكون من شريطين."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"إشارة الهاتف تتكون من ثلاثة أشرطة."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"إشارة الهاتف كاملة."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"لا تتوفر بيانات."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"إشارة البيانات تتكون من شريط واحد."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"إشارة البيانات تتكون من شريطين."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"إشارة البيانات تتكون من ثلاثة أشرطة."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"إشارة البيانات كاملة."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"تم قطع اتصال Ethernet."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"تم إنشاء اتصال Ethernet."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index e482329..a259687 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"ট্ৰেন্সক’ডিং ডিফ’ল্ট অ’ভাৰৰাইড কৰক"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"ট্ৰেন্সক’ডিং সক্ষম কৰক"</string>
<string name="transcode_default" msgid="3784803084573509491">"এপে আধুনিক ফৰ্মেট সমৰ্থন কৰে বুলি ধৰি লওক"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"এপৰ বাবে ট্ৰান্সক\'ডিং সক্ষম কৰক"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"চলিত সেৱা"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"বৰ্তমান চলি থকা সেৱাসমূহ চাওক আৰু নিয়ন্ত্ৰণ কৰক"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"ৱেবভিউ প্ৰয়োগ"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"তাঁৰযুক্ত হেডফ\'ন"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"অন"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"অফ"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"বাহক নেটৱৰ্কৰ পৰিৱৰ্তন"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"জিপিআৰএছ"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"এলটিই"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"এলটিই+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"ম’বাইল ডেটা অফ অৱস্থাত আছে"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"ডেটা ব্যৱহাৰ কৰিবলৈ ছেট কৰা নাই"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"ফ\'নত ছিগনেল নাই৷"</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"ফ\'ন ছিগনেলৰ এডাল দণ্ড।"</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"ফ\'ন ছিগনেলৰ দুডাল দণ্ড।"</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"ফ\'নৰ ছিগনেলৰ তিনিডাল দণ্ড আছে।"</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"ফ\'নৰ ছিগনেল পূৰা আছে৷"</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"কোনো ডেটা নাই।"</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"ডেটা ছিগনেলৰ এডাল দণ্ড।"</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"ডেটা ছংনেলৰ তিনিডাল দণ্ড।"</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"ডেটা ছিংগনেলত তিনিডাল দণ্ড আছে।"</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"ডেটা ছিগনেল পূৰা আছে।"</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ইথাৰনেট সংযোগ বিচ্ছিন্ন হৈছে।"</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"ইথাৰনেট সংযোগ হৈছে।"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 637785d..2cbd681 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Yenidən kodlaşdırma defoltlarını əvəzləyin"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Yenidən kodlaşdırmanı aktiv edin"</string>
<string name="transcode_default" msgid="3784803084573509491">"Tətbiqlərin müasir formatları dəstəklədiyini qəbul edin"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Tətbiqlər üçün yenidən kodlaşdırmanı aktiv edin"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"İşləyən xidmətlər"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Hazırda prosesdə olan xidmətləri görüntüləyin və onlara nəzarət edin"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView icrası"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Simli qulaqlıq"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Aktiv"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Deaktiv"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Operator şəbəkəsinin dəyişilməsi"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobil data deaktivdir"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Data istifadə etmək üçün ayarlanmayıb"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Telefon yoxdur."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Şəbəkə bir xətdir."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Şəbəkə iki xətdir."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Şəbəkə üç xətdir."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Tam şəbəkə."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Məlumat yoxdur."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data bir xətdir."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Data iki xətdir."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Data üç xətdir."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Data siqnalı tamdır."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet bağlantısı kəsilib."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet qoşuludur."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 219d5a0..4d8e348 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Zameni podrazumevana podešavanja transkodiranja"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Omogući transkodiranje"</string>
<string name="transcode_default" msgid="3784803084573509491">"Podrazumevaj da aplikacije podržavaju moderne formate"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Omogućite transkodiranje za aplikacije"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Pokrenute usluge"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Prikaz i kontrola trenutno pokrenutih usluga"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Primena WebView-a"</string>
@@ -567,4 +566,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Žičane slušalice"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Uključeno"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Isključeno"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Promena mreže mobilnog operatera"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobilni podaci su isključeni"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Nije podešeno za korišćenje podataka"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Nema telefona."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Signal telefona ima jednu crtu."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Signal telefona od dve crte."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Signal telefona od tri crte."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Signal telefona je pun."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Nema podataka."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Signal za podatke ima jednu crtu."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Signal za podatke od dve crte."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Signal za podatke od tri crte."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Signal za podatke je najjači."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Veza sa eternetom je prekinuta."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Eternet je povezan."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 4772e03..4d6f3ac 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -400,13 +400,9 @@
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Актыўная. Краніце, каб пераключыць."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Стан праграмы ў рэжыме чакання: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
<string name="transcode_settings_title" msgid="2581975870429850549">"Налады перакадзіравання мультымедыя"</string>
- <!-- no translation found for transcode_user_control (6176368544817731314) -->
- <skip />
- <!-- no translation found for transcode_enable_all (2411165920039166710) -->
- <skip />
- <!-- no translation found for transcode_default (3784803084573509491) -->
- <skip />
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Уключыць перакадзіраванне для праграм"</string>
+ <string name="transcode_user_control" msgid="6176368544817731314">"Перавызначыць стандартныя налады перакадзіравання"</string>
+ <string name="transcode_enable_all" msgid="2411165920039166710">"Уключыць перакадзіраванне"</string>
+ <string name="transcode_default" msgid="3784803084573509491">"Лічыца, што праграмы падтрымліваюць сучасныя фарматы"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Запушчаныя службы"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Прагляд запушчаных службаў i кіраванне iмi"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Рэалізацыя WebView"</string>
@@ -571,4 +567,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Правадныя навушнікі"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Уключана"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Выключана"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Змяненне аператара сеткі"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Мабільная перадача даных выключана"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Не зададзена для выкарыстання даных"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Няма тэлефона."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Адна планка на тэлефоне."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"2 планкі тэлефона."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"3 планкі тэлефона."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Поўны сігнал тэлефона."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Няма дадзеных."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Адна планка дадзеных."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"2 планкі дадзеных."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"3 планкі дадзеных."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Поўны сігнал перадачы дадзеных."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet адлучаны."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet падлучаны."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 75d1eeb..ef0412b 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Отмяна на стандартните настройки за прекодирането"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Активиране на прекодирането"</string>
<string name="transcode_default" msgid="3784803084573509491">"Предполагане, че приложенията поддържат съвременни формати"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Активиране на прекодирането за приложения"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Изпълнявани услуги"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Преглед и контрол върху изпълняващите се понастоящем услуги"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Внедряване на WebView"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Слушалки с кабел"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Включване"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Изключване"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Промяна на мрежата на оператора"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Мобилните данни са изключени"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Не е зададено да използва данни"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Няма телефон."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Телефонът е с една чертичка."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Телефонът е с две чертички."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Телефонът е с три чертички."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Сигналът за телефона е пълен."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Няма данни."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Данните са с една чертичка."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Данните са с две чертички."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Данните са с три чертички."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Сигналът за данни е пълен."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Връзката с Ethernet е прекратена."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Установена е връзка с Ethernet."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index 325f2bd..5b95399 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -400,13 +400,9 @@
<string name="inactive_app_active_summary" msgid="8047630990208722344">"সক্রিয় রয়েছে৷ টগল করতে আলতো চাপুন৷"</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"অ্যাপ স্ট্যান্ডবাই-এর অবস্থা:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
<string name="transcode_settings_title" msgid="2581975870429850549">"মিডিয়া ট্রান্সকোডিং সেটিংস"</string>
- <!-- no translation found for transcode_user_control (6176368544817731314) -->
- <skip />
- <!-- no translation found for transcode_enable_all (2411165920039166710) -->
- <skip />
- <!-- no translation found for transcode_default (3784803084573509491) -->
- <skip />
- <string name="transcode_skip_apps" msgid="8249721984597390142">"অ্যাপের জন্য ট্রান্সকোডিং চালু করুন"</string>
+ <string name="transcode_user_control" msgid="6176368544817731314">"ট্রান্সকোডিং ডিফল্ট সেটিংস ওভাররাইড করুন"</string>
+ <string name="transcode_enable_all" msgid="2411165920039166710">"ট্রান্সকোডিং চালু করুন"</string>
+ <string name="transcode_default" msgid="3784803084573509491">"অ্যাপ মর্ডার্ন ফর্ম্যাটে কাজ করবে বলে ধরে নিন"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"এখন চলছে যে পরিষেবাগুলি"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"বর্তমান চলমান পরিষেবাগুলি দেখুন এবং নিয়ন্ত্রণ করুন"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"ওয়েবভিউ প্রয়োগ"</string>
@@ -569,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"তার যুক্ত হেডফোন"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"চালু আছে"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"বন্ধ আছে"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"পরিষেবা প্রদানকারীর নেটওয়ার্ক পরিবর্তন করা হচ্ছে"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"মোবাইল ডেটা বন্ধ করা হয়েছে"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"ডেটা ব্যবহার করার জন্য সেট করা নেই"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"কোনো ফোনের সংকেত নেই৷"</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"এক দন্ড ফোনের সংকেত রয়েছে৷"</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"দুই দন্ড ফোনের সংকেত রয়েছে৷"</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"তিন দন্ড ফোনের সংকেত রয়েছে৷"</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"ফোনের সংকেত পূর্ণ রয়েছে৷"</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"কোনো ডেটা নেই৷"</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"এক দন্ড ডেটার সংকেত৷"</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"দুই দন্ড ডেটার সংকেত রয়েছে৷"</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"তিন দন্ড ডেটার সংকেত৷"</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"পূর্ণ ডেটার সংকেত রয়েছে৷"</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ইথারনেটের সংযোগ বিচ্ছিন্ন হয়েছে৷"</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"ইথারনেট সংযুক্ত হয়েছে৷"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index ab4ac14..00d8087 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Zaobiđi zadane postavke transkodiranja"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Omogući transkodiranje"</string>
<string name="transcode_default" msgid="3784803084573509491">"Pretpostavi da aplikacije podržavaju moderne formate"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Omogućite transkodiranje za aplikacije"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Pokrenute usluge"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Prikaz i kontrola trenutno pokrenutih usluga"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Postavljanje WebViewa"</string>
@@ -567,4 +566,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Žičane slušalice"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Uključi"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Isključi"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Promjena mreže mobilnog operatera"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Prijenos podataka na mobilnoj mreži je isključen"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Nije postavljeno za korištenje podataka"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Nema telefonskog signala."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefonski signal na jednoj crtici."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefonski signal na dvije crtice."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefonski signal na tri crtice."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefonski signal pun."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Nema podataka."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Prijenos podataka na jednoj crtici."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Prijenos podataka na dvije crtice."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Prijenos podataka na tri crtice."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Signal za prijenos podataka pun."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Veza sa Ethernetom je prekinuta."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet je spojen."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 9bb919f..300b475 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Substitueix els valors predeterminats de la transcodificació"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Activa la transcodificació"</string>
<string name="transcode_default" msgid="3784803084573509491">"Assumeix que les aplicacions són compatibles amb formats moderns"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Activa la transcodificació per a les aplicacions"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Serveis en execució"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Visualitza i controla els serveis en execució"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementació de WebView"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Auriculars amb cable"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Activa"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Desactiva"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"S\'està canviant la xarxa de l\'operador de telefonia mòbil"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"S\'han desactivat les dades mòbils"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"No s\'ha definit per utilitzar dades"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"No hi ha senyal de telèfon."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Senyal de telèfon: una barra"</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Senyal de telèfon: dues barres."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Senyal de telèfon: tres barres."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Senyal de telèfon: complet."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Senyal de dades: no n\'hi ha"</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Senyal de dades: una barra."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Senyal de dades: dues barres."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Senyal de dades: tres barres."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Senyal de dades: complet."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"S\'ha desconnectat l\'Ethernet."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet connectada"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 5f2e005..a9a5f48 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Přepsat výchozí nastavení překódování"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Povolit překódování"</string>
<string name="transcode_default" msgid="3784803084573509491">"Předpokládat, že aplikace podporují moderní formáty"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Povolit překódování pro aplikace"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Spuštěné služby"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Umožňuje zobrazit a ovládat aktuálně spuštěné služby"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementace WebView"</string>
@@ -568,4 +567,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Kabelová sluchátka"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Zapnout"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Vypnout"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Probíhá změna sítě operátora"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobilní data jsou vypnuta"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Nenastaveno k využití dat"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Žádná telefonní síť."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Jedna čárka signálu telefonní sítě."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Dvě čárky signálu telefonní sítě."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Tři čárky signálu telefonní sítě."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Plný signál telefonní sítě."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Žádné datové připojení."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Jedna čárka signálu datové sítě."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Dvě čárky signálu datové sítě."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Tři čárky signálu datové sítě."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Plný signál datové sítě."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Síť ethernet je odpojena."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Síť ethernet je připojena."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index f4f4650..738ed3c 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Tilsidesæt standardindstillingerne for omkodning"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Aktivér omkodning"</string>
<string name="transcode_default" msgid="3784803084573509491">"Gå ud fra, at apps understøtter moderne formater"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Aktivér omkodning for apps"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Kørende tjenester"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Vis og administrer kørende tjenester"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-implementering"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Høretelefoner med ledning"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Til"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Fra"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Skift af mobilnetværk"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobildata er deaktiveret"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Ikke indstillet til at anvende data"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Ingen telefon."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefon en bjælke."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefon to bjælker."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefon tre bjælker."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefonsignal fuldt."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Ingen data."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data en bjælke."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Data to bjælker."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Data tre bjælker."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Datasignal fuldt."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet er ikke tilsluttet."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet er tilsluttet."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 1d6894b..e274d63 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -400,13 +400,9 @@
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktiv. Zum Wechseln tippen."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Standby-Status der App:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
<string name="transcode_settings_title" msgid="2581975870429850549">"Einstellungen für Medientranscodierung"</string>
- <!-- no translation found for transcode_user_control (6176368544817731314) -->
- <skip />
- <!-- no translation found for transcode_enable_all (2411165920039166710) -->
- <skip />
- <!-- no translation found for transcode_default (3784803084573509491) -->
- <skip />
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Transcodierung für Apps aktivieren"</string>
+ <string name="transcode_user_control" msgid="6176368544817731314">"Standardeinstellungen für Transcodierung überschreiben"</string>
+ <string name="transcode_enable_all" msgid="2411165920039166710">"Transcodierung aktivieren"</string>
+ <string name="transcode_default" msgid="3784803084573509491">"Voraussetzen, dass Apps moderne Formate unterstützen"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Aktive Dienste"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Momentan ausgeführte Dienste anzeigen und steuern"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-Implementierung"</string>
@@ -569,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Kabelgebundene Kopfhörer"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"An"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Aus"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Mobilfunknetzwerk wird gewechselt"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobile Daten deaktiviert"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Nicht für Datennutzung konfiguriert"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Kein Telefon"</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefonsignal - ein Balken"</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefonsignal - zwei Balken"</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefonsignal - drei Balken"</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Volle Telefonsignalstärke"</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Keine Daten"</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Datensignal - ein Balken"</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Datensignal - zwei Balken"</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Datensignal - drei Balken"</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Volle Datensignalstärke"</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet nicht verbunden"</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet verbunden"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 3affbce..66244eb 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Παράκαμψη προεπιλογών διακωδικοποίησης"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Ενεργοποίηση διακωδικοποίησης"</string>
<string name="transcode_default" msgid="3784803084573509491">"Να θεωρείται ότι οι εφαρμογές χρησιμοποιούν σύγχρονες μορφές"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Ενεργοποίηση διακωδικοποίησης για εφαρμογές"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Υπηρεσίες που εκτελούνται"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Προβολή και έλεγχος των εφαρμογών που εκτελούνται αυτή τη στιγμή"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Υλοποίηση WebView"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Ενσύρματα ακουστικά"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Ενεργό"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Ανενεργό"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Αλλαγή δικτύου εταιρείας κινητής τηλεφωνίας"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Τα δεδομένα κινητής τηλεφωνίας απενεργοποιήθηκαν"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Δεν ρυθμίστηκε ώστε να χρησιμοποιεί δεδομένα"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Δεν υπάρχει τηλέφωνο."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Μία γραμμή τηλεφώνου."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Δύο γραμμές τηλεφώνου."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Τρεις γραμμές μπαταρίας."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Πλήρες σήμα τηλεφώνου."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Δεν υπάρχουν δεδομένα."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Μία γραμμή δεδομένων."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Δύο γραμμές δεδομένων."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Τρεις γραμμές δεδομένων."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Πλήρες σήμα δεδομένων."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Το Ethernet αποσυνδέθηκε."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Το Ethernet συνδέθηκε."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 9d5debb..f5a0e2c 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Override transcoding defaults"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Enable transcoding"</string>
<string name="transcode_default" msgid="3784803084573509491">"Assume apps support modern formats"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Enable transcoding for apps"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Running services"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"View and control currently running services"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView implementation"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Wired headphones"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"On"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Off"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Operator network changing"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobile data off"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Not set to use data"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"No phone."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Phone one bar."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Phone two bars."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Phone three bars."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Phone signal full."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"No data."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data one bar."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Data two bars."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Data three bars."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Data signal full."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet disconnected."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet connected."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index b0190a2..6f11e80 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Override transcoding defaults"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Enable transcoding"</string>
<string name="transcode_default" msgid="3784803084573509491">"Assume apps support modern formats"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Enable transcoding for apps"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Running services"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"View and control currently running services"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView implementation"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Wired headphones"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"On"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Off"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Operator network changing"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobile data off"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Not set to use data"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"No phone."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Phone one bar."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Phone two bars."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Phone three bars."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Phone signal full."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"No data."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data one bar."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Data two bars."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Data three bars."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Data signal full."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet disconnected."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet connected."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 9d5debb..f5a0e2c 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Override transcoding defaults"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Enable transcoding"</string>
<string name="transcode_default" msgid="3784803084573509491">"Assume apps support modern formats"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Enable transcoding for apps"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Running services"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"View and control currently running services"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView implementation"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Wired headphones"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"On"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Off"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Operator network changing"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobile data off"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Not set to use data"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"No phone."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Phone one bar."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Phone two bars."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Phone three bars."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Phone signal full."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"No data."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data one bar."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Data two bars."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Data three bars."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Data signal full."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet disconnected."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet connected."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 9d5debb..f5a0e2c 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Override transcoding defaults"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Enable transcoding"</string>
<string name="transcode_default" msgid="3784803084573509491">"Assume apps support modern formats"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Enable transcoding for apps"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Running services"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"View and control currently running services"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView implementation"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Wired headphones"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"On"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Off"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Operator network changing"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobile data off"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Not set to use data"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"No phone."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Phone one bar."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Phone two bars."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Phone three bars."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Phone signal full."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"No data."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data one bar."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Data two bars."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Data three bars."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Data signal full."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet disconnected."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet connected."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 9296a59..bfca109 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Override transcoding defaults"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Enable transcoding"</string>
<string name="transcode_default" msgid="3784803084573509491">"Assume apps support modern formats"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Enable transcoding for apps"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Running services"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"View and control currently running services"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView implementation"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Wired headphone"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"On"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Off"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Carrier network changing"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobile data off"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Not set to use data"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"No phone."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Phone one bar."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Phone two bars."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Phone three bars."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Phone signal full."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"No data."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data one bar."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Data two bars."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Data three bars."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Data signal full."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet disconnected."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet connected."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 41466be..44ae8c2 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Anular los valores predeterminados de transcodificación"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Habilitar la transcodificación"</string>
<string name="transcode_default" msgid="3784803084573509491">"Suponer que las apps admiten formatos modernos"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Habilitar transcodificación en apps"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"En ejecución"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Ver y controlar servicios actuales en ejecución"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementación de WebView"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Auriculares con cable"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Activar"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Desactivar"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Cambio de proveedor de red"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Datos móviles desactivados"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"No se configuró para usar datos"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Sin teléfono"</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Una barra de teléfono"</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Dos barras de teléfono"</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Tres barras de teléfono"</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Señal de teléfono completa"</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"No hay datos."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Una barra de datos"</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Dos barras de datos"</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Tres barras de datos"</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Señal de datos completa"</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet desconectada"</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet conectada"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 8a0a123..236394c 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Anular valores predeterminados de transcodificación"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Habilitar transcodificación"</string>
<string name="transcode_default" msgid="3784803084573509491">"Considerar que las aplicaciones admiten formatos modernos"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Habilitar transcodificación en las aplicaciones"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Servicios en ejecución"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Ver y controlar los servicios en ejecución"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementación de WebView"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Auriculares con cable"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Activado"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Desactivado"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Cambiando la red del operador"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Datos desactiv."</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"No está establecido para usar los datos"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Sin teléfono"</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Una barra de cobertura"</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Dos barras de cobertura"</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Tres barras de cobertura"</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Cobertura al máximo"</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Sin datos"</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Una barra de datos"</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Dos barras de datos"</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Tres barras de datos"</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Señal de datos al máximo"</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Conexión Ethernet desconectada."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Conexión Ethernet conectada."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 4b82c08..c8fd94f 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Alista transkodeerimise vaikeseaded"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Luba transkodeerimine"</string>
<string name="transcode_default" msgid="3784803084573509491">"Oleta, et rakendused toetavad kaasaegseid vorminguid"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Luba rakenduste puhul transkodeerimine"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Käitatud teenused"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Praegu käitatud teenuste vaatamine ja juhtimine"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView\' rakendamine"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Juhtmega kõrvaklapid"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Sees"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Väljas"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Operaatori võrku muudetakse"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobiilne andmeside on väljas"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Ei ole andmeside kasutamiseks seadistatud"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Telefonisignaal puudub"</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefonisignaal: üks pulk."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefonisignaal: kaks pulka."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefonisignaal: kolm pulka."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefonisignaal on tugev."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Andmed puuduvad."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Andmesignaal: üks pulk."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Andmeside: kaks pulka."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Andmeside: kolm pulka."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Andmesignaal on tugev."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Etherneti-ühendus on katkestatud."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Etherneti-ühendus on loodud."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 37c1fd8..226ffba 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Ez erabili transkodetzearen balio lehenetsiak"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Gaitu transkodetzea"</string>
<string name="transcode_default" msgid="3784803084573509491">"Arduratu aplikazioek formatu modernoak onartzeaz"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Gaitu aplikazioak transkodetzeko aukera"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Abian diren zerbitzuak"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Ikusi eta kontrolatu une honetan abian diren zerbitzuak"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView inplementazioa"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Entzungailu kableduna"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Aktibatu"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Desaktibatu"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Operadorearen sarea aldatzen"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Desaktibatuta dago datu-konexioa"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Ez dago ezarrita datuak erabiltzeko"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Ez dago telefono-zenbakirik."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefono-seinaleak barra bat du."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefono-seinaleak bi barra ditu."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefono-seinaleak hiru barra ditu."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefono-seinale osoa."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Ez dago daturik."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Datu-seinaleak barra bat du."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Datu-seinaleak bi barra ditu."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Datu-seinaleak hiru barra ditu."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Datu-seinale osoa."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet bidezko konexioa eten da."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet bidez konektatu da."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 7d20aaf..917a637 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"ملغی کردن پیشفرضهای تراتبدیل"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"فعال کردن تراتبدیل"</string>
<string name="transcode_default" msgid="3784803084573509491">"فرض شود برنامهها از قالبهای مدرن پشتیبانی میکنند"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"فعال کردن تراتبدیل برای برنامهها"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"سرویسهای در حال اجرا"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"مشاهده و کنترل سرویسهای در حال اجرای فعلی"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"اجرای وبنما"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"هدفون سیمی"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"روشن"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"خاموش"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"تغییر شبکه شرکت مخابراتی"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"داده تلفن همراه خاموش است"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"برای استفاده از داده تنظیم نشده است"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"بدون تلفن."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"یک نوار برای تلفن."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"دو نوار برای تلفن."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"سه نوار برای تلفن."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"قدرت امواج تلفن همراه کامل است."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"دادهای وجود ندارد."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"یک نوار برای داده."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"دو نوار برای داده."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"سه نوار برای داده."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"قدرت سیگنال داده کامل است."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"اترنت قطع شد."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"اترنت متصل شد."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index a43c5d7..6081b2a 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Ohita transkoodauksen oletukset"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Salli transkoodaus"</string>
<string name="transcode_default" msgid="3784803084573509491">"Oleta, että sovellukset tukevat nykyaikaisia formaatteja"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Ota sovellusten transkoodaus käyttöön"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Käynnissä olevat palvelut"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Tarkastele ja hallitse käynnissä olevia palveluita."</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-käyttöönotto"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Langalliset kuulokkeet"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Päällä"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Poissa päältä"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Operaattorin verkko muuttuu"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobiilidata poistettu käytöstä"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Ei käytä dataa"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Ei puhelinverkkoyhteyttä."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Puhelinverkkosignaali - yksi palkki."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Puhelinverkkosignaali - kaksi palkkia."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Puhelinverkkosignaali - kolme palkkia."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Vahva puhelinverkkosignaali."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Ei datasignaalia."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Datasignaali - yksi palkki."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Datasignaali - kaksi palkkia."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Datasignaali - kolme palkkia"</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Vahva kuuluvuus."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet on irrotettu."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet on yhdistetty."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 0cb7b17..91d14d4 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Remplacer les valeurs par défaut de transcodage"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Activer le transcodage"</string>
<string name="transcode_default" msgid="3784803084573509491">"Présumer que les applications prennent en charge les formats modernes"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Activer le transcodage pour les applications"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Services en cours d\'exécution"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Afficher et contrôler les services en cours d\'exécution"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Mise en œuvre WebView"</string>
@@ -494,7 +493,6 @@
<string name="wifi_status_mac_randomized" msgid="466382542497832189">"Les adresses MAC sont randomisées"</string>
<plurals name="wifi_tether_connected_summary" formatted="false" msgid="6317236306047306139">
<item quantity="one">%1$d appareil connecté</item>
- <item quantity="many">%1$d devices connected</item>
<item quantity="other">%1$d appareils connectés</item>
</plurals>
<string name="accessibility_manual_zen_more_time" msgid="5141801092071134235">"Plus longtemps."</string>
@@ -567,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Écouteurs filaires"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Activé"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Désactivé"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Changer de réseau de fournisseur de services"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Désactivées"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Non configuré pour l\'utilisation des données cellulaires"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Aucun signal"</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Signal : faible"</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Signal : moyen"</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Signal : bon"</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Signal excellent"</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Aucun signal"</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Signal faible"</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Signal moyen"</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Signal bon"</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Signal excellent"</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet déconnecté."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet connecté."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index e928a48..2518fe1 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -251,7 +251,7 @@
<string name="wifi_display_certification" msgid="1805579519992520381">"Certification affichage sans fil"</string>
<string name="wifi_verbose_logging" msgid="1785910450009679371">"Autoriser l\'enregistrement d\'infos Wi-Fi détaillées"</string>
<string name="wifi_scan_throttling" msgid="2985624788509913617">"Limiter la recherche Wi‑Fi"</string>
- <string name="wifi_enhanced_mac_randomization" msgid="5437378364995776979">"Chgt aléatoire d\'adresse MAC en Wi-Fi"</string>
+ <string name="wifi_enhanced_mac_randomization" msgid="5437378364995776979">"Changement aléatoire d\'adresse MAC en Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="8275958101875563572">"Données mobiles toujours actives"</string>
<string name="tethering_hardware_offload" msgid="4116053719006939161">"Accélération matérielle pour le partage de connexion"</string>
<string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Afficher les appareils Bluetooth sans nom"</string>
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Ignorer les paramètres de transcodage par défaut"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Activer le transcodage"</string>
<string name="transcode_default" msgid="3784803084573509491">"Supposer que les applications sont compatibles avec les formats modernes"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Activer le transcodage pour les applications"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Services en cours d\'exécution"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Afficher et contrôler les services en cours d\'exécution"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Mise en œuvre WebView"</string>
@@ -494,7 +493,6 @@
<string name="wifi_status_mac_randomized" msgid="466382542497832189">"La sélection des adresses MAC est aléatoire"</string>
<plurals name="wifi_tether_connected_summary" formatted="false" msgid="6317236306047306139">
<item quantity="one">%1$d appareil connecté</item>
- <item quantity="many">%1$d devices connected</item>
<item quantity="other">%1$d appareils connectés</item>
</plurals>
<string name="accessibility_manual_zen_more_time" msgid="5141801092071134235">"Plus longtemps."</string>
@@ -567,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Casque filaire"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Allumé"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Éteint"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Modification du réseau de l\'opérateur"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Désactivées"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Non configuré pour utiliser les données"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Aucun signal"</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Signal : faible"</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Signal : moyen"</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Signal : bon"</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Signal excellent"</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Aucun signal"</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Signal faible"</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Signal moyen"</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Signal bon"</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Signal excellent"</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet déconnecté"</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet connecté"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index c439253..486afe3 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Anular valores predeterminados de transcodificación"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Activar transcodificación"</string>
<string name="transcode_default" msgid="3784803084573509491">"Considerar que as aplicacións admiten formatos modernos"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Activar transcodificación para as aplicacións"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Servizos en uso"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Comproba e controla os servizos actualmente en uso"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementación de WebView"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Auriculares con cable"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Activar"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Desactivar"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Cambio de rede do operador"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Os datos móbiles están desactivados"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Non se configurou para utilizar datos"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Sen teléfono"</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Unha barra de cobertura"</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Dúas barras de cobertura"</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Tres barras de cobertura"</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Cobertura ao máximo"</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Sen datos"</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Unha barra de sinal de datos"</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Sinal de datos: dúas barras"</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Tres barras de sinal de datos"</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Sinal de datos: completo"</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Desconectouse a Ethernet."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Conectouse a Ethernet."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 7dfdcee..2bebe36 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -400,13 +400,9 @@
<string name="inactive_app_active_summary" msgid="8047630990208722344">"સક્રિય. ટોગલ કરવા માટે ટૅપ કરો."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"ઍપ સ્ટૅન્ડબાયની સ્થિતિ:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
<string name="transcode_settings_title" msgid="2581975870429850549">"મીડિયાનું ફૉર્મેટ બદલવાની પ્રક્રિયાના સેટિંગ"</string>
- <!-- no translation found for transcode_user_control (6176368544817731314) -->
- <skip />
- <!-- no translation found for transcode_enable_all (2411165920039166710) -->
- <skip />
- <!-- no translation found for transcode_default (3784803084573509491) -->
- <skip />
- <string name="transcode_skip_apps" msgid="8249721984597390142">"ઍપ માટે ફૉર્મેટ બદલવાની પ્રક્રિયા ચાલુ કરો"</string>
+ <string name="transcode_user_control" msgid="6176368544817731314">"ફૉર્મેટ બદલવાની પ્રક્રિયાના ડિફૉલ્ટ સેટિંગ ઓવરરાઇડ કરો"</string>
+ <string name="transcode_enable_all" msgid="2411165920039166710">"ફૉર્મેટ બદલવાની પ્રક્રિયા ચાલુ કરો"</string>
+ <string name="transcode_default" msgid="3784803084573509491">"ધારો કે ઍપ આધુનિક ફૉર્મેટ પર કામ કરે છે"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"ચાલુ સેવાઓ"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"હાલમાં ચાલતી સેવાઓ જુઓ અને નિયંત્રિત કરો"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView અમલીકરણ"</string>
@@ -569,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"વાયરવાળો હૅડફોન"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ચાલુ"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"બંધ"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"કૅરીઅર નેટવર્કમાં ફેરફાર થઈ રહ્યો છે"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"મોબાઇલ ડેટા બંધ છે"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"ડેટાનો ઉપયોગ કરવાનું સેટ કર્યું નથી"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"કોઈ ફોન નથી."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"ફોન એક બાર."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"ફોન બે બાર."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"ફોન ત્રણ બાર."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"પૂર્ણ ફોન સિગ્નલ."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"કોઈ ડેટા નથી."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"ડેટા એક બાર."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"ડેટા બે બાર."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"ડેટા ત્રણ બાર."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"ડેટા સિગ્નલ પૂર્ણ."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ઇથરનેટ ડિસ્કનેક્ટ થયું."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"ઇથરનેટ કનેક્ટ થયું."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 26d1a756..824ab25 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -402,8 +402,7 @@
<string name="transcode_settings_title" msgid="2581975870429850549">"मीडिया ट्रांसकोडिंग सेटिंग"</string>
<string name="transcode_user_control" msgid="6176368544817731314">"ट्रांसकोडिंग की डिफ़ॉल्ट सेटिंग बदलें"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"ट्रांसकोडिंग चालू करें"</string>
- <string name="transcode_default" msgid="3784803084573509491">"मानकर चलें कि ऐप्लिकेशन, मॉडर्न फ़ॉर्मैट के साथ काम करेंगे"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"ऐप्लिकेशन के लिए ट्रांसकोडिंग चालू करें"</string>
+ <string name="transcode_default" msgid="3784803084573509491">"मानकर चलें कि ऐप्लिकेशन, नए फ़ॉर्मैट के साथ काम करेंगे"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"चल रही सेवाएं"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"इस समय चल रही सेवाओं को देखें और नियंत्रित करें"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"वेबव्यू लागू करें"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"वायर वाला हेडफ़ोन"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"चालू है"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"बंद है"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"मोबाइल और इंटरनेट सेवा देने वाली कंपनी का नेटवर्क बदल रहा है"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3जी"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"एलटीई"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"मोबाइल डेटा बंद है"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"डेटा इस्तेमाल करने के लिए सेट नहीं किया गया है"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"कोई फ़ोन नहीं."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"फ़ोन एक बार."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"फ़ोन दो बार."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"फोन तीन बार."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"फ़ोन सिग्नल पूरा."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"कोई डेटा नहीं."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"डेटा एक बार."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"डेटा दो बार."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"डेटा तीन बार."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"डेटा सिग्नल पूरा."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ईथरनेट डिस्कनेक्ट किया गया."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"ईथरनेट कनेक्ट किया गया."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index eccfd7a..cd21a5f 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Nadjačaj zadane postavke konvertiranja"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Omogući konvertiranje"</string>
<string name="transcode_default" msgid="3784803084573509491">"Pretpostavi da aplikacije podržavaju moderne formate"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Omogućivanje konvertiranja za aplikacije"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Pokrenute usluge"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Pregledajte i kontrolirajte pokrenute usluge"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementacija WebViewa"</string>
@@ -567,4 +566,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Žičane slušalice"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Uključeno"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Isključeno"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Promjena mreže mobilnog operatera"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G i više"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobilni su podaci isključeni"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Nije postavljeno za upotrebu podataka"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Nema telefona."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefonski signal jedan stupac."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefonski signal dva stupca."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefonski signal tri stupca."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefonski signal pun."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Nema podataka."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Podatkovni signal jedan stupac."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Podatkovni signal dva stupca."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Podatkovni signal tri stupca."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Podatkovni signal pun."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Prekinuta je veza s ethernetom."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Uspostavljena je veza s ethernetom."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index e5d4bd1..c3b859c 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Az átkódolás alapértelmezett beállításainak felülbírálása"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Átkódolás engedélyezése"</string>
<string name="transcode_default" msgid="3784803084573509491">"Annak feltételezése, hogy az alkalmazások támogatják a modern formátumokat"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Átkódolás engedélyezése az alkalmazásoknál"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Futó szolgáltatások"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"A jelenleg futó szolgáltatások megtekintése és vezérlése"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-megvalósítás"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Vezetékes fejhallgató"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Be"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Ki"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Szolgáltatói hálózat váltása"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobiladatok kikapcsolva"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Nincs beállítva az adathasználat"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Nincs telefon."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefon egy sáv."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefon két sáv."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefon három sáv."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefonjel megtelt."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Nincsenek adatok."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Adat egy sáv."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Adat két sáv."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Adat három sáv."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Adatjel teljes."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet leválasztva."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet csatlakoztatva."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 53eb766..041ad0e 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Չեղարկել վերակոդավորման կանխադրված կարգավորումները"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Միացնել վերակոդավորումը"</string>
<string name="transcode_default" msgid="3784803084573509491">"Ենթադրել, որ հավելվածներն աջակցում են ժամանակակից ձևաչափեր"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Միացնել վերակոդավորումը հավելվածների համար"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Աշխատող ծառայություններ"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Դիտել և վերահսկել ընթացիկ աշխատող ծառայությունները"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ծառայություն"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Լարով ականջակալ"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Միացնել"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Անջատել"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Օպերատորի ցանցի փոփոխություն"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Բջջային ինտերնետն անջատված է"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Բջջային ինտերնետն ըստ կանխադրման չի օգտագործվում"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Հեռախոս չկա:"</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Հեռախոսի մեկ գիծ:"</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Հեռախոսի երկու գիծ:"</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Հեռախոսի երեք գիծ:"</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Հեռախոսի ազդանշանը լիքն է:"</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Տվյալներ չկան:"</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Տվյալների մեկ գիծ:"</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Տվյալների երկու գիծ:"</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Տվյալների երեք գիծ:"</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Տվյալների ազդանշանը լրիվ է:"</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet-ը անջատված է:"</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet-ը կապակցված է:"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index edce3c5..69d4582 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Ganti default transcoding"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Aktifkan transcoding"</string>
<string name="transcode_default" msgid="3784803084573509491">"Asumsikan aplikasi mendukung format modern"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Mengaktifkan transcoding untuk aplikasi"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Layanan yang sedang berjalan"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Melihat dan mengontrol layanan yang sedang berjalan"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Penerapan WebView"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Headphone berkabel"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Aktif"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Nonaktif"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Jaringan operator berubah"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Kuota nonaktif"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Tidak disetel untuk menggunakan data"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Tidak dapat melakukan panggilan."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Ponsel satu batang."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Ponsel dua batang."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Ponsel tiga batang."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Sinyal ponsel penuh."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Tidak ada data yang diterima."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data satu batang."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Data dua batang."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Data tiga batang."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Sinyal data penuh."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet terputus."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet tersambung."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 9e072cc..f401364 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Hnekkja sjálfgefinni umkóðun"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Kveikja á umkóðun"</string>
<string name="transcode_default" msgid="3784803084573509491">"Gera ráð fyrir að forrit styðji nútímasnið"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Kveikja á umkóðun í forritum"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Þjónustur í gangi"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Skoða og stjórna þjónustum í gangi"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Innleiðing WebView"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Heyrnartól með snúru"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Kveikt"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Slökkt"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Skiptir um farsímakerfi"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Slökkt á farsímagögnum"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Ekki stillt á að nota gögn"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Ekkert símasamband."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Styrkur símasambands er eitt strik."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Styrkur símasambands er tvö strik."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Styrkur símasambands er þrjú strik."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Fullur styrkur símasambands."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Engin gögn."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Sendistyrkur gagnatengingar er eitt strik."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Sendistyrkur gagnatengingar tvö strik."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Sendistyrkur gagnatengingar er þrjú strik."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Fullur sendistyrkur gagnatengingar."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet aftengt."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet tengt."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index fc87d89..ef5e2ff 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Sostituisci impostazioni predefinite transcodifica"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Attiva transcodifica"</string>
<string name="transcode_default" msgid="3784803084573509491">"Presupponi che le app supportino i formati moderni"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Attiva transcodifica per le app"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Servizi in esecuzione"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Visualizza e controlla i servizi attualmente in esecuzione"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementazione di WebView"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Cuffie con cavo"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"On"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Off"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Cambio della rete dell\'operatore"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Dati mobili disattivati"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Non impostato per l\'utilizzo dei dati"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Nessun telefono."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefono: una barra."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefono: due barre."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefono: tre barre."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Massimo segnale telefonico."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Nessun dato."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Dati: una barra."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Dati: due barre."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Dati: tre barre."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Massimo segnale dati."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Connessione Ethernet annullata."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Connessione Ethernet stabilita."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index b899b59..4cc6775 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"ביטול ברירות המחדל של המרת קידוד"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"הפעלת המרת קידוד"</string>
<string name="transcode_default" msgid="3784803084573509491">"הנחת העבודה היא שאפליקציות תומכות בפורמטים מודרניים"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"הפעלה של המרת קידוד לאפליקציות"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"שירותים פועלים"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"הצגת השירותים הפועלים כעת ושליטה בהם"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"יישום WebView"</string>
@@ -568,4 +567,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"אוזניות חוטיות"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"פועלת"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"כבויה"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"רשת ספק משתנה"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"+H"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"+4G"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"+LTE"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"חבילת הגלישה כבויה"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"לא מוגדרת לשימוש בנתונים"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"אין טלפון."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"פס אחד של טלפון."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"שני פסים של טלפון."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"שלושה פסים של טלפון."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"אות הטלפון מלא."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"אין נתונים."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"פס אחד של נתונים."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"שני פסים של נתונים."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"שלושה פסים של נתונים."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"אות הנתונים מלא."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"אתרנט מנותק."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"אתרנט מחובר."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index ded207d..9e9db3d 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"デフォルトのコード変換をオーバーライド"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"コード変換を有効にする"</string>
<string name="transcode_default" msgid="3784803084573509491">"アプリによる最新形式のサポートを想定"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"アプリに対しコード変換を有効にする"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"実行中のサービス"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"現在実行中のサービスを表示して制御する"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView の実装"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"有線ヘッドフォン"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ON"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"OFF"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"携帯通信会社のネットワークを変更します"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"モバイルデータ OFF"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"データを使用するように設定されていません"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"電波状態:なし"</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"電波状態:レベル1"</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"電波状態:レベル2"</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"電波状態:レベル3"</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"電波状態:フル"</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"データ信号:なし"</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"データ信号:レベル1"</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"データ信号:レベル2"</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"データ信号:レベル3"</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"データ信号:フル"</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"イーサネット接続を解除しました。"</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"イーサネットに接続しました。"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 2d89dc6..ec39008 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"ტრანსკოდირების ნაგულისხმევების უგულებელყოფა"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"ტრანსკოდირების ჩართვა"</string>
<string name="transcode_default" msgid="3784803084573509491">"დაშვება, რომ აპებს აქვთ თანამედროვე ფორმატების მხარდაჭერა"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"ტრანსკოდირების ჩართვა აპებისთვის"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"მიმდინარე სერვისები"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"ამჟამად მოქმედი სერვისების ნახვა და მართვა"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView რეალიზაცია"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"სადენიანი ყურსასმენი"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ჩართვა"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"გამორთვა"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"ოპერატორის ქსელის შეცვლა"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"მობილური ინტერნეტი გამორთულია"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"არ არის დაყენებული მონაცემების გამოყენებისთვის"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"ტელეფონი არ არის."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"ტელეფონის სიგნალი ერთ ზოლზეა."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"ტელეფონის სიგნალი ორ ზოლზეა."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"ტელეფონის სიგნალი სამ ზოლზეა."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"ტელეფონის სიგნალი სრულია."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"მონაცემები არ არის."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"თარიღი ზოლზე."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"მონაცემების გადაცემა: ორი ზოლი"</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"მონაცემების გადაცემა: სამი ზოლი"</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"მონაცემთა გადაცემის საიმედო სიგნალი."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet კავშირი შეწყვეტილია."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet დაკავშირებულია."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index fa99529..881a13c 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Қайта қодтаудың әдепкі параметрлерін қайта анықтау"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Қайта кодтауды қосу"</string>
<string name="transcode_default" msgid="3784803084573509491">"Қолданбалар қазіргі заманғы форматтарды қолдайды делік"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Қолданбалар үшін қайта кодтауға рұқсат ету"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Қосылып тұрған қызметтер"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Қазір істеп тұрған қызметтерді көру және басқару"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView қызметі"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Сымды құлақаспап"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Қосу"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Өшіру"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Оператор желісін өзгерту"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Мобильдік деректер өшірулі"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Деректерді пайдалануға реттелмеген."</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Телефон жоқ."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Телефон бір баған."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Телефон екі баған."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Телефон үш баған."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Телефон сигналы толық."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Дерекқор жоқ."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Дерекқор бір баған."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Дерекқор екі баған."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Дерекқор үш баған."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Дерекқор сигналы толы."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet ажыратылған."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet қосылған."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index a2b5e01..14f7788 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"លុបពីលើលំនាំដើមនៃការបំប្លែងកូដ"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"បើកការបំប្លែងកូដ"</string>
<string name="transcode_default" msgid="3784803084573509491">"សន្មតថាកម្មវិធីអាចប្រើទម្រង់ទំនើបបាន"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"បើកការបំប្លែងកូដសម្រាប់កម្មវិធី"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"សេវាកម្មកំពុងដំណើរការ"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"មើល និងគ្រប់គ្រងសេវាកម្មកំពុងដំណើរការបច្ចុប្បន្ន"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"ការអនុវត្ត WebView"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"កាសមានខ្សែ"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"បើក"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"បិទ"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"បណ្តាញក្រុមហ៊ុនសេវាទូរសព្ទកំពុងផ្លាស់ប្តូរ"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"ទិន្នន័យទូរសព្ទចល័តបានបិទ"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"មិនបានកំណត់ឱ្យប្រើទិន្នន័យទេ"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"គ្មានទូរស័ព្ទ។"</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"សេវាទូរស័ព្ទមួយកាំ។"</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"សេវាទូរស័ព្ទពីរកាំ។"</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"សេវាទូរស័ព្ទបីកាំ។"</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"សេវាទូរស័ព្ទពេញ។"</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"គ្មានទិន្នន័យ។"</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"ទិន្នន័យមួយកាំ។"</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"ទិន្នន័យពីរកាំ។"</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"ទិន្នន័យបីកាំ។"</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"សញ្ញាទិន្នន័យពេញ។"</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"បានផ្តាច់អ៊ីសឺរណិត។"</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"បានភ្ជាប់អ៊ីសឺរណិត។"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index f37cf8b..a279d22 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -400,13 +400,9 @@
<string name="inactive_app_active_summary" msgid="8047630990208722344">"ಸಕ್ರಿಯ. ಟಾಗಲ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"ಅಪ್ಲಿಕೇಶನ್ ಸ್ಟ್ಯಾಂಡ್ಬೈ ಸ್ಥಿತಿ:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
<string name="transcode_settings_title" msgid="2581975870429850549">"ಮೀಡಿಯಾ ಟ್ರಾನ್ಸ್ಕೋಡಿಂಗ್ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
- <!-- no translation found for transcode_user_control (6176368544817731314) -->
- <skip />
- <!-- no translation found for transcode_enable_all (2411165920039166710) -->
- <skip />
- <!-- no translation found for transcode_default (3784803084573509491) -->
- <skip />
- <string name="transcode_skip_apps" msgid="8249721984597390142">"ಆ್ಯಪ್ಗಳಿಗಾಗಿ ಟ್ರಾನ್ಸ್ಕೋಡಿಂಗ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
+ <string name="transcode_user_control" msgid="6176368544817731314">"ಟ್ರಾನ್ಸ್ಕೋಡಿಂಗ್ ಡೀಫಾಲ್ಟ್ಗಳನ್ನು ಅತಿಕ್ರಮಿಸಿ"</string>
+ <string name="transcode_enable_all" msgid="2411165920039166710">"ಟ್ರಾನ್ಸ್ಕೋಡಿಂಗ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
+ <string name="transcode_default" msgid="3784803084573509491">"ಆ್ಯಪ್ಗಳು ಆಧುನಿಕ ಫಾರ್ಮ್ಯಾಟ್ಗಳನ್ನು ಬೆಂಬಲಿಸುತ್ತದೆ ಎಂದು ಊಹಿಸಿ"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"ರನ್ ಆಗುತ್ತಿರುವ ಸೇವೆಗಳು"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"ಈಗ ರನ್ ಆಗುತ್ತಿರುವ ಸೇವೆಗಳನ್ನು ವೀಕ್ಷಿಸಿ ಮತ್ತು ನಿಯಂತ್ರಿಸಿ"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ಹೊಂದಿಸಿ"</string>
@@ -569,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"ವೈಯರ್ ಹೊಂದಿರುವ ಹೆಡ್ಫೋನ್"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ಆನ್ ಆಗಿದೆ"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"ಆಫ್ ಆಗಿದೆ"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"ವಾಹಕ ನೆಟ್ವರ್ಕ್ ಬದಲಾಯಿಸುವಿಕೆ"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"ಮೊಬೈಲ್ ಡೇಟಾ ಆಫ್"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"ಡೇಟಾ ಬಳಸಲು ಹೊಂದಿಸಲಾಗಿಲ್ಲ"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"ಯಾವುದೇ ಫೋನ್ ಇಲ್ಲ."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"ಪೋನ್ ಒಂದು ಪಟ್ಟಿ."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"ಫೋನ್ ಎರಡು ಪಟ್ಟಿಗಳು."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"ಫೋನ್ ಮೂರು ಪಟ್ಟಿಗಳು."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"ಫೋನ್ ಸಂಕೇತ ಪೂರ್ತಿ ಇದೆ."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"ಯಾವುದೇ ಡೇಟಾ ಇಲ್ಲ."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"ಡೇಟಾ ಒಂದು ಪಟ್ಟಿ."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"ಡೇಟಾ ಎರಡು ಪಟ್ಟಿಗಳು."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"ಡೇಟಾ ಮೂರು ಪಟ್ಟಿಗಳು."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"ಡೇಟಾ ಸಂಕೇತ ತುಂಬಿದೆ."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ಇಥರ್ನೆಟ್ ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಲಾಗಿದೆ."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"ಇಥರ್ನೆಟ್ ಸಂಪರ್ಕಗೊಳಿಸಲಾಗಿದೆ."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 73921c2..de69488 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"트랜스코딩 기본값 재정의"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"트랜스코딩 사용"</string>
<string name="transcode_default" msgid="3784803084573509491">"앱이 최신 형식을 지원하는 것으로 가정"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"앱 트랜스코딩 사용 설정"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"실행 중인 서비스"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"현재 실행 중인 서비스 보기 및 제어"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView 구현"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"유선 헤드폰"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"사용"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"사용 안 함"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"이동통신사 네트워크 변경"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G 이상"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"모바일 데이터 꺼짐"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"데이터를 사용하도록 설정되지 않음"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"휴대전화의 신호가 없습니다."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"휴대전화 신호 막대가 하나입니다."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"휴대전화 신호 막대가 두 개입니다."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"휴대전화 신호 막대가 세 개입니다."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"휴대전화의 신호가 강합니다."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"데이터가 없습니다."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"데이터 신호 막대가 하나입니다."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"데이터 신호 막대가 두 개입니다."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"데이터 신호 막대가 세 개입니다."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"데이터 신호가 강합니다."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"이더넷에서 연결 해제되었습니다."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"이더넷에 연결되었습니다."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 5e978ba..e70460f 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Демейки жүргүзүлгөн транскоддоону өзгөртүп коюу"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Транскоддоо жүргүзүүнү иштетүү"</string>
<string name="transcode_default" msgid="3784803084573509491">"Колдонмолордо заманбап форматтар колдоого алынат"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Колдонмолорду транскоддоону күйгүзүү"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Иштеп жаткан кызматтар"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Учурда иштеп жаткан кызматтарды көрүп, көзөмөлдөп турасыз"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView кызматы"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Зымдуу гарнитура"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Күйгүзүү"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Өчүрүү"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Байланыш оператору өзгөртүлүүдө"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Мобилдик Интернет өчүрүлгөн"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Дайындарды колдонуу үчүн жөндөлгөн эмес"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Телефон сигналы жок."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Телефон сигналы бир таякча."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Телефон сигналы эки таякча."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Телефон сигналы үч таякча."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Телефон сигналы толук."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Сигнал жок."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Мобилдик интернеттин сигналы бир таякча."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Мобилдик интернеттин сигналы эки таякча."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Мобилдик интернеттин сигналы үч таякча."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Мобилдик интернеттин сигналы толук."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet ажырады."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet туташты."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 498cb25..c63cec8 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"ຍົກເລີກຄ່າເລີ່ມຕົ້ນການປ່ຽນຮູບແບບລະຫັດ"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"ເປີດການນຳໃຊ້ການປ່ຽນຮູບແບບລະຫັດ"</string>
<string name="transcode_default" msgid="3784803084573509491">"ສົມມຸດວ່າແອັບຮອງຮັບຮູບແບບສະໄໝໃໝ່"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"ເປີດການນຳໃຊ້ການປ່ຽນຮູບແບບລະຫັດສຳລັບແອັບ"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"ບໍລິການທີ່ເຮັດວຽກຢູ່"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"ເບິ່ງ ແລະຈັດການບໍລິການທີ່ກຳລັງເຮັດວຽກຢູ່ໃນປັດຈຸບັນ"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"ການຈັດຕັ້ງປະຕິບັດ WebView"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"ຫູຟັງແບບມີສາຍ"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ເປີດ"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"ປິດ"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"ການປ່ຽນເຄືອຂ່າຍຜູ້ໃຫ້ບໍລິການ"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"ປິດອິນເຕີເນັດມືຖືແລ້ວ"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"ບໍ່ໄດ້ຕັ້ງໃຫ້ໃຊ້ອິນເຕີເນັດ"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"ບໍ່ມີໂທລະສັບ."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"ສັນຍານນຶ່ງຂີດ."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"ສັນຍານສອງຂີດ."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"ສັນຍານສາມຂີດ."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"ສັນຍານເຕັມ."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"ບໍ່ມີຂໍ້ມູນ."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"ຂໍ້ມູນນຶ່ງຂີດ."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"ຂໍ້ມູນສອງຂີດ."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"ຂໍ້ມູນສາມຂີດ."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"ສັນຍານຂໍ້ມູນເຕັມ."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ອີເທີເນັດຕັດເຊື່ອມຕໍ່ແລ້ວ."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"ອີເທີເນັດເຊື່ອມຕໍ່ແລ້ວ."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index c077268..d040edf 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Perkodavimo numatytųjų nustatymų nepaisymas"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Perkodavimo įgalinimas"</string>
<string name="transcode_default" msgid="3784803084573509491">"Manoma, kad programos palaiko modernius formatus"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Įjungti programų perkodavimą"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Vykdomos paslaugos"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Žiūrėti ir valdyti dabar vykdomas paslaugas"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"„WebView“ diegimas"</string>
@@ -568,4 +567,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Laidinės ausinės"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Įjungta"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Išjungta"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Keičiamas operatoriaus tinklas"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobiliojo ryšio duomenys išjungti"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Nenustatyta naudoti duomenis"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Nėra telefono."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Viena telefono juosta."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Dvi telefono juostos."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Trys telefono juostos."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefono signalas stiprus."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Duomenų nėra."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Viena duomenų juosta."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Dvi duomenų juostos."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Trys duomenų juostos."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Stiprus duomenų signalas."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Atsijungta nuo eterneto."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Prijungta prie eterneto."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index d5755511..74c0dd5 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Ignorēt pārkodēšanas noklusējuma iestatījumus"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Iespējot pārkodēšanu"</string>
<string name="transcode_default" msgid="3784803084573509491">"Pieņemt, ka lietotnēs tiek atbalstīti moderni formāti"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Iespējot pārkodēšanu noteiktām lietotnēm"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Aktīvie pakalpojumi"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Pašreiz darbojošos pakalpojumu skatīšana un vadība"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ieviešana"</string>
@@ -567,4 +566,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Vadu austiņas"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Ieslēgts"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Izslēgts"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Mobilo sakaru operatora tīkla mainīšana"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobilie dati izslēgti"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Nav iestatīts datu lietošanai"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Nav tālruņa."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Tālrunis: viena josla."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Tālrunis: divas joslas."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Tālrunis: trīs joslas."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Pilna piekļuve tālruņa signālam"</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Nav datu."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Dati: viena josla"</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Dati: divas joslas."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Dati: trīs joslas."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Pilna piekļuve datu signālam."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Pārtraukts savienojums ar tīklu Ethernet."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Izveidots savienojums ar tīklu Ethernet."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 21dcb02..739bceb 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Отфрли стандардни вредности за транскодирање"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Овозможи транскодирање"</string>
<string name="transcode_default" msgid="3784803084573509491">"Претпостави дека апликациите поддржуваат модерни формати"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Овозможете транскодирање за апликациите"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Активни услуги"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Погледнете и контролирајте услуги што се моментално активни"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Воведување WebView"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Жичени слушалки"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Вклучено"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Исклучено"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Променување на мрежата на операторот"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Мобилниот интернет е исклучен"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Не е поставен да користи интернет"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Нема сигнал."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Телефон една цртичка.."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Телефон две цртички."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Телефон три цртички."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Сигналот за телефон е исполнет."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Нема податоци."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Податоци една цртичка."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Сигналот за податоци е на две цртички."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Податоци три цртички."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Сигналот за податоци е исполнет."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Етернетот е исклучен."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Етернетот е поврзан."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 97c22d5..122b481 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -400,13 +400,9 @@
<string name="inactive_app_active_summary" msgid="8047630990208722344">"സജീവം. മാറ്റുന്നതിന് ടാപ്പുചെയ്യുക."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"ആപ്പ് സ്റ്റാൻഡ്ബൈ നില:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
<string name="transcode_settings_title" msgid="2581975870429850549">"മീഡിയ ട്രാൻസ്കോഡ് ചെയ്യൽ ക്രമീകരണം"</string>
- <!-- no translation found for transcode_user_control (6176368544817731314) -->
- <skip />
- <!-- no translation found for transcode_enable_all (2411165920039166710) -->
- <skip />
- <!-- no translation found for transcode_default (3784803084573509491) -->
- <skip />
- <string name="transcode_skip_apps" msgid="8249721984597390142">"ആപ്പുകൾക്കായി ട്രാൻസ്കോഡ് ചെയ്യുന്നത് പ്രവർത്തനക്ഷമമാക്കുക"</string>
+ <string name="transcode_user_control" msgid="6176368544817731314">"ട്രാൻസ്കോഡ് ചെയ്യൽ ഡിഫോൾട്ടുകൾ അസാധുവാക്കുക"</string>
+ <string name="transcode_enable_all" msgid="2411165920039166710">"ട്രാൻസ്കോഡ് ചെയ്യൽ പ്രവർത്തനക്ഷമമാക്കുക"</string>
+ <string name="transcode_default" msgid="3784803084573509491">"ആപ്പുകൾ ആധുനിക ഫോർമാറ്റുകളെ പിന്തുണയ്ക്കുമെന്ന് കരുതുക"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"പ്രവർത്തിക്കുന്ന സേവനങ്ങൾ"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"നിലവിൽ പ്രവർത്തിക്കുന്ന സേവനങ്ങൾ കാണുക, നിയന്ത്രിക്കുക"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView നടപ്പാക്കൽ"</string>
@@ -569,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"വയേർഡ് ഹെഡ്ഫോൺ"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ഓണാണ്"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"ഓഫാണ്"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"കാരിയർ നെറ്റ്വർക്ക് മാറ്റൽ"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDG"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"മൊബൈൽ ഡാറ്റ ഓഫാണ്"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"ഡാറ്റ ഉപയോഗിക്കുന്നതിന് സജ്ജീകരിച്ചിട്ടില്ല"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"ഫോൺ സിഗ്നൽ ഒന്നുമില്ല."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"ഫോണിൽ ഒരു ബാർ."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"ഫോണിൽ രണ്ട് ബാർ."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"ഫോണിൽ മൂന്ന് ബാർ."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"ഫോൺ സിഗ്നൽ പൂർണ്ണമാണ്."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"ഡാറ്റാ സിഗ്നൽ ഒന്നുമില്ല."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"ഡാറ്റ ഒരു ബാർ."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"ഡാറ്റ രണ്ട് ബാറുകൾ."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"ഡാറ്റ മൂന്ന് ബാർ."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"ഡാറ്റ സിഗ്നൽ പൂർണ്ണമാണ്."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ഇതർനെറ്റ് വിച്ഛേദിച്ചു."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"ഇതർനെറ്റ് കണക്റ്റുചെയ്തു."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 8d1cc33..c7a2edd 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Хөрвүүлгийн өгөгдмөлийг дарах"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Хөрвүүлгийг идэвхжүүлэх"</string>
<string name="transcode_default" msgid="3784803084573509491">"Аппыг орчин үеийн форматыг дэмждэг гэж үздэг"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Аппуудад хөрвүүлгийг идэвхжүүлэх"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Ажиллаж байгаа үйлчилгээнүүд"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Одоо ажиллаж байгаа үйлчилгээнүүдийг харах болон хянах"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView хэрэгжилт"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Утастай чихэвч"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Асаах"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Унтраах"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Оператор компанийн сүлжээг өөрчилж байна"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Мобайл дата унтраалттай байна"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Дата ашиглахаар тохируулаагүй"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Утас байхгүй."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Утас нэг баганатай."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Утас хоёр баганатай."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Утас гурван баганатай."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Утасны дохио дүүрэн."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Дата байхгүй."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Дата нэг баганатай."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Дата хоёр баганатай."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Дата гурван баганатай."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Дата дохио дүүрэн."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet саллаа."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet холбогдсон."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index c20888e..d29cb59 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -400,13 +400,9 @@
<string name="inactive_app_active_summary" msgid="8047630990208722344">"सक्रिय. टॉगल करण्यासाठी टॅप करा."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"अॅप स्टँडबाय स्थिती: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
<string name="transcode_settings_title" msgid="2581975870429850549">"मीडिया ट्रान्सकोडिंगची सेटिंग्ज"</string>
- <!-- no translation found for transcode_user_control (6176368544817731314) -->
- <skip />
- <!-- no translation found for transcode_enable_all (2411165920039166710) -->
- <skip />
- <!-- no translation found for transcode_default (3784803084573509491) -->
- <skip />
- <string name="transcode_skip_apps" msgid="8249721984597390142">"ॲप्ससाठी ट्रान्सकोडिंग सुरू करा"</string>
+ <string name="transcode_user_control" msgid="6176368544817731314">"ट्रान्सकोडिंग डीफॉल्ट ओव्हरराइड करा"</string>
+ <string name="transcode_enable_all" msgid="2411165920039166710">"ट्रान्सकोडिंग सुरू करा"</string>
+ <string name="transcode_default" msgid="3784803084573509491">"असे गृहीत धरा की, ॲप्स आधुनिक फॉरमॅटना सपोर्ट करतात"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"सुरू सेवा"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"सध्या सुरू असलेल्या सेवा पहा आणि नियंत्रित करा"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"वेबदृश्य अंमलबजावणी"</string>
@@ -569,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"वायर असलेला हेडफोन"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"सुरू करा"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"बंद करा"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"वाहक नेटवर्क बदलत आहे"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"३G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"१X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"४G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"४G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"मोबाइल डेटा बंद आहे"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"डेटा वापरण्यासाठी सेट केलेले नाही"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"कोणताही फोन नाही."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"फोन एक बार."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"फोन दोन बार."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"फोन तीन बार."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"फोन सिग्नल पूर्ण."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"कोणताही डेटा नाही."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"डेटा एक बार."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"डेटा दोन बार."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"डेटा तीन बार."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"डेटा सिग्नल पूर्ण."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"इथरनेट डिस्कनेक्ट केले."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"इथरनेट कनेक्ट केले."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 76840a5..c593e4b 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Batalkan transpengekodan lalai"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Dayakan transpengekodan"</string>
<string name="transcode_default" msgid="3784803084573509491">"Mengambil alih sokongan apl format moden"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Dayakan transpengekodan untuk apl"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Perkhidmatan dijalankan"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Lihat dan kawal perkhidmatan yang sedang dijalankan"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Pelaksanaan WebView"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Fon kepala berwayar"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Hidup"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Mati"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Rangkaian pembawa berubah"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Data mudah alih dimatikan"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Tidak ditetapkan untuk menggunakan data"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Tiada telefon."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefon satu bar."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefon dua bar."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefon tiga bar."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Isyarat telefon penuh."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Tiada data."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data satu bar."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Data dua bar."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Data tiga bar."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Isyarat data penuh."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet diputuskan sambungan."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet disambungkan."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 377e49da..aa9d3d6 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"အမျိုးအစားပြောင်းခြင်း၏ မူရင်းဆက်တင်များကို အစားထိုးရန်"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"အမျိုးအစားပြောင်းခြင်းကို ဖွင့်ရန်"</string>
<string name="transcode_default" msgid="3784803084573509491">"ဤအက်ပ်များက ဖော်မက်အသစ်များကို ပံ့ပိုးသည်"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"အက်ပ်များအတွက် အမျိုးအစားပြောင်းခြင်းကို ဖွင့်ရန်"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"အလုပ်လုပ်နေသောဝန်ဆောင်မှုများ"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"လက်ရှိ ဝန်ဆောင်မှုများကို ကြည့်ရှု ထိန်းသိမ်းသည်"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView အကောင်အထည်ဖော်မှု"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"ကြိုးတပ်နားကြပ်"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ဖွင့်ထားသည်"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"ပိတ်ထားသည်"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"ဝန်ဆောင်မှုပေးသူ ကွန်ရက် ပြောင်းလဲနေသည်။"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"မိုဘိုင်းဒေတာ ပိတ်ထားသည်"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"ဒေတာအသုံးပြုရန် သတ်မှတ်မထားပါ"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"ဖုန်းလိုင်းမရှိပါ။"</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"ဖုန်းလိုင်းတစ်ဘား။"</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"ဖုန်းလိုင်းနှစ်ဘား။"</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"ဖုန်းလိုင်းသုံးဘား။"</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"ဖုန်းလိုင်းအပြည့်။"</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"ဒေတာမရှိပါ။"</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"ဒေတာတစ်ဘား။"</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"ဒေတာထုတ်လွှင့်မှု ၂ဘားဖမ်းမိခြင်း။"</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"ဒေတာသုံးဘား။"</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"ဒေတာထုတ်လွှင့်မှုအပြည့်ဖမ်းမိခြင်း"</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet နှင့်ချိတ်ဆက်မှုပြတ်တောက်"</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet ချိတ်ဆက်ထား။"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index db93121..9494c39 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Overstyr omkodingsstandarder"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Slå på omkoding"</string>
<string name="transcode_default" msgid="3784803084573509491">"Anta at apper støtter moderne formater"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Aktiver omkoding for apper"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Aktive tjenester"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Se og kontrollér tjenester som kjører"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-implementering"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Hodetelefoner med kabel"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"På"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Av"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Bytting av operatørnettverk"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobildata er slått av"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Ikke konfigurert til å bruke data"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Ingen telefon."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefon – én stolpe."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefon – to stolper."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefon – tre stolper."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefonsignal er fullt."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Ingen data."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data – én stolpe"</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Data – to stolper."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Data – tre stolper."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Datasignal er fullt."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet er frakoblet."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet er tilkoblet."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 25a2919..e31fb4e 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -400,13 +400,9 @@
<string name="inactive_app_active_summary" msgid="8047630990208722344">"सक्रिय। टगल गर्न ट्याप गर्नुहोस्।"</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"एपको स्ट्यान्डबाई अवस्था:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
<string name="transcode_settings_title" msgid="2581975870429850549">"मिडिया ट्रान्सकोडिङ सेटिङ"</string>
- <!-- no translation found for transcode_user_control (6176368544817731314) -->
- <skip />
- <!-- no translation found for transcode_enable_all (2411165920039166710) -->
- <skip />
- <!-- no translation found for transcode_default (3784803084573509491) -->
- <skip />
- <string name="transcode_skip_apps" msgid="8249721984597390142">"एपहरूमा ट्रान्सकोडिङ अन गर्नुहोस्"</string>
+ <string name="transcode_user_control" msgid="6176368544817731314">"ट्रान्सकोडिङसम्बन्धी पूर्वनिर्धारित सेटिङ परिवर्तन गर्नुहोस्"</string>
+ <string name="transcode_enable_all" msgid="2411165920039166710">"ट्रान्सकोडिङ अन गर्नुहोस्"</string>
+ <string name="transcode_default" msgid="3784803084573509491">"एपहरूमा आधुनिक फर्म्याट प्रयोग गर्न मिल्छ भनी मान्नुहोस्"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"चलिरहेका सेवाहरू"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"हाल चालु भइरहेका सेवाहरू हेर्नुहोस् र नियन्त्रण गर्नुहोस्"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView कार्यान्वयन"</string>
@@ -569,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"तारसहितको हेडफोन"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"अन छ"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"अफ छ"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"सेवा प्रदायकको नेटवर्क परिवर्तन गर्ने आइकन"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"मोबाइल डेटा निष्क्रिय छ"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"डेटा प्रयोग गर्ने गरी सेट गरिएन"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"फोन छैन्।"</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"फोन एउटा पट्टि।"</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"फोन दुई पट्टि।"</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"फोन तिन पट्टिहरू।"</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"फोन सङ्केत भरिएको।"</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"डेटा छैन।"</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"डेटाको एउटा पट्टि।"</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"डेटा दुई बाधाहरू।"</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"डेटा तिन बाधाहरू।"</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"डेटा संकेत पूर्ण।"</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"इथरनेट विच्छेद भयो।"</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"इथरनेट जोडियो।"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 0f2cc6f..0b75fdd 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Standaardwaarden voor transcodering overschrijven"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Transcodering inschakelen"</string>
<string name="transcode_default" msgid="3784803084573509491">"Aannemen dat apps moderne indelingen ondersteunen"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Transcodering inschakelen voor apps"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Actieve services"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Services die momenteel actief zijn, weergeven en beheren"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-implementatie"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Bedrade hoofdtelefoon"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Aan"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Uit"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Netwerk van provider wordt gewijzigd"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobiele data uit"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Gebruik van gegevens is niet ingesteld"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Geen telefoonsignaal."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefoon: één streepje."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefoon: twee streepjes."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefoon: drie streepjes."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefoonsignaal is op volle sterkte."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Geen gegevens."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Gegevens: één streepje."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Gegevens: twee streepjes."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Gegevens: drie streepjes."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Gegevenssignaal is op volle sterkte."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernetverbinding verbroken."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet verbonden."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 040dddd..cfde61f 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -400,13 +400,9 @@
<string name="inactive_app_active_summary" msgid="8047630990208722344">"ସକ୍ରିୟ। ବଦଳାଇବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ"</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"ଆପ୍ ଷ୍ଟାଣ୍ଡବାଏ ଅବସ୍ଥା:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
<string name="transcode_settings_title" msgid="2581975870429850549">"ମିଡିଆ ଟ୍ରାନ୍ସକୋଡିଂ ସେଟିଂସ୍"</string>
- <!-- no translation found for transcode_user_control (6176368544817731314) -->
- <skip />
- <!-- no translation found for transcode_enable_all (2411165920039166710) -->
- <skip />
- <!-- no translation found for transcode_default (3784803084573509491) -->
- <skip />
- <string name="transcode_skip_apps" msgid="8249721984597390142">"ଆପଗୁଡ଼ିକ ପାଇଁ ଟ୍ରାନ୍ସକୋଡିଂ ସକ୍ଷମ କରନ୍ତୁ"</string>
+ <string name="transcode_user_control" msgid="6176368544817731314">"ଟ୍ରାନ୍ସକୋଡିଂ ଡିଫଲ୍ଟଗୁଡ଼ିକୁ ଓଭରରାଇଡ୍ କରନ୍ତୁ"</string>
+ <string name="transcode_enable_all" msgid="2411165920039166710">"ଟ୍ରାନ୍ସକୋଡିଂକୁ ସକ୍ଷମ କରନ୍ତୁ"</string>
+ <string name="transcode_default" msgid="3784803084573509491">"ଧରିନିଅନ୍ତୁ ଆପଗୁଡ଼ିକ ଆଧୁନିକ ଫର୍ମାଟଗୁଡ଼ିକୁ ସମର୍ଥନ କରେ"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"ଚାଲୁଥିବା ସେବାଗୁଡ଼ିକ"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"ଏବେ ଚାଲୁଥିବା ସେବାଗୁଡ଼ିକୁ ଦେଖନ୍ତୁ ଓ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"ୱେବ୍ଭ୍ୟୁ ପ୍ରୟୋଗ"</string>
@@ -569,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"ତାରଯୁକ୍ତ ହେଡଫୋନ୍"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ଚାଲୁ ଅଛି"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"ବନ୍ଦ ଅଛି"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"କେରିଅର୍ ନେଟ୍ୱର୍କ ବଦଳୁଛି"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"ମୋବାଇଲ୍ ଡାଟା ବନ୍ଦ ଅଛି"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"ବ୍ୟବହୃତ ଡାଟା ପାଇଁ ସେଟ୍ ହୋଇନାହିଁ"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"କୌଣସି ଫୋନ୍ ନାହିଁ।"</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"ଫୋନର ଗୋଟିଏ ବାର ଅଛି।"</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"ଫୋନର ଦୁଇଟି ବାର୍ ଅଛି।"</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"ଫୋନ୍ରେ ତିନୋଟି ବାର୍ ଅଛି।"</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"ଫୋନ୍ ସିଗ୍ନାଲ୍ ପୂର୍ଣ୍ଣ ଅଛି।"</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"କୌଣସି ଡାଟା ନାହିଁ।"</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"ଡାଟାର ଗୋଟିଏ ବାର ଅଛି।"</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"ଡାଟାର ଦୁଇଟି ବାର୍ ଅଛି।"</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"ଡାଟାର ତିନୋଟି ବାର୍ ଅଛି।"</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"ଡାଟା ସିଗ୍ନାଲ୍ ପୂର୍ଣ୍ଣ ଅଛି।"</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ଇଥରନେଟ୍ ବିଚ୍ଛିନ୍ନ ହୋଇଛି।"</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"ଇଥରନେଟ୍ ସଂଯୁକ୍ତ ହୋଇଛି।"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index e6adff3..1221862 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -400,13 +400,9 @@
<string name="inactive_app_active_summary" msgid="8047630990208722344">"ਕਿਰਿਆਸ਼ੀਲ। ਟੌਗਲ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"ਐਪ ਸਟੈਂਡਬਾਈ ਸਥਿਤੀ:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
<string name="transcode_settings_title" msgid="2581975870429850549">"ਮੀਡੀਆ ਟ੍ਰਾਂਸਕੋਡਿੰਗ ਸੈਟਿੰਗਾਂ"</string>
- <!-- no translation found for transcode_user_control (6176368544817731314) -->
- <skip />
- <!-- no translation found for transcode_enable_all (2411165920039166710) -->
- <skip />
- <!-- no translation found for transcode_default (3784803084573509491) -->
- <skip />
- <string name="transcode_skip_apps" msgid="8249721984597390142">"ਐਪਾਂ ਲਈ ਟ੍ਰਾਂਸਕੋਡਿੰਗ ਚਾਲੂ ਕਰੋ"</string>
+ <string name="transcode_user_control" msgid="6176368544817731314">"ਟ੍ਰਾਂਸਕੋਡਿੰਗ ਦੀਆਂ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਸੈਟਿੰਗਾਂ ਨੂੰ ਓਵਰਰਾਈਡ ਕਰੋ"</string>
+ <string name="transcode_enable_all" msgid="2411165920039166710">"ਟ੍ਰਾਂਸਕੋਡਿੰਗ ਚਾਲੂ ਕਰੋ"</string>
+ <string name="transcode_default" msgid="3784803084573509491">"ਮੰਨ ਲਓ ਕਿ ਐਪਾਂ ਆਧੁਨਿਕ ਫਾਰਮੈਟਾਂ ਦਾ ਸਮਰਥਨ ਕਰਦੀਆਂ ਹਨ"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"ਚੱਲ ਰਹੀਆਂ ਸੇਵਾਵਾਂ"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"ਇਸ ਵੇਲੇ ਚੱਲ ਰਹੀਆਂ ਸੇਵਾਵਾਂ ਦੇਖੋ ਅਤੇ ਇਹਨਾਂ ਨੂੰ ਕੰਟਰੋਲ ਕਰੋ"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ਅਮਲ"</string>
@@ -569,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"ਤਾਰ ਵਾਲੇ ਹੈੱਡਫ਼ੋਨ"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ਚਾਲੂ"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"ਬੰਦ"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"ਕੈਰੀਅਰ ਨੈੱਟਵਰਕ ਦੀ ਬਦਲੀ"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"ਮੋਬਾਈਲ ਡਾਟਾ ਬੰਦ"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"ਡਾਟਾ ਵਰਤਣ ਲਈ ਸੈੱਟ ਨਹੀਂ"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"ਕੋਈ ਫ਼ੋਨ ਨਹੀਂ।"</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"ਫ਼ੋਨ ਇੱਕ ਬਾਰ।"</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"ਫ਼ੋਨ ਦੋ ਬਾਰਸ।"</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"ਫ਼ੋਨ ਤਿੰਨ ਬਾਰਸ।"</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"ਫ਼ੋਨ ਸਿਗਨਲ ਪੂਰਾ।"</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"ਕੋਈ ਡਾਟਾ ਨਹੀਂ।"</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">" ਡਾਟਾ ਇੱਕ ਬਾਰ।"</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">" ਡਾਟਾ ਦੋ ਬਾਰਸ।"</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">" ਡਾਟਾ ਤਿੰਨ ਬਾਰ।"</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">" ਡਾਟਾ ਸਿਗਨਲ ਪੂਰਾ।"</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ਈਥਰਨੈੱਟ ਡਿਸਕਨੈਕਟ ਹੋ ਗਿਆ।"</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"ਈਥਰਨੈੱਟ ਕਨੈਕਟ ਹੋ ਗਿਆ।"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 5690e74..102835c 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -400,13 +400,9 @@
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktywna. Dotknij, by zmienić."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Stan aplikacji w trybie czuwania: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
<string name="transcode_settings_title" msgid="2581975870429850549">"Ustawienia transkodowania multimediów"</string>
- <!-- no translation found for transcode_user_control (6176368544817731314) -->
- <skip />
- <!-- no translation found for transcode_enable_all (2411165920039166710) -->
- <skip />
- <!-- no translation found for transcode_default (3784803084573509491) -->
- <skip />
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Włącz transkodowanie dla aplikacji"</string>
+ <string name="transcode_user_control" msgid="6176368544817731314">"Zastąp ustawienia domyślne transkodowania"</string>
+ <string name="transcode_enable_all" msgid="2411165920039166710">"Włącz transkodowanie"</string>
+ <string name="transcode_default" msgid="3784803084573509491">"Zakładaj, że aplikacje obsługują nowoczesne formaty"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Uruchomione usługi"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Wyświetl obecnie uruchomione usługi i nimi zarządzaj"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementacja WebView"</string>
@@ -571,4 +567,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Słuchawki przewodowe"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Włączono"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Wyłączono"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Zmiana sieci operatora"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Wyłączona"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Nie skonfigurowano do transmisji danych"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Brak sygnału telefonu."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefon: jeden pasek."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefon: dwa paski."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefon: trzy paski."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefon: pełna moc sygnału."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Brak danych."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Dane: jeden pasek."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Dane: dwa paski."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Dane: trzy paski."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Dane: pełna moc sygnału."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Rozłączono z siecią Ethernet."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Połączono z siecią Ethernet."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index a0ddcf2..99019a6 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Substituir os padrões de transcodificação"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Ativar transcodificação"</string>
<string name="transcode_default" msgid="3784803084573509491">"Considerar que os apps são compatíveis com formatos modernos"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Ativar transcodificação para apps"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Serviços em execução"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Visualizar e controlar os serviços em execução no momento"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementação do WebView"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Fones de ouvido com fio"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Ativado"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Desativado"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Alteração de rede da operadora"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Dados móveis desativados"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Sem configuração para uso de dados"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Sem telefone."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Uma barra de sinal do telefone."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Duas barras de sinal do telefone."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Três barras de sinal do telefone."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Sinal do telefone cheio."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Nenhum dado."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Uma barra de sinal de dados."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Duas barras de sinal de dados."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Três barras do sinal de dados."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Sinal de dados cheio."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet desconectada."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet conectada."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index adaed74..238e54b 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Substituir as predefinições da transcodificação"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Ativar a transcodificação"</string>
<string name="transcode_default" msgid="3784803084573509491">"Assumir que as apps suportam formatos modernos"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Ative a transcodificação para apps"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Serviços em execução"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Ver e controlar os serviços actualmente em execução"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementação WebView"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Auscultadores com fios"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Ligado"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Desligado"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Rede do operador em mudança."</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Dados móveis desativados"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Não definido para utilizar dados"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Sem telefone."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Uma barra de telefone."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Duas barras de telefone."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Três barras de telefone."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Sinal de telefone completo."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Sem dados."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Uma barra de dados."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Duas barras de dados."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Três barras de dados."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Sinal de dados completo."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet desligada."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet ligada."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index a0ddcf2..99019a6 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Substituir os padrões de transcodificação"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Ativar transcodificação"</string>
<string name="transcode_default" msgid="3784803084573509491">"Considerar que os apps são compatíveis com formatos modernos"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Ativar transcodificação para apps"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Serviços em execução"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Visualizar e controlar os serviços em execução no momento"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementação do WebView"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Fones de ouvido com fio"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Ativado"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Desativado"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Alteração de rede da operadora"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Dados móveis desativados"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Sem configuração para uso de dados"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Sem telefone."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Uma barra de sinal do telefone."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Duas barras de sinal do telefone."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Três barras de sinal do telefone."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Sinal do telefone cheio."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Nenhum dado."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Uma barra de sinal de dados."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Duas barras de sinal de dados."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Três barras do sinal de dados."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Sinal de dados cheio."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet desconectada."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet conectada."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 266dff2..df95dbc 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Modificați setările prestabilite de transcodare"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Activați transcodarea"</string>
<string name="transcode_default" msgid="3784803084573509491">"Presupuneți că aplicațiile acceptă formatele moderne"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Activați transcodarea pentru aplicații"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Servicii în curs de funcționare"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Vedeți și controlați serviciile care funcționează în prezent"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementare WebView"</string>
@@ -567,4 +566,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Căști cu fir"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Activat"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Dezactivat"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Se schimbă rețeaua operatorului"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Date mobile dezactivate"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Nu este setat pentru a folosi datele"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Nu există semnal pentru telefon."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Semnal pentru telefon: o bară."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Semnal pentru telefon: două bare."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Semnal pentru telefon: trei bare."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Semnal pentru telefon: complet."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Nu există semnal pentru date."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Semnal pentru date: o bară."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Semnal pentru date: două bare."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Semnal pentru date: trei bare."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Semnal pentru date: complet."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet deconectat."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet conectat."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index ca20bae..68826d7 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Переопределять настройки транскодирования по умолчанию"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Включить перекодирование"</string>
<string name="transcode_default" msgid="3784803084573509491">"Считать, что приложения поддерживают современные форматы кодирования"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Включить перекодирование для приложений"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Работающие службы"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Просмотр и управление работающими службами"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Сервис WebView"</string>
@@ -568,4 +567,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Проводные наушники"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Вкл."</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Выкл."</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Сменить сеть"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Мобильный Интернет отключен"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Мобильный Интернет по умолчанию не используется."</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Сигнал телефонной сети отсутствует."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Сигнал телефонной сети: одно деление."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Сигнал телефонной сети: два деления."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Сигнал телефонной сети: три деления."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Надежный телефонный сигнал."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Сигнал передачи данных отсутствует."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Сигнал передачи данных: одно деление."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Сигнал передачи данных: два деления."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Сигнал передачи данных: три деления."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Надежный сигнал передачи данных."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Устройство отключено от Ethernet."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Устройство подключено к Ethernet."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index da69b81..736445d 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"ට්රාන්ස්කෝඩින් පෙරනිමි ප්රතික්ෂේප කරන්න"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"ට්රාන්ස්කෝඩින් සබල කරන්න"</string>
<string name="transcode_default" msgid="3784803084573509491">"යෙදුම් නවීන ආකෘති සඳහා සහාය දක්වයි යැයි උපකල්පනය කරමු"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"යෙදුම් සඳහා ට්රාන්ස්කෝඩින් සබල කරන්න"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"ධාවනය වන සේවා"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"දැනට ධාවනය වන සේවා බලන්න සහ පාලනය කරන්න"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ක්රියාත්මක කිරීම"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"රැහැන්ගත කළ හෙඩ්ෆෝන්"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ක්රියාත්මකයි"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"ක්රියාවිරහිතයි"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"වාහක ජාලය වෙනස් වෙමින්"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"ජංගම දත්ත ක්රියාවිරහිතයි"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"දත්ත භාවිත කිරීමට සකසා නැත"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"දුරකථනයක් නැත."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"දුරකථනය තීරු එකයි."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"දුරකථනය තීරු දෙකයි."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"දුරකථනය තීරු තුනයි."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"දුරකථනයේ සංඥාව පිරී ඇත."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"දත්ත නැත."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"දත්ත තීරු එකයි."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"දත්ත තීරු 2."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"දත්ත තීරු 3."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"දත්ත සංඥාව පිරී ඇත."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ඊතර්නෙට් විසන්ධි කරන ලදී."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"ඊතර්නෙට් සම්බන්ධ කරන ලදී."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index b428b42..265ec8f 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Prepísať predvolené nastavenia prekódovania"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Povoliť prekódovanie"</string>
<string name="transcode_default" msgid="3784803084573509491">"Prepdokladať, že aplikácie podporujú moderné formáty"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Zapnúť prekódovanie aplikácií"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Spustené služby"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Zobrazovať a riadiť aktuálne spustené služby"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Implementácia WebView"</string>
@@ -568,4 +567,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Slúchadlá s káblom"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Zapnúť"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Vypnúť"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Mení sa sieť operátora"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobilné dáta sú vypnuté"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Nie je nastavené na používanie dát"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Žiadna telefónna sieť."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Jeden stĺpec signálu telefónnej siete."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Dve čiarky signálu telefónnej siete."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Tri čiarky signálu telefónnej siete."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Plný signál telefónnej siete."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Žiadna dátová sieť."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Jedna čiarka signálu dátovej siete."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Dve čiarky signálu dátovej siete."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Tri čiarky signálu dátovej siete."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Plný signál dátovej siete."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Sieť ethernet je odpojená"</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Sieť ethernet je pripojená"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 3ba31fa..2e6fc0e 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Preglasi privzete nastavitve prekodiranja"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Omogoči prekodiranje"</string>
<string name="transcode_default" msgid="3784803084573509491">"Aplikacije naj bi podpirale sodobne oblike zapisov"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Omogočanje prekodiranja za aplikacije"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Zagnane storitve"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Preglejte in nadzorujte storitve, ki so trenutno zagnane"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Izvedba spletnega pogleda"</string>
@@ -568,4 +567,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Žične slušalke"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Vklop"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Izklop"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Spreminjanje omrežja operaterja"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Prenos podatkov v mobilnem omrežju je izklopljen"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Ni nastavljeno za uporabo prenosa podatkov"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Ni telefona."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefon z eno črtico."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefon z dvema črticama."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefon s tremi črticami."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Signal telefona je poln."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Ni podatkov."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Podatkovni signal z eno črtico."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Podatki z dvema črticama."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Podatki s tremi črticami."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Podatkovni signal poln."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernetna povezava je prekinjena."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernetna povezava je vzpostavljena."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 15cbb74..5774d9b 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -400,13 +400,9 @@
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktiv. Trokit për ta ndryshuar."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Gjendja e gatishmërisë e aplikacionit:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
<string name="transcode_settings_title" msgid="2581975870429850549">"Cilësimet e transkodimit të multimediave"</string>
- <!-- no translation found for transcode_user_control (6176368544817731314) -->
- <skip />
- <!-- no translation found for transcode_enable_all (2411165920039166710) -->
- <skip />
- <!-- no translation found for transcode_default (3784803084573509491) -->
- <skip />
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Aktivizo transkodimin për aplikacionet"</string>
+ <string name="transcode_user_control" msgid="6176368544817731314">"Anulo parazgjedhjet e transkodimit"</string>
+ <string name="transcode_enable_all" msgid="2411165920039166710">"Aktivizo transkodimin"</string>
+ <string name="transcode_default" msgid="3784803084573509491">"Supozo se aplikacionet i mbështetin formatet moderne"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Shërbimet në ekzekutim"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Shiko dhe kontrollo shërbimet që po ekzekutohen aktualisht"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Zbatimi i WebView"</string>
@@ -569,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Kufje me tela"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Aktive"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Joaktive"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Rrjeti i operatorit celular po ndryshohet"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Të dhënat celulare janë joaktive"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Nuk është caktuar të përdorë të dhënat"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Nuk ka telefon."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefoni ka edhe një vijë."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefoni ka dy vija."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefoni ka tre vija."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Sinjali i telefonit është i plotë."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Nuk ka të dhëna."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Sinjali është vetëm një vijë."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Të dhënat kanë dy vija."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Sinjali është me tre vija."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Sinjali i të dhënave është i plotë."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Lidhja e eternetit u shkëput."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Lidhja e eternetit u lidh."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index c337182..207ca74 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Замени подразумевана подешавања транскодирања"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Омогући транскодирање"</string>
<string name="transcode_default" msgid="3784803084573509491">"Подразумевај да апликације подржавају модерне формате"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Омогућите транскодирање за апликације"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Покренуте услуге"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Приказ и контрола тренутно покренутих услуга"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Примена WebView-а"</string>
@@ -567,4 +566,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Жичане слушалице"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Укључено"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Искључено"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Промена мреже мобилног оператера"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Мобилни подаци су искључени"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Није подешено за коришћење података"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Нема телефона."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Сигнал телефона има једну црту."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Сигнал телефона од две црте."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Сигнал телефона од три црте."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Сигнал телефона је пун."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Нема података."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Сигнал за податке има једну црту."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Сигнал за податке од две црте."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Сигнал за податке од три црте."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Сигнал за податке је најјачи."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Веза са етернетом је прекинута."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Етернет је повезан."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 2bf9785..7afd344 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Åsidosätta standardinställningar för omkodning"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Aktivera omkodning"</string>
<string name="transcode_default" msgid="3784803084573509491">"Anta att appar har stöd för moderna format"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Aktivera omkodning för appar"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Aktiva tjänster"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Visa och styr aktiva tjänster"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView-implementering"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Hörlurar med sladd"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"På"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Av"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Byter leverantörsnätverk"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobildata har inaktiverats"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Inte inställd på mobildata"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Ingen telefon."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefon: en stapel."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefon: två staplar."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefon: tre staplar."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefonsignalen är full."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Inga data."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data: en stapel."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Data: två staplar."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Data: tre staplar."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Datasignalen är full."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet har kopplats från."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet har anslutits."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 610bfee..084b5c93 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Batilisha chaguomsingi za kubadilisha miundo ya faili"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Ruhusu ubadilishaji wa miundo ya faili"</string>
<string name="transcode_default" msgid="3784803084573509491">"Chukulia kuwa programu zinatumia miundo ya kisasa"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Washa ubadilishaji muundo wa faili kwenye programu"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Huduma zinazoendeshwa"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Onyesha na udhibiti huduma zinazoendeshwa kwa sasa"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Utekelezaji wa WebView"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Vipokea sauti vya waya"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Umewashwa"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Umezimwa"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Mabadiliko katika mtandao wa mtoa huduma"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Umezima data ya mtandao wa simu"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Haijawekewa mipangilio ya kutumia data"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Hakuna simu"</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Mwambaa mmoja wa simu."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Miambaa miwili ya simu"</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Miambaa mitatu ya simu."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Ishara ya simu imejaa."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Hakuna data."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Upapi mmoja wa habari"</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Miamba miwili ya data."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Fito tatu za habari."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Ishara ya data imejaa."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethaneti imeondolewa."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethaneti imeunganishwa."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 7d77967..5fdf8bd 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"இயல்புநிலை குறிமாற்றங்களை மீறிச் செயல்படு"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"குறிமாற்றத்தை இயக்கு"</string>
<string name="transcode_default" msgid="3784803084573509491">"ஆப்ஸ் மாடர்ன் வடிவங்களை ஆதரிக்கும்படி அமை"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"ஆப்ஸுக்குக் குறிமாற்றத்தை இயக்கு"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"இயங்கும் சேவைகள்"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"தற்போது இயக்கத்தில் இருக்கும் சேவைகளைப் பார்த்து கட்டுப்படுத்து"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView செயல்படுத்தல்"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"வயருள்ள ஹெட்ஃபோன்"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ஆன்"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"ஆஃப்"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"மொபைல் நிறுவன நெட்வொர்க்கை மாற்றும்"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"மொபைல் டேட்டா ஆஃப் செய்யப்பட்டது"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"தரவை உபயோகிக்க அமைக்கப்படவில்லை"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"சிக்னல் இல்லை."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"சிக்னல் ஒரு கோட்டில் உள்ளது."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"சிக்னல் இரண்டு கோட்டில் உள்ளது."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"சிக்னல் மூன்று கோட்டில் உள்ளது."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"சிக்னல் முழுமையாக உள்ளது."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"டேட்டா சிக்னல் இல்லை."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"தரவு சிக்னல் ஒரு கோட்டில் உள்ளது."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"தரவின் சிக்னல் இரண்டு கோடு வரை உள்ளது."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"தரவு சிக்னல் மூன்று கோட்டில் உள்ளது."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"தரவு சிக்னல் முழுமையாக உள்ளது."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ஈத்தர்நெட் துண்டிக்கப்பட்டது."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"ஈத்தர்நெட் இணைக்கப்பட்டது."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index f24caec..38f08b2 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -400,13 +400,9 @@
<string name="inactive_app_active_summary" msgid="8047630990208722344">"సక్రియంగా ఉంది. టోగుల్ చేయడానికి నొక్కండి."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"యాప్ స్టాండ్బై స్థితి:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
<string name="transcode_settings_title" msgid="2581975870429850549">"మీడియా ట్రాన్స్కోడింగ్ సెట్టింగ్లు"</string>
- <!-- no translation found for transcode_user_control (6176368544817731314) -->
- <skip />
- <!-- no translation found for transcode_enable_all (2411165920039166710) -->
- <skip />
- <!-- no translation found for transcode_default (3784803084573509491) -->
- <skip />
- <string name="transcode_skip_apps" msgid="8249721984597390142">"యాప్ల కోసం ట్రాన్స్కోడింగ్ను ఎనేబుల్ చేయండి"</string>
+ <string name="transcode_user_control" msgid="6176368544817731314">"ట్రాన్స్కోడింగ్ ఆటోమేటిక్ సెట్టింగ్లను ఓవర్రైడ్ చేయండి"</string>
+ <string name="transcode_enable_all" msgid="2411165920039166710">"ట్రాన్స్కోడింగ్ను ఎనేబుల్ చేయండి"</string>
+ <string name="transcode_default" msgid="3784803084573509491">"యాప్లు ఆధునిక ఫార్మాట్లకు సపోర్ట్ చేస్తాయని అనుకోండి"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"అమలులో ఉన్న సేవలు"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"ప్రస్తుతం అమలులో ఉన్న సేవలను వీక్షించండి మరియు నియంత్రించండి"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"వెబ్ వీక్షణ అమలు"</string>
@@ -569,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"వైర్ ఉన్న హెడ్ఫోన్"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"ఆన్లో ఉంది"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"ఆఫ్లో ఉంది"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"క్యారియర్ నెట్వర్క్ మారుతోంది"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"మొబైల్ డేటా ఆఫ్లో ఉంది"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"డేటాను ఉపయోగించే విధంగా సెట్ చేయలేదు"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"ఫోన్ లేదు."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"ఫోన్ ఒక బారు."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"ఫోన్ రెండు బార్లు."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"ఫోన్ మూడు బార్లు."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"ఫోన్ సిగ్నల్ పూర్తిగా ఉంది."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"డేటా లేదు."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"డేటా ఒక బారు."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"డేటా రెండు బార్లు."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"డేటా మూడు బార్లు."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"డేటా సిగ్నల్ సంపూర్ణంగా ఉంది."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ఈథర్నెట్ డిస్కనెక్ట్ చేయబడింది."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"ఈథర్నెట్ కనెక్ట్ చేయబడింది."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 2c01998..dabb9d3 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"ลบล้างค่าเริ่มต้นของการแปลง"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"เปิดใช้การแปลง"</string>
<string name="transcode_default" msgid="3784803084573509491">"ถือว่าแอปรองรับรูปแบบสมัยใหม่"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"เปิดใช้การแปลงสำหรับแอป"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"บริการที่ทำงานอยู่"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"ดูและควบคุมบริการที่ทำงานอยู่"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"การใช้งาน WebView"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"หูฟังแบบมีสาย"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"เปิด"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"ปิด"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"การเปลี่ยนเครือข่ายผู้ให้บริการ"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"เน็ตมือถือปิดอยู่"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"ไม่ได้ตั้งค่าให้ใช้อินเทอร์เน็ตมือถือ"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"ไม่มีสัญญาณโทรศัพท์"</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"สัญญาณโทรศัพท์หนึ่งขีด"</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"สัญญาณโทรศัพท์สองขีด"</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"สัญญาณโทรศัพท์สามขีด"</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"สัญญาณโทรศัพท์เต็ม"</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"ไม่มีข้อมูล"</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"สัญญาณข้อมูลหนึ่งขีด"</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"สัญญาณข้อมูลสองขีด"</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"สัญญาณข้อมูลสามขีด"</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"สัญญาณข้อมูลเต็ม"</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ยกเลิกการเชื่อมต่ออีเทอร์เน็ตแล้ว"</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"เชื่อมต่ออีเทอร์เน็ตแล้ว"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 54ba90e..b451d89 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"I-override ang mga default ng pagta-transcode"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"I-enable ang pagta-transcode"</string>
<string name="transcode_default" msgid="3784803084573509491">"Ipagpalagay na sinusuportahan ng mga app ang mga modernong format"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"I-enable ang pag-transcode para sa mga app"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Mga tumatakbong serbisyo"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Tingnan at kontrolin ang mga kasalukuyang tumatakbong serbisyo"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Pagpapatupad sa WebView"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Wired na headphone"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Naka-on"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Naka-off"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Nagpapalit ng carrier network"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Naka-off ang mobile data"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Hindi nakatakdang gumamit ng data"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Walang telepono."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telepono na isang bar."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telepono na dalawang bar."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telepono na tatlong bar."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Puno ang signal ng telepono."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Walang data."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Data na isang bar."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Data na dalawang bar."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Data na tatlong bar."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Puno ang signal ng data."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Nadiskonekta ang Ethernet."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Nakakonekta ang Ethernet."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 942834f..e1ff56b 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Kod dönüştürme varsayılanlarını geçersiz kıl"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Kod dönüştürmeyi etkinleştir"</string>
<string name="transcode_default" msgid="3784803084573509491">"Uygulamaların modern biçimleri desteklediğini varsay"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Uygulamalar için kod dönüştürmeyi etkinleştir"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Çalışan hizmetler"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Şu anda çalışan hizmetleri görüntüle ve denetle"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Web Görünümü kullanımı"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Kablolu kulaklık"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Açık"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Kapalı"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Operatör ağı değiştiriliyor"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobil veri kapalı"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Veri kullanmak üzere ayarlanmadı"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Telefon sinyali yok."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefon sinyali bir çubuk."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefon sinyali iki çubuk."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefon sinyali üç çubuk."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefon sinyali tam."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Veri yok."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Veri sinyali bir çubuk."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Veri sinyali iki çubuk."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Veri sinyali üç çubuk."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Veri sinyali tam."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet bağlantısı kesildi."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet bağlandı."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index f6063f8..6806ce6 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Замінити стандартні налаштування перекодування"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Увімкнути перекодування"</string>
<string name="transcode_default" msgid="3784803084573509491">"Вважати, що додатки підтримують сучасні формати"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Увімкнути перекодування додатків"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Запущені сервіси"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Переглянути й налаштувати запущені сервіси"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Застосування WebView"</string>
@@ -568,4 +567,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Дротові навушники"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Увімкнено"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Вимкнено"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Змінення мережі оператора"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Мобільне передавання даних вимкнено"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Не вибрано для використання даних"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Немає сигналу телефону."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Одна смужка сигналу телефону."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Дві смужки сигналу телефону."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Три смужки сигналу телефону."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Максимальний сигнал телефону."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Немає сигналу даних."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Одна смужка сигналу даних."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Дві смужки сигналу даних."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Три смужки сигналу даних."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Максимальний сигнал даних."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Ethernet відключено."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Ethernet підключено."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 5d75437..4363f0b 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -400,13 +400,9 @@
<string name="inactive_app_active_summary" msgid="8047630990208722344">"فعال۔ ٹوگل کرنے کیلئے تھپتھپائیں۔"</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"ایپ اسٹینڈ بائی کی حالت:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
<string name="transcode_settings_title" msgid="2581975870429850549">"میڈیا ٹرانسکوڈنگ کی ترتیبات"</string>
- <!-- no translation found for transcode_user_control (6176368544817731314) -->
- <skip />
- <!-- no translation found for transcode_enable_all (2411165920039166710) -->
- <skip />
- <!-- no translation found for transcode_default (3784803084573509491) -->
- <skip />
- <string name="transcode_skip_apps" msgid="8249721984597390142">"ایپس کے لئے ٹرانسکوڈنگ فعال کریں"</string>
+ <string name="transcode_user_control" msgid="6176368544817731314">"ٹرانسکوڈنگ ڈیفالٹس کو اوور رائیڈ کریں"</string>
+ <string name="transcode_enable_all" msgid="2411165920039166710">"ٹرانسکوڈنگ فعال کریں"</string>
+ <string name="transcode_default" msgid="3784803084573509491">"فرض کریں کہ ایپس جدید فارمیٹس کو سپورٹ کرتی ہیں"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"چل رہی سروسز"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"فی الحال چل رہی سروسز دیکھیں اور انہیں کنٹرول کریں"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView کا نفاذ"</string>
@@ -569,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"وائرڈ ہیڈ فون"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"آن"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"آف"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"کیریئر نیٹ ورک کی تبدیلی"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"موبائل ڈیٹا آف ہے"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"ڈیٹا استعمال کرنے کے لیے سیٹ نہیں ہے"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"کوئی فون نہیں ہے۔"</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"فون کا ایک بار۔"</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"فون کے دو بارز۔"</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"فون کے تین بارز۔"</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"فون سگنل پورا ہے۔"</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"کوئی ڈیٹا نہیں ہے۔"</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"ڈیٹا کا ایک بار۔"</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"ڈیٹا کے دو بارز۔"</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"ڈیٹا کے تین بارز۔"</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"ڈیٹا سگنل بھرا ہوا ہے۔"</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"ایتھرنیٹ منقطع ہے۔"</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"ایتھرنیٹ منسلک ہے۔"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index f1fc8dd..1eecf88 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -402,8 +402,7 @@
<string name="transcode_settings_title" msgid="2581975870429850549">"Media transkripsiyasi sozlamalari"</string>
<string name="transcode_user_control" msgid="6176368544817731314">"Transkripsiya parametrlarini almashtirish"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Transkripsiyasini yoqish"</string>
- <string name="transcode_default" msgid="3784803084573509491">"Ilovalar zamonaviy kodlash formatlarini qoʻllab-quvvatlaydi deb hisoblash"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Ilovalar uchun transkripsiyani yoqish"</string>
+ <string name="transcode_default" msgid="3784803084573509491">"Ilovalarda zamonaviy kodlash formatlari ishlaydi deb hisoblash"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Ishlab turgan ilovalar"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Ishlab turgan ilovalarni ko‘rish va boshqarish"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView ta’minotchisi"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Simli quloqlik"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Yoniq"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Oʻchiq"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Mobil tarmoqni o‘zgartirish"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Mobil internet yoqilmagan"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Maʼlumotlardan foydalanish uchun sozlanmagan"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Signal yo‘q."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Telefon bitta panelda."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Telefon ikkita panelda."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Telefon uchta panelda."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Telefon signali to‘liq."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Ma’lumotlar yo‘q."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Ma’lumotlar bitta panelda."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Ma’lumotlar ikkita panelda."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Ma’lumotlar uchta panelda."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Internet signali butun."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Qurilma Ethernet tarmog‘idan uzildi."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Qurilma Ethernet tarmog‘iga ulandi."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 910fa26..643fdb9 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Ghi đè tùy chọn chuyển mã mặc định"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Bật tính năng chuyển mã"</string>
<string name="transcode_default" msgid="3784803084573509491">"Giả định rằng các ứng dụng hỗ trợ định dạng hiện đại"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Bật tùy chọn chuyển mã cho ứng dụng"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Các dịch vụ đang chạy"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Xem và kiểm soát các dịch vụ đang chạy"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Triển khai WebView"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Tai nghe có dây"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Đang bật"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Đang tắt"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Thay đổi mạng của nhà mạng"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Đã tắt dữ liệu di động"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Chưa được đặt để sử dụng dữ liệu"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Không có điện thoại nào."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Tín hiệu điện thoại một vạch."</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Tín hiệu điện thoại hai vạch."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Tín hiệu điện thoại ba vạch."</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Tín hiệu điện thoại đầy đủ."</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Không có dữ liệu."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Tín hiệu dữ liệu một vạch."</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Tín hiệu dữ liệu hai vạch."</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Tín hiệu dữ liệu ba vạch."</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Tín hiệu dữ liệu đầy đủ."</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"Đã ngắt kết nối Ethernet."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"Đã kết nối Ethernet."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index c9ecab1..81d8106 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"覆盖转码默认设置"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"启用转码"</string>
<string name="transcode_default" msgid="3784803084573509491">"假设应用支持现代格式"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"为应用启用转码功能"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"正在运行的服务"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"查看和控制当前正在运行的服务"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView 实现"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"有线耳机"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"开启"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"关闭"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"运营商网络正在更改"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"移动数据网络已关闭"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"未设置为使用移动数据"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"没有手机信号。"</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"手机信号强度为一格。"</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"手机信号强度为两格。"</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"手机信号强度为三格。"</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"手机信号满格。"</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"没有数据网络信号。"</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"数据信号强度为一格。"</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"数据信号强度为两格。"</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"数据信号强度为三格。"</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"数据信号满格。"</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"以太网已断开连接。"</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"以太网已连接。"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 3bbfa21..39a12aa 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"覆寫轉碼預設設定"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"啟用轉碼功能"</string>
<string name="transcode_default" msgid="3784803084573509491">"假設應用程式支援新型格式"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"為應用程式啟用轉碼功能"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"執行中的服務"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"查看並控制目前正在執行中的服務"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView 設置"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"有線耳機"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"開啟"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"關閉"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"流動網絡供應商網絡正在變更"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"流動數據已關閉"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"未設定至可使用資料"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"沒有電話訊號。"</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"電話訊號強度為一格。"</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"電話訊號強度為兩格。"</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"電話訊號強度為三格。"</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"電話訊號滿格。"</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"沒有數據網絡。"</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"數據網絡訊號強度為一格。"</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"數據網絡訊號強度為兩格。"</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"數據網絡訊號強度為三格。"</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"數據網絡訊號滿格。"</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"以太網連接中斷。"</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"已連接以太網。"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index b0dbb5f..cc35ed3 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"覆寫轉碼預設設定"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"啟用轉碼"</string>
<string name="transcode_default" msgid="3784803084573509491">"假設應用程式支援新格式"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"替應用程式啟用轉碼功能"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"正在運作的服務"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"查看並管理目前正在執行的服務"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView 實作"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"有線耳機"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"開啟"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"關閉"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"電信業者網路正在進行變更"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"行動數據已關閉"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"並未設為使用行動數據"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"沒有電話訊號。"</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"電話訊號強度一格。"</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"電話訊號強度兩格。"</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"電話訊號強度三格。"</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"電話訊號滿格。"</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"沒有數據網路。"</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"數據網路訊號強度一格。"</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"數據網路訊號強度兩格。"</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"數據網路訊號強度三格。"</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"數據網路訊號滿格。"</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"未連上乙太網路。"</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"已連上乙太網路。"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 8f7c2ac..bcc6369 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -403,7 +403,6 @@
<string name="transcode_user_control" msgid="6176368544817731314">"Khipha okuzenzakalelayo kokudlulisela ikhodi"</string>
<string name="transcode_enable_all" msgid="2411165920039166710">"Nika amandla ukudlulisela ikhodi"</string>
<string name="transcode_default" msgid="3784803084573509491">"Kuthathe njengokungathi izinhlelo zokusebenza zisekela amafomethi esimanje"</string>
- <string name="transcode_skip_apps" msgid="8249721984597390142">"Nika amandla ukudlulisela ikhodi kwezinhlelo zokusebenza"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Amasevisi asebenzayo"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Buka futhi ulawule amasevisi asebenzayo okwamanje"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"Ukufakwa ke-WebView"</string>
@@ -566,4 +565,29 @@
<string name="media_transfer_wired_usb_device_name" msgid="7699141088423210903">"Ama-headphone anentambo"</string>
<string name="wifi_hotspot_switch_on_text" msgid="9212273118217786155">"Vuliwe"</string>
<string name="wifi_hotspot_switch_off_text" msgid="7245567251496959764">"Valiwe"</string>
+ <string name="carrier_network_change_mode" msgid="4257621815706644026">"Inethiwekhi yenkampani yenethiwekhi iyashintsha"</string>
+ <string name="data_connection_3g" msgid="931852552688157407">"3G"</string>
+ <string name="data_connection_edge" msgid="4625509456544797637">"I-EDGE"</string>
+ <string name="data_connection_cdma" msgid="9098161966701934334">"1X"</string>
+ <string name="data_connection_gprs" msgid="1251945769006770189">"I-GPRS"</string>
+ <string name="data_connection_3_5g" msgid="4298721462047921400">"H"</string>
+ <string name="data_connection_3_5g_plus" msgid="6683055858295918170">"H+"</string>
+ <string name="data_connection_4g" msgid="2581705503356752044">"4G"</string>
+ <string name="data_connection_4g_plus" msgid="5194902328408751020">"4G+"</string>
+ <string name="data_connection_lte" msgid="7675461204366364124">"I-LTE"</string>
+ <string name="data_connection_lte_plus" msgid="6643158654804916653">"I-LTE+"</string>
+ <string name="cell_data_off_content_description" msgid="2280700839891636498">"Idatha yeselula ivaliwe"</string>
+ <string name="not_default_data_content_description" msgid="6517068332106592887">"Akusethiwe ukuze kusetshenziswe idatha"</string>
+ <string name="accessibility_no_phone" msgid="2687419663127582503">"Ayikho ifoni."</string>
+ <string name="accessibility_phone_one_bar" msgid="5719721147018970063">"Ibha eyodwa yefoni"</string>
+ <string name="accessibility_phone_two_bars" msgid="2531458337458953263">"Amabha amabilil efoni."</string>
+ <string name="accessibility_phone_three_bars" msgid="1523967995996696619">"Amabha amathathu efoni"</string>
+ <string name="accessibility_phone_signal_full" msgid="4302338883816077134">"Isiginali yefoni igcwele"</string>
+ <string name="accessibility_no_data" msgid="4563181886936931008">"Ayikho idatha."</string>
+ <string name="accessibility_data_one_bar" msgid="6892888138070752480">"Idatha enye yebha"</string>
+ <string name="accessibility_data_two_bars" msgid="9202641507241802499">"Amabha amabili edatha"</string>
+ <string name="accessibility_data_three_bars" msgid="2813876214466722413">"Amabha amathathu edatha"</string>
+ <string name="accessibility_data_signal_full" msgid="1808301899314382337">"Igcwele i-signal yedatha"</string>
+ <string name="accessibility_ethernet_disconnected" msgid="2832501530856497489">"I-Ethernet inqanyuliwe."</string>
+ <string name="accessibility_ethernet_connected" msgid="2093872142317190618">"I-Ethernet ixhunyiwe."</string>
</resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/MediaOutputSliceConstants.java b/packages/SettingsLib/src/com/android/settingslib/media/MediaOutputSliceConstants.java
index fc16eb6..61af5a7 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/MediaOutputSliceConstants.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/MediaOutputSliceConstants.java
@@ -22,16 +22,6 @@
public class MediaOutputSliceConstants {
/**
- * Key for the Media output setting.
- */
- public static final String KEY_MEDIA_OUTPUT = "media_output";
-
- /**
- * Key for the Media output group setting.
- */
- public static final String KEY_MEDIA_OUTPUT_GROUP = "media_output_group";
-
- /**
* Key for the Remote Media slice.
*/
public static final String KEY_REMOTE_MEDIA = "remote_media";
@@ -47,19 +37,6 @@
public static final String KEY_SESSION_INFO_ID = "key_session_info_id";
/**
- * Activity Action: Show a settings dialog containing {@link MediaDevice} to transfer media.
- */
- public static final String ACTION_MEDIA_OUTPUT =
- "com.android.settings.panel.action.MEDIA_OUTPUT";
-
- /**
- * Activity Action: Show a settings dialog containing {@link MediaDevice} to handle media group
- * operation.
- */
- public static final String ACTION_MEDIA_OUTPUT_GROUP =
- "com.android.settings.panel.action.MEDIA_OUTPUT_GROUP";
-
- /**
* A string extra specifying a media package name.
*/
public static final String EXTRA_PACKAGE_NAME =
@@ -72,12 +49,6 @@
"com.android.systemui.action.LAUNCH_MEDIA_OUTPUT_DIALOG";
/**
- * An intent action to dismiss media output dialog.
- */
- public static final String ACTION_DISMISS_MEDIA_OUTPUT_DIALOG =
- "com.android.systemui.action.DISMISS_MEDIA_OUTPUT_DIALOG";
-
- /**
* Settings package name.
*/
public static final String SETTINGS_PACKAGE_NAME = "com.android.settings";
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 846efa7..6c51f2f 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -241,6 +241,12 @@
<!-- Default for setting for Settings.Global.HDMI_CONTROL_AUTO_DEVICE_OFF_ENABLED -->
<bool name="def_hdmiControlAutoDeviceOff">false</bool>
+ <!-- Default for Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED -->
+ <bool name="def_swipe_bottom_to_notification_enabled">true</bool>
+
+ <!-- Default for Settings.Secure.ONE_HANDED_MODE_ENABLED -->
+ <bool name="def_one_handed_mode_enabled">false</bool>
+
<!-- Default for Settings.Secure.ACCESSIBILITY_MAGNIFICATION_CAPABILITY -->
<integer name="def_accessibility_magnification_capabilities">3</integer>
</resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index c9e3b6f..edb5506 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -3342,7 +3342,7 @@
}
private final class UpgradeController {
- private static final int SETTINGS_VERSION = 196;
+ private static final int SETTINGS_VERSION = 197;
private final int mUserId;
@@ -4786,6 +4786,35 @@
currentVersion = 196;
}
+ if (currentVersion == 196) {
+ // Version 196: Set the default value for Secure Settings:
+ // SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED & ONE_HANDED_MODE_ENABLED
+ final SettingsState secureSettings = getSecureSettingsLocked(userId);
+ final Setting swipeNotification = secureSettings.getSettingLocked(
+ Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED);
+ if (swipeNotification.isNull()) {
+ final boolean defSwipeNotification = getContext().getResources()
+ .getBoolean(R.bool.def_swipe_bottom_to_notification_enabled);
+ secureSettings.insertSettingLocked(
+ Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED,
+ defSwipeNotification ? "1" : "0", null, true,
+ SettingsState.SYSTEM_PACKAGE_NAME);
+ }
+
+ final Setting oneHandedModeEnabled = secureSettings.getSettingLocked(
+ Secure.ONE_HANDED_MODE_ENABLED);
+ if (oneHandedModeEnabled.isNull()) {
+ final boolean defOneHandedModeEnabled = getContext().getResources()
+ .getBoolean(R.bool.def_one_handed_mode_enabled);
+ secureSettings.insertSettingLocked(
+ Secure.ONE_HANDED_MODE_ENABLED,
+ defOneHandedModeEnabled ? "1" : "0", null, true,
+ SettingsState.SYSTEM_PACKAGE_NAME);
+ }
+
+ currentVersion = 197;
+ }
+
// vXXX: Add new settings above this point.
if (currentVersion != newVersion) {
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index 40b0fcff..53d868a 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -42,6 +42,8 @@
import android.util.Slog;
import android.util.SparseIntArray;
import android.util.TimeUtils;
+import android.util.TypedXmlPullParser;
+import android.util.TypedXmlSerializer;
import android.util.Xml;
import android.util.proto.ProtoOutputStream;
@@ -52,7 +54,6 @@
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
import java.io.File;
import java.io.FileInputStream;
@@ -60,7 +61,6 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
-import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
@@ -806,13 +806,10 @@
try {
out = destination.startWrite();
- XmlSerializer serializer = Xml.newSerializer();
- serializer.setOutput(out, StandardCharsets.UTF_8.name());
- serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output",
- true);
+ TypedXmlSerializer serializer = Xml.resolveSerializer(out);
serializer.startDocument(null, true);
serializer.startTag(null, TAG_SETTINGS);
- serializer.attribute(null, ATTR_VERSION, String.valueOf(version));
+ serializer.attributeInt(null, ATTR_VERSION, version);
final int settingCount = settings.size();
for (int i = 0; i < settingCount; i++) {
@@ -908,7 +905,7 @@
}
}
- static void writeSingleSetting(int version, XmlSerializer serializer, String id,
+ static void writeSingleSetting(int version, TypedXmlSerializer serializer, String id,
String name, String value, String defaultValue, String packageName,
String tag, boolean defaultSysSet, boolean isValuePreservedInRestore)
throws IOException {
@@ -926,18 +923,18 @@
if (defaultValue != null) {
setValueAttribute(ATTR_DEFAULT_VALUE, ATTR_DEFAULT_VALUE_BASE64,
version, serializer, defaultValue);
- serializer.attribute(null, ATTR_DEFAULT_SYS_SET, Boolean.toString(defaultSysSet));
+ serializer.attributeBoolean(null, ATTR_DEFAULT_SYS_SET, defaultSysSet);
setValueAttribute(ATTR_TAG, ATTR_TAG_BASE64,
version, serializer, tag);
}
if (isValuePreservedInRestore) {
- serializer.attribute(null, ATTR_PRESERVE_IN_RESTORE, Boolean.toString(true));
+ serializer.attributeBoolean(null, ATTR_PRESERVE_IN_RESTORE, true);
}
serializer.endTag(null, TAG_SETTING);
}
static void setValueAttribute(String attr, String attrBase64, int version,
- XmlSerializer serializer, String value) throws IOException {
+ TypedXmlSerializer serializer, String value) throws IOException {
if (version >= SETTINGS_VERSION_NEW_ENCODING) {
if (value == null) {
// Null value -> No ATTR_VALUE nor ATTR_VALUE_BASE64.
@@ -956,7 +953,7 @@
}
}
- private static void writeSingleNamespaceHash(XmlSerializer serializer, String namespace,
+ private static void writeSingleNamespaceHash(TypedXmlSerializer serializer, String namespace,
String bannedHashCode) throws IOException {
if (namespace == null || bannedHashCode == null) {
return;
@@ -971,7 +968,7 @@
return Integer.toString(keyValues.hashCode());
}
- private String getValueAttribute(XmlPullParser parser, String attr, String base64Attr) {
+ private String getValueAttribute(TypedXmlPullParser parser, String attr, String base64Attr) {
if (mVersion >= SETTINGS_VERSION_NEW_ENCODING) {
final String value = parser.getAttributeValue(null, attr);
if (value != null) {
@@ -1039,8 +1036,7 @@
@GuardedBy("mLock")
private boolean parseStateFromXmlStreamLocked(FileInputStream in) {
try {
- XmlPullParser parser = Xml.newPullParser();
- parser.setInput(in, StandardCharsets.UTF_8.name());
+ TypedXmlPullParser parser = Xml.resolvePullParser(in);
parseStateLocked(parser);
return true;
} catch (XmlPullParserException | IOException e) {
@@ -1060,7 +1056,7 @@
return stateFile.exists();
}
- private void parseStateLocked(XmlPullParser parser)
+ private void parseStateLocked(TypedXmlPullParser parser)
throws IOException, XmlPullParserException {
final int outerDepth = parser.getDepth();
int type;
@@ -1080,10 +1076,10 @@
}
@GuardedBy("mLock")
- private void parseSettingsLocked(XmlPullParser parser)
+ private void parseSettingsLocked(TypedXmlPullParser parser)
throws IOException, XmlPullParserException {
- mVersion = Integer.parseInt(parser.getAttributeValue(null, ATTR_VERSION));
+ mVersion = parser.getAttributeInt(null, ATTR_VERSION);
final int outerDepth = parser.getDepth();
int type;
@@ -1101,14 +1097,12 @@
String packageName = parser.getAttributeValue(null, ATTR_PACKAGE);
String defaultValue = getValueAttribute(parser, ATTR_DEFAULT_VALUE,
ATTR_DEFAULT_VALUE_BASE64);
- String isPreservedInRestoreString = parser.getAttributeValue(null,
- ATTR_PRESERVE_IN_RESTORE);
- boolean isPreservedInRestore = Boolean.parseBoolean(isPreservedInRestoreString);
+ boolean isPreservedInRestore = parser.getAttributeBoolean(null,
+ ATTR_PRESERVE_IN_RESTORE, false);
String tag = null;
boolean fromSystem = false;
if (defaultValue != null) {
- fromSystem = Boolean.parseBoolean(parser.getAttributeValue(
- null, ATTR_DEFAULT_SYS_SET));
+ fromSystem = parser.getAttributeBoolean(null, ATTR_DEFAULT_SYS_SET, false);
tag = getValueAttribute(parser, ATTR_TAG, ATTR_TAG_BASE64);
}
mSettings.put(name, new Setting(name, value, defaultValue, packageName, tag,
@@ -1122,7 +1116,7 @@
}
@GuardedBy("mLock")
- private void parseNamespaceHash(XmlPullParser parser)
+ private void parseNamespaceHash(TypedXmlPullParser parser)
throws IOException, XmlPullParserException {
final int outerDepth = parser.getDepth();
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsStateTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsStateTest.java
index 9f448af..69eb713 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsStateTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsStateTest.java
@@ -17,15 +17,13 @@
import android.os.Looper;
import android.test.AndroidTestCase;
+import android.util.TypedXmlSerializer;
import android.util.Xml;
-import org.xmlpull.v1.XmlSerializer;
-
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintStream;
-import java.nio.charset.StandardCharsets;
public class SettingsStateTest extends AndroidTestCase {
public static final String CRAZY_STRING =
@@ -93,9 +91,7 @@
public void testWriteReadNoCrash() throws Exception {
ByteArrayOutputStream os = new ByteArrayOutputStream();
- XmlSerializer serializer = Xml.newSerializer();
- serializer.setOutput(os, StandardCharsets.UTF_8.name());
- serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
+ TypedXmlSerializer serializer = Xml.resolveSerializer(os);
serializer.startDocument(null, true);
for (int ch = 0; ch < 0x10000; ch++) {
@@ -118,12 +114,12 @@
serializer, "1", "k", "v", null, null, null, false, false);
}
- private void checkWriteSingleSetting(XmlSerializer serializer, String key, String value)
+ private void checkWriteSingleSetting(TypedXmlSerializer serializer, String key, String value)
throws Exception {
checkWriteSingleSetting(key + "/" + value, serializer, key, value);
}
- private void checkWriteSingleSetting(String msg, XmlSerializer serializer,
+ private void checkWriteSingleSetting(String msg, TypedXmlSerializer serializer,
String key, String value) throws Exception {
// Make sure the XML serializer won't crash.
SettingsState.writeSingleSetting(
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 411a78a..7ea9686 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -368,6 +368,9 @@
<!-- Permission required for CTS test - HideOverlayWindowsTest -->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
+ <!-- Permission required for CTS test - CtsHdmiCecHostTestCases -->
+ <uses-permission android:name="android.permission.HDMI_CEC" />
+
<application android:label="@string/app_label"
android:theme="@android:style/Theme.DeviceDefault.DayNight"
android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index d50f08d..a2608a0 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -380,6 +380,11 @@
public void onFinished() {
mInfo.renameBugreportFile();
mInfo.renameScreenshots();
+ if (mInfo.bugreportFile.length() == 0) {
+ Log.e(TAG, "Bugreport file empty. File path = " + mInfo.bugreportFile);
+ onError(BUGREPORT_ERROR_RUNTIME);
+ return;
+ }
synchronized (mLock) {
sendBugreportFinishedBroadcastLocked();
mMainThreadHandler.post(() -> mInfoDialog.onBugreportFinished(mInfo));
@@ -408,10 +413,6 @@
@GuardedBy("mLock")
private void sendBugreportFinishedBroadcastLocked() {
final String bugreportFilePath = mInfo.bugreportFile.getAbsolutePath();
- if (mInfo.bugreportFile.length() == 0) {
- Log.e(TAG, "Bugreport file empty. File path = " + bugreportFilePath);
- return;
- }
if (mInfo.type == BugreportParams.BUGREPORT_MODE_REMOTE) {
sendRemoteBugreportFinishedBroadcast(mContext, bugreportFilePath,
mInfo.bugreportFile);
@@ -617,12 +618,21 @@
BugreportInfo info = new BugreportInfo(mContext, baseName, name,
shareTitle, shareDescription, bugreportType, mBugreportsDir);
+ synchronized (mLock) {
+ if (info.bugreportFile.exists()) {
+ Log.e(TAG, "Failed to start bugreport generation, the requested bugreport file "
+ + info.bugreportFile + " already exists");
+ return;
+ }
+ info.createBugreportFile();
+ }
ParcelFileDescriptor bugreportFd = info.getBugreportFd();
if (bugreportFd == null) {
Log.e(TAG, "Failed to start bugreport generation as "
+ " bugreport parcel file descriptor is null.");
return;
}
+ info.createScreenshotFile(mBugreportsDir);
ParcelFileDescriptor screenshotFd = null;
if (isDefaultScreenshotRequired(bugreportType, /* hasScreenshotButton= */ !mIsTv)) {
screenshotFd = info.getDefaultScreenshotFd();
@@ -1919,12 +1929,10 @@
this.shareDescription = shareDescription == null ? "" : shareDescription;
this.type = type;
this.baseName = baseName;
- createBugreportFile(bugreportsDir);
- createScreenshotFile(bugreportsDir);
+ this.bugreportFile = new File(bugreportsDir, getFileName(this, ".zip"));
}
- void createBugreportFile(File bugreportsDir) {
- bugreportFile = new File(bugreportsDir, getFileName(this, ".zip"));
+ void createBugreportFile() {
createReadWriteFile(bugreportFile);
}
diff --git a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
index 3b02e3b..9476912 100644
--- a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
+++ b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
@@ -40,6 +40,7 @@
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.app.ActivityManager;
@@ -513,6 +514,17 @@
}
@Test
+ public void testBugreportFinished_withEmptyBugreportFile() throws Exception {
+ sendBugreportStarted();
+
+ IoUtils.closeQuietly(mBugreportFd);
+ mBugreportFd = null;
+ sendBugreportFinished();
+
+ assertServiceNotRunning();
+ }
+
+ @Test
public void testShareBugreportAfterServiceDies() throws Exception {
sendBugreportStarted();
waitForScreenshotButtonEnabled(true);
@@ -523,6 +535,18 @@
assertActionSendMultiple(extras);
}
+ @Test
+ public void testBugreportRequestTwice_oneStartBugreportInvoked() throws Exception {
+ sendBugreportStarted();
+ new BugreportRequestedReceiver().onReceive(mContext,
+ new Intent(INTENT_BUGREPORT_REQUESTED));
+ getInstrumentation().waitForIdleSync();
+
+ verify(mMockIDumpstate, times(1)).startBugreport(anyInt(), any(), any(), any(),
+ anyInt(), any(), anyBoolean());
+ sendBugreportFinished();
+ }
+
private void cancelExistingNotifications() {
// Must kill service first, because notifications from a foreground service cannot be
// canceled.
@@ -576,9 +600,10 @@
*/
private void sendBugreportStarted() throws Exception {
Intent intent = new Intent(INTENT_BUGREPORT_REQUESTED);
- intent.setPackage("com.android.shell");
- intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
- mContext.sendBroadcast(intent);
+ // Ideally, we should invoke BugreportRequestedReceiver by sending
+ // INTENT_BUGREPORT_REQUESTED. But the intent has been protected broadcast by the system
+ // starting from S.
+ new BugreportRequestedReceiver().onReceive(mContext, intent);
ArgumentCaptor<IDumpstateListener> listenerCap = ArgumentCaptor.forClass(
IDumpstateListener.class);
@@ -646,7 +671,9 @@
* Callbacks to service to finish the bugreport.
*/
private void sendBugreportFinished() throws Exception {
- writeZipFile(mBugreportFd, BUGREPORT_FILE, BUGREPORT_CONTENT);
+ if (mBugreportFd != null) {
+ writeZipFile(mBugreportFd, BUGREPORT_FILE, BUGREPORT_CONTENT);
+ }
if (mScreenshotFd != null) {
writeScreenshotFile(mScreenshotFd, SCREENSHOT_CONTENT);
}
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 2ea0c22..fda1e36 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -74,6 +74,7 @@
"androidx.lifecycle_lifecycle-extensions",
"androidx.dynamicanimation_dynamicanimation",
"androidx-constraintlayout_constraintlayout",
+ "androidx.exifinterface_exifinterface",
"kotlinx-coroutines-android",
"kotlinx-coroutines-core",
"iconloader_base",
@@ -140,6 +141,7 @@
"androidx.lifecycle_lifecycle-extensions",
"androidx.dynamicanimation_dynamicanimation",
"androidx-constraintlayout_constraintlayout",
+ "androidx.exifinterface_exifinterface",
"kotlinx-coroutines-android",
"kotlinx-coroutines-core",
"iconloader_base",
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 3fb5a9c..070c021 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -570,15 +570,10 @@
<!-- People Space UI Screen -->
<activity android:name=".people.PeopleSpaceActivity"
android:label="People"
- android:icon="@drawable/ic_music_note"
android:exported="true"
- android:enabled="false"
- android:theme="@android:style/Theme.Material.NoActionBar"
- android:launchMode="singleInstance">
+ android:theme="@android:style/Theme.Material.NoActionBar">
<intent-filter>
- <action android:name="android.intent.action.MAIN"/>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
- <category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
diff --git a/packages/SystemUI/res/drawable/ic_fingerprint.xml b/packages/SystemUI/res/drawable/ic_fingerprint.xml
new file mode 100644
index 0000000..e5f3360
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_fingerprint.xml
@@ -0,0 +1,59 @@
+<!--
+ 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="32dp"
+ android:height="32dp"
+ android:tint="?attr/wallpaperTextColor"
+ android:alpha=".75"
+ android:viewportHeight="32.0"
+ android:viewportWidth="32.0">
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M23.7,5.9c-0.1,0.0 -0.2,0.0 -0.3,-0.1C21.0,4.5 18.6,3.9 16.0,3.9c-2.5,0.0
+ -4.6,0.6 -6.9,1.9C8.8,6.0 8.3,5.9 8.1,5.5C7.9,5.2 8.0,4.7 8.4,4.5c2.5,-1.4 4.9,-2.1 7.7,
+ -2.1c2.8,0.0 5.4,0.7 8.0,2.1c0.4,0.2 0.5,0.6 0.3,1.0C24.2,5.7 24.0,5.9 23.7,5.9z" />
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M5.3,13.2c-0.1,0.0 -0.3,0.0 -0.4,-0.1c-0.3,-0.2 -0.4,-0.7 -0.2,-1.0c1.3,
+ -1.9 2.9,-3.4 4.9,-4.5c4.1,-2.2 9.3,-2.2 13.4,0.0c1.9,1.1 3.6,2.5 4.9,4.4c0.2,0.3 0.1,0.8
+ -0.2,1.0c-0.3,0.2 -0.8,0.1 -1.0,-0.2c-1.2,-1.7 -2.6,-3.0 -4.3,-4.0c-3.7,-2.0 -8.3,-2.0
+ -12.0,0.0c-1.7,0.9 -3.2,2.3 -4.3,4.0C5.7,13.1 5.5,13.2 5.3,13.2z" />
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M13.3,29.6c-0.2,0.0 -0.4,-0.1 -0.5,-0.2c-1.1,-1.2 -1.7,-2.0 -2.6,
+ -3.6c-0.9,-1.7 -1.4,-3.7 -1.4,-5.9c0.0,-4.1 3.3,-7.4 7.4,-7.4c4.1,0.0 7.4,3.3 7.4,7.4c0.0,
+ 0.4 -0.3,0.7 -0.7,0.7s-0.7,-0.3 -0.7,-0.7c0.0,-3.3 -2.7,-5.9 -5.9,-5.9c-3.3,0.0 -5.9,
+ 2.7 -5.9,5.9c0.0,2.0 0.4,3.8 1.2,5.2c0.8,1.6 1.4,2.2 2.4,3.3c0.3,0.3 0.3,0.8 0.0,1.0
+ C13.7,29.5 13.5,29.6 13.3,29.6z" />
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M22.6,27.1c-1.6,0.0 -2.9,-0.4 -4.1,-1.2c-1.9,-1.4 -3.1,-3.6 -3.1,
+ -6.0c0.0,-0.4 0.3,-0.7 0.7,-0.7s0.7,0.3 0.7,0.7c0.0,1.9 0.9,3.7 2.5,4.8c0.9,0.6 1.9,
+ 1.0 3.2,1.0c0.3,0.0 0.8,0.0 1.3,-0.1c0.4,-0.1 0.8,0.2 0.8,0.6c0.1,0.4 -0.2,0.8 -0.6,
+ 0.8C23.4,27.1 22.8,27.1 22.6,27.1z" />
+ <path
+ android:fillColor="#ffffff"
+ android:pathData="M20.0,29.9c-0.1,0.0 -0.1,0.0 -0.2,0.0c-2.1,-0.6 -3.4,-1.4 -4.8,-2.9c-1.8,
+ -1.9 -2.8,-4.4 -2.8,-7.1c0.0,-2.2 1.8,-4.1 4.1,-4.1c2.2,0.0 4.1,1.8 4.1,4.1c0.0,1.4 1.2,
+ 2.6 2.6,2.6c1.4,0.0 2.6,-1.2 2.6,-2.6c0.0,-5.1 -4.2,-9.3 -9.3,-9.3c-3.6,0.0 -6.9,2.1 -8.4,
+ 5.4C7.3,17.1 7.0,18.4 7.0,19.8c0.0,1.1 0.1,2.7 0.9,4.9c0.1,0.4 -0.1,0.8 -0.4,0.9c-0.4,
+ 0.1 -0.8,-0.1 -0.9,-0.4c-0.6,-1.8 -0.9,-3.6 -0.9,-5.4c0.0,-1.6 0.3,-3.1 0.9,-4.4c1.7,
+ -3.8 5.6,-6.3 9.8,-6.3c5.9,0.0 10.7,4.8 10.7,10.7c0.0,2.2 -1.8,4.1 -4.1,4.1s-4.0,
+ -1.8 -4.0,-4.1c0.0,-1.4 -1.2,-2.6 -2.6,-2.6c-1.4,0.0 -2.6,1.2 -2.6,2.6c0.0,2.3 0.9,
+ 4.5 2.4,6.1c1.2,1.3 2.4,2.0 4.2,2.5c0.4,0.1 0.6,0.5 0.5,0.9C20.6,29.7 20.3,29.9 20.0,
+ 29.9z" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_tune_black_16dp.xml b/packages/SystemUI/res/drawable/ic_tune_black_16dp.xml
index 339cb70..c41d102 100644
--- a/packages/SystemUI/res/drawable/ic_tune_black_16dp.xml
+++ b/packages/SystemUI/res/drawable/ic_tune_black_16dp.xml
@@ -18,7 +18,8 @@
android:width="16dp"
android:height="16dp"
android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/textColorPrimary">
<path
android:fillColor="#FF000000"
android:pathData="M3,17v2h6v-2L3,17zM3,5v2h10L13,5L3,5zM13,21v-2h8v-2h-8v-2h-2v6h2zM7,9v2L3,11v2h4v2h2L9,9L7,9zM21,13v-2L11,11v2h10zM15,9h2L17,7h4L21,5h-4L17,3h-2v6z"/>
diff --git a/packages/SystemUI/res/drawable/ic_volume_accessibility.xml b/packages/SystemUI/res/drawable/ic_volume_accessibility.xml
index 71376d5..c6d133a 100644
--- a/packages/SystemUI/res/drawable/ic_volume_accessibility.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_accessibility.xml
@@ -19,7 +19,7 @@
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
- android:tint="?android:attr/colorControlNormal">
+ android:tint="?android:attr/textColorPrimary">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M20.5,6c-2.61,0.7 -5.67,1 -8.5,1s-5.89,-0.3 -8.5,-1L3,8c1.86,0.5 4,0.83 6,1v13h2v-6h2v6h2V9c2,-0.17 4.14,-0.5 6,-1l-0.5,-2zM12,6c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2z"/>
diff --git a/packages/SystemUI/res/drawable/ic_volume_alarm.xml b/packages/SystemUI/res/drawable/ic_volume_alarm.xml
index 771b466..6fc2f20 100644
--- a/packages/SystemUI/res/drawable/ic_volume_alarm.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_alarm.xml
@@ -17,7 +17,8 @@
android:height="24dp"
android:width="24dp"
android:viewportHeight="24"
- android:viewportWidth="24">
+ android:viewportWidth="24"
+ android:tint="?android:attr/textColorPrimary">
<path
android:fillColor="#FFFFFF"
android:pathData="M13,8h-2v5.41l3.79,3.8 1.42,-1.42 -3.21,-3.2zM12,4c-4.97,0 -9,4.03 -9,9s4.03,9 9,9 9,-4.03 9,-9 -4.03,-9 -9,-9zM12,20c-3.86,0 -7,-3.14 -7,-7s3.14,-7 7,-7 7,3.14 7,7 -3.14,7 -7,7zM16.056,3.346l1.282,-1.535 4.607,3.85 -1.28,1.54zM2.056,5.654L6.663,1.81l1.28,1.536L3.338,7.19z"/>
diff --git a/packages/SystemUI/res/drawable/ic_volume_alarm_mute.xml b/packages/SystemUI/res/drawable/ic_volume_alarm_mute.xml
index 18e2736..730c26f 100644
--- a/packages/SystemUI/res/drawable/ic_volume_alarm_mute.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_alarm_mute.xml
@@ -18,7 +18,7 @@
android:viewportHeight="24.0"
android:viewportWidth="24.0"
android:width="24.0dp"
- android:tint="?android:attr/colorControlNormal" >
+ android:tint="?android:attr/textColorPrimary" >
<path
android:fillColor="#FFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_volume_bt_sco.xml b/packages/SystemUI/res/drawable/ic_volume_bt_sco.xml
index b0b9404..9ed77fe 100644
--- a/packages/SystemUI/res/drawable/ic_volume_bt_sco.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_bt_sco.xml
@@ -18,7 +18,7 @@
android:viewportHeight="24.0"
android:viewportWidth="24.0"
android:width="24.0dp"
- android:tint="?android:attr/colorControlNormal" >
+ android:tint="?android:attr/textColorPrimary" >
<path
android:fillColor="#FFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_volume_media.xml b/packages/SystemUI/res/drawable/ic_volume_media.xml
index 99be7b6..bffb5a4 100644
--- a/packages/SystemUI/res/drawable/ic_volume_media.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_media.xml
@@ -18,7 +18,7 @@
android:viewportHeight="24.0"
android:viewportWidth="24.0"
android:width="24.0dp"
- android:tint="?android:attr/colorControlNormal" >
+ android:tint="?android:attr/textColorPrimary" >
<path
android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_volume_media_bt.xml b/packages/SystemUI/res/drawable/ic_volume_media_bt.xml
index 23cb206..ea467c6 100644
--- a/packages/SystemUI/res/drawable/ic_volume_media_bt.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_media_bt.xml
@@ -18,7 +18,7 @@
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
- android:tint="?android:attr/colorControlNormal">
+ android:tint="?android:attr/textColorPrimary">
<path
android:fillColor="@android:color/white"
android:pathData="M9 3l0.01 10.55c-0.6-0.34-1.28-0.55-2-0.55C4.79 13 3 14.79 3 17s1.79 4 4.01 4S11 19.21 11 17V7h4V3H9zm12 9.43L17.57 9h-0.6v4.55l-2.75-2.75-0.85 0.85 L16.73 15l-3.35 3.35 0.85 0.85 2.75-2.75V21h0.6L21 17.57 18.42 15 21 12.43zm-2.83-1.13l1.13 1.13-1.13 1.13V11.3zm1.13 6.27l-1.13 1.13v-2.26l1.13 1.13z" />
diff --git a/packages/SystemUI/res/drawable/ic_volume_media_bt_mute.xml b/packages/SystemUI/res/drawable/ic_volume_media_bt_mute.xml
index 2469ddc..f01e49f 100644
--- a/packages/SystemUI/res/drawable/ic_volume_media_bt_mute.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_media_bt_mute.xml
@@ -18,7 +18,7 @@
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
- android:tint="?android:attr/colorControlNormal">
+ android:tint="?android:attr/textColorPrimary">
<path
android:fillColor="@android:color/white"
android:pathData="M9 6.17V3h6v4h-4v1.17l-2-2zM19.42 15L22 17.57l-0.8 0.8 -6.78-6.78 0.8 -0.8 2.75 2.75V9h0.6L22 12.43 19.42 15zm-0.25-1.45l1.13-1.13-1.13-1.13v2.26zm-1.96 3.66l3.98 3.98-1.41 1.41-3.98-3.98-0.58 0.58 -0.85-0.85 0.58 -0.58L11 13.83V17c0 2.21-1.78 4-3.99 4S3 19.21 3 17s1.79-4 4.01-4c0.73 0 1.41 0.21 2 0.55v-1.72L1.39 4.22 2.8 2.81l13.56 13.56 0.85 0.84z" />
diff --git a/packages/SystemUI/res/drawable/ic_volume_media_mute.xml b/packages/SystemUI/res/drawable/ic_volume_media_mute.xml
index 3a495963..63dfe8f 100644
--- a/packages/SystemUI/res/drawable/ic_volume_media_mute.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_media_mute.xml
@@ -18,7 +18,7 @@
android:viewportHeight="24.0"
android:viewportWidth="24.0"
android:width="24.0dp"
- android:tint="?android:attr/colorControlNormal" >
+ android:tint="?android:attr/textColorPrimary" >
<path
android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_volume_odi_captions.xml b/packages/SystemUI/res/drawable/ic_volume_odi_captions.xml
index 719b702..946c137 100644
--- a/packages/SystemUI/res/drawable/ic_volume_odi_captions.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_odi_captions.xml
@@ -17,7 +17,8 @@
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
- android:viewportHeight="24">
+ android:viewportHeight="24"
+ android:tint="?android:attr/textColorPrimary">
<path
android:fillColor="#FF000000"
android:pathData="M20,4L4,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2zM20,18L4,18L4,6h16v12zM6,10h2v2L6,12zM6,14h8v2L6,16zM16,14h2v2h-2zM10,10h8v2h-8z"/>
diff --git a/packages/SystemUI/res/drawable/ic_volume_odi_captions_disabled.xml b/packages/SystemUI/res/drawable/ic_volume_odi_captions_disabled.xml
index 953d4fe..5af38e4 100644
--- a/packages/SystemUI/res/drawable/ic_volume_odi_captions_disabled.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_odi_captions_disabled.xml
@@ -17,7 +17,8 @@
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
- android:viewportHeight="24">
+ android:viewportHeight="24"
+ android:tint="?android:attr/textColorPrimary">
<path
android:fillColor="#FF000000"
android:pathData="M18,10l-5.18,0l2,2l3.18,0z"/>
diff --git a/packages/SystemUI/res/drawable/ic_volume_ringer.xml b/packages/SystemUI/res/drawable/ic_volume_ringer.xml
index 42eb7b7..998344f 100644
--- a/packages/SystemUI/res/drawable/ic_volume_ringer.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_ringer.xml
@@ -18,7 +18,7 @@
android:width="24dp"
android:viewportHeight="24"
android:viewportWidth="24"
- android:tint="?android:attr/colorControlNormal" >
+ android:tint="?android:attr/textColorPrimary" >
<path
android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_volume_ringer_mute.xml b/packages/SystemUI/res/drawable/ic_volume_ringer_mute.xml
index 9cb7ca3..064e239 100644
--- a/packages/SystemUI/res/drawable/ic_volume_ringer_mute.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_ringer_mute.xml
@@ -18,7 +18,7 @@
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp"
- android:tint="?android:attr/colorControlNormal" >
+ android:tint="?android:attr/textColorPrimary" >
<path
android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_volume_ringer_vibrate.xml b/packages/SystemUI/res/drawable/ic_volume_ringer_vibrate.xml
index 314e06c..b18e0a7 100644
--- a/packages/SystemUI/res/drawable/ic_volume_ringer_vibrate.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_ringer_vibrate.xml
@@ -17,7 +17,8 @@
android:height="19dp"
android:width="19dp"
android:viewportHeight="24.0"
- android:viewportWidth="24.0">
+ android:viewportWidth="24.0"
+ android:tint="?android:attr/textColorPrimary">
<path
android:fillColor="#FFFFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_volume_system.xml b/packages/SystemUI/res/drawable/ic_volume_system.xml
index 71eed34..ad3d881 100644
--- a/packages/SystemUI/res/drawable/ic_volume_system.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_system.xml
@@ -18,7 +18,7 @@
android:viewportHeight="24.0"
android:viewportWidth="24.0"
android:width="24.0dp"
- android:tint="?android:attr/colorControlNormal" >
+ android:tint="?android:attr/textColorPrimary" >
<path
android:fillColor="#FFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_volume_system_mute.xml b/packages/SystemUI/res/drawable/ic_volume_system_mute.xml
index baad92a..c68f587 100644
--- a/packages/SystemUI/res/drawable/ic_volume_system_mute.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_system_mute.xml
@@ -18,7 +18,7 @@
android:viewportHeight="24.0"
android:viewportWidth="24.0"
android:width="24.0dp"
- android:tint="?android:attr/colorControlNormal" >
+ android:tint="?android:attr/textColorPrimary" >
<path
android:fillColor="#FFFFFF"
diff --git a/packages/SystemUI/res/drawable/ic_volume_voice.xml b/packages/SystemUI/res/drawable/ic_volume_voice.xml
index 7dc3dac..3e7748a 100644
--- a/packages/SystemUI/res/drawable/ic_volume_voice.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_voice.xml
@@ -18,7 +18,7 @@
android:viewportHeight="48.0"
android:viewportWidth="48.0"
android:width="24.0dp"
- android:tint="?android:attr/colorControlNormal" >
+ android:tint="?android:attr/textColorPrimary" >
<path
android:fillColor="#FFFFFF"
diff --git a/packages/SystemUI/res/layout/people_space_small_avatar_tile.xml b/packages/SystemUI/res/layout/people_space_small_avatar_tile.xml
index 085e955..5aa0533 100644
--- a/packages/SystemUI/res/layout/people_space_small_avatar_tile.xml
+++ b/packages/SystemUI/res/layout/people_space_small_avatar_tile.xml
@@ -18,89 +18,177 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
- <LinearLayout
+ <RelativeLayout
android:background="@drawable/people_space_tile_view_card"
- android:id="@+id/item"
- android:orientation="vertical"
- android:paddingTop="6dp"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:orientation="horizontal"
- android:paddingHorizontal="12dp"
- android:paddingBottom="4dp"
- android:gravity="top"
android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
- <ImageView
- android:id="@+id/person_icon"
- android:layout_width="34dp"
- android:layout_height="34dp" />
-
+ android:layout_height="match_parent"
+ android:gravity="start">
+ <TextView
+ android:id="@+id/punctuation1"
+ android:textColor="?android:attr/textColorSecondary"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textSize="36sp"
+ android:textStyle="bold"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="5dp"
+ android:maxLines="1"
+ android:alpha="0.2"
+ android:rotation="350" />
+ <TextView
+ android:id="@+id/punctuation2"
+ android:textColor="?android:attr/textColorSecondary"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textSize="36sp"
+ android:textStyle="bold"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="25dp"
+ android:maxLines="1"
+ android:alpha="0.2"
+ android:rotation="5" />
+ <TextView
+ android:id="@+id/punctuation3"
+ android:textColor="?android:attr/textColorSecondary"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textSize="36sp"
+ android:textStyle="bold"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="5dp"
+ android:layout_marginStart="25dp"
+ android:maxLines="1"
+ android:alpha="0.2"
+ android:rotation="355"/>
+ <TextView
+ android:id="@+id/punctuation4"
+ android:textColor="?android:attr/textColorSecondary"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textSize="36sp"
+ android:textStyle="bold"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="-5dp"
+ android:layout_marginStart="25dp"
+ android:maxLines="1"
+ android:alpha="0.2"
+ android:rotation="10" />
+ <TextView
+ android:id="@+id/punctuation5"
+ android:textColor="?android:attr/textColorSecondary"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textSize="36sp"
+ android:textStyle="bold"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="5dp"
+ android:layout_marginStart="25dp"
+ android:maxLines="1"
+ android:alpha="0.2"
+ android:rotation="15" />
+ <TextView
+ android:id="@+id/punctuation6"
+ android:textColor="?android:attr/textColorSecondary"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textSize="36sp"
+ android:textStyle="bold"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="-5dp"
+ android:layout_marginStart="25dp"
+ android:maxLines="1"
+ android:alpha="0.2"
+ android:rotation="345" />
+ </LinearLayout>
+ <LinearLayout
+ android:id="@+id/item"
+ android:orientation="vertical"
+ android:paddingTop="6dp"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
<LinearLayout
- android:background="@drawable/people_space_rounded_border"
- android:layout_marginStart="-5dp"
- android:layout_marginTop="18dp"
- android:layout_width="8dp"
- android:layout_height="8dp">
-
- <ImageView
- android:id="@+id/package_icon"
- android:layout_width="6dp"
- android:layout_marginEnd="1dp"
- android:layout_marginStart="1dp"
- android:layout_marginBottom="1dp"
- android:layout_marginTop="1dp"
- android:layout_height="6dp" />
- </LinearLayout>
-
- <LinearLayout
- android:orientation="vertical"
- android:paddingStart="6dp"
+ android:orientation="horizontal"
+ android:paddingHorizontal="12dp"
+ android:paddingBottom="4dp"
+ android:gravity="top"
android:layout_width="match_parent"
android:layout_height="wrap_content">
- <TextView
- android:id="@+id/name"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
- android:textColor="?android:attr/textColorPrimary"
- android:textSize="14sp"
- android:maxLines="1"
- android:ellipsize="end"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
+ <ImageView
+ android:id="@+id/person_icon"
+ android:layout_width="34dp"
+ android:layout_height="34dp" />
+ <LinearLayout
+ android:background="@drawable/people_space_rounded_border"
+ android:layout_marginStart="-5dp"
+ android:layout_marginTop="18dp"
+ android:layout_width="8dp"
+ android:layout_height="8dp">
+
+ <ImageView
+ android:id="@+id/package_icon"
+ android:layout_width="6dp"
+ android:layout_marginEnd="1dp"
+ android:layout_marginStart="1dp"
+ android:layout_marginBottom="1dp"
+ android:layout_marginTop="1dp"
+ android:layout_height="6dp" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:paddingStart="6dp"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:id="@+id/name"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textColor="?android:attr/textColorPrimary"
+ android:textSize="14sp"
+ android:maxLines="1"
+ android:ellipsize="end"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <TextView
+ android:id="@+id/time"
+ android:textColor="?android:attr/textColorSecondary"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
+ android:textSize="10sp"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:maxLines="1"
+ android:ellipsize="end" />
+ </LinearLayout>
+ </LinearLayout>
+ <LinearLayout
+ android:background="@drawable/people_space_content_background"
+ android:layout_gravity="center"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
<TextView
- android:id="@+id/time"
- android:textColor="?android:attr/textColorSecondary"
+ android:id="@+id/content"
+ android:paddingVertical="3dp"
+ android:paddingHorizontal="12dp"
+ android:gravity="center"
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
- android:textSize="10sp"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:maxLines="1"
+ android:textSize="16sp"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:maxLines="2"
android:ellipsize="end" />
+ <ImageView
+ android:id="@+id/image"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:visibility="gone"/>
</LinearLayout>
</LinearLayout>
- <LinearLayout
- android:background="@drawable/people_space_content_background"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- <TextView
- android:id="@+id/content"
- android:paddingVertical="3dp"
- android:paddingHorizontal="12dp"
- android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
- android:textSize="14sp"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:maxLines="2"
- android:ellipsize="end" />
- <ImageView
- android:id="@+id/image"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:visibility="gone"/>
- </LinearLayout>
- </LinearLayout>
+ </RelativeLayout>
</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/status_bar_notification_row.xml b/packages/SystemUI/res/layout/status_bar_notification_row.xml
index 84b9e3d..2c08f5d 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_row.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_row.xml
@@ -18,6 +18,7 @@
<!-- extends FrameLayout -->
<com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/expandableNotificationRow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml
index a90b1eb..1810c19 100644
--- a/packages/SystemUI/res/layout/volume_dialog.xml
+++ b/packages/SystemUI/res/layout/volume_dialog.xml
@@ -58,7 +58,7 @@
android:layout_height="match_parent"
android:scaleType="fitCenter"
android:padding="@dimen/volume_dialog_ringer_icon_padding"
- android:tint="@color/accent_tint_color_selector"
+ android:tint="?android:attr/textColorPrimary"
android:layout_gravity="center"
android:soundEffectsEnabled="false" />
@@ -105,7 +105,7 @@
android:layout_gravity="center"
android:contentDescription="@string/accessibility_volume_settings"
android:background="@drawable/ripple_drawable_20dp"
- android:tint="?android:attr/textColorSecondary"
+ android:tint="?android:attr/textColorPrimary"
android:soundEffectsEnabled="false" />
</FrameLayout>
</LinearLayout>
@@ -127,7 +127,7 @@
android:background="@drawable/rounded_ripple"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:tint="@color/caption_tint_color_selector"
+ android:tint="?android:attr/textColorPrimary"
android:layout_gravity="center"
android:soundEffectsEnabled="false"
sysui:optedOut="false"/>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index ce47ed8..da91f27 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Battery, drie stawe."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Battery vol."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Batterypersentasie is onbekend."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Geen foon nie."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Foon, een staaf."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Foon, twee stawe."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Foon, drie stawe."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Foonsein is vol."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Geen data nie."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Data, een staaf."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Data, twee stawe."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Data, drie stawe."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Datasein vol."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Gekoppel aan <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Gekoppel aan <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Gekoppel aan <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX twee strepies."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX drie strepies."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX-sein vol."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet is ontkoppel."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet gekoppel."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Geen sein nie."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Nie gekoppel nie."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Geen stawe."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Af"</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Gekoppel."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Koppel tans."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Swerwing"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Geen SIM nie."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Mobiele data"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobiele data is aan"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobiele data is af"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Nie gestel om data te gebruik nie"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Af"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth-verbinding."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Vliegtuigmodus."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN aan."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Geen SIM-kaart nie."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Diensverskaffernetwerk verander tans"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Maak batterybesonderhede oop"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Battery <xliff:g id="NUMBER">%d</xliff:g> persent."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Battery <xliff:g id="PERCENTAGE">%1$s</xliff:g> persent, ongeveer <xliff:g id="TIME">%2$s</xliff:g> oor gegrond op jou gebruik"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Kan lui of vibreer op grond van fooninstellings. Gesprekke van <xliff:g id="APP_NAME">%1$s</xliff:g> af verskyn by verstek in \'n borrel."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Hou jou aandag met \'n swewende kortpad na hierdie inhoud toe."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Laat die stelsel bepaal of hierdie kennisgewing \'n klank moet maak of vibreer"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Wys boaan die gespreksafdeling, verskyn as \'n swewende borrel, wys profielfoto op sluitskerm"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Instellings"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioriteit"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Hierdie program wys tans bo-oor ander programme op jou skerm en gebruik die mikrofoon en kamera."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Instellings"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Die stelsel het hierdie kennisgewing stilgemaak."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Die stelsel het hierdie kennisgewing bevorder."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Die stelsel het hierdie kennisgewing gedegradeer."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Is dit korrek?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Dankie vir jou terugvoer!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 2573175..d098079 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"ባትሪ ሦስት አሞሌዎች።"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"ባትሪ ሙሉ ነው።"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"የባትሪ መቶኛ አይታወቅም።"</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"ምንም ስልክ የለም።"</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"የስልክ አንድ አሞሌ"</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"የስልክ ሁለት አሞሌ"</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"የስልክ ሦስት አሞሌ"</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"የስልክ አመልካች ሙሉ ነው።"</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"ምንም ውሂብ የለም።"</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"የውሂብ አንድ አሞሌ"</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"የውሂብ ሁለት አሞሌዎች።"</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"የውሂብ ሦስት አሞሌዎች።"</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"የውሂብ አመልካች ሙሉ ነው።"</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"ከ<xliff:g id="WIFI">%s</xliff:g> ጋር ተገናኝቷል።"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"ከ<xliff:g id="BLUETOOTH">%s</xliff:g> ጋር ተገናኝቷል።"</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"ከ<xliff:g id="CAST">%s</xliff:g> ጋር ተገናኝቷል።"</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX ሁለት አሞሌዎች።"</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX ሦስት አሞሌዎች።"</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX አመልካች ሙሉ ነው።"</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"ኤተርኔት ተነቅሏል።"</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"ኤተርኔት ተገናኝቷል።"</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"ምንም ምልክት የለም።"</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"አልተገናኘም።"</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"ዜሮ አሞሌዎች።"</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"ጠፍቷል።"</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"ተገናኝቷል።"</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"በማገናኘት ላይ።"</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"ጂፒአርኤስ"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"ኤችኤስፒኤ"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3ጂ"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"ሰ"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"ሰ+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4ጂ"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"በማዛወር ላይ"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"ኤጅ"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"ምንም SIM የለም።"</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"የተንቀሳቃሽ ስልክ ውሂብ"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"የተንቀሳቃሽ ስልክ ውሂብ በርቷል"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"የተንቀሳቃሽ ስልክ ውሂብ ጠፍቷል"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"ውሂብን ለመጠቀም አልተቀናበረም"</string>
<string name="cell_data_off" msgid="4886198950247099526">"ጠፍቷል"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"ብሉቱዝ ማያያዝ።"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"የአውሮፕላን ሁነታ።"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"ቪፒኤን በርቷል።"</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"ምንም SIM ካርድ የለም።"</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"የአገልግሎት አቅራቢ አውታረ መረብን በመቀየር ላይ"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"የባትሪ ዝርዝሮችን ክፈት"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"የባትሪ <xliff:g id="NUMBER">%d</xliff:g> መቶኛ።"</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ባትሪ <xliff:g id="PERCENTAGE">%1$s</xliff:g> በመቶ፣ በአጠቃቀምዎ ላይ በመመስረት <xliff:g id="TIME">%2$s</xliff:g> ገደማ ይቀራል"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"በእርስዎ የስልክ ቅንብሮች የሚወሰን ሆኖ ሊደውል ወይም ሊነዝር ይችላል። የ<xliff:g id="APP_NAME">%1$s</xliff:g> አረፋ ውይይቶች በነባሪነት።"</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ለዚህ ይዞታ ከተንሳፋፊ አቋራጭ ጋር የእርስዎን ትኩረት ያቆያል።"</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"ይህ ማሳወቂያ ድምጽ ወይም ንዝረት መደረግ ካለበት ስርዓቱ እንዲወሰን ያድርጉት"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"በውይይት ክፍል አናት ላይ ያሳያል፣ እንደ ተንሳፋፊ አረፋ ብቅ ይላል፣ በቆልፍ ማያ ገጽ ላይ የመገለጫ ሥዕልን ያሳያል"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"ቅንብሮች"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"ቅድሚያ"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"ይህ መተግበሪያ በማያ ገጽዎ ላይ በሌሎች መተግበሪያዎች ላይ እያሳየ እና ማይክሮፎኑንና ካሜራውን እየተጠቀመ ነው።"</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"ቅንብሮች"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"እሺ"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"ይህ ማስታወቂያ በስርዓቱ ጸጥ እንዲል ተደርጓል።"</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"ይህ ማስታወቂያ በስርዓቱ ከፍ ተደርጓል።"</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"ይህ ማስታወቂያ በስርዓቱ ዝቅ ተደርጓል።"</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"ይህ ትክክል ነበር?"</string>
<string name="feedback_response" msgid="4671729244976641339">"ለግብረመልስዎ እናመሰግናለን!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"እሺ"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index f0d0b84..2fa6b27 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"إشارة البطارية تتكون من ثلاثة أشرطة."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"إشارة البطارية كاملة."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"نسبة شحن البطارية غير معروفة."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"ليست هناك إشارة بالهاتف."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"إشارة الهاتف تتكون من شريط واحد."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"إشارة الهاتف تتكون من شريطين."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"إشارة الهاتف تتكون من ثلاثة أشرطة."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"إشارة الهاتف كاملة."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"لا تتوفر بيانات."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"إشارة البيانات تتكون من شريط واحد."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"إشارة البيانات تتكون من شريطين."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"إشارة البيانات تتكون من ثلاثة أشرطة."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"إشارة البيانات كاملة."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"متصل بـ <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"متصل بـ <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"تم الاتصال بـ <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"شريطا WiMAX."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"أشرطة WiMAX الثلاثة."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"إشارة WiMAX كاملة."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"تم قطع اتصال Ethernet."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"تم إنشاء اتصال Ethernet."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"ليست هناك إشارة."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"غير متصل."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"ليست هناك أشرطة."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"تم الإيقاف."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"متصل."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"جارٍ الاتصال."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"شبكة GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"شبكة الجيل الثالث"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"شبكة الجيل الرابع"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"شبكة الجيل الرابع أو أحدث"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"التجوال"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"شبكة EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"ليست هناك شريحة SIM."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"بيانات الجوّال"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"تفعيل بيانات الجوال"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"تم إيقاف بيانات الجوال"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"لم يتم الضبط على استخدام البيانات"</string>
<string name="cell_data_off" msgid="4886198950247099526">"غير مفعّلة"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"التوصيل عبر البلوتوث"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"وضع الطيران."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"الشبكة الافتراضية الخاصة (VPN) قيد التفعيل."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"ليس هناك شريحة SIM."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"جارٍ تغيير شبكة مشغِّل شبكة الجوّال."</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"فتح تفاصيل البطارية"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"مستوى البطارية <xliff:g id="NUMBER">%d</xliff:g> في المائة."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"نسبة الشحن بالبطارية <xliff:g id="PERCENTAGE">%1$s</xliff:g> بالمائة، ويتبقى <xliff:g id="TIME">%2$s</xliff:g> تقريبًا بناءً على استخدامك."</string>
@@ -735,6 +710,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"يمكن إصدار رنين أو اهتزاز بناءً على إعدادات الهاتف. تظهر المحادثات من <xliff:g id="APP_NAME">%1$s</xliff:g> كفقاعات تلقائيًا."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"يلفِت هذا الإشعار انتباهك لهذا المحتوى باستخدام اختصار عائم."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"السماح للنظام بتحديد ما إذا يجب اهتزاز الجهاز أو إصدار رنين عند تلقّي هذا الإشعار"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"تظهر في أعلى قسم المحادثات وتظهر كفقاعة عائمة وتعرض صورة الملف الشخصي على شاشة القفل"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"الإعدادات"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"الأولوية"</string>
@@ -753,9 +736,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"يتم عرض هذا التطبيق فوق التطبيقات الأخرى على شاشتك ويستخدم الميكروفون والكاميرا."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"الإعدادات"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"حسنًا"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"كتم النظام صوت هذا الإشعار."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"رفع النظام ترتيب هذا الإشعار."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"خفض النظام ترتيب هذا الإشعار."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"هل كان هذا صحيحًا؟"</string>
<string name="feedback_response" msgid="4671729244976641339">"شكرًا على تعليقك"</string>
<string name="feedback_ok" msgid="6481426753298857144">"حسنًا"</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 366a86f..85bd4a7 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"বেটাৰিৰ তিনিডাল দণ্ড।"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"বেটাৰি পূৰাকৈ চ্চাৰ্জ হৈছে।"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"বেটাৰীৰ চাৰ্জৰ শতাংশ অজ্ঞাত।"</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"ফ\'নত ছিগনেল নাই৷"</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"ফ\'ন ছিগনেলৰ এডাল দণ্ড।"</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"ফ\'ন ছিগনেলৰ দুডাল দণ্ড।"</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"ফ\'নৰ ছিগনেলৰ তিনিডাল দণ্ড আছে।"</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"ফ\'নৰ ছিগনেল পূৰা আছে৷"</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"কোনো ডেটা নাই।"</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"ডেটা ছিগনেলৰ এডাল দণ্ড।"</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"ডেটা ছংনেলৰ তিনিডাল দণ্ড।"</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"ডেটা ছিংগনেলত তিনিডাল দণ্ড আছে।"</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"ডেটা ছিগনেল পূৰা আছে।"</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g>ৰ লগত সংযোগ কৰা হ’ল।"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>ৰ লগত সংযোগ কৰা হ’ল।"</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g>ত সংযোগ হ’ল।"</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAXৰ দুডাল দণ্ড আছে।"</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAXৰ তিনিডাল দণ্ড আছে।"</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAXৰ ছিগনেল পূৰা আছে৷"</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"ইথাৰনেট সংযোগ বিচ্ছিন্ন হৈছে।"</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"ইথাৰনেট সংযোগ হৈছে।"</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"কোনো ছিগনেল নাই।"</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"সংযোগ হৈ থকা নাই।"</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"এডালো দণ্ড নাই।"</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"অফ।"</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"সংযোগ কৰা হ’ল।"</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"সংযোগ কৰি থকা হৈছে।"</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"জিপিআৰএছ"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"এলটিই"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"এলটিই+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"ৰ\'মিং"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"ৱাই-ফাই"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"ছিম নাই।"</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"ম’বাইল ডেটা"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"ম’বাইল ডেটা অন অৱস্থাত আছে"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"ম’বাইল ডেটা অফ অৱস্থাত আছে"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"ডেটা ব্যৱহাৰ কৰিবলৈ ছেট কৰা নাই"</string>
<string name="cell_data_off" msgid="4886198950247099526">"অফ অৱস্থাত আছে"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"ব্লুটুথ টেডাৰিং।"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"এয়াৰপ্লেইন ম\'ড।"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"ভিপিএন অন অৱস্থাত আছে।"</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"কোনো ছিম কাৰ্ড নাই"</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"বাহক নেটৱৰ্কৰ পৰিৱৰ্তন"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"বেটাৰিৰ বিৱৰণসমূহ খোলক"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> শতাংশ বেটাৰি।"</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"আপোনাৰ ব্যৱহাৰৰ ওপৰত ভিত্তি কৰি বেটাৰী <xliff:g id="PERCENTAGE">%1$s</xliff:g> শতাংশ, প্ৰায় <xliff:g id="TIME">%2$s</xliff:g> বাকী আছে"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ফ’নৰ ছেটিঙৰ ওপৰত নিৰ্ভৰ কৰি ৰিং কৰিব অথবা কম্পন হ’ব পাৰে। <xliff:g id="APP_NAME">%1$s</xliff:g>ৰ বাৰ্তালাপ ডিফ’ল্ট হিচাপে বাবল হয়।"</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"উপঙি থকা এটা শ্বৰ্টকাটৰ জৰিয়তে এই সমলখিনিৰ প্ৰতি আপোনাক মনোযোগী কৰি ৰাখে।"</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"এই জাননীটোৱে ধ্বনি নে কম্পন সৃষ্টি কৰিব সেয়া ছিষ্টেমটোক নিৰ্ধাৰণ কৰিবলৈ দিয়ক"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"বাৰ্তালাপ শাখাটোৰ শীৰ্ষত দেখুৱায়, ওপঙা বাবল হিচাপে দেখা পোৱা যায়, লক স্ক্ৰীনত প্ৰ’ফাইলৰ চিত্ৰ প্ৰদৰ্শন কৰে"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"ছেটিংসমূহ"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"অগ্ৰাধিকাৰ"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"এই এপে আপোনাৰ স্ক্ৰীণত থকা অন্য় এপৰ ওপৰত প্ৰদৰ্শিত হৈ মাইক্ৰ\'ফ\'ন আৰু কেমেৰা ব্য়ৱহাৰ কৰি আছে।"</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"ছেটিংসমূহ"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"ঠিক আছে"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"ছিষ্টেমটোৱে এই জাননীক নীৰৱ কৰিছে।"</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"ছিষ্টেমটোৱে এই জাননীটোৰ ক্ষেত্ৰত দিয়া গুৰুত্ব বৃদ্ধি কৰিছে।"</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"ছিষ্টেমটোৱে এই জাননীটোৰ ক্ষেত্ৰত দিয়া গুৰুত্ব হ্ৰাস কৰিছে।"</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"এইটো শুদ্ধ আছিলনে?"</string>
<string name="feedback_response" msgid="4671729244976641339">"আপোনাৰ মতামতৰ বাবে ধন্যবাদ!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"ঠিক আছে"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index d201926..84f9560 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Batareya üç xətdir."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Batareya doludur"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Batareyanın faizi naməlumdur."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Telefon yoxdur."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Şəbəkə bir xətdir."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Şəbəkə iki xətdir."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Şəbəkə üç xətdir."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Tam şəbəkə."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Məlumat yoxdur."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Data bir xətdir."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Data iki xətdir."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Data üç xətdir."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Data siqnalı tamdır."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g> üzərindən qoşuldu."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> üzərindən qoşuldu."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> cihazına qoşulub."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX iki xətdir."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX üç xətdir."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX siqnalı tamdır."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet bağlantısı kəsilib."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet qoşuludur."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Siqnal yoxdur."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Qoşulu deyil."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Sıfır xətt."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Deaktiv"</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Qoşuludur."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Birləşdirilir."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Rominq"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"SIM yoxdur"</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Mobil Data"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobil Data Aktivdir"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobil data deaktivdir"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Data istifadə etmək üçün ayarlanmayıb"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Deaktiv"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth tezering."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Uçuş rejimi"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN aktivdir."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"SIM kart yoxdur."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Operator şəbəkəsinin dəyişilməsi"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Batareya detallarını açın"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Batareya <xliff:g id="NUMBER">%d</xliff:g> faizdir."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Batareya <xliff:g id="PERCENTAGE">%1$s</xliff:g> faizdir, istifadəyə əsasən təxminən <xliff:g id="TIME">%2$s</xliff:g> qalıb"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Telefon ayarlarına əsasən zəng çala və ya vibrasiya edə bilər. <xliff:g id="APP_NAME">%1$s</xliff:g> tətbiqindən söhbətlərdə defolt olaraq qabarcıq çıxır."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Bu məzmuna üzən qısayol ilə diqqətinizi cəlb edir."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Bu bildirişin səs çıxarması və ya vibrasiya etməsi sistem tərəfindən təyin edilsin"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Söhbət bölməsinin yuxarısında göstərilir, üzən qabarcıq kimi görünür, kilid ekranında profil şəkli göstərir"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Ayarlar"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritet"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Bu tətbiq ekranda digər tətbiqlərin üzərində göstərilir və mikrofon ilə kameradan istifadə edir."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Ayarlar"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Bu bildiriş sistem tərəfindən səssiz edilib."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Bu bildiriş sistem tərəfindən irəli çəkilib."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Bu bildiriş sistem tərəfindən geri çəkilib."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Bu, doğru oldu?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Rəyiniz üçün təşəkkür edirik!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index aa44b36..7c0e652 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Baterija od tri crte."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Baterija je puna."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Procenat napunjenosti baterije nije poznat."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Nema telefona."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Signal telefona ima jednu crtu."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Signal telefona od dve crte."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Signal telefona od tri crte."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Signal telefona je pun."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Nema podataka."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Signal za podatke ima jednu crtu."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Signal za podatke od dve crte."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Signal za podatke od tri crte."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Signal za podatke je najjači."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Povezani ste sa <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Povezani ste sa <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Povezani smo sa uređajem <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX signal ima dve crte."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX signal ima tri crte."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX signal je najjači."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Veza sa eternetom je prekinuta."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Eternet je povezan."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Nema signala."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Nije povezano."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Nijedna crta."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Isključeno."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Povezano je."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Povezivanje."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Roming"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"WiFi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Nema SIM kartice."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Mobilni podaci"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobilni podaci su uključeni"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobilni podaci su isključeni"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Nije podešeno za korišćenje podataka"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Isključeno"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth privezivanje."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Režim rada u avionu."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN je uključen."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Nema SIM kartice."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Promena mreže mobilnog operatera"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Otvori detalje o bateriji"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Baterija je na <xliff:g id="NUMBER">%d</xliff:g> posto."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Baterija je na <xliff:g id="PERCENTAGE">%1$s</xliff:g> posto, preostalo vreme na osnovu korišćenja je <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -726,6 +701,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Može da zvoni ili vibrira u zavisnosti od podešavanja telefona. Konverzacije iz aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g> se podrazumevano prikazuju u oblačićima."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Privlači vam pažnju pomoću plutajuće prečice do ovog sadržaja."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Neka sistem utvrdi da li ovo obaveštenje treba da emituje zvuk ili da vibrira"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Prikazuje se u vrhu odeljka za konverzacije kao plutajući oblačić, prikazuje sliku profila na zaključanom ekranu"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Podešavanja"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritet"</string>
@@ -744,9 +727,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Ova aplikacija se prikazuje preko drugih aplikacija na ekranu i koristi mikrofon i kameru."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Podešavanja"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"Potvrdi"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Sistem je isključio ovo obaveštenje."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Sistem je promovisao ovo obaveštenje."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Sistem je postavio ovo obaveštenje na dno."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Da li je to tačno?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Hvala vam na povratnim informacijama!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"Potvrdi"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index bc28f9b..65d45b9 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Тры планкі акумулятара."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Акумулятар поўны."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Працэнт зараду акумулятара невядомы."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Няма тэлефона."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Адна планка на тэлефоне."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"2 планкі тэлефона."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"3 планкі тэлефона."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Поўны сігнал тэлефона."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Няма дадзеных."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Адна планка дадзеных."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"2 планкі дадзеных."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"3 планкі дадзеных."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Поўны сігнал перадачы дадзеных."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Падключаны да <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Падлучаны да <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Ёсць падключэнне да <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Два слупкi сiгналу WiMAX."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Тры слупкi сiгналу WiMAX."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Моцны сiгнал WiMAX."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet адлучаны."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet падлучаны."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Няма сігналу."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Няма падключэння."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Няма."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Выключана."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Падключана."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Падлучэнне."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Роўмінг"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Няма SIM-карты."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Мабільная перадача даных"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Мабільная перадача даных уключана"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Мабільная перадача даных выключана"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Не зададзена для выкарыстання даных"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Выключана"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Сувязь па Bluetooth."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Рэжым палёту."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN уключана."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Няма SIM-карты."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Змяненне аператара сеткі"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Паказаць падрабязную інфармацыю пра акумулятар"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Працэнт зараду акумулятара: <xliff:g id="NUMBER">%d</xliff:g>."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Зарад акумулятара ў працэнтах: <xliff:g id="PERCENTAGE">%1$s</xliff:g>. Пры такім выкарыстанні яго хопіць прыблізна на <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -729,6 +704,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"У залежнасці ад налад тэлефона магчымы званок або вібрацыя. Размовы ў праграме \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" стандартна паяўляюцца ў выглядзе ўсплывальных апавяшчэнняў."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Прыцягвае ўвагу да гэтага змесціва ўсплывальнай кнопкай."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Сістэма сама будзе вызначаць, ці трэба для гэтага апавяшчэння ўключаць гук або вібрацыю"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Паказваецца ўверсе раздзела размоў, як усплывальнае апавяшчэнне, паказвае фота профілю на экране блакіроўкі"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Налады"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Прыярытэт"</string>
@@ -747,9 +730,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Гэта праграма паказваецца на экране паверх іншых праграм. Яна выкарыстоўвае мікрафон і камеру."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Налады"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"ОК"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Гук гэтага апавяшчэння выключаны сістэмай."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Прыярытэт гэтага апавяшчэння павышаны сістэмай."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Прыярытэт гэтага апавяшчэння паніжаны сістэмай."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Усё правільна?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Дзякуй за водгук!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"ОК"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index faa7e56..6f90c2a 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Батерията е с три чертички."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Батерията е пълна."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Процентът на батерията е неизвестен."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Няма телефон."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Телефонът е с една чертичка."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Телефонът е с две чертички."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Телефонът е с три чертички."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Сигналът за телефона е пълен."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Няма данни."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Данните са с една чертичка."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Данните са с две чертички."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Данните са с три чертички."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Сигналът за данни е пълен."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Има връзка с <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Има връзка с <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Установена е връзка с/ъс <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX е с две чертички."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX е с три чертички."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Сигналът за WiMAX е пълен."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Връзката с Ethernet е прекратена."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Установена е връзка с Ethernet."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Няма сигнал."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Няма връзка."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Нула чертички."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Изкл."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Има връзка."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Установява се връзка."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Роуминг"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Няма SIM карта."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Мобилни данни"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Мобилните данни са включени"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Мобилните данни са изключени"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Не е зададено да използва данни"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Изключени"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Тетъринг през Bluetooth."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Самолетен режим."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"Функцията за виртуална частна мрежа (VPN) е включена."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Няма SIM карта."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Промяна на мрежата на оператора"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Отваряне на подробностите за батерията"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> процента батерия."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Батерията е на <xliff:g id="PERCENTAGE">%1$s</xliff:g> процента. Още около <xliff:g id="TIME">%2$s</xliff:g> въз основа на използването"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Може да звъни или да вибрира въз основа на настройките за телефона. Разговорите от <xliff:g id="APP_NAME">%1$s</xliff:g> се показват като балончета по подразбиране."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Задържа вниманието ви посредством плаващ пряк път към това съдържание."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Нека системата да определя дали дадено известие да се придружава от звук, или вибриране"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Показва се като плаващо балонче в горната част на секцията с разговори, показва снимката на потр. профил на заключения екран"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Настройки"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Приоритет"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Това приложение се показва върху други приложения на екрана и използва микрофона и камерата."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Настройки"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Това известие бе заглушено от системата."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Това известие бе повишено от системата."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Това известие бе понижено от системата."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Правилно ли е това?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Благодарим ви за отзивите!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"ОК"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 04fd1ca..6b23edc 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"তিন দন্ড ব্যাটারি রয়েছে৷"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"ব্যাটারি পূর্ণ রয়েছে৷"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"ব্যাটারি কত শতাংশ আছে তা জানা যায়নি।"</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"কোনো ফোনের সংকেত নেই৷"</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"এক দন্ড ফোনের সংকেত রয়েছে৷"</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"দুই দন্ড ফোনের সংকেত রয়েছে৷"</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"তিন দন্ড ফোনের সংকেত রয়েছে৷"</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"ফোনের সংকেত পূর্ণ রয়েছে৷"</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"কোনো ডেটা নেই৷"</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"এক দন্ড ডেটার সংকেত৷"</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"দুই দন্ড ডেটার সংকেত রয়েছে৷"</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"তিন দন্ড ডেটার সংকেত৷"</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"পূর্ণ ডেটার সংকেত রয়েছে৷"</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g> এর সাথে সংযুক্ত।"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>এ সংযুক্ত হয়ে আছে।"</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> এর সাথে সংযুক্ত৷"</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX এ দুইটি দণ্ড৷"</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX এ তিনটি দণ্ড৷"</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX এ সম্পূর্ণ সিগন্যাল৷"</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"ইথারনেটের সংযোগ বিচ্ছিন্ন হয়েছে৷"</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"ইথারনেট সংযুক্ত হয়েছে৷"</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"কোনো সিগন্যাল নেই৷"</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"সংযুক্ত নয়৷"</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"কোনো দণ্ড নেই৷"</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"বন্ধ৷"</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"সংযুক্ত৷"</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"সংযুক্ত হচ্ছে৷"</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"রোমিং"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"ওয়াই-ফাই"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"কোনো সিম নেই৷"</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"মোবাইল ডেটা"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"মোবাইল ডেটা চালু আছে"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"মোবাইল ডেটা বন্ধ করা হয়েছে"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"ডেটা ব্যবহার করার জন্য সেট করা নেই"</string>
<string name="cell_data_off" msgid="4886198950247099526">"বন্ধ"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"ব্লুটুথ টিথারিং৷"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"বিমান মোড৷"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN চালু আছে।"</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"কোনো সিম কার্ড নেই।"</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"পরিষেবা প্রদানকারীর নেটওয়ার্ক পরিবর্তন করা হচ্ছে"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"ব্যাটারির বিশদ বিবরণ খুলুন"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> শতাংশ ব্যাটারি রয়েছে৷"</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ব্যাটারি <xliff:g id="PERCENTAGE">%1$s</xliff:g> শতাংশ, বর্তমান ব্যবহারের উপর ভিত্তি করে আর <xliff:g id="TIME">%2$s</xliff:g> চলবে"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ফোনের সেটিংস অনুযায়ী ফোন রিং বা ভাইব্রেট হতে পারে। <xliff:g id="APP_NAME">%1$s</xliff:g>-এর কথোপকথন সাধারণত বাবলের মতো দেখাবে।"</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ফ্লোটিং শর্টকাট ব্যবহার করে এই কন্টেন্টে আপনার দৃষ্টি আকর্ষণ করে রাখে।"</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"এই বিজ্ঞপ্তি এলে ডিভাইস আওয়াজ করবে না ভাইব্রেট করবে তা সিস্টেমকে সেট করতে দিন"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"কথোপকথন বিভাগের উপরে ভাসমান বাবলের মতো দেখা যাবে, লক স্ক্রিনে প্রোফাইল ছবি দেখাবে"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"সেটিংস"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"অগ্রাধিকার"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"এই অ্যাপটি স্ক্রিনে অন্যান্য অ্যাপের উপরে দেখানো হচ্ছে এবং মাইক্রোফোন ও ক্যামেরা ব্যবহার করছে।"</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"সেটিংস"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"ঠিক আছে"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"সিস্টেম এই বিজ্ঞপ্তি মিউট করে রেখেছিল।"</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"সিস্টেম এই বিজ্ঞপ্তি দেখাতে চেয়েছে।"</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"সিস্টেম এই বিজ্ঞপ্তি বন্ধ রেখেছে।"</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"এটি কি সঠিক ছিল?"</string>
<string name="feedback_response" msgid="4671729244976641339">"মতামতের জন্য ধন্যবাদ!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"বুঝেছি"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index e2a623c..bb2bd8b 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Baterija na tri crtice."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Baterija je puna."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Postotak napunjenosti baterije nije poznat"</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Nema telefonskog signala."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefonski signal na jednoj crtici."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefonski signal na dvije crtice."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefonski signal na tri crtice."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Telefonski signal pun."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Nema podataka."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Prijenos podataka na jednoj crtici."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Prijenos podataka na dvije crtice."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Prijenos podataka na tri crtice."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Signal za prijenos podataka pun."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Povezan na <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Povezan na <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Povezan na <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX signal na dvije crtice."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX signal na tri crtice."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX signal pun."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Veza sa Ethernetom je prekinuta."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet je spojen."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Nema signala."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Nije povezano."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Nema crtica."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Isključeno."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Povezano"</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Povezivanje."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Roming"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"WiFi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Nema SIM kartice."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Prijenos podataka na mobilnoj mreži"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Prijenos podataka na mobilnoj mreži je uključen"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Prijenos podataka na mobilnoj mreži je isključen"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Nije postavljeno za korištenje podataka"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Isključeno"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Dijeljenje Bluetooth veze."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Način rada u avionu."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN uključen."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Nema SIM kartice."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Promjena mreže mobilnog operatera"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Otvori detalje o potrošnji baterije"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Baterija na <xliff:g id="NUMBER">%d</xliff:g> posto."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Baterija je na <xliff:g id="PERCENTAGE">%1$s</xliff:g> posto. Na osnovu vaše potrošnje preostalo vam je otprilike <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -726,6 +701,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Može zvoniti ili vibrirati na osnovu postavki vašeg telefona. Razgovori iz oblačića u aplikaciji <xliff:g id="APP_NAME">%1$s</xliff:g> kao zadana opcija."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Privlači vašu pažnju pomoću plutajuće prečice do ovog sadržaja."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Neka sistem odluči treba li se ovo obavještenje oglasiti zvukom ili vibracijom"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Prikazuje se na vrhu odjeljka za razgovor, pojavljuje se kao plutajući oblačić, prikazuje sliku profila na zaključanom ekranu"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Postavke"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritetni"</string>
@@ -744,9 +727,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Ova aplikacija prekriva druge aplikacije na ekranu i koristi mikrofon i kameru."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Postavke"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"Uredu"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Sistem je utišao ovo obavještenje."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Sistem je pomovirao ovo obavještenje."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Sistem je umanjio značaj ovog obavještenja."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Je li ovo bilo tačno?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Hvala na povratnim informacijama!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"UREDU"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 1fa0c9a..bb7bdd4 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Bateria: tres barres."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Bateria carregada."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Es desconeix el percentatge de bateria."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"No hi ha senyal de telèfon."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Senyal de telèfon: una barra"</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Senyal de telèfon: dues barres."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Senyal de telèfon: tres barres."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Senyal de telèfon: complet."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Senyal de dades: no n\'hi ha"</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Senyal de dades: una barra."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Senyal de dades: dues barres."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Senyal de dades: tres barres."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Senyal de dades: complet."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"S\'ha connectat a <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"S\'ha connectat a <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Està connectat amb <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Dues barres de WiMAX."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Tres barres de WiMAX."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Senyal de WiMAX plena."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"S\'ha desconnectat l\'Ethernet."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet connectada"</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Sense senyal."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Sense connexió."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Cap barra."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Desactivat."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Connectat"</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"S’està connectant."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Itinerància"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"No hi ha cap SIM."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Dades mòbils"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Dades mòbils activades"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"S\'han desactivat les dades mòbils"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"No s\'ha definit per utilitzar dades"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Desactivades"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Compartició de xarxa per Bluetooth"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Mode d\'avió."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN activada"</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"No hi ha cap SIM."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"S\'està canviant la xarxa de l\'operador de telefonia mòbil"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Obre els detalls de la bateria"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> per cent de bateria."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> per cent de bateria amb aproximadament <xliff:g id="TIME">%2$s</xliff:g> de temps restant segons l\'ús que en fas"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Pot sonar o vibrar en funció de la configuració del telèfon. Les converses de l\'aplicació <xliff:g id="APP_NAME">%1$s</xliff:g> es mostren com a bombolles de manera predeterminada."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Atrau la teva atenció amb una drecera flotant a aquest contingut."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Fes que el sistema determini si aquesta notificació ha d\'emetre un so o una vibració"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Es mostra com a bombolla flotant a la part superior de la secció de converses i mostra la foto de perfil a la pantalla de bloqueig"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Configuració"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritat"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Aquesta aplicació es mostra sobre altres aplicacions a la pantalla i utilitza el micròfon i la càmera."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Configuració"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"D\'acord"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"El sistema ha silenciat aquesta notificació."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"El sistema ha augmentat el nivell d\'aquesta notificació."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"El sistema ha disminuït el nivell d\'aquesta notificació."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"La informació ha estat correcta?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Gràcies pels suggeriments."</string>
<string name="feedback_ok" msgid="6481426753298857144">"D\'acord"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index e414fd0..7cfe95c 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Tři čárky baterie."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Baterie je nabitá."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Procento baterie není známé."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Žádná telefonní síť."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Jedna čárka signálu telefonní sítě."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Dvě čárky signálu telefonní sítě."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Tři čárky signálu telefonní sítě."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Plný signál telefonní sítě."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Žádné datové připojení."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Jedna čárka signálu datové sítě."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Dvě čárky signálu datové sítě."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Tři čárky signálu datové sítě."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Plný signál datové sítě."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Připojeno k zařízení <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Připojeno k zařízení <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Jste připojeni k zařízení <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Dvě čárky signálu sítě WiMAX."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Tři čárky signálu sítě WiMAX."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Plný signál sítě WiMAX."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Síť ethernet je odpojena."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Síť ethernet je připojena."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Není signál."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Nepřipojeno."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Žádná čárka."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Vypnuto."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Připojeno."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Připojování."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Žádná SIM karta."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Mobilní data"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobilní data jsou zapnuta"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobilní data jsou vypnuta"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Nenastaveno k využití dat"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Vypnuto"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Sdílené připojení přes Bluetooth."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Režim Letadlo."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN je zapnuto."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Chybí SIM karta"</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Probíhá změna sítě operátora"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Otevřít podrobnosti o baterii"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Stav baterie: <xliff:g id="NUMBER">%d</xliff:g> procent."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Baterie je nabitá na <xliff:g id="PERCENTAGE">%1$s</xliff:g> procent, při vašem používání vydrží ještě <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -729,6 +704,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Může vyzvánět nebo vibrovat v závislosti na nastavení telefonu. Konverzace z aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> ve výchozím nastavení bublají."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Přitahuje pozornost pomocí plovoucí zkratky k tomuto obsahu."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Nechat systém rozhodnout, zda má toto oznámení vydat zvuk či zavibrovat"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Zobrazuje se v horní části sekce konverzací a má podobu plovoucí bubliny, zobrazuje profilovou fotku na obrazovce uzamčení"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Nastavení"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Priorita"</string>
@@ -747,9 +730,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Tato aplikace se zobrazuje přes ostatní aplikace na obrazovce a využívá mikrofon a fotoaparát."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Nastavení"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Toto oznámení systém ztlumil."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"U tohoto oznámení systém zvýšil prioritu."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"U tohoto oznámení systém snížil prioritu."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Udělal to správně?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Děkujeme za zpětnou vazbu."</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 4be2c26..5bde4d8 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Batteri tre bjælker."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Batteri fuldt."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Batteriniveauet er ukendt."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Ingen telefon."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefon en bjælke."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefon to bjælker."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefon tre bjælker."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Telefonsignal fuldt."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Ingen data."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Data en bjælke."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Data to bjælker."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Data tre bjælker."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Datasignal fuldt."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Tilsluttet <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Tilsluttet <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Forbundet til <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX to bjælker."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX tre bjælker."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX-signal er fuldt."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet er ikke tilsluttet."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet er tilsluttet."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Intet signal."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Ikke tilsluttet."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Nul bjælker."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Fra."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Forbundet."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Opretter forbindelse..."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Intet SIM-kort."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Mobildata"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobildata er aktiveret"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobildata er deaktiveret"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Ikke indstillet til at anvende data"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Fra"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth-netdeling."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Flytilstand."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN er slået til."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Der er ikke noget SIM-kort."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Skift af mobilnetværk"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Åbn oplysninger om batteri"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Batteri <xliff:g id="NUMBER">%d</xliff:g> procent."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Batteriniveauet er på <xliff:g id="PERCENTAGE">%1$s</xliff:g> procent, så du har ca. <xliff:g id="TIME">%2$s</xliff:g> tilbage, alt efter hvordan du bruger enheden"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Kan ringe eller vibrere baseret på telefonens indstillinger. Samtaler fra <xliff:g id="APP_NAME">%1$s</xliff:g> vises som standard i bobler."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Fastholder din opmærksomhed med en svævende genvej til indholdet."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Få systemet til at afgøre, om denne notifikation skal vibrere eller afspille en lyd"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Vises øverst i samtalesektionen som en svævende boble og med profilbillede på låseskærmen"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Indstillinger"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritet"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Denne app vises over andre apps på din skærm og anvender mikrofonen og kameraet."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Indstillinger"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Denne notifikation blev sat på lydløs af systemet."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Denne notifikation blev rykket op af systemet."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Denne notifikation blev rykket ned af systemet."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Var dette korrekt?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Tak for din feedback"</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 0386240..14e7e16 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Akku - drei Balken"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Akku voll"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Akkustand unbekannt."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Kein Telefon"</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefonsignal - ein Balken"</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefonsignal - zwei Balken"</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefonsignal - drei Balken"</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Volle Telefonsignalstärke"</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Keine Daten"</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Datensignal - ein Balken"</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Datensignal - zwei Balken"</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Datensignal - drei Balken"</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Volle Datensignalstärke"</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Mit <xliff:g id="WIFI">%s</xliff:g> verbunden"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Mit <xliff:g id="BLUETOOTH">%s</xliff:g> verbunden"</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Verbunden mit <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX - zwei Balken"</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX - drei Balken"</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Volle WiMAX-Signalstärke"</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet nicht verbunden"</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet verbunden"</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Kein Signal"</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Nicht verbunden"</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Kein Balken"</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Aus"</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Verbunden"</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Verbindung wird hergestellt."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"WLAN"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Keine SIM-Karte"</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Mobile Daten"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobile Datennutzung aktiviert"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobile Daten deaktiviert"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Nicht für Datennutzung konfiguriert"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Aus"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth-Tethering"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Flugmodus"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN an."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Keine SIM-Karte"</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Mobilfunknetzwerk wird gewechselt"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Akkudetails öffnen"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Akku bei <xliff:g id="NUMBER">%d</xliff:g> Prozent."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Akku bei <xliff:g id="PERCENTAGE">%1$s</xliff:g> Prozent. Bei deinem Nutzungsmuster hast du noch Strom für etwa <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Kann klingeln oder vibrieren, je nach Telefoneinstellungen. Unterhaltungen von <xliff:g id="APP_NAME">%1$s</xliff:g> werden standardmäßig als Bubble angezeigt."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Du wirst mit einer unverankerten Verknüpfung darauf aufmerksam gemacht."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Das System entscheiden lassen, ob bei dieser Benachrichtigung ein Ton oder eine Vibration ausgegeben wird"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Wird oben im Bereich \"Unterhaltungen\" als unverankerte Bubble mit einem Profilbild auf dem Sperrbildschirm angezeigt"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Einstellungen"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Priorität"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Diese App wird über anderen Apps auf dem Bildschirm angezeigt und verwendet das Mikrofon und die Kamera."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Einstellungen"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"Ok"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Diese Benachrichtigung wurde vom System stummgeschaltet."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Diese Benachrichtigung wurde vom System hochgestuft."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Diese Benachrichtigung wurde vom System heruntergestuft."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"War das richtig?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Vielen Dank für dein Feedback."</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 2985064..1e65310 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Τρεις γραμμές μπαταρίας."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Πλήρης μπαταρία."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Άγνωστο ποσοστό μπαταρίας."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Δεν υπάρχει τηλέφωνο."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Μία γραμμή τηλεφώνου."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Δύο γραμμές τηλεφώνου."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Τρεις γραμμές μπαταρίας."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Πλήρες σήμα τηλεφώνου."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Δεν υπάρχουν δεδομένα."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Μία γραμμή δεδομένων."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Δύο γραμμές δεδομένων."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Τρεις γραμμές δεδομένων."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Πλήρες σήμα δεδομένων."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Συνδέθηκε στο <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Συνδέθηκε στο <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Συνδέθηκε σε <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Σήμα WiMAX δύο γραμμές."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Σήμα WiMAX τρεις γραμμές."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Πλήρες σήμα WiMAX."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Το Ethernet αποσυνδέθηκε."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Το Ethernet συνδέθηκε."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Δεν υπάρχει σήμα."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Μη συνδεδεμένο"</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Μηδέν γραμμές."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Ανενεργό."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Έχει συνδεθεί."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Σύνδεση."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Περιαγωγή"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Δεν υπάρχει SIM."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Δεδομένα κινητής τηλεφωνίας"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Τα δεδομένα κινητής τηλεφωνίας ενεργοποιήθηκαν"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Τα δεδομένα κινητής τηλεφωνίας απενεργοποιήθηκαν"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Δεν ρυθμίστηκε ώστε να χρησιμοποιεί δεδομένα"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Ανενεργά"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Σύνδεση με Bluetooth"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Λειτουργία πτήσης."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ενεργό."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Δεν υπάρχει κάρτα SIM."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Αλλαγή δικτύου εταιρείας κινητής τηλεφωνίας"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Άνοιγμα λεπτομερειών μπαταρίας"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Μπαταρία <xliff:g id="NUMBER">%d</xliff:g> τοις εκατό."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Μπαταρία στο <xliff:g id="PERCENTAGE">%1$s</xliff:g> τοις εκατό. Περίπου <xliff:g id="TIME">%2$s</xliff:g> ακόμη, βάσει της χρήσης σας"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Ενδέχεται να κουδουνίζει ή να δονείται βάσει των ρυθμίσεων του τηλεφώνου. Οι συζητήσεις από την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> εμφανίζονται σε συννεφάκι από προεπιλογή."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Κρατάει την προσοχή σας με μια κινούμενη συντόμευση προς αυτό το περιεχόμενο."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Επιτρέψτε στο σύστημα να αποφασίσει αν αυτή η ειδοποίηση θα αναπαράγει έναν ήχο ή θα ενεργοποιήσει τη δόνηση της συσκευής"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Εμφανίζεται επάνω στις συζητήσεις, προβάλλεται ως κιν. συννεφάκι, εμφανίζει τη φωτ. προφίλ στην οθ. κλειδ."</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Ρυθμίσεις"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Προτεραιότητα"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Αυτή η εφαρμογή εμφανίζεται πάνω σε άλλες εφαρμογές στην οθόνη σας και χρησιμοποιεί το μικρόφωνο και την κάμερα."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Ρυθμίσεις"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"ΟΚ"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Αυτή η ειδοποίηση τέθηκε σε σίγαση από το σύστημα."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Αυτή η ειδοποίηση προωθήθηκε από το σύστημα."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Αυτή η ειδοποίηση υποβιβάστηκε από το σύστημα."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Ήταν σωστό αυτό;"</string>
<string name="feedback_response" msgid="4671729244976641339">"Σας ευχαριστούμε για τα σχόλιά σας!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"ΟΚ"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index fbc0396..0779fba 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Battery three bars."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Battery full."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Battery percentage unknown."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"No phone."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Phone one bar."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Phone two bars."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Phone three bars."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Phone signal full."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"No data."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Data one bar."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Data two bars."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Data three bars."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Data signal full."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Connected to <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Connected to <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Connected to <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX two bars."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX three bars."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX signal full."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet disconnected."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet connected."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"No signal."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Not connected."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Zero bars."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Off."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Connected."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Connecting."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"No SIM."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Mobile data"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobile data on"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobile data off"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Not set to use data"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Off"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth tethering"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Aeroplane mode"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN on."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"No SIM card."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Operator network changing"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Open battery details"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Battery <xliff:g id="NUMBER">%d</xliff:g> per cent."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Battery <xliff:g id="PERCENTAGE">%1$s</xliff:g> percentage, about <xliff:g id="TIME">%2$s</xliff:g> left based on your usage"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"May ring or vibrate based on phone settings. Conversations from <xliff:g id="APP_NAME">%1$s</xliff:g> bubble by default."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Keeps your attention with a floating shortcut to this content."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Have the system determine if this notification should make sound or vibration"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Shows at top of conversation section, appears as floating bubble, displays profile picture on lock screen"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Settings"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Priority"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"This app is displaying over other apps on your screen and using the microphone and camera."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Settings"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"This notification was silenced by the system."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"This notification was promoted by the system."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"This notification was demoted by the system."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Was this correct?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Thanks for your feedback!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index a8eed15..3d93f9f 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Battery three bars."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Battery full."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Battery percentage unknown."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"No phone."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Phone one bar."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Phone two bars."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Phone three bars."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Phone signal full."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"No data."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Data one bar."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Data two bars."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Data three bars."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Data signal full."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Connected to <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Connected to <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Connected to <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX two bars."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX three bars."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX signal full."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet disconnected."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet connected."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"No signal."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Not connected."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Zero bars."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Off."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Connected."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Connecting."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"No SIM."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Mobile data"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobile data on"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobile data off"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Not set to use data"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Off"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth tethering"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Airplane mode."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN on."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"No SIM card."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Operator network changing"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Open battery details"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Battery <xliff:g id="NUMBER">%d</xliff:g> per cent."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Battery <xliff:g id="PERCENTAGE">%1$s</xliff:g> percentage, about <xliff:g id="TIME">%2$s</xliff:g> left based on your usage"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"May ring or vibrate based on phone settings. Conversations from <xliff:g id="APP_NAME">%1$s</xliff:g> bubble by default."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Keeps your attention with a floating shortcut to this content."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Have the system determine if this notification should make sound or vibration"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Shows at top of conversation section, appears as floating bubble, displays profile picture on lock screen"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Settings"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Priority"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"This app is displaying over other apps on your screen and using the microphone and camera."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Settings"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"This notification was silenced by the system."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"This notification was promoted by the system."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"This notification was demoted by the system."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Was this correct?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Thanks for your feedback!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index fbc0396..0779fba 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Battery three bars."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Battery full."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Battery percentage unknown."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"No phone."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Phone one bar."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Phone two bars."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Phone three bars."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Phone signal full."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"No data."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Data one bar."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Data two bars."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Data three bars."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Data signal full."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Connected to <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Connected to <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Connected to <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX two bars."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX three bars."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX signal full."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet disconnected."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet connected."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"No signal."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Not connected."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Zero bars."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Off."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Connected."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Connecting."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"No SIM."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Mobile data"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobile data on"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobile data off"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Not set to use data"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Off"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth tethering"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Aeroplane mode"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN on."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"No SIM card."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Operator network changing"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Open battery details"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Battery <xliff:g id="NUMBER">%d</xliff:g> per cent."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Battery <xliff:g id="PERCENTAGE">%1$s</xliff:g> percentage, about <xliff:g id="TIME">%2$s</xliff:g> left based on your usage"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"May ring or vibrate based on phone settings. Conversations from <xliff:g id="APP_NAME">%1$s</xliff:g> bubble by default."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Keeps your attention with a floating shortcut to this content."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Have the system determine if this notification should make sound or vibration"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Shows at top of conversation section, appears as floating bubble, displays profile picture on lock screen"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Settings"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Priority"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"This app is displaying over other apps on your screen and using the microphone and camera."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Settings"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"This notification was silenced by the system."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"This notification was promoted by the system."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"This notification was demoted by the system."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Was this correct?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Thanks for your feedback!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index fbc0396..0779fba 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Battery three bars."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Battery full."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Battery percentage unknown."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"No phone."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Phone one bar."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Phone two bars."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Phone three bars."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Phone signal full."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"No data."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Data one bar."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Data two bars."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Data three bars."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Data signal full."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Connected to <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Connected to <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Connected to <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX two bars."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX three bars."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX signal full."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet disconnected."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet connected."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"No signal."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Not connected."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Zero bars."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Off."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Connected."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Connecting."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"No SIM."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Mobile data"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobile data on"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobile data off"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Not set to use data"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Off"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth tethering"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Aeroplane mode"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN on."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"No SIM card."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Operator network changing"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Open battery details"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Battery <xliff:g id="NUMBER">%d</xliff:g> per cent."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Battery <xliff:g id="PERCENTAGE">%1$s</xliff:g> percentage, about <xliff:g id="TIME">%2$s</xliff:g> left based on your usage"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"May ring or vibrate based on phone settings. Conversations from <xliff:g id="APP_NAME">%1$s</xliff:g> bubble by default."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Keeps your attention with a floating shortcut to this content."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Have the system determine if this notification should make sound or vibration"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Shows at top of conversation section, appears as floating bubble, displays profile picture on lock screen"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Settings"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Priority"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"This app is displaying over other apps on your screen and using the microphone and camera."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Settings"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"This notification was silenced by the system."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"This notification was promoted by the system."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"This notification was demoted by the system."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Was this correct?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Thanks for your feedback!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 47bda8b..7d7e4b9 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Battery three bars."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Battery full."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Battery percentage unknown."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"No phone."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Phone one bar."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Phone two bars."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Phone three bars."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Phone signal full."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"No data."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Data one bar."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Data two bars."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Data three bars."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Data signal full."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Connected to <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Connected to <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Connected to <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX two bars."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX three bars."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX signal full."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet disconnected."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet connected."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"No signal."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Not connected."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Zero bars."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Off."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Connected."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Connecting."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"No SIM."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Mobile Data"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobile Data On"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobile data off"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Not set to use data"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Off"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth tethering."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Airplane mode."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN on."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"No SIM card."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Carrier network changing"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Open battery details"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Battery <xliff:g id="NUMBER">%d</xliff:g> percent."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Battery <xliff:g id="PERCENTAGE">%1$s</xliff:g> percent, about <xliff:g id="TIME">%2$s</xliff:g> left based on your usage"</string>
@@ -723,6 +698,10 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"May ring or vibrate based on phone settings. Conversations from <xliff:g id="APP_NAME">%1$s</xliff:g> bubble by default."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Keeps your attention with a floating shortcut to this content."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Have the system determine if this notification should make sound or vibration"</string>
+ <string name="notification_channel_summary_automatic_alerted" msgid="954166812246932240">"<b>Status:</b> Promoted to Default"</string>
+ <string name="notification_channel_summary_automatic_silenced" msgid="7403004439649872047">"<b>Status:</b> Demoted to Silent"</string>
+ <string name="notification_channel_summary_automatic_promoted" msgid="1301710305149590426">"<b>Status:</b> Ranked Higher"</string>
+ <string name="notification_channel_summary_automatic_demoted" msgid="1831303964660807700">"<b>Status:</b> Ranked Lower"</string>
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Shows at top of conversation section, appears as floating bubble, displays profile picture on lock screen"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Settings"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Priority"</string>
@@ -741,9 +720,10 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"This app is displaying over other apps on your screen and using the microphone and camera."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Settings"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"This notification was silenced by the system."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"This notification was promoted by the system."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"This notification was demoted by the system."</string>
+ <string name="feedback_alerted" msgid="5192459808484271208">"This notification was automatically <b>promoted to Default</b> by the system."</string>
+ <string name="feedback_silenced" msgid="9116540317466126457">"This notification was automatically <b>demoted to Silent</b> by the system."</string>
+ <string name="feedback_promoted" msgid="2125562787759780807">"This notification was automatically <b>ranked higher</b> in your shade."</string>
+ <string name="feedback_demoted" msgid="951884763467110604">"This notification was automatically <b>ranked lower</b> in your shade."</string>
<string name="feedback_prompt" msgid="2278631214125128281">"Was this correct?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Thanks for your feedback!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index ab23eb6..5940767 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Tres barras de batería"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Batería completa"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Se desconoce el porcentaje de la batería."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Sin teléfono"</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Una barra de teléfono"</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Dos barras de teléfono"</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Tres barras de teléfono"</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Señal de teléfono completa"</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"No hay datos."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Una barra de datos"</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Dos barras de datos"</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Tres barras de datos"</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Señal de datos completa"</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Conectado a <xliff:g id="WIFI">%s</xliff:g>"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Conectado a <xliff:g id="BLUETOOTH">%s</xliff:g>"</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Conectado a <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Dos barras de WiMAX"</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Tres barras de WiMAX"</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Señal de WiMAX al máximo"</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet desconectada"</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet conectada"</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Sin señal"</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"No conectado"</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Cero barras"</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Desactivado"</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Conectado"</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Conectando"</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Sin tarjeta SIM"</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Datos móviles"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Activar datos móviles"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Datos móviles desactivados"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"No se configuró para usar datos"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Desactivados"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Conexión Bluetooth"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Modo avión"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN activada"</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Sin tarjeta SIM"</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Cambio de proveedor de red"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Abrir detalles de la batería"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Batería <xliff:g id="NUMBER">%d</xliff:g> por ciento"</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Batería: <xliff:g id="PERCENTAGE">%1$s</xliff:g> por ciento; tiempo restante: aproximadamente <xliff:g id="TIME">%2$s</xliff:g> en función del uso"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Puede sonar o vibrar en función de la configuración del teléfono. Conversaciones de la burbuja de <xliff:g id="APP_NAME">%1$s</xliff:g> de forma predeterminada."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Retiene tu atención con un acceso directo flotante a este contenido."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Dejar que el sistema determine si esta notificación debe emitir un sonido o una vibración"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Aparece en la parte superior de la sección de conversaciones, en forma de burbuja flotante, y muestra la foto de perfil en la pantalla de bloqueo."</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Configuración"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritaria"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Esta app se muestra sobre otras apps en la pantalla y está usando el micrófono y la cámara."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Configuración"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"Aceptar"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"El sistema silenció la notificación."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"El sistema ascendió el nivel de esta notificación."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"El sistema descendió el nivel de esta notificación."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"¿Te parece bien?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Gracias por tus comentarios."</string>
<string name="feedback_ok" msgid="6481426753298857144">"Aceptar"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index e589ce6..1f6a153 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Tres barras de batería"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Batería completa"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Porcentaje de batería desconocido."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Sin teléfono"</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Una barra de cobertura"</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Dos barras de cobertura"</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Tres barras de cobertura"</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Cobertura al máximo"</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Sin datos"</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Una barra de datos"</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Dos barras de datos"</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Tres barras de datos"</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Señal de datos al máximo"</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Conectado a <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Conectado a <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Conectado a <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Dos barras de WiMAX"</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Tres barras de WiMAX"</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Señal de WiMAX al máximo"</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Conexión Ethernet desconectada."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Conexión Ethernet conectada."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"No hay señal"</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"No conectado"</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Ninguna barra"</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Desactivado"</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Conectado"</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Conectando."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Itinerancia"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Sin tarjeta SIM"</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Datos móviles"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Datos móviles activados"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Datos desactiv."</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"No está establecido para usar los datos"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Desactivados"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Compartir conexión por Bluetooth"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Modo avión"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"La red VPN está activada."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"No hay tarjeta SIM."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Cambiando la red del operador"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Abrir detalles de la batería"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> por ciento de batería"</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Queda un <xliff:g id="PERCENTAGE">%1$s</xliff:g> por ciento de batería (<xliff:g id="TIME">%2$s</xliff:g> aproximadamente según tu uso)"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Es posible que suene o vibre según los ajustes del teléfono. Las conversaciones de <xliff:g id="APP_NAME">%1$s</xliff:g> aparecen como burbujas de forma predeterminada."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Llama tu atención con un acceso directo flotante a este contenido."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Haz que el sistema determine si con esta notificación el dispositivo debe sonar o vibrar"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Se muestra arriba en la sección de conversaciones, como burbuja flotante, y la imagen de perfil aparece en la pantalla de bloqueo"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Ajustes"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioridad"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Esta aplicación se está mostrando sobre otras aplicaciones en tu pantalla y está usando el micrófono y la cámara."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Ajustes"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"Aceptar"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"El sistema ha silenciado esta notificación."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"El sistema ha promocionado esta notificación."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"El sistema ha disminuido el nivel de esta notificación."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"¿Estuvo bien?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Gracias por tus comentarios."</string>
<string name="feedback_ok" msgid="6481426753298857144">"Aceptar"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index cce8d83..3e454f2 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Aku: kolm pulka."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Aku täis."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Aku laetuse protsent on teadmata."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Telefonisignaal puudub"</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefonisignaal: üks pulk."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefonisignaal: kaks pulka."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefonisignaal: kolm pulka."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Telefonisignaal on tugev."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Andmed puuduvad."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Andmesignaal: üks pulk."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Andmeside: kaks pulka."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Andmeside: kolm pulka."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Andmesignaal on tugev."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Ühendatud: <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Ühendatud: <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Ühendatud ülekandega <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX-i on kaks riba."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX-i on kolm riba."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX-i signaal on tugev."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Etherneti-ühendus on katkestatud."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Etherneti-ühendus on loodud."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Signaal puudub."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Ühendus puudub."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Null pulka."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Väljas."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Ühendatud."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Ühenduse loomine."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Rändlus"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"WiFi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"SIM-kaarti pole."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Mobiilne andmeside"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobiilne andmeside on sees"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobiilne andmeside on väljas"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Ei ole andmeside kasutamiseks seadistatud"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Väljas"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Jagamine Bluetoothiga."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Lennukirežiim."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN on sees."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"SIM-kaarti pole."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Operaatori võrku muudetakse"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Aku üksikasjade avamine"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Aku: <xliff:g id="NUMBER">%d</xliff:g> protsenti."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Aku protsent <xliff:g id="PERCENTAGE">%1$s</xliff:g>, teie kasutuse põhjal on jäänud ligikaudu <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Võib telefoni seadete põhjal heliseda või vibreerida. Rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> vestlused kuvatakse vaikimisi mullis."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Hoiab teie tähelepanu hõljuva otseteega selle sisu juurde."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Laske süsteemil määrata, kas selle märguande puhul peaks esitama heli või vibreerima"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Kuvatakse vestluste jaotise ülaosas hõljuva mullina ja lukustuskuval kuvatakse profiilipilt"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Seaded"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioriteetne"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"See rakendus kuvatakse teie ekraanil muude rakenduste peal ning see kasutab mikrofoni ja kaamerat."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Seaded"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Selle märguande vaigistas süsteem."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Selle märguande ülendas süsteem."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Selle märguande alandas süsteem."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Kas see oli õige?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Täname tagasiside eest!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index ad64da2..5dcfa7f 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Bateriak hiru barra ditu."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Bateria beteta dago."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Bateriaren ehunekoa ezezaguna da."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Ez dago telefono-zenbakirik."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefono-seinaleak barra bat du."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefono-seinaleak bi barra ditu."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefono-seinaleak hiru barra ditu."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Telefono-seinale osoa."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Ez dago daturik."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Datu-seinaleak barra bat du."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Datu-seinaleak bi barra ditu."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Datu-seinaleak hiru barra ditu."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Datu-seinale osoa."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g> sarera konektatuta."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> gailura konektatuta."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Hona konektatuta: <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX sarearen bi barra."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX sarearen hiru barra."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX sarearen seinalea osoa."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet bidezko konexioa eten da."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet bidez konektatu da."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Ez dago seinalerik."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Konektatu gabe."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Barrarik ez."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Desaktibatuta."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Konektatuta."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Konektatzen."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Ibiltaritza"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wifia"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Ez dago SIM txartelik."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Datu-konexioa"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Datu-konexioa aktibatuta"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Desaktibatuta dago datu-konexioa"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Ez dago ezarrita datuak erabiltzeko"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Desaktibatuta"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Konexioa partekatzea (Bluetooth)"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Hegaldi-modua"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN eginbidea aktibatuta."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Ez dago SIM txartelik."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Operadorearen sarea aldatzen"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Ireki bateriaren xehetasunak"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Bateriaren karga: <xliff:g id="NUMBER">%d</xliff:g>."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Bateriak ehuneko <xliff:g id="PERCENTAGE">%1$s</xliff:g> dauka kargatuta. Zure erabilera kontuan izanda, <xliff:g id="TIME">%2$s</xliff:g> inguru gelditzen zaizkio."</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Tonua jo edo dar-dar egin dezake, telefonoaren ezarpenen arabera. Modu lehenetsian, <xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioko elkarrizketak burbuila gisa agertzen dira."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Eduki honetarako lasterbide gainerakor bat eskaintzen dizu, arretarik gal ez dezazun."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Ezarri sistemak zehaztu dezala jakinarazpen honek soinua edo dardara egin behar duen ala ez"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Burbuila gisa agertzen da elkarrizketen atalaren goialdean, eta profileko argazkia bistaratzen du pantaila blokeatuta dagoenean"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Ezarpenak"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Lehentasuna"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Aplikazioa pantailako beste aplikazioen gainean agertzen da, eta mikrofonoa eta kamera erabiltzen ari da."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Ezarpenak"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"Ados"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Sistemak isilarazi egin du jakinarazpen hau."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Sistemak mailaz igo du jakinarazpen hau."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Sistemak mailaz jaitsi du jakinarazpen hau."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Zuzena al da hau?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Mila esker iritzia emateagatik!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"Ados"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index f5f9580..85a89b3 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"سه نوار برای باتری."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"باتری پر است."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"درصد شارژ باتری مشخص نیست."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"بدون تلفن."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"یک نوار برای تلفن."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"دو نوار برای تلفن."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"سه نوار برای تلفن."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"قدرت امواج تلفن همراه کامل است."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"دادهای وجود ندارد."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"یک نوار برای داده."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"دو نوار برای داده."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"سه نوار برای داده."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"قدرت سیگنال داده کامل است."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"به <xliff:g id="WIFI">%s</xliff:g> متصل شد."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"به <xliff:g id="BLUETOOTH">%s</xliff:g> متصل شد."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"به <xliff:g id="CAST">%s</xliff:g> متصل شد."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX دو نوار دارد."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX سه نوار دارد."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"قدرت سیگنال WiMAX کامل است."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"اترنت قطع شد."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"اترنت متصل شد."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"فاقد سیگنال."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"متصل نیست."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"بدون میله."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"خاموش."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"متصل."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"در حال مرتبط شدن."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"فراگردی"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"بدون سیم کارت."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"داده تلفن همراه"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"داده تلفن همراه روشن"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"داده تلفن همراه خاموش است"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"برای استفاده از داده تنظیم نشده است"</string>
<string name="cell_data_off" msgid="4886198950247099526">"خاموش"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"اشتراکگذاری اینترنت با بلوتوث."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"حالت هواپیما."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN روشن است."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"سیمکارتی موجود نیست."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"تغییر شبکه شرکت مخابراتی"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"باز کردن جزئیات باتری"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"باتری <xliff:g id="NUMBER">%d</xliff:g> درصد."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"باتری <xliff:g id="PERCENTAGE">%1$s</xliff:g> درصد شارژ دارد، براساس مصرفتان تقریباً <xliff:g id="TIME">%2$s</xliff:g> شارژ باقیمانده است"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"بسته به تنظیمات ممکن است تلفن زنگ بزند یا لرزش داشته باشد. مکالمههای <xliff:g id="APP_NAME">%1$s</xliff:g> بهطور پیشفرض در حبابک نشان داده میشوند."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"با میانبری شناور به این محتوا، توجهتان را جلب میکند."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"سیستم را تنظیم کنید که تشخیص دهد اعلان صدا و لرزش داشته باشد یا نه"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"در بالای بخش مکالمه بهصورت حبابک شناور نشان داده میشود و تصویر نمایه را در صفحه قفل نمایش میدهد"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"تنظیمات"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"اولویت"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"این برنامه روی برنامههای دیگر در صفحهنمایش نشان داده میشود و از میکروفون و دوربین استفاده میکند."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"تنظیمات"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"تأیید"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"سیستم این اعلان را بیصدا کرده است."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"سیستمْ این اعلان را ارتقا داده است."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"سیستمْ این اعلان را تنزل داده است."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"این مورد درست بود؟"</string>
<string name="feedback_response" msgid="4671729244976641339">"از بازخوردتان سپاسگزاریم!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"تأیید"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 65db4ce..bb17d32 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Akun virta - kolme palkkia."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Akku täynnä."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Akun varaustaso ei tiedossa."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Ei puhelinverkkoyhteyttä."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Puhelinverkkosignaali - yksi palkki."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Puhelinverkkosignaali - kaksi palkkia."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Puhelinverkkosignaali - kolme palkkia."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Vahva puhelinverkkosignaali."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Ei datasignaalia."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Datasignaali - yksi palkki."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Datasignaali - kaksi palkkia."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Datasignaali - kolme palkkia"</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Vahva kuuluvuus."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Yhteys: <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Yhteys: <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Yhdistetty kohteeseen <xliff:g id="CAST">%s</xliff:g>"</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX: kaksi palkkia."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX: kolme palkkia."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Vahva WiMAX-signaali."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet on irrotettu."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet on yhdistetty."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Ei signaalia."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Ei yhteyttä."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Nolla palkkia."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Pois käytöstä."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Yhdistetty."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Yhdistetään."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Ei SIM-korttia."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Mobiilidata"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobiilidata käytössä"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobiilidata poistettu käytöstä"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Ei käytä dataa"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Pois käytöstä"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Internetin jakaminen Bluetoothin kautta."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Lentokonetila."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN päällä"</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Ei SIM-korttia."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Operaattorin verkko muuttuu"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Avaa akun tiedot."</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Akun virta <xliff:g id="NUMBER">%d</xliff:g> prosenttia."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Akkua jäljellä <xliff:g id="PERCENTAGE">%1$s</xliff:g> prosenttia eli noin <xliff:g id="TIME">%2$s</xliff:g> käyttösi perusteella"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Voi soida tai väristä puhelimen asetuksista riippuen. Näistä keskusteluista (<xliff:g id="APP_NAME">%1$s</xliff:g>) syntyy oletuksena kuplia."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Kelluva sisällön pikakuvake säilyttää huomiosi"</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Järjestelmä valitsee, kuuluuko tästä ilmoituksesta ääntä tai väriseekö se"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Näkyy keskusteluosion yläosassa kelluvana kuplana, profiilikuva näkyy lukitusnäytöllä"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Asetukset"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Tärkeä"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Tämä sovellus näkyy näytöllä muiden sovellusten päällä ja käyttää mikrofonia sekä kameraa."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Asetukset"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Järjestelmä hiljensi tämän ilmoituksen."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Järjestelmä nosti tämän ilmoituksen tasoa."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Järjestelmä laski tämän ilmoituksen tasoa."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Oliko tämä oikein?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Kiitos palautteesta!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 9f5c98d..897a475 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Niveau de batterie : bon"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Batterie pleine"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Pourcentage de la pile inconnu."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Aucun signal"</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Signal : faible"</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Signal : moyen"</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Signal : bon"</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Signal excellent"</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Aucun signal"</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Signal faible"</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Signal moyen"</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Signal bon"</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Signal excellent"</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Connecté à : <xliff:g id="WIFI">%s</xliff:g>"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Connecté à : <xliff:g id="BLUETOOTH">%s</xliff:g>"</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Connecté à <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Signal WiMAX : moyen"</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Signal WiMAX : bon"</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Signal WiMAX : excellent"</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet déconnecté."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet connecté."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Aucun signal"</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Non connecté"</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Aucun signal"</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Désactivé"</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Connecté"</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Connexion."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Itinérance"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Aucune carte SIM"</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Données cellulaires"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Données cellulaires activées"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Désactivées"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Non configuré pour l\'utilisation des données cellulaires"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Désactivé"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Partage de connexion Bluetooth"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Mode Avion"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"RPV activé."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Aucune carte SIM."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Changer de réseau de fournisseur de services"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Ouvrir les détails de la pile"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Pile : <xliff:g id="NUMBER">%d</xliff:g> pour cent"</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Pile chargée à <xliff:g id="PERCENTAGE">%1$s</xliff:g> pour cent (environ <xliff:g id="TIME">%2$s</xliff:g> d\'autonomie en fonction de votre usage)"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Peut sonner ou vibrer, selon les paramètres du téléphone. Conversations des bulles de <xliff:g id="APP_NAME">%1$s</xliff:g> par défaut."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Garde votre attention à l\'aide d\'un raccourci flottant vers ce contenu."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Faire en sorte que le système détermine si cette notification devrait émettre un son ou vibrer"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"S\'affiche en haut de la section des conversations sous forme de bulle flottante et affiche la photo du profil sur l\'écran de verrouillage"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Paramètres"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritaire"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Cette application superpose du contenu par-dessus d\'autres applications à l\'écran et utilise le microphone et l\'appareil photo."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Paramètres"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Cette notification a été désactivée par le système."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Cette notification a été promue par le système."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Cette notification a été rétrogradée par le système."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Était-ce correct?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Merci de vos commentaires!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index b482c24..d756991 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Niveau de batterie : bon"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Batterie pleine"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Pourcentage de la batterie inconnu."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Aucun signal"</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Signal : faible"</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Signal : moyen"</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Signal : bon"</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Signal excellent"</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Aucun signal"</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Signal faible"</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Signal moyen"</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Signal bon"</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Signal excellent"</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Connecté à : <xliff:g id="WIFI">%s</xliff:g>"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Connecté à : <xliff:g id="BLUETOOTH">%s</xliff:g>"</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Connecté à <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Signal WiMAX : moyen"</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Signal WiMAX : bon"</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Signal WiMAX : excellent"</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet déconnecté"</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet connecté"</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Aucun signal"</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Non connecté"</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Aucun signal"</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Désactivé"</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Connecté"</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Connexion en cours…"</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Itinérance"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Aucune carte SIM"</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Données mobiles"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Données mobiles activées"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Désactivées"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Non configuré pour utiliser les données"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Désactivées"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Partage de connexion Bluetooth"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Mode Avion"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"Le VPN est activé."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Aucune carte SIM"</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Modification du réseau de l\'opérateur"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Ouvrir les détails de la batterie"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Batterie : <xliff:g id="NUMBER">%d</xliff:g> pour cent"</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Batterie chargée à <xliff:g id="PERCENTAGE">%1$s</xliff:g> pour cent : il reste environ <xliff:g id="TIME">%2$s</xliff:g> d\'autonomie, selon votre utilisation"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Peut sonner ou vibrer en fonction des paramètres du téléphone. Les conversations provenant de <xliff:g id="APP_NAME">%1$s</xliff:g> s\'affichent sous forme de bulles par défaut."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Attire votre attention à l\'aide d\'un raccourci flottant vers ce contenu."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Laisser le système déterminer si cette notification doit être accompagnée d\'un son ou d\'une vibration"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"S\'affiche en haut de la section des conversations, apparaît sous forme de bulle flottante, affiche la photo de profil sur l\'écran de verrouillage"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Paramètres"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritaire"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Cette application se superpose aux autres applications sur l\'écran, et utilise le micro et la caméra."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Paramètres"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Le son de cette notification a été coupé par le système."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Cette notification a été mise en avant par le système."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Cette notification a été rétrogradée par le système."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Est-ce que c\'était correct ?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Merci de nous avoir envoyé vos commentaires."</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 808048b..abfdf6b 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Tres barras de batería"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Batería cargada"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Descoñécese a porcentaxe da batería."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Sen teléfono"</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Unha barra de cobertura"</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Dúas barras de cobertura"</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Tres barras de cobertura"</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Cobertura ao máximo"</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Sen datos"</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Unha barra de sinal de datos"</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Sinal de datos: dúas barras"</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Tres barras de sinal de datos"</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Sinal de datos: completo"</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Conectado a <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Conectado a <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Dispositivo conectado: <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Dúas barras de WiMAX"</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Tres barras de WiMAX"</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Sinal completo de WiMAX"</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Desconectouse a Ethernet."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Conectouse a Ethernet."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Sen sinal"</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Non conectada"</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Ningunha barra"</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Desactivada"</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Conectado"</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Conectando."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Itinerancia"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Sen SIM"</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Datos móbiles"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Os datos móbiles están activados"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Os datos móbiles están desactivados"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Non se configurou para utilizar datos"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Desactivado"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Conexión compartida por Bluetooth."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Modo avión"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"A VPN está activada."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Non hai tarxeta SIM"</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Cambio de rede do operador"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Abrir os detalles da batería"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Carga da batería: <xliff:g id="NUMBER">%d</xliff:g> por cento."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Batería: <xliff:g id="PERCENTAGE">%1$s</xliff:g> por cento, durará <xliff:g id="TIME">%2$s</xliff:g> co uso que adoitas darlle"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Podería soar ou vibrar en función da configuración do teléfono. Conversas desde a burbulla da aplicación <xliff:g id="APP_NAME">%1$s</xliff:g> de forma predeterminada."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Mantén a túa atención cun atallo flotante a este contido."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Fai que o sistema determine se a notificación debe emitir un son ou unha vibración"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Móstranse na parte superior da sección de conversas en forma de burbulla flotante e aparece a imaxe do perfil na pantalla de bloqueo"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Configuración"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioridade"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Esta aplicación móstrase sobre outras aplicacións da pantalla e está utilizando o micrófono e a cámara."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Configuración"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"Aceptar"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"O sistema silenciou esta notificación."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"O sistema subiu o nivel desta notificación."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"O sistema diminuíu o nivel desta notificación."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"A información era correcta?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Grazas polo teu comentario"</string>
<string name="feedback_ok" msgid="6481426753298857144">"Aceptar"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 1ba649a..a4562aa 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"બૅટરી ત્રણ બાર."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"બૅટરી પૂર્ણ."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"બૅટરીની ટકાવારી અજાણ છે."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"કોઈ ફોન નથી."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"ફોન એક બાર."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"ફોન બે બાર."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"ફોન ત્રણ બાર."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"પૂર્ણ ફોન સિગ્નલ."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"કોઈ ડેટા નથી."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"ડેટા એક બાર."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"ડેટા બે બાર."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"ડેટા ત્રણ બાર."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"ડેટા સિગ્નલ પૂર્ણ."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g> થી કનેક્ટ થયેલું છે."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> થી કનેક્ટ થયાં."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> થી કનેક્ટ કરેલ."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX બે બાર."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX ત્રણ બાર."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"પૂર્ણ WiMAX સિગ્નલ."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"ઇથરનેટ ડિસ્કનેક્ટ થયું."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"ઇથરનેટ કનેક્ટ થયું."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"કોઈ સિગ્નલ નથી."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"કનેક્ટ થયેલ નથી."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"શૂન્ય બાર."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"બંધ."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"કનેક્ટ કરી"</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"કનેક્ટ થઈ રહ્યું છે."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"રોમિંગ"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"વાઇ-ફાઇ"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"સિમ નથી."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"મોબાઇલ ડેટા"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"મોબાઇલ ડેટા ચાલુ છે"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"મોબાઇલ ડેટા બંધ છે"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"ડેટાનો ઉપયોગ કરવાનું સેટ કર્યું નથી"</string>
<string name="cell_data_off" msgid="4886198950247099526">"બંધ કરો"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"બ્લૂટૂથ ટિથરિંગ."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"એરપ્લેન મોડ."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ચાલુ છે."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"કોઈ સિમ કાર્ડ નથી."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"કૅરીઅર નેટવર્કમાં ફેરફાર થઈ રહ્યો છે"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"બૅટરીની વિગતો ખોલો"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"બૅટરી <xliff:g id="NUMBER">%d</xliff:g> ટકા."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"તમારા વપરાશના આધારે બૅટરી <xliff:g id="PERCENTAGE">%1$s</xliff:g> ટકા, જે લગભગ <xliff:g id="TIME">%2$s</xliff:g> સુધી ચાલે તેટલી બચી છે"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ફોન સેટિંગના આધારે રિંગ અથવા વાઇબ્રેટ થઈ શકે છે. ડિફૉલ્ટ તરીકે <xliff:g id="APP_NAME">%1$s</xliff:g> બબલની વાતચીત."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ફ્લોટિંગ શૉર્ટકટથી આ કન્ટેન્ટ પર તમારું ધ્યાન દોરી રાખે છે."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"આ નોટિફિકેશન સાઉન્ડ અથવા વાઇબ્રેટ કરી શકશે કે નહીં તે સિસ્ટમને નક્કી કરવા દો"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"એને વાતચીત વિભાગની ટોચ પર બતાવે છે, તરતા બબલ તરીકે દેખાય છે, લૉક સ્ક્રીન પર પ્રોફાઇલ ફોટા તરીકે બતાવે છે"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"સેટિંગ"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"પ્રાધાન્યતા"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"આ ઍપ તમારી સ્ક્રીન પરની અન્ય ઍપની ઉપર પ્રદર્શિત થઈ રહી છે અને માઇક્રોફોન અને કૅમેરાનો ઉપયોગ કરી રહી છે."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"સેટિંગ"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"ઓકે"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"આ નોટિફિકેશનને સિસ્ટમ દ્વારા સાઇલન્ટ કરવામાં આવ્યું હતું."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"આ નોટિફિકેશનને સિસ્ટમ દ્વારા બઢતી આપવામાં આવી હતી."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"આ નોટિફિકેશનને સિસ્ટમ દ્વારા ડિમોટ કરવામાં આવ્યું હતું."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"શું આ યોગ્ય હતું?"</string>
<string name="feedback_response" msgid="4671729244976641339">"તમારા પ્રતિસાદ બદલ આભાર!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"ઓકે"</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 330ff90..6cde262 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"बैटरी तीन बार."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"बैटरी पूरी है."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"इस बारे में जानकारी नहीं है कि अभी बैटरी कितने प्रतिशत चार्ज है."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"कोई फ़ोन नहीं."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"फ़ोन एक बार."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"फ़ोन दो बार."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"फोन तीन बार."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"फ़ोन सिग्नल पूरा."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"कोई डेटा नहीं."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"डेटा एक बार."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"डेटा दो बार."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"डेटा तीन बार."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"डेटा सिग्नल पूरा."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g> से कनेक्ट किया गया."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> से कनेक्ट किया गया."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> से कनेक्ट है."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX दो बार."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX तीन बार."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX सिग्नल पूरा है."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"ईथरनेट डिस्कनेक्ट किया गया."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"ईथरनेट कनेक्ट किया गया."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"कोई सिग्नल नहीं."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"कनेक्ट नहीं है."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"शून्य बार."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"बंद."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"कनेक्ट है."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"कनेक्ट हो रहा है."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3जी"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"एलटीई"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"रोमिंग"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"वाई-फ़ाई"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"कोई सिम नहीं."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"मोबाइल डेटा"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"मोबाइल डेटा चालू है"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"मोबाइल डेटा बंद है"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"डेटा इस्तेमाल करने के लिए सेट नहीं किया गया है"</string>
<string name="cell_data_off" msgid="4886198950247099526">"बंद है"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"ब्लूटूथ से टेदरिंग."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"हवाई जहाज़ मोड."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN चालू."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"कोई सिम कार्ड नहीं है."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"मोबाइल और इंटरनेट सेवा देने वाली कंपनी का नेटवर्क बदल रहा है"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"बैटरी का विवरण खोलें"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> प्रतिशत बैटरी."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> प्रतिशत बैटरी बची है और आपके इस्तेमाल के हिसाब से यह <xliff:g id="TIME">%2$s</xliff:g> में खत्म हो जाएगी"</string>
@@ -725,6 +700,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"फ़ोन की सेटिंग के आधार पर, सूचना आने पर घंटी बज सकती है या वाइब्रेशन हो सकता है. <xliff:g id="APP_NAME">%1$s</xliff:g> में होने वाली बातचीत, डिफ़ॉल्ट रूप से बबल के तौर पर दिखती है."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"फ़्लोट करने वाले शॉर्टकट की मदद से इस सामग्री पर आपका ध्यान बना रहता है."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"सिस्टम को यह तय करने की अनुमति दें कि इस सूचना के मिलने पर आवाज़ हो या वाइब्रेशन हो"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"इससे बातचीत, सेक्शन में सबसे ऊपर और फ़्लोटिंग बबल के तौर पर दिखती है. साथ ही, लॉक स्क्रीन पर प्रोफ़ाइल फ़ोटो दिखती है"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"सेटिंग"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"प्राथमिकता"</string>
@@ -743,9 +726,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"यह ऐप्लिकेशन आपकी स्क्रीन पर इस्तेमाल हो रहे दूसरे ऐप्लिकेशन के ऊपर दिखाया जा रहा है. इसके साथ ही यह माइक्रोफ़ोन और कैमरे का भी इस्तेमाल कर रहा है."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"सेटिंग"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"ठीक है"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"सिस्टम ने उपयोगकर्ता के इस्तेमाल के आधार पर, इस सूचना के मिलने पर होने वाली आवाज़ बंद कर दी है."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"सिस्टम ने उपयोगकर्ता के इस्तेमाल के आधार पर यह तय किया है कि कोई सूचना, खोज के क्रम में एकदम नीचे दिखेगी या फिर बिना आवाज़ किए मिलेगी."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"सिस्टम ने उपयोगकर्ता के इस्तेमाल के आधार पर यह तय किया है कि कोई सूचना, खोज के क्रम में एकदम नीचे दिखेगी या फिर बिना आवाज़ किए मिलेगी."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"आपको यह सुविधा कैसी लगी?"</string>
<string name="feedback_response" msgid="4671729244976641339">"सुझाव या शिकायत के लिए धन्यवाद!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"ठीक है"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 6879259..3b25e38 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Baterija tri stupca."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Baterija je puna."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Postotak baterije nije poznat."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Nema telefona."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefonski signal jedan stupac."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefonski signal dva stupca."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefonski signal tri stupca."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Telefonski signal pun."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Nema podataka."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Podatkovni signal jedan stupac."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Podatkovni signal dva stupca."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Podatkovni signal tri stupca."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Podatkovni signal pun."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Spojen na <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Spojen na <xliff:g id="BLUETOOTH">%s</xliff:g> ."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Povezani ste sa sljedećim uređajem: <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX s dva stupca."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX s tri stupca."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Signal WiMAX potpun je."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Prekinuta je veza s ethernetom."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Uspostavljena je veza s ethernetom."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Nema signala."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Nije povezano."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Nijedan stupac."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Isključeno."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Povezano."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Povezivanje."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G i više"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Nema SIM kartice."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Mobilni podaci"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobilni su podaci uključeni"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobilni su podaci isključeni"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Nije postavljeno za upotrebu podataka"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Isključeno"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Posredno povezivanje Bluetootha."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Način rada u zrakoplovu"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN uključen."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Nema SIM kartice."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Promjena mreže mobilnog operatera"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Otvaranje pojedinosti o bateriji"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Baterija <xliff:g id="NUMBER">%d</xliff:g> posto."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Baterija je na <xliff:g id="PERCENTAGE">%1$s</xliff:g> posto, još otprilike <xliff:g id="TIME">%2$s</xliff:g> na temelju vaše upotrebe"</string>
@@ -726,6 +701,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Možda će zvoniti ili vibrirati, ovisno o postavkama telefona. Razgovori iz aplikacije <xliff:g id="APP_NAME">%1$s</xliff:g> prikazuju se u oblačiću prema zadanim postavkama."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Održava vam pozornost pomoću plutajućeg prečaca ovom sadržaju."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Neka sustav odredi treba li obavijest najaviti zvukom ili vibracijom"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Prikazuje se pri vrhu odjeljka razgovora kao pomični oblačić i prikazuje profilnu sliku na zaključanom zaslonu"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Postavke"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritet"</string>
@@ -744,9 +727,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Ova se aplikacija prikazuje preko drugih aplikacija na zaslonu i upotrebljava mikrofon i kameru."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Postavke"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"U redu"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Ovu obavijest utišao je sustav."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Ovu obavijest promovirao je sustav."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Ovu obavijest degradirao je sustav."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Je li to bilo točno?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Zahvaljujemo na povratnim informacijama!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"U redu"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 90f42cb..e7ee331 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Akkumulátor három sáv."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Akkumulátor feltöltve."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Az akkumulátor töltöttségi szintje ismeretlen."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Nincs telefon."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefon egy sáv."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefon két sáv."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefon három sáv."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Telefonjel megtelt."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Nincsenek adatok."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Adat egy sáv."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Adat két sáv."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Adat három sáv."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Adatjel teljes."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Csatlakoztatva a következőhöz: <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Csatlakoztatva a következőhöz: <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Csatlakozva a következőhöz: <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX-jel: két sáv."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX-jel: három sáv."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX-jel: teljes."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet leválasztva."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet csatlakoztatva."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Nincs jel."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Nincs csatlakozva."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Nincs sáv."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Kikapcsolva."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Csatlakoztatva."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Csatlakozás."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Nincs SIM."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Mobiladatok"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobiladatok bekapcsolva"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobiladatok kikapcsolva"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Nincs beállítva az adathasználat"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Ki"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth megosztása."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Repülőgép üzemmód."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN bekapcsolva."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Nincs SIM-kártya."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Szolgáltatói hálózat váltása"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Az akkumulátorral kapcsolatos részletek megnyitása"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Akkumulátor <xliff:g id="NUMBER">%d</xliff:g> százalék."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Az akkumulátor <xliff:g id="PERCENTAGE">%1$s</xliff:g> százalékon áll, a használati adatok alapján körülbelül <xliff:g id="TIME">%2$s</xliff:g> múlva merül le"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"A telefonbeállítások alapján csöröghet és rezeghet. A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazásban lévő beszélgetések alapértelmezés szerint buborékban jelennek meg."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"A tartalomra mutató lebegő parancsikon segítségével tartja fenn az Ön figyelmét."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"A rendszer határozza meg, hogy ez az értesítés adjon-e ki hangot, illetve rezegjen-e"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"A beszélgetések szakaszának tetején, lebegő buborékként látható, megjeleníti a profilképet a lezárási képernyőn"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Beállítások"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritás"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Ez az alkalmazás a képernyőn lévő egyéb alkalmazások előtt jelenik meg, és használja a mikrofont és a kamerát."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Beállítások"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Ezt az értesítést lenémította a rendszer."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Ezt az értesítést magasabb prioritásra állította a rendszer."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Ezt az értesítést alacsonyabb prioritásra állította a rendszer."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Megfelelő ez így?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Köszönjük a visszajelzést!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index aaa2794..af300ea 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Մարտկոցի երեք գիծ:"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Մարտկոցը լիքն է:"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Մարտկոցի լիցքի մակարդակն անհայտ է։"</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Հեռախոս չկա:"</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Հեռախոսի մեկ գիծ:"</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Հեռախոսի երկու գիծ:"</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Հեռախոսի երեք գիծ:"</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Հեռախոսի ազդանշանը լիքն է:"</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Տվյալներ չկան:"</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Տվյալների մեկ գիծ:"</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Տվյալների երկու գիծ:"</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Տվյալների երեք գիծ:"</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Տվյալների ազդանշանը լրիվ է:"</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Միացված է <xliff:g id="WIFI">%s</xliff:g>-ին:"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Միացված է <xliff:g id="BLUETOOTH">%s</xliff:g>-ին:"</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Միացված է <xliff:g id="CAST">%s</xliff:g>-ին:"</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX-ի երկու գիծ:"</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX-ի երեք գիծ:"</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX-ի ազդանշանը լիքն է:"</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet-ը անջատված է:"</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet-ը կապակցված է:"</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Ազդանշան չկա:"</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Միացված չէ:"</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Զրո գիծ:"</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Անջատված է:"</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Միացված է:"</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Միանում է:"</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Ռոումինգ"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"SIM չկա:"</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Բջջային ինտերնետ"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Բջջային տվյալները միացված են"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Բջջային ինտերնետն անջատված է"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Բջջային ինտերնետն ըստ կանխադրման չի օգտագործվում"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Անջատված է"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth մոդեմ"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Ավիառեժիմ"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"Միացնել VPN-ը։"</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"SIM քարտ չկա:"</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Օպերատորի ցանցի փոփոխություն"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Բացել մարտկոցի տվյալները"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Մարտկոցը <xliff:g id="NUMBER">%d</xliff:g> տոկոս է:"</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Մարտկոցի լիցքը <xliff:g id="PERCENTAGE">%1$s</xliff:g> տոկոս է և կբավարարի մոտ <xliff:g id="TIME">%2$s</xliff:g>՝ կախված օգտագործման եղանակից:"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Կարող է զնգալ կամ թրթռալ (հեռախոսի կարգավորումներից կախված)։ <xliff:g id="APP_NAME">%1$s</xliff:g>-ի զրույցներն ըստ կանխադրման հայտնվում են ամպիկների տեսքով։"</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Լողացող դյուրանցման միջոցով ձեր ուշադրությունն է գրավում բովանդակության նկատմամբ"</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Թող համակարգն ավտոմատ որոշի՝ արդյոք այս ծանուցումը ձայնով, թե թրթռոցով է պետք մատուցել"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Ցուցադրվում է զրույցների ցանկի վերևում, հայտնվում է լողացող ամպիկի տեսքով, ցուցադրում է պրոֆիլի նկարը կողպէկրանին"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Կարգավորումներ"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Կարևոր"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Այս հավելվածը ցուցադրվում է մյուս հավելվածների վրայից և օգտագործում է խոսափողն ու տեսախցիկը:"</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Կարգավորումներ"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"Եղավ"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Այս ծանուցման ձայնն անջատվել է համակարգի կողմից։"</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Այս ծանուցման կարևորության մակարդակը բարձրացվել է համակարգի կողմից։"</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Այս ծանուցման կարևորության մակարդակը իջեցվել է համակարգի կողմից։"</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Սա ճի՞շտ էր"</string>
<string name="feedback_response" msgid="4671729244976641339">"Շնորհակալություն արձագանքելու համար"</string>
<string name="feedback_ok" msgid="6481426753298857144">"Եղավ"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index ff5d4ed..0038463 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Baterai tiga batang."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Baterai penuh."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Persentase baterai tidak diketahui."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Tidak dapat melakukan panggilan."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Ponsel satu batang."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Ponsel dua batang."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Ponsel tiga batang."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Sinyal ponsel penuh."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Tidak ada data yang diterima."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Data satu batang."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Data dua batang."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Data tiga batang."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Sinyal data penuh."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Terhubung ke <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Terhubung ke <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Terhubung ke <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX dua batang."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX tiga batang."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Sinyal WiMAX penuh."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet terputus."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet tersambung."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Tidak ada sinyal."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Tidak terhubung."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"0 baris."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Nonaktif."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Tersambung."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Menyambung."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Tidak ada SIM."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Data Seluler"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Data Seluler Aktif"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Kuota nonaktif"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Tidak disetel untuk menggunakan data"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Nonaktif"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Tethering bluetooth."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Mode pesawat."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN aktif."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Tidak ada kartu SIM."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Jaringan operator berubah"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Membuka detail baterai"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Baterai <xliff:g id="NUMBER">%d</xliff:g> persen."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Baterai <xliff:g id="PERCENTAGE">%1$s</xliff:g> persen, sekitar <xliff:g id="TIME">%2$s</xliff:g> lagi berdasarkan penggunaan Anda"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Dapat berdering atau bergetar berdasarkan setelan ponsel. Percakapan dari balon <xliff:g id="APP_NAME">%1$s</xliff:g> secara default."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Menjaga perhatian dengan pintasan floating ke konten ini."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Biarkan sistem menentukan apakah notifikasi ini akan berbunyi atau bergetar"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Muncul di atas bagian percakapan, ditampilkan sebagai balon yang mengambang, menampilkan gambar profil di layar kunci"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Setelan"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritas"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Aplikasi ini ditampilkan di atas aplikasi lain di layar serta sedang menggunakan mikrofon dan kamera."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Setelan"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"Ya"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Notifikasi ini disenyapkan oleh sistem."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Notifikasi ini dipromosikan oleh sistem."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Notifikasi ini didemosikan oleh sistem."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Sudah benar?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Terima kasih atas masukan Anda"</string>
<string name="feedback_ok" msgid="6481426753298857144">"Oke"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 20231b4..25b907f 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Þrjú strik á rafhlöðu."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Rafhlaða fullhlaðin."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Staða rafhlöðu óþekkt."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Ekkert símasamband."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Styrkur símasambands er eitt strik."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Styrkur símasambands er tvö strik."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Styrkur símasambands er þrjú strik."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Fullur styrkur símasambands."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Engin gögn."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Sendistyrkur gagnatengingar er eitt strik."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Sendistyrkur gagnatengingar tvö strik."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Sendistyrkur gagnatengingar er þrjú strik."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Fullur sendistyrkur gagnatengingar."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Tengt við <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Tengt við <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Tengt við <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX: Tvö strik."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX: Þrjú strik."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Fullur WiMAX-sendistyrkur."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet aftengt."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet tengt."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Ekkert merki."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Engin tenging."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Engin strik."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Slökkt."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Tenging virk."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Tengist."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Reiki"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Ekkert SIM-kort."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Farsímagögn"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Kveikt á farsímagögnum"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Slökkt á farsímagögnum"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Ekki stillt á að nota gögn"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Slökkt"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Tjóðrun með Bluetooth."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Flugstilling"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"Kveikt á VPN."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Ekkert SIM-kort."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Skiptir um farsímakerfi"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Opna upplýsingar um rafhlöðu"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> prósent á rafhlöðu."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Rafhlaða í <xliff:g id="PERCENTAGE">%1$s</xliff:g> prósentum, um það bil <xliff:g id="TIME">%2$s</xliff:g> eftir miðað við notkun þína"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Gæti hringt eða titrað eftir stillingum símans. Samtöl á <xliff:g id="APP_NAME">%1$s</xliff:g> birtast sjálfkrafa í blöðru."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Fangar athygli þína með fljótandi flýtileið á þetta efni."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Láta kerfið ákvarða hvort hljóð eða titringur fylgir þessari tilkynningu"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Birtist efst í samtalshluta, birtist sem fljótandi blaðra, birtir prófílmynd á lásskjánum"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Áfram"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Forgangur"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Þetta forrit er að birta efni yfir öðrum forritum á skjánum þínum og er að nota hljóðnemann og myndavélina."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Stillingar"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"Í lagi"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Kerfið þaggaði þessa tilkynningu."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Kerfið hækkaði þessa tilkynningu."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Kerfið lækkaði þessa tilkynningu."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Var þetta rétt?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Takk fyrir að segja þína skoðun!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"Í lagi"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index a7952ba..e393cea 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Batteria: tre barre."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Batteria carica."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Percentuale della batteria sconosciuta."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Nessun telefono."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefono: una barra."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefono: due barre."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefono: tre barre."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Massimo segnale telefonico."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Nessun dato."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Dati: una barra."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Dati: due barre."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Dati: tre barre."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Massimo segnale dati."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Connesso a <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Connesso a <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Connesso a: <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX: due barre."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX: tre barre."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Massimo segnale WiMAX."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Connessione Ethernet annullata."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Connessione Ethernet stabilita."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Nessun segnale."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Non connesso."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Nessuna barra."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Off"</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Connesso."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Connessione in corso."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Nessuna SIM presente."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Dati mobili"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Dati mobili attivati"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Dati mobili disattivati"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Non impostato per l\'utilizzo dei dati"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Off"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Tethering Bluetooth."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Modalità aereo."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN attiva."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Nessuna SIM presente."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Cambio della rete dell\'operatore"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Visualizza i dettagli relativi alla batteria"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Batteria: <xliff:g id="NUMBER">%d</xliff:g> percento."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Livello della batteria: <xliff:g id="PERCENTAGE">%1$s</xliff:g> percento. Tempo rimanente in base al tuo utilizzo: <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Può suonare o vibrare in base alle impostazioni del telefono. Conversazioni dalla bolla <xliff:g id="APP_NAME">%1$s</xliff:g> per impostazione predefinita."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Mantiene la tua attenzione con una scorciatoia mobile a questi contenuti."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Fai stabilire al sistema se questa notifica deve emettere suoni o vibrazioni"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Appare in cima alla sezione delle conversazioni e sotto forma di bolla mobile, mostra l\'immagine del profilo nella schermata di blocco"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Impostazioni"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Priorità"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Questa app è visualizzata sopra altre app sullo schermo e sta utilizzando il microfono e la fotocamera."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Impostazioni"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"Ok"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Questa notifica è stata silenziata dal sistema."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Questa notifica è stata promossa dal sistema."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Questa notifica è stata retrocessa dal sistema."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Era corretto?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Grazie per il feedback."</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index cd07d77..4f30f1f 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"שלושה פסים של סוללה."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"סוללה מלאה."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"אחוז טעינת הסוללה לא ידוע."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"אין טלפון."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"פס אחד של טלפון."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"שני פסים של טלפון."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"שלושה פסים של טלפון."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"אות הטלפון מלא."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"אין נתונים."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"פס אחד של נתונים."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"שני פסים של נתונים."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"שלושה פסים של נתונים."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"אות הנתונים מלא."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"מחובר אל <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"מחובר אל <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"מחובר אל <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"שני פסים של WiMAX."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"שלושה פסים של WiMAX."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"אות ה-WiMAX מלא."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"אתרנט מנותק."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"אתרנט מחובר."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"אין אות."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"אין חיבור."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"אפס פסים."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"כבוי."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"מחובר."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"מתחבר."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"+H"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"+4G"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"+LTE"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"נדידה"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"אין כרטיס SIM."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"חבילת גלישה"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"חבילת הגלישה פועלת"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"חבילת הגלישה כבויה"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"לא מוגדרת לשימוש בנתונים"</string>
<string name="cell_data_off" msgid="4886198950247099526">"כבוי"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"שיתוף אינטרנט דרך Bluetooth"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"מצב טיסה"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN פועל."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"אין כרטיס SIM."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"רשת ספק משתנה"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"פתיחת פרטי סוללה"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> אחוזים של סוללה."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"רמת הטעינה בסוללה: <xliff:g id="PERCENTAGE">%1$s</xliff:g> אחוזים, הזמן הנותר המשוער על סמך השימוש שלך:<xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -729,6 +704,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ייתכן שיופעל צלצול או רטט בהתאם להגדרות הטלפון. שיחות מהאפליקציה <xliff:g id="APP_NAME">%1$s</xliff:g> מופיעות בבועות כברירת מחדל."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"מעוררת תשומת לב באמצעות קיצור דרך צף לתוכן הזה."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"אפשר לתת למערכת לקבוע אם ההתראה הזאת צריכה להיות מלווה בצליל או ברטט"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"מוצגת בחלק העליון של קטע התראות השיחה, מופיעה בבועה צפה, תוצג תמונת פרופיל במסך הנעילה"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"הגדרות"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"עדיפות"</string>
@@ -747,9 +730,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"האפליקציה הזו מוצגת מעל אפליקציות אחרות במסך, ומשתמשת במיקרופון ובמצלמה."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"הגדרות"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"אישור"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"ההתראה הזאת הושתקה על-ידי המערכת."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"ההתראה הזאת קודמה על-ידי המערכת."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"ההתראה הזאת הורדה בדרגה על-ידי המערכת."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"האם פעולה זו הייתה נכונה?"</string>
<string name="feedback_response" msgid="4671729244976641339">"תודה על המשוב!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"אישור"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 1b30a92..baca136 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"電池残量:レベル3"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"電池残量:満"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"電池残量は不明です。"</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"電波状態:なし"</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"電波状態:レベル1"</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"電波状態:レベル2"</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"電波状態:レベル3"</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"電波状態:フル"</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"データ信号:なし"</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"データ信号:レベル1"</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"データ信号:レベル2"</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"データ信号:レベル3"</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"データ信号:フル"</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g>に接続しました。"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>に接続しました。"</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g>に接続されています。"</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX電波状態:レベル2"</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX電波状態:レベル3"</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX電波状態:フル"</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"イーサネット接続を解除しました。"</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"イーサネットに接続しました。"</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"圏外です。"</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"接続されていません。"</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"レベル0"</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"OFF"</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"接続済みです。"</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"接続しています。"</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"ローミング"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"SIMがありません。"</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"モバイルデータ"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"モバイルデータ ON"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"モバイルデータ OFF"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"データを使用するように設定されていません"</string>
<string name="cell_data_off" msgid="4886198950247099526">"OFF"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetoothテザリング。"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"機内モード。"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN は ON です。"</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"SIMカードが挿入されていません。"</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"携帯通信会社のネットワークを変更します"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"電池の詳細情報を開きます"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"電池残量: <xliff:g id="NUMBER">%d</xliff:g>パーセント"</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"電池残量: <xliff:g id="PERCENTAGE">%1$s</xliff:g>、およそ <xliff:g id="TIME">%2$s</xliff:g> に電池切れ(使用状況に基づく)"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"スマートフォンの設定を基に着信音またはバイブレーションが有効になります。デフォルトでは <xliff:g id="APP_NAME">%1$s</xliff:g> からの会話がバブルとして表示されます。"</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"このコンテンツのフローティング ショートカットで通知をお知らせします。"</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"この通知を音またはバイブレーションで知らせるかどうかの自動判断"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"会話セクションの一番上にバブルとして表示され、プロフィール写真がロック画面に表示されます"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"設定"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"優先"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"このアプリは画面上で他のアプリの上に重ねて表示されます。また、マイクとカメラを使用しています。"</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"設定"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"この通知はシステムによってサイレントに設定されました。"</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"この通知はシステムによって順位が上げられました。"</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"この通知はシステムによって順位が下げられました。"</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"間違いありませんか?"</string>
<string name="feedback_response" msgid="4671729244976641339">"フィードバックをお寄せいただきありがとうございます。"</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index f128dde..d11c302 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"ბატარეა სამ ზოლზე."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"ბატარეა სავსეა."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"ბატარეის პროცენტული მაჩვენებელი უცნობია."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"ტელეფონი არ არის."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"ტელეფონის სიგნალი ერთ ზოლზეა."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"ტელეფონის სიგნალი ორ ზოლზეა."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"ტელეფონის სიგნალი სამ ზოლზეა."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"ტელეფონის სიგნალი სრულია."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"მონაცემები არ არის."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"თარიღი ზოლზე."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"მონაცემების გადაცემა: ორი ზოლი"</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"მონაცემების გადაცემა: სამი ზოლი"</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"მონაცემთა გადაცემის საიმედო სიგნალი."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"დაკავშირებულია <xliff:g id="WIFI">%s</xliff:g>-თან."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"დაკავშირებულია <xliff:g id="BLUETOOTH">%s</xliff:g>-თან."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"დაკავშირებულია მოწყობილობასთან: <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX-ის ორი ზოლი."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX-ის სამი ზოლი."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX სიგნალი სრულია."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet კავშირი შეწყვეტილია."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet დაკავშირებულია."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"სიგნალი არ არის."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"არ არის დაკავშირებული."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"სიგნალი ნულ ზოლზეა."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"გამორთულია."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"დაკავშირებულია."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"უკავშირდება."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"როუმინგი"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"SIM არ არის."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"მობილური ინტერნეტი"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"მობილური ინტერნეტი ჩართულია"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"მობილური ინტერნეტი გამორთულია"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"არ არის დაყენებული მონაცემების გამოყენებისთვის"</string>
<string name="cell_data_off" msgid="4886198950247099526">"გამორთული"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth ტეტერინგის ჩართვა"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"თვითმფრინავის რეჟიმი"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ჩართულია."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"SIM ბარათი არ არის."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"ოპერატორის ქსელის შეცვლა"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"ბატარეის დეტალების გახსნა"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"ბატარეა: <xliff:g id="NUMBER">%d</xliff:g> პროცენტი."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ბატარეა <xliff:g id="PERCENTAGE">%1$s</xliff:g> პროცენტზეა, მოხმარების გათვალისწინებით დარჩა დაახლოებით <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"დარეკვა ან ვიბრაცია ტელეფონის პარამეტრების მიხედვით. მიმოწერები <xliff:g id="APP_NAME">%1$s</xliff:g>-ის ბუშტიდან, ნაგულისხმევად."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"იპყრობს თქვენს ყურადღებას ამ კონტენტის მოლივლივე მალსახმობით."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"სისტემისთვის ისეთი უფლების მინიჭება, რომ მან განსაზღვროს, ამ შეტყობინებამ ხმოვანი სიგნალი უნდა აამოქმედოს თუ ვიბრაცია"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"გამოჩნდება მიმოწერების ზედა ნაწილში ბუშტის სახით, აჩვენებს პროფილის სურათს ჩაკეტილ ეკრანზე"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"პარამეტრები"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"პრიორიტეტი"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"ეს აპი თქვენს ეკრანზე ფარავს სხვა აპებს და იყენებს მიკროფონსა და კამერას."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"პარამეტრები"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"კარგი"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"ეს შეტყობინება სისტემის მიერ არის ჩაჩუმებული."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"ამ შეტყობინების მნიშვნელობა სისტემის მიერ არის აწეული."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"ამ შეტყობინების მნიშვნელობა სისტემის მიერ არის დაწეული."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"სწორია ეს?"</string>
<string name="feedback_response" msgid="4671729244976641339">"გმადლობთ გამოხმაურებისთვის!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"კარგი"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index b9c54cc..55552e9 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Батарея үш баған."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Батарея толы."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Батарея зарядының мөлшері белгісіз."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Телефон жоқ."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Телефон бір баған."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Телефон екі баған."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Телефон үш баған."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Телефон сигналы толық."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Дерекқор жоқ."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Дерекқор бір баған."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Дерекқор екі баған."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Дерекқор үш баған."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Дерекқор сигналы толы."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g> қосылған."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> қосылған."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> трансляциясына қосылды."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX екі жолақ."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX үш жолақ."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX сигналы толық."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet ажыратылған."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet қосылған."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Сигнал жоқ."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Жалғанбаған."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Нөл жолақ."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Өшірулі."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Жалғанған."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Қосылуда."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Роуминг"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"SIM жоқ."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Мобильдік дерекқор"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Мобильдік деректер қосулы"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Мобильдік деректер өшірулі"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Деректерді пайдалануға реттелмеген."</string>
<string name="cell_data_off" msgid="4886198950247099526">"Өшірулі"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth тетеринг."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Ұшақ режимі."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN қосулы."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"SIM картасы жоқ."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Оператор желісін өзгерту"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Батарея мәліметтерін ашу"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Батарея <xliff:g id="NUMBER">%d</xliff:g> пайыз."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Батарея заряды: <xliff:g id="PERCENTAGE">%1$s</xliff:g> пайыз. Пайдалануға байланысты шамамен <xliff:g id="TIME">%2$s</xliff:g> уақытқа жетеді."</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Телефон параметрлеріне байланысты шылдырлауы не дірілдеуі мүмкін. <xliff:g id="APP_NAME">%1$s</xliff:g> чаттары әдепкісінше қалқымалы етіп көрсетіледі."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Осы мазмұнға бекітілген қалқымалы таңбашамен назарыңызды өзіне тартады."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Хабарландыру дыбысының немесе дірілдің қосылуын жүйе анықтайтын болады"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Әңгімелер бөлімінің жоғарғы жағында тұрады, қалқыма хабар түрінде шығады, құлыптаулы экранда профиль суретін көрсетеді"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Параметрлер"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Маңызды"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Бұл қолданба экранда басқа қолданбалардың үстінен көрсетіліп тұр және ол микрофон мен камераны пайдалануда."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Параметрлер"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"Жарайды"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Хабарландырудың дыбысы жүйе арқылы өшірілген."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Хабарландырудың күйі жүйе арқылы көтерілген."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Хабарландырудың күйі жүйе арқылы түсірілген."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Барлығы дұрыс па?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Пікіріңіз үшін рақмет!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"Жарайды"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index d293c0d..5885383 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"ថ្មទាំងបីកាំ។"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"ថ្មពេញហើយ។"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"មិនដឹងអំពីភាគរយថ្មទេ។"</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"គ្មានទូរស័ព្ទ។"</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"សេវាទូរស័ព្ទមួយកាំ។"</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"សេវាទូរស័ព្ទពីរកាំ។"</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"សេវាទូរស័ព្ទបីកាំ។"</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"សេវាទូរស័ព្ទពេញ។"</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"គ្មានទិន្នន័យ។"</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"ទិន្នន័យមួយកាំ។"</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"ទិន្នន័យពីរកាំ។"</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"ទិន្នន័យបីកាំ។"</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"សញ្ញាទិន្នន័យពេញ។"</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"បានភ្ជាប់ទៅ <xliff:g id="WIFI">%s</xliff:g> ។"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"បានភ្ជាប់ទៅ <xliff:g id="BLUETOOTH">%s</xliff:g> ។"</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"បានភ្ជាប់ទៅ <xliff:g id="CAST">%s</xliff:g>"</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX ពីរកាំ។"</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX បីកាំ។"</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"សញ្ញា WiMAX ពេញ។"</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"បានផ្តាច់អ៊ីសឺរណិត។"</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"បានភ្ជាប់អ៊ីសឺរណិត។"</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"គ្មានសញ្ញា។"</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"មិនបានតភ្ជាប់។"</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"សូន្យកាំ។"</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"បិទ"</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"បានតភ្ជាប់។"</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"ការភ្ជាប់។"</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"រ៉ូមីង"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"គ្មានស៊ីមកាត។"</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"ទិន្នន័យទូរសព្ទចល័ត"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"ទិន្នន័យទូរសព្ទចល័តបានបើក"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"ទិន្នន័យទូរសព្ទចល័តបានបិទ"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"មិនបានកំណត់ឱ្យប្រើទិន្នន័យទេ"</string>
<string name="cell_data_off" msgid="4886198950247099526">"បិទ"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"ការភ្ជាប់តាមប៊្លូធូស"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"ពេលជិះយន្តហោះ"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"បើក VPN ។"</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"គ្មានស៊ីមកាតទេ។"</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"បណ្តាញក្រុមហ៊ុនសេវាទូរសព្ទកំពុងផ្លាស់ប្តូរ"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"បើកព័ត៌មានលម្អិតអំពីថ្ម"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"ថ្ម <xliff:g id="NUMBER">%d</xliff:g> ភាគរយ។"</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ថ្ម <xliff:g id="PERCENTAGE">%1$s</xliff:g> ភាគរយ អាចប្រើបានប្រហែល <xliff:g id="TIME">%2$s</xliff:g> ទៀត ផ្អែកលើការប្រើប្រាស់របស់អ្នក"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"អាចរោទ៍ ឬញ័រ ដោយផ្អែកលើការកំណត់ទូរសព្ទ។ ការសន្ទនាពីពពុះ <xliff:g id="APP_NAME">%1$s</xliff:g> តាមលំនាំដើម។"</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ធ្វើឱ្យអ្នកចាប់អារម្មណ៍ដោយប្រើផ្លូវកាត់អណ្ដែតសម្រាប់ខ្លឹមសារនេះ។"</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"ឱ្យប្រព័ន្ធកំណត់ថាតើការជូនដំណឹងនេះគួរតែបន្លឺសំឡេង ឬញ័រ"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"បង្ហាញនៅខាងលើផ្នែកសន្ទនា បង្ហាញជាពពុះអណ្ដែត បង្ហាញរូបភាពកម្រងព័ត៌មាននៅលើអេក្រង់ចាក់សោ"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"ការកំណត់"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"អាទិភាព"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"កម្មវិធីនេះកំពុងបង្ហាញពីលើកម្មវិធីផ្សេងទៀតនៅលើអេក្រង់របស់អ្នក និងកំពុងប្រើមីក្រូហ្វូន ក៏ដូចជាកាមេរ៉ា។"</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"ការកំណត់"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"យល់ព្រម"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"ការជូនដំណឹងនេះត្រូវបានបិទសំឡេងដោយប្រព័ន្ធ។"</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"ការជូនដំណឹងនេះត្រូវបានដំឡើងតំណែងដោយប្រព័ន្ធ។"</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"ការជូនដំណឹងនេះត្រូវបានបន្ទាបតំណែងដោយប្រព័ន្ធ។"</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"តើវាត្រឹមត្រូវទេ?"</string>
<string name="feedback_response" msgid="4671729244976641339">"សូមអរគុណចំពោះមតិកែលម្អរបស់អ្នក!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"យល់ព្រម"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index a906a39..0b3c4e3 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"ಬ್ಯಾಟರಿ ಮೂರು ಪಟ್ಟಿಗಳು."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"ಬ್ಯಾಟರಿ ಭರ್ತಿಯಾಗಿದೆ."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"ಬ್ಯಾಟರಿ ಶೇಕಡಾವಾರು ತಿಳಿದಿಲ್ಲ."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"ಯಾವುದೇ ಫೋನ್ ಇಲ್ಲ."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"ಪೋನ್ ಒಂದು ಪಟ್ಟಿ."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"ಫೋನ್ ಎರಡು ಪಟ್ಟಿಗಳು."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"ಫೋನ್ ಮೂರು ಪಟ್ಟಿಗಳು."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"ಫೋನ್ ಸಂಕೇತ ಪೂರ್ತಿ ಇದೆ."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"ಯಾವುದೇ ಡೇಟಾ ಇಲ್ಲ."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"ಡೇಟಾ ಒಂದು ಪಟ್ಟಿ."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"ಡೇಟಾ ಎರಡು ಪಟ್ಟಿಗಳು."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"ಡೇಟಾ ಮೂರು ಪಟ್ಟಿಗಳು."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"ಡೇಟಾ ಸಂಕೇತ ತುಂಬಿದೆ."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g> ಗೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆ."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> ಗೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆ."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> ಗೆ ಸಂಪರ್ಕಿಸಲಾಗಿದೆ."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX ಎರಡು ಪಟ್ಟಿಗಳು."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX ಮೂರು ಪಟ್ಟಿಗಳು."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX ಸಿಗ್ನಲ್ ಪೂರ್ತಿ ಇದೆ."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"ಇಥರ್ನೆಟ್ ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಲಾಗಿದೆ."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"ಇಥರ್ನೆಟ್ ಸಂಪರ್ಕಗೊಳಿಸಲಾಗಿದೆ."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"ಸಂಕೇತವಿಲ್ಲ."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"ಸಂಪರ್ಕಗೊಂಡಿಲ್ಲ."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"ಶೂನ್ಯ ಪಟ್ಟಿಗಳು."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"ಆಫ್."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"ಸಂಪರ್ಕಗೊಂಡಿದೆ."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"ಸಂಪರ್ಕಗೊಳ್ಳುತ್ತಿದೆ."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"ರೋಮಿಂಗ್"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"ವೈ-ಫೈ"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"ಯಾವುದೇ ಸಿಮ್ ಇಲ್ಲ."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"ಮೊಬೈಲ್ ಡೇಟಾ"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"ಮೊಬೈಲ್ ಡೇಟಾ ಆನ್"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"ಮೊಬೈಲ್ ಡೇಟಾ ಆಫ್"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"ಡೇಟಾ ಬಳಸಲು ಹೊಂದಿಸಲಾಗಿಲ್ಲ"</string>
<string name="cell_data_off" msgid="4886198950247099526">"ಆಫ್"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"ಬ್ಲೂಟೂತ್ ಟೆಥರಿಂಗ್."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"ಏರೋಪ್ಲೇನ್ ಮೋಡ್"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"ನಲ್ಲಿ VPN"</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"ಯಾವುದೇ ಸಿಮ್ ಇಲ್ಲ."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"ವಾಹಕ ನೆಟ್ವರ್ಕ್ ಬದಲಾಯಿಸುವಿಕೆ"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"ಬ್ಯಾಟರಿ ವಿವರಗಳನ್ನು ತೆರೆಯಿರಿ"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"ಬ್ಯಾಟರಿ <xliff:g id="NUMBER">%d</xliff:g> ಪ್ರತಿಶತ."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ನಿಮ್ಮ ಬಳಕೆಯ ಆಧಾರದ ಮೇಲೆ ಬ್ಯಾಟರಿಯು ಪ್ರತಿಶತ <xliff:g id="PERCENTAGE">%1$s</xliff:g> ರಷ್ಟು ಮತ್ತು <xliff:g id="TIME">%2$s</xliff:g> ಸಮಯ ಬಾಕಿ ಉಳಿದಿದೆ"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ಸೆಟ್ಟಿಂಗ್ಗಳನ್ನು ಆಧರಿಸಿ ಫೋನ್ ರಿಂಗ್ ಅಥವಾ ವೈಬ್ರೇಟ್ ಆಗುತ್ತದೆ. ಡಿಫಾಲ್ಟ್ ಆಗಿ, <xliff:g id="APP_NAME">%1$s</xliff:g> ನ ಬಬಲ್ ಸಂಭಾಷಣೆಗಳು."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ಈ ವಿಷಯಕ್ಕೆ ಲಿಂಕ್ ಮಾಡಿ ಕೊಂಡೊಯ್ಯುವ ಶಾರ್ಟ್ಕಟ್ ಕಡೆಗೆ ಗಮನ ಇರಿಸಿ."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"ಈ ಅಧಿಸೂಚನೆಯು ಶಬ್ದ ಮಾಡಬೇಕೇ ಅಥವಾ ವೈಬ್ರೇಟ್ ಮಾಡಬೇಕೇ ಎಂಬುದನ್ನು ನಿರ್ಧರಿಸುವ ಅವಕಾಶವನ್ನು ಸಿಸ್ಟಂಗೆ ನೀಡಿ"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"ಸಂಭಾಷಣೆ ವಿಭಾಗದ ಮೇಲ್ಭಾಗದಲ್ಲಿ ತೇಲುವ ಬಬಲ್ ಆಗಿ ಗೋಚರಿಸುತ್ತದೆ ಮತ್ತು ಪ್ರೊಫೈಲ್ ಚಿತ್ರವನ್ನು ಲಾಕ್ಸ್ಕ್ರೀನ್ ಮೇಲೆ ಗೋಚರಿಸುತ್ತದೆ"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"ಆದ್ಯತೆ"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"ಈ ಅಪ್ಲಿಕೇಶನ್ ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ನಲ್ಲಿ ಇತರ ಅಪ್ಲಿಕೇಶನ್ಗಳ ಮೇಲಿಂದ ಪ್ರದರ್ಶಿಸುತ್ತಿದೆ ಮತ್ತು ಮೈಕ್ರೊಫೋನ್ ಮತ್ತು ಕ್ಯಾಮರಾವನ್ನು ಬಳಸುತ್ತಿದೆ."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"ಸರಿ"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"ಈ ಅಧಿಸೂಚನೆಯನ್ನು ಸಿಸ್ಟಂ ಮೌನಗೊಳಿಸಿದೆ."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"ಈ ಅಧಿಸೂಚನೆಯನ್ನು ಸಿಸ್ಟಂ ಮೇಲ್ದರ್ಜೆಗೆ ಏರಿಸಿದೆ."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"ಈ ಅಧಿಸೂಚನೆಯನ್ನು ಸಿಸ್ಟಂ ಕೆಳದರ್ಜೆಗೆ ಇಳಿಸಿದೆ."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"ಇದು ಸರಿಯಾಗಿತ್ತೇ?"</string>
<string name="feedback_response" msgid="4671729244976641339">"ನಿಮ್ಮ ಪ್ರತಿಕ್ರಿಯೆಗೆ ಧನ್ಯವಾದಗಳು!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"ಸರಿ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index adedb88..e39ffaa 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"배터리 막대가 세 개입니다."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"배터리 충전이 완료되었습니다."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"배터리 잔량을 알 수 없습니다."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"휴대전화의 신호가 없습니다."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"휴대전화 신호 막대가 하나입니다."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"휴대전화 신호 막대가 두 개입니다."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"휴대전화 신호 막대가 세 개입니다."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"휴대전화의 신호가 강합니다."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"데이터가 없습니다."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"데이터 신호 막대가 하나입니다."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"데이터 신호 막대가 두 개입니다."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"데이터 신호 막대가 세 개입니다."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"데이터 신호가 강합니다."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g>에 연결되었습니다."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>에 연결되었습니다."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g>에 연결됨"</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX 신호 막대가 두 개입니다."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX 신호 막대가 세 개입니다."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX 신호가 강합니다."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"이더넷에서 연결 해제되었습니다."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"이더넷에 연결되었습니다."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"신호가 없습니다."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"연결되지 않았습니다."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"신호 막대가 없습니다."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"사용 안함"</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"연결됨"</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"연결 중..."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G 이상"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"로밍"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"SIM이 없습니다."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"모바일 데이터"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"모바일 데이터 사용"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"모바일 데이터 꺼짐"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"데이터를 사용하도록 설정되지 않음"</string>
<string name="cell_data_off" msgid="4886198950247099526">"사용 안함"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"블루투스 테더링입니다."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"비행기 모드입니다."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN 켜짐"</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"SIM 카드가 없습니다."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"이동통신사 네트워크 변경"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"배터리 세부정보 열기"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"배터리 <xliff:g id="NUMBER">%d</xliff:g>퍼센트"</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"배터리 <xliff:g id="PERCENTAGE">%1$s</xliff:g>퍼센트, 평소 사용량 기준 약 <xliff:g id="TIME">%2$s</xliff:g> 남음"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"휴대전화 설정에 따라 벨소리나 진동이 울릴 수 있습니다. 기본적으로 <xliff:g id="APP_NAME">%1$s</xliff:g>의 대화는 대화창으로 표시됩니다."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"이 콘텐츠로 연결되는 플로팅 바로가기로 사용자의 주의를 끕니다."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"시스템에서 알림 시 소리 또는 진동을 사용할지 결정하도록 허용합니다."</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"대화 섹션 상단에 표시, 플로팅 대화창으로 표시, 그리고 잠금 화면에 프로필 사진이 표시됨"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"설정"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"우선순위"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"앱이 화면의 다른 앱 위에 표시되고 있으며, 마이크와 카메라를 사용 중입니다.."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"설정"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"확인"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"시스템에서 이 알림을 숨겼습니다."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"시스템에서 이 알림의 순위를 올렸습니다."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"시스템에서 이 알림의 순위를 내렸습니다."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"맞나요?"</string>
<string name="feedback_response" msgid="4671729244976641339">"의견을 보내 주셔서 감사합니다."</string>
<string name="feedback_ok" msgid="6481426753298857144">"확인"</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 92b98fb..99cc3d5 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -189,16 +189,6 @@
<!-- String.format failed for translation -->
<!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
<skip />
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Телефон сигналы жок."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Телефон сигналы бир таякча."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Телефон сигналы эки таякча."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Телефон сигналы үч таякча."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Телефон сигналы толук."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Сигнал жок."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Мобилдик интернеттин сигналы бир таякча."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Мобилдик интернеттин сигналы эки таякча."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Мобилдик интернеттин сигналы үч таякча."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Мобилдик интернеттин сигналы толук."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g> менен туташкан."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> менен туташкан."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> менен туташты."</string>
@@ -207,8 +197,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX эки таякча."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX үч таякча."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX сигналы толук."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet ажырады."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet туташты."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Сигнал жок."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Интернет жок."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Таякча жок."</string>
@@ -220,30 +208,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Өчүк."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Туташтып турат."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Туташууда."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Роуминг"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"SIM карта жок."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Мобилдик Интернет"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Мобилдик Интернет күйгүзүлгөн"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Мобилдик Интернет өчүрүлгөн"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Дайындарды колдонуу үчүн жөндөлгөн эмес"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Өчүк"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth аркылуу интернет бөлүшүү."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Учак тартиби."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN күйүк."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"SIM карта жок"</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Байланыш оператору өзгөртүлүүдө"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Батареянын чоо-жайын ачуу"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Батарея <xliff:g id="NUMBER">%d</xliff:g> пайыз."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Батареянын деңгээли <xliff:g id="PERCENTAGE">%1$s</xliff:g> пайыз, колдонгонуңузга караганда болжол менен <xliff:g id="TIME">%2$s</xliff:g> калды"</string>
@@ -725,6 +700,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Телефондун жөндөөлөрүнө жараша шыңгырап же дирилдеши мүмкүн. <xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосундагы жазышуулар демейки жөндөө боюнча калкып чыкма билдирмелер түрүндө көрүнөт."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Калкыма ыкчам баскыч менен көңүлүңүздү бул мазмунга буруп турат."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Билдирменин үнүн чыгартууну же басууну тутумга тапшырыңыз"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Жазышуулар тизмесинин өйдө жагында калкып чыкма билдирме түрүндө көрүнүп, профиль сүрөтү кулпуланган экрандан чагылдырылат"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Жөндөөлөр"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Маанилүүлүгү"</string>
@@ -743,9 +726,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Бул колдонмо экрандагы башка терезелердин үстүнөн көрсөтүлүп, микрофонду жана камераны колдонууда."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Жөндөөлөр"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"ЖАРАЙТ"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Бул билдирменин үнү тутум тарабынан басылды."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Бул билдирменин маанилүүлүгү тутум тарабынан жогорулатылды."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Бул билдирменин маанилүүлүгү тутум тарабынан төмөндөтүлдү."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Бул туурабы?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Пикириңиз үчүн рахмат!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"Жарайт"</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index aa3bc88..a01d1a4 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"ແບັດເຕີຣີສາມຂີດ."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"ແບັດເຕີຣີເຕັມ."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"ບໍ່ຮູ້ເປີເຊັນແບັດເຕີຣີ."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"ບໍ່ມີໂທລະສັບ."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"ສັນຍານນຶ່ງຂີດ."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"ສັນຍານສອງຂີດ."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"ສັນຍານສາມຂີດ."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"ສັນຍານເຕັມ."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"ບໍ່ມີຂໍ້ມູນ."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"ຂໍ້ມູນນຶ່ງຂີດ."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"ຂໍ້ມູນສອງຂີດ."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"ຂໍ້ມູນສາມຂີດ."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"ສັນຍານຂໍ້ມູນເຕັມ."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"ເຊື່ອມຕໍ່ຫາ <xliff:g id="WIFI">%s</xliff:g> ແລ້ວ."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"ເຊື່ອມຕໍ່ຫາ <xliff:g id="BLUETOOTH">%s</xliff:g> ແລ້ວ."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"ເຊື່ອມຕໍ່ຫາ <xliff:g id="CAST">%s</xliff:g> ແລ້ວ."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX ສອງຂີດ."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX ສາມຂີດ."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"ສັນຍານ WiMAX ເຕັມ."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"ອີເທີເນັດຕັດເຊື່ອມຕໍ່ແລ້ວ."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"ອີເທີເນັດເຊື່ອມຕໍ່ແລ້ວ."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"ບໍ່ມີສັນຍານ."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"ບໍ່ໄດ້ເຊື່ອມຕໍ່."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"ບໍ່ມີຈັກຂີດ."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"ປິດ."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"ເຊື່ອມຕໍ່ແລ້ວ."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"ກຳລັງເຊື່ອມຕໍ່."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"ໂຣມມິງ"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"ບໍ່ມີຊິມ."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"ອິນເຕີເນັດມືຖື"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"ເປີດອິນເຕີເນັດມືຖືແລ້ວ"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"ປິດອິນເຕີເນັດມືຖືແລ້ວ"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"ບໍ່ໄດ້ຕັ້ງໃຫ້ໃຊ້ອິນເຕີເນັດ"</string>
<string name="cell_data_off" msgid="4886198950247099526">"ປິດ"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"ການປ່ອຍສັນຍານ Bluetooth."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"ໂໝດໃນຍົນ."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ເປີດ."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"ບໍ່ມີແຜ່ນ SIM."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"ການປ່ຽນເຄືອຂ່າຍຜູ້ໃຫ້ບໍລິການ"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"ເປີດລາຍລະອຽດແບັດເຕີຣີ"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"ແບັດເຕີຣີ <xliff:g id="NUMBER">%d</xliff:g> ເປີເຊັນ."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ແບັດເຕີຣີ <xliff:g id="PERCENTAGE">%1$s</xliff:g> ເປີເຊັນ, ເຫຼືອປະມານ <xliff:g id="TIME">%2$s</xliff:g> ອ້າງອີງຈາກການນຳໃຊ້ຂອງທ່ານ"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ອາດສົ່ງສຽງ ຫຼື ສັ່ນເຕືອນໂດຍອ້າງອີງຈາກການຕັ້ງຄ່າໂທລະສັບ. ການສົນທະນາຈາກ <xliff:g id="APP_NAME">%1$s</xliff:g> ຈະເປັນ bubble ຕາມຄ່າເລີ່ມຕົ້ນ."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ເອົາໃຈໃສ່ທາງລັດແບບລອຍໄປຫາເນື້ອຫານີ້."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"ໃຫ້ລະບົບກຳນົດວ່າການແຈ້ງເຕືອນນິ້ຄວນມີສຽງ ຫຼື ສັ່ນເຕືອນຫຼືບໍ່"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"ສະແດງຢູ່ເທິງສຸດຂອງພາກສ່ວນການສົນທະນາ, ປາກົດເປັນ bubble ແບບລອຍ, ສະແດງຮູບໂປຣໄຟລ໌ຢູ່ໜ້າຈໍລັອກ"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"ຕັ້ງຄ່າ"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"ສຳຄັນ"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"ແອັບນີ້ກຳລັງສະແດງຜົນບັງແອັບອື່ນຢູ່ໜ້າຈໍຂອງທ່ານ ແລະ ກຳລັງໃຊ້ໄມໂຄຣໂຟນ ແລະ ກ້ອງຖ່າຍຮູບຢູ່."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"ການຕັ້ງຄ່າ"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"ຕົກລົງ"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"ການແຈ້ງເຕືອນນີ້ຖືກປີດສຽງໂດຍລະບົບແລ້ວ."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"ການແຈ້ງເຕືອນນີ້ຖືກຍົກລະດັບໂດຍລະບົບແລ້ວ."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"ການແຈ້ງເຕືອນນີ້ຖືກຫຼຸດລະດັບໂດຍລະບົບແລ້ວ."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"ສິ່ງນີ້ບໍ່ຖືກຕ້ອງບໍ?"</string>
<string name="feedback_response" msgid="4671729244976641339">"ຂອບໃຈສຳລັບຄຳເຫັນຂອງທ່ານ!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"ຕົກລົງ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index c40c5c9..7cb83b9 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Trys akumuliatoriaus juostos."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Akumuliatorius įkrautas."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Akumuliatoriaus energija procentais nežinoma."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Nėra telefono."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Viena telefono juosta."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Dvi telefono juostos."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Trys telefono juostos."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Telefono signalas stiprus."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Duomenų nėra."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Viena duomenų juosta."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Dvi duomenų juostos."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Trys duomenų juostos."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Stiprus duomenų signalas."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Prisijungta prie „<xliff:g id="WIFI">%s</xliff:g>“."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Prisijungta prie „<xliff:g id="BLUETOOTH">%s</xliff:g>“."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Prisijungta prie <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Dvi „WiMAX“ signalo juostos."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Trys „WiMAX“ signalo juostos."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"„WiMAX“ signalas stiprus."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Atsijungta nuo eterneto."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Prijungta prie eterneto."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Nėra signalo."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Neprijungta."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Nė vienos juostos."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Išjungta."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Prijungta."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Prisijungiama."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Tarptinklinis ryšys"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Nėra SIM kortelės."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Mobiliojo ryšio duomenys"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobiliojo ryšio duomenys įjungti"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobiliojo ryšio duomenys išjungti"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Nenustatyta naudoti duomenis"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Išjungta"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"„Bluetooth“ įrenginio kaip modemo naudojimas."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Lėktuvo režimas."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN įjungtas."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Nėra SIM kortelės."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Keičiamas operatoriaus tinklas"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Atidaryti išsamią akumuliatoriaus informaciją"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Akumuliatorius: <xliff:g id="NUMBER">%d</xliff:g> proc."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> proc. akumuliatoriaus energijos – liko maždaug <xliff:g id="TIME">%2$s</xliff:g>, atsižvelgiant į naudojimą"</string>
@@ -729,6 +704,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Gali skambėti arba vibruoti, atsižvelgiant į telefono nustatymus. Pokalbiai iš „<xliff:g id="APP_NAME">%1$s</xliff:g>“ debesėlio pagal numatytuosius nustatymus."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Naudojant slankųjį spartųjį klavišą lengviau sutelkti dėmesį į šį turinį."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Nustatykite, kad sistema aptiktų, ar šis pranešimas turi skambėti, ar vibruoti"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Rodoma pokalbių skilties viršuje, rodoma kaip slankusis burbulas, pateikiama profilio nuotrauka užrakinimo ekrane"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Nustatymai"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritetiniai"</string>
@@ -747,9 +730,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Ši programa rodoma ekrane virš kitų programų, ji naudoja mikrofoną ir fotoaparatą."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Nustatymai"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"Gerai"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Sistema nutildė šį pranešimą."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Sistema paaukštino šį pranešimą."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Sistema pažemino šį pranešimą."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Ar tai teisinga?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Dėkojame už atsiliepimą!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"Gerai"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 85b272a..2d6a509 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Akumulators: trīs joslas."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Akumulators ir pilnīgi uzlādēts."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Akumulatora uzlādes līmenis procentos nav zināms."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Nav tālruņa."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Tālrunis: viena josla."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Tālrunis: divas joslas."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Tālrunis: trīs joslas."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Pilna piekļuve tālruņa signālam"</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Nav datu."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Dati: viena josla"</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Dati: divas joslas."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Dati: trīs joslas."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Pilna piekļuve datu signālam."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Ir izveidots savienojums ar <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Ir izveidots savienojum ar <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Savienots ar ierīci <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX divas joslas."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX trīs joslas."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX signāls pilns."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Pārtraukts savienojums ar tīklu Ethernet."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Izveidots savienojums ar tīklu Ethernet."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Nav signāla."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Savienojums nav izveidots."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Nulle joslu"</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Izslēgts"</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Savienojums ir izveidots."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Notiek savienojuma izveide..."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Viesabonēšana"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Nav SIM kartes."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Mobilie dati"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobilie dati ieslēgti"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobilie dati izslēgti"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Nav iestatīts datu lietošanai"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Izslēgti"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth piesaiste."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Lidmašīnas režīms."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ieslēgts"</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Nav SIM kartes."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Mobilo sakaru operatora tīkla mainīšana"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Atvērt akumulatora informāciju"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Akumulators: <xliff:g id="NUMBER">%d</xliff:g> procenti"</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Akumulatora uzlādes līmenis: <xliff:g id="PERCENTAGE">%1$s</xliff:g> procenti. Ņemot vērā lietojumu, atlikušais laiks ir apmēram <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -726,6 +701,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Atkarībā no tālruņa iestatījumiem var zvanīt vai vibrēt. Sarunas no lietotnes <xliff:g id="APP_NAME">%1$s</xliff:g> pēc noklusējuma tiek parādītas burbulī."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Piesaista jūsu uzmanību, rādot peldošu saīsni uz šo saturu."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Iestatiet, lai sistēma noteiktu, vai šim paziņojumam būs skaņa vai vibrācija"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Parādās sarunu sadaļas augšdaļā un kā peldošs burbulis, kā arī bloķēšanas ekrānā tiek rādīts profila attēls"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Iestatījumi"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritārs"</string>
@@ -744,9 +727,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Šī lietotne tiek rādīta ekrānā pāri citām lietotnēm, un tajā tiek izmantots mikrofons un kamera."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Iestatījumi"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"Labi"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Šim paziņojumam tika izslēgta skaņa sistēmā."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Šis paziņojums tika paaugstināts sistēmā."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Šis paziņojums tika pazemināts sistēmā."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Vai šī informācija ir pareiza?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Paldies par atsauksmēm!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"Labi"</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index bbcf93c..2168279 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Батерија три цртички."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Батеријата е полна."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Процентот на батеријата е непознат."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Нема сигнал."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Телефон една цртичка.."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Телефон две цртички."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Телефон три цртички."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Сигналот за телефон е исполнет."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Нема податоци."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Податоци една цртичка."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Сигналот за податоци е на две цртички."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Податоци три цртички."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Сигналот за податоци е исполнет."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Поврзано со <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Поврзано со <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Поврзано со <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX две цртички."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX три цртички."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Полн сигнал на WiMAX."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Етернетот е исклучен."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Етернетот е поврзан."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Нема сигнал."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Не е поврзана"</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Нула цртички."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Исклучено."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Поврзано."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Се поврзува."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Роаминг"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Нема SIM картичка."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Мобилен интернет"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Мобилниот интернет е вклучен"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Мобилниот интернет е исклучен"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Не е поставен да користи интернет"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Исклучено"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Се поврзува со Bluetooth."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Авионски режим."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN е вклучена."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Нема SIM-картичка"</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Променување на мрежата на операторот"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Отвори ги деталите за батеријата"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Батерија <xliff:g id="NUMBER">%d</xliff:g> проценти."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Батерија <xliff:g id="PERCENTAGE">%1$s</xliff:g> отсто, уште околу <xliff:g id="TIME">%2$s</xliff:g> според вашето користење"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Може да ѕвони или вибрира во зависност од поставките на телефонот Стандардно, разговорите од <xliff:g id="APP_NAME">%1$s</xliff:g> се во балончиња."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Ви го задржува вниманието со лебдечка кратенка на содржинава."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Дозволете системот да определи дали известувањево треба да испушти звук или да вибрира"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Се појавува на горниот дел од секцијата на разговорот во вид на лебдечко меурче, покажувајќи ја профилната слика на заклучениот екран"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Поставки"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Приоритетно"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Апликацијава се прикажува врз други апликации на вашиот екран и ги користи микрофонот и камерата."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Поставки"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"Во ред"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Системот го стиши известувањево."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Системот ја зголеми приоритетноста на известувањево."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Системот ја намали приоритетноста на известувањево."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Дали ова беше точно?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Фала за повратните информации!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"Во ред"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index b4db453..3cbb8e7 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"ബാറ്ററി മൂന്ന് ബാർ."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"ബാറ്ററി നിറഞ്ഞു."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"ബാറ്ററി ശതമാനം അജ്ഞാതമാണ്."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"ഫോൺ സിഗ്നൽ ഒന്നുമില്ല."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"ഫോണിൽ ഒരു ബാർ."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"ഫോണിൽ രണ്ട് ബാർ."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"ഫോണിൽ മൂന്ന് ബാർ."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"ഫോൺ സിഗ്നൽ പൂർണ്ണമാണ്."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"ഡാറ്റാ സിഗ്നൽ ഒന്നുമില്ല."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"ഡാറ്റ ഒരു ബാർ."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"ഡാറ്റ രണ്ട് ബാറുകൾ."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"ഡാറ്റ മൂന്ന് ബാർ."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"ഡാറ്റ സിഗ്നൽ പൂർണ്ണമാണ്."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g> എന്നതിലേക്ക് കണക്റ്റുചെയ്തു."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> എന്നതിലേക്ക് കണക്റ്റുചെയ്തു."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> എന്നതിലേക്ക് കണക്റ്റുചെയ്തു."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX രണ്ട് ബാറുകൾ."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX മൂന്ന് ബാറുകൾ."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX മികച്ച സിഗ്നൽ."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"ഇതർനെറ്റ് വിച്ഛേദിച്ചു."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"ഇതർനെറ്റ് കണക്റ്റുചെയ്തു."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"സിഗ്നൽ ഇല്ല."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"കണക്റ്റുചെയ്തിട്ടില്ല."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"ബാറുകളൊന്നുമില്ല."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"ഓഫാണ്."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"കണക്റ്റുചെയ്തു."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"കണക്റ്റുചെയ്യുന്നു."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"റോമിംഗ്"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDG"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"വൈഫൈ"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"സിം ഇല്ല."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"മൊബൈൽ ഡാറ്റ"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"മൊബൈൽ ഡാറ്റ ഓണാണ്"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"മൊബൈൽ ഡാറ്റ ഓഫാണ്"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"ഡാറ്റ ഉപയോഗിക്കുന്നതിന് സജ്ജീകരിച്ചിട്ടില്ല"</string>
<string name="cell_data_off" msgid="4886198950247099526">"ഓഫ്"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"ബ്ലൂടൂത്ത് ടെതറിംഗ്."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"ഫ്ലൈറ്റ് മോഡ്."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ഓണാണ്."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"SIM കാർഡൊന്നുമില്ല."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"കാരിയർ നെറ്റ്വർക്ക് മാറ്റൽ"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"ബാറ്ററി വിശദാംശങ്ങൾ തുറക്കുക"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"ബാറ്ററി <xliff:g id="NUMBER">%d</xliff:g> ശതമാനം."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ബാറ്ററി <xliff:g id="PERCENTAGE">%1$s</xliff:g> ശതമാനം, നിങ്ങളുടെ ഉപയോഗത്തിൻ്റെ അടിസ്ഥാനത്തിൽ ഏകദേശം <xliff:g id="TIME">%2$s</xliff:g> സമയം കൂടി ശേഷിക്കുന്നു"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ഫോൺ ക്രമീകരണം അടിസ്ഥാനമാക്കി റിംഗ് ചെയ്തേക്കാം അല്ലെങ്കിൽ വൈബ്രേറ്റ് ചെയ്തേക്കാം. <xliff:g id="APP_NAME">%1$s</xliff:g>-ൽ നിന്നുള്ള സംഭാഷണങ്ങൾ ഡിഫോൾട്ടായി ബബ്ൾ ആവുന്നു."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ഈ ഉള്ളടക്കത്തിലേക്ക് ഒരു ഫ്ലോട്ടിംഗ് കുറുക്കുവഴി ഉപയോഗിച്ച് നിങ്ങളുടെ ശ്രദ്ധ നിലനിർത്തുന്നു."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"ഈ അറിയിപ്പ് വരുമ്പോൾ ശബ്ദിക്കുകയാണോ വൈബ്രേറ്റ് ചെയ്യുകയാണോ വേണ്ടതെന്ന് നിർണ്ണയിക്കാൻ സിസ്റ്റത്തെ അനുവദിക്കുക"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"സംഭാഷണ വിഭാഗത്തിന് മുകളിലായി കാണിക്കുന്നു, ഫ്ലോട്ടിംഗ് ബബിളായി ദൃശ്യമാകുന്നു, ലോക്ക് സ്ക്രീനിൽ പ്രൊഫൈൽ ചിത്രം പ്രദർശിപ്പിക്കുന്നു"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"ക്രമീകരണം"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"മുൻഗണന"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"ഈ ആപ്പ് നിങ്ങളുടെ സ്ക്രീനിലെ മറ്റ് ആപ്പുകൾക്ക് മുകളിൽ പ്രദർശിപ്പിക്കുന്നു, മൈക്രോഫോണും ക്യാമറയും ഉപയോഗിക്കുകയും ചെയ്യുന്നു."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"ക്രമീകരണം"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"ശരി"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"ഈ അറിയിപ്പ്, സിസ്റ്റം നിശബ്ദമാക്കിയിരിക്കുന്നു."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"ഈ അറിയിപ്പ്, സിസ്റ്റം പ്രമോട്ട് ചെയ്തിരിക്കുന്നു."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"ഈ അറിയിപ്പ്, സിസ്റ്റം താഴേക്ക് മാറ്റിയിരിക്കുന്നു."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"ഇത് ശരിയായിരുന്നോ?"</string>
<string name="feedback_response" msgid="4671729244976641339">"നിങ്ങളുടെ ഫീഡ്ബാക്കിന് നന്ദി!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"ശരി"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 1e5a67a..9ce77ef 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Батерей гурван баганатай."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Батерей дүүрэн."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Батарейн хувь тодорхойгүй байна."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Утас байхгүй."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Утас нэг баганатай."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Утас хоёр баганатай."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Утас гурван баганатай."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Утасны дохио дүүрэн."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Дата байхгүй."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Дата нэг баганатай."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Дата хоёр баганатай."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Дата гурван баганатай."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Дата дохио дүүрэн."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g>-тай холбогдсон."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>-тай холбогдсон."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g>-д холбогдсон."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX хоёр баганатай."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX гурван баганатай."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX дохио дүүрэн."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet саллаа."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet холбогдсон."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Дохио байхгүй."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Холбогдоогүй."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Тэг баганатай."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Унтраах"</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Холбогдсон."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Холбож байна."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Роуминг"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"SIM байхгүй."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Мобайл дата"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Мобайл дата асаалттай байна"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Мобайл дата унтраалттай байна"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Дата ашиглахаар тохируулаагүй"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Идэвхгүй"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth модем болж байна."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Нислэгийн горим"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN асаалттай байна."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"SIM карт байхгүй."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Оператор компанийн сүлжээг өөрчилж байна"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Тэжээлийн дэлгэрэнгүй мэдээллийг нээх"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Батерей <xliff:g id="NUMBER">%d</xliff:g> хувьтай."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Батарей <xliff:g id="PERCENTAGE">%1$s</xliff:g> хувьтай байна. Таны хэрэглээнд тулгуурлан ойролцоогоор <xliff:g id="TIME">%2$s</xliff:g> үлдсэн"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Утасны тохиргоонд тулгуурлан хонх дуугаргах эсвэл чичирхийлж болзошгүй. <xliff:g id="APP_NAME">%1$s</xliff:g>-н харилцан яриаг өгөгдмөл тохиргооны дагуу бөмбөлөг болгоно."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Энэ контентын хөвөн гарч ирэх товчлолтойгоор таны анхаарлыг татдаг."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Энэ мэдэгдэл дуу гаргах эсвэл чичрэх эсэхийг системээр тодорхойлуулаарай"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Харилцан ярианы хэсгийн дээд талд хөвж буй бөмбөлөг хэлбэрээр харагдах бөгөөд профайлын зургийг түгжигдсэн дэлгэцэд үзүүлнэ"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Тохиргоо"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Ач холбогдол"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Энэ аппыг таны дэлгэцэд бусад аппын дээр харуулж байгаа бөгөөд микрофон болон камерыг ашиглаж байна."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Тохиргоо"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"ОК"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Систем энэ мэдэгдлийг дуугүй болгосон."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Систем энэ мэдэгдлийн зэргийг дэвшүүлсэн."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Систем энэ мэдэгдлийн зэргийг бууруулсан."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Энэ зөв байсан уу?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Санал хүсэлтээ илгээсэнд баярлалаа!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"ОК"</string>
@@ -839,7 +827,7 @@
<string name="switch_bar_on" msgid="1770868129120096114">"Идэвхтэй"</string>
<string name="switch_bar_off" msgid="5669805115416379556">"Идэвхгүй"</string>
<string name="tile_unavailable" msgid="3095879009136616920">"Боломжгүй"</string>
- <string name="nav_bar" msgid="4642708685386136807">"Навигацийн самбар"</string>
+ <string name="nav_bar" msgid="4642708685386136807">"Навигацын самбар"</string>
<string name="nav_bar_layout" msgid="4716392484772899544">"Бүдүүвч"</string>
<string name="left_nav_bar_button_type" msgid="2634852842345192790">"Нэмэлт зүүн товчлуураар шивэх"</string>
<string name="right_nav_bar_button_type" msgid="4472566498647364715">"Нэмэлт баруун товчлуураар шивэх"</string>
@@ -861,7 +849,7 @@
<string name="reset" msgid="8715144064608810383">"Шинэчлэх"</string>
<string name="adjust_button_width" msgid="8313444823666482197">"Товчлуурын өргөнг тохируулах"</string>
<string name="clipboard" msgid="8517342737534284617">"Түр санах ой"</string>
- <string name="accessibility_key" msgid="3471162841552818281">"Навигацийн товчлуурыг өөрчлөх"</string>
+ <string name="accessibility_key" msgid="3471162841552818281">"Навигацын товчлуурыг өөрчлөх"</string>
<string name="left_keycode" msgid="8211040899126637342">"Зүүн түлхүүрийн код"</string>
<string name="right_keycode" msgid="2480715509844798438">"Баруун түлхүүрийн код"</string>
<string name="left_icon" msgid="5036278531966897006">"Зүүн дүрс тэмдэг"</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index a667ab7..ed4b7f4 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"बॅटरी तीन बार."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"बॅटरी पूर्ण भरली."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"बॅटरीच्या चार्जिंगची टक्केवारी माहित नाही."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"कोणताही फोन नाही."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"फोन एक बार."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"फोन दोन बार."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"फोन तीन बार."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"फोन सिग्नल पूर्ण."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"कोणताही डेटा नाही."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"डेटा एक बार."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"डेटा दोन बार."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"डेटा तीन बार."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"डेटा सिग्नल पूर्ण."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g> शी कनेक्ट केले."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> शी कनेक्ट केले."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> शी कनेक्ट केले."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX दोन बार."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX तीन बार."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX सिग्नल पूर्ण."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"इथरनेट डिस्कनेक्ट केले."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"इथरनेट कनेक्ट केले."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"सिग्नल नाही."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"कनेक्ट केले नाही."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"शून्य बार."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"बंद."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"कनेक्ट केले."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"कनेक्ट करत आहे."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"३G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"४G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"४G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"१X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"रोमिंग"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"वाय-फाय"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"सिम नाही."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"मोबाइल डेटा"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"मोबाइल डेटा सुरू आहे"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"मोबाइल डेटा बंद आहे"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"डेटा वापरण्यासाठी सेट केलेले नाही"</string>
<string name="cell_data_off" msgid="4886198950247099526">"बंद"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"ब्लूटूथ टेदरिंग."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"विमान मोड."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN सुरू."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"सिम कार्ड नाही."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"वाहक नेटवर्क बदलत आहे"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"बॅटरी तपशील उघडा"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"बॅटरी <xliff:g id="NUMBER">%d</xliff:g> टक्के."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"बॅटरी <xliff:g id="PERCENTAGE">%1$s</xliff:g> टक्के, तुमच्या वापराच्या आधारावर सुमारे <xliff:g id="TIME">%2$s</xliff:g> शिल्लक आहे"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"फोन सेटिंग्जच्या आधारावर रिंग किंवा व्हायब्रेट होऊ शकतो. <xliff:g id="APP_NAME">%1$s</xliff:g> मधील संभाषणे बाय डीफॉल्ट बबल होतात."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"या आशयाच्या फ्लोटिंग शॉर्टकटसह तुमचे लक्ष केंद्रित करते."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"ही सूचना मिळाल्यावर आवाज व्हावा की व्हायब्रेशन व्हावे ते सिस्टममध्ये नमूद करा"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"संभाषण विभागात सर्वात वरती फ्लोटिंग बबल म्हणून दिसते, लॉक स्क्रीनवर प्रोफाइल पिक्चर दाखवते"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"सेटिंग्ज"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"प्राधान्य"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"हे अॅप तुमच्या स्क्रीनवरील इतर अॅप्स वर प्रदर्शित होत आहे आणि मायक्रोफोन आणि कॅमेरा वापरत आहे."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"सेटिंग्ज"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"ओके"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"ही सूचना सिस्टमने सायलंट केली होती."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"ही सूचना सिस्टमने प्रमोट केली होती."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"ही सूचना सिस्टमने डीमोट केली होती."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"हे बरोबर होते का?"</string>
<string name="feedback_response" msgid="4671729244976641339">"तुमच्या फीडबॅकबद्दल धन्यवाद!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"ओके"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 8656590..e03de37 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Bateri tiga bar."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Bateri penuh."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Peratusan kuasa bateri tidak diketahui."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Tiada telefon."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefon satu bar."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefon dua bar."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefon tiga bar."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Isyarat telefon penuh."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Tiada data."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Data satu bar."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Data dua bar."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Data tiga bar."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Isyarat data penuh."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Disambungkan kepada <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Disambungkan kepada <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Disambungkan ke <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX dua bar."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX tiga bar."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Isyarat WiMAX penuh."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet diputuskan sambungan."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet disambungkan."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Tiada isyarat."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Tidak disambungkan."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Tiada bar."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Dimatikan."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Disambungkan."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Menyambung."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Perayauan"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Tiada SIM."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Data Mudah Alih"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Data Mudah Alih Dihidupkan"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Data mudah alih dimatikan"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Tidak ditetapkan untuk menggunakan data"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Mati"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Penambatan Bluetooth."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Mod pesawat"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN dihidupkan."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Tiada kad SIM."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Rangkaian pembawa berubah"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Buka butiran bateri"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Bateri <xliff:g id="NUMBER">%d</xliff:g> peratus."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Bateri <xliff:g id="PERCENTAGE">%1$s</xliff:g> peratus, tinggal kira-kira <xliff:g id="TIME">%2$s</xliff:g> lagi berdasarkan penggunaan anda"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Mungkin berbunyi atau bergetar berdasarkan tetapan telefon. Perbualan daripada gelembung <xliff:g id="APP_NAME">%1$s</xliff:g> secara lalai."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Memastikan anda memberikan perhatian dengan pintasan terapung ke kandungan ini."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Minta sistem menentukan jika pemberitahuan ini patut menghasilkan bunyi atau getaran"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Ditunjukkan di sebelah atas bahagian perbualan, muncul sebagai gelembung terapung, memaparkan gambar profil pada skrin kunci"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Tetapan"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Keutamaan"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Apl ini dipaparkan di atas apl lain pada skrin anda dan sedang menggunakan mikrofon dan kamera."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Tetapan"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Pemberitahuan ini disenyapkan oleh sistem."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Pemberitahuan ini dinaik taraf oleh sistem."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Pemberitahuan ini diturun taraf oleh sistem."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Adakah ini betul?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Terima kasih atas maklum balas anda!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 5b5531d0..50154ba 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"ဘတ္တရီသုံးဘား။"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"ဘတ္တရီအပြည့်။"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"ဘက်ထရီရာခိုင်နှုန်းကို မသိပါ။"</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"ဖုန်းလိုင်းမရှိပါ။"</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"ဖုန်းလိုင်းတစ်ဘား။"</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"ဖုန်းလိုင်းနှစ်ဘား။"</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"ဖုန်းလိုင်းသုံးဘား။"</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"ဖုန်းလိုင်းအပြည့်။"</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"ဒေတာမရှိပါ။"</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"ဒေတာတစ်ဘား။"</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"ဒေတာထုတ်လွှင့်မှု ၂ဘားဖမ်းမိခြင်း။"</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"ဒေတာသုံးဘား။"</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"ဒေတာထုတ်လွှင့်မှုအပြည့်ဖမ်းမိခြင်း"</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g>သို့ ချိတ်ဆက်ထား။"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>သို့ ချိတ်ဆက်ထား"</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> သို့ချိတ်ဆက်ထားပါသည်။"</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"ဝိုင်မက်စ် ၂ ဘားရှိ"</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"ဝိုင်မက်စ် ၃ ဘား"</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"ဝိုင်မက်စ် အပြည့်ရှိ"</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet နှင့်ချိတ်ဆက်မှုပြတ်တောက်"</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet ချိတ်ဆက်ထား။"</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"အချက်ပြမှု မရှိပါ"</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"ချိတ်ဆက်မထားပါ"</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"၀ ဘား"</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"ပိတ်ထားသည်"</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"ချိတ်ဆက်ထားသည်"</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"ချိတ်ဆက်နေ။"</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"ပြင်ပကွန်ရက်နှင့် ချိတ်ဆက်ခြင်း"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"ဆင်းကဒ်မရှိပါ။"</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"မိုဘိုင်းဒေတာ"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"မိုဘိုင်းဒေတာကို ဖွင့်ထားပါသည်"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"မိုဘိုင်းဒေတာ ပိတ်ထားသည်"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"ဒေတာအသုံးပြုရန် သတ်မှတ်မထားပါ"</string>
<string name="cell_data_off" msgid="4886198950247099526">"ပိတ်ရန်"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"ဘလူးတုသ်သုံး၍ ချိတ်ဆက်ခြင်း"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"လေယာဉ်ပျံမုဒ်"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ကို ဖွင့်ထားသည်။"</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"SIM ကတ် မရှိပါ"</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"ဝန်ဆောင်မှုပေးသူ ကွန်ရက် ပြောင်းလဲနေသည်။"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"ဘက်ထရီ အသေးစိတ် အချက်အလက်များကို ဖွင့်ပါ"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"ဘက်ထရီ <xliff:g id="NUMBER">%d</xliff:g> ရာခိုင်နှုန်း။"</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ဘက်ထရီ <xliff:g id="PERCENTAGE">%1$s</xliff:g> ရာခိုင်နှုန်း၊ သင်၏ အသုံးပြုမှုအပေါ် မူတည်၍ <xliff:g id="TIME">%2$s</xliff:g> ခန့်ကျန်သည်"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ဖုန်းဆက်တင်များပေါ် အခြေခံပြီး အသံမြည်နိုင်သည် သို့မဟုတ် တုန်ခါနိုင်သည်။ မူရင်းသတ်မှတ်ချက်အဖြစ် <xliff:g id="APP_NAME">%1$s</xliff:g> မှ စကားဝိုင်းများကို ပူဖောင်းကွက်ဖြင့် ပြသည်။"</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"အကြောင်းအရာကို floating shortcut ကိုသုံး၍ အာရုံစိုက်လာအောင်လုပ်ပါ။"</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"ဤအကြောင်းကြားချက်က အသံ သို့မဟုတ် တုန်ခါမှု ပေးရန် သင့်/မသင့်ကို စနစ်က ဆုံးဖြတ်ပါစေ"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"စကားဝိုင်းကဏ္ဍ၏ ထိပ်ပိုင်းတွင် ပြပြီး ပူဖောင်းကွက်အဖြစ် မြင်ရသည်၊ လော့ခ်ချထားချိန် မျက်နှာပြင်တွင် ပရိုဖိုင်ပုံကို ပြသည်"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"ဆက်တင်များ"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"ဦးစားပေး"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"ဤအက်ပ်က မိုက်ခရိုဖုန်းနှင့် ကင်မရာကို အသုံးပြု၍ ဖန်သားမျက်နှာပြင်ပေါ်ရှိ အခြားအက်ပ်များ အပေါ်မှ ထပ်ပြီး ပြသနေပါသည်။"</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"ဆက်တင်များ"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"ဤအကြောင်းကြားချက်ကို စနစ်က အသံပိတ်ထားလိုက်သည်။"</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"ဤအကြောင်းကြားချက်ကို စနစ်က အဆင့်မြှင့်လိုက်သည်။"</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"ဤအကြောင်းကြားချက်ကို စနစ်က အဆင့်ချလိုက်သည်။"</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"ဤအရာက မှန်ပါသလား။"</string>
<string name="feedback_response" msgid="4671729244976641339">"အကြံပြုချက်အတွက် ကျေးဇူးတင်ပါသည်"</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 6b0568d..4147bc8 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Batteri – tre stolper."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Batteriet er fullt."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Batteriprosenten er ukjent."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Ingen telefon."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefon – én stolpe."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefon – to stolper."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefon – tre stolper."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Telefonsignal er fullt."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Ingen data."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Data – én stolpe"</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Data – to stolper."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Data – tre stolper."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Datasignal er fullt."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Koblet til <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Koblet til <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Koblet til <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX – to stolper."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX – tre stolper."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Fullt WiMAX-signal."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet er frakoblet."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet er tilkoblet."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Ikke noe signal."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Ikke tilkoblet."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Ingen stolper."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Av."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Tilkoblet."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Kobler til."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Uten SIM."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Mobildata"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobildata er slått på"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobildata er slått av"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Ikke konfigurert til å bruke data"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Av"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth-internettdeling."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Flymodus."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN på."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Mangler SIM-kort."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Bytting av operatørnettverk"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Åpne informasjon om batteriet"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Batteri – <xliff:g id="NUMBER">%d</xliff:g> prosent."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Batterinivået er <xliff:g id="PERCENTAGE">%1$s</xliff:g> prosent – omtrent <xliff:g id="TIME">%2$s</xliff:g> gjenstår basert på bruken din"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Kan ringe eller vibrere basert på telefoninnstillingene. Samtaler fra <xliff:g id="APP_NAME">%1$s</xliff:g> lager bobler som standard."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Holder deg oppmerksom med en svevende snarvei til dette innholdet."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"La systemet velge om dette varselet skal lage lyd eller vibrere"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Vises øverst i samtaledelen, vises som en flytende boble, viser profilbildet på låseskjermen"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Innstillinger"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritet"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Denne appen vises over andre apper på skjermen, og bruker mikrofonen og kameraet."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Innstillinger"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Dette varselet ble dempet av systemet."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Dette varselet ble oppgradert av systemet."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Dette varselet ble nedgradert av systemet."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Var det riktig?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Takk for tilbakemeldingen!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index f72808f..e4fbe93 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"ब्याट्रिका तिनवटा पट्टिहरू"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"ब्याट्री पूर्ण छ।"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"ब्याट्रीमा कति प्रतिशत चार्ज छ भन्ने कुराको जानाकरी छैन।"</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"फोन छैन्।"</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"फोन एउटा पट्टि।"</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"फोन दुई पट्टि।"</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"फोन तिन पट्टिहरू।"</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"फोन सङ्केत भरिएको।"</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"डेटा छैन।"</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"डेटाको एउटा पट्टि।"</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"डेटा दुई बाधाहरू।"</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"डेटा तिन बाधाहरू।"</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"डेटा संकेत पूर्ण।"</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g> मा जडित।"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> मा जडित।"</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> मा कनेक्ट गरियो।"</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"वाइम्याक्स दुईवटा बारहरू।"</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"वाइम्याक्स तिनवटा बारहरू।"</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"वाइम्याक्स सङ्केत भरिएका।"</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"इथरनेट विच्छेद भयो।"</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"इथरनेट जोडियो।"</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"सङ्केत छैन।"</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"जडान नगरिएको।"</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"शून्य पट्टि।"</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"बन्द गर्नुहोस्।"</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"जडान गरिएको।"</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"जडान हुँदै।"</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"रोमिङ"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"SIM छैन।"</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"मोबाइल डेटा"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"मोबाइल डेटा सक्रिय छ"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"मोबाइल डेटा निष्क्रिय छ"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"डेटा प्रयोग गर्ने गरी सेट गरिएन"</string>
<string name="cell_data_off" msgid="4886198950247099526">"निष्क्रिय पार्नु"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"ब्लुटुथ टेदर गर्दै।"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"हवाइजहाज मोड।"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN सक्रिय छ।"</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"SIM कार्ड छैन।"</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"सेवा प्रदायकको नेटवर्क परिवर्तन गर्ने आइकन"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"ब्याट्री सम्बन्धी विवरणहरूलाई खोल्नुहोस्"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"ब्याट्री <xliff:g id="NUMBER">%d</xliff:g> प्रतिशत"</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ब्याट्रीको चार्ज <xliff:g id="PERCENTAGE">%1$s</xliff:g> प्रतिशत छ, तपाईंको प्रयोगका आधारमा <xliff:g id="TIME">%2$s</xliff:g> बाँकी छ"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"फोनको सेटिङका आधारमा घन्टी बज्न वा कम्पन हुन सक्छ। <xliff:g id="APP_NAME">%1$s</xliff:g> का वार्तालापहरू पूर्वनिर्धारित रूपमा बबलमा देखाइन्छन्।"</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"फ्लोटिङ सर्टकटमार्फत यो सामग्रीतर्फ तपाईंको ध्यान आकर्षित गर्दछ।"</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"सिस्टमलाई यो सूचना आउँदा ध्वनि बज्नु पर्छ वा कम्पन हुनु पर्छ भन्ने कुराको निधो गर्न दिनुहोस्"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"वार्तालाप खण्डको सिरानमा देखा पर्छ, तैरने बबलका रूपमा देखा पर्छ, लक स्क्रिनमा प्रोफाइल फोटो देखाइन्छ"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"सेटिङ"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"प्राथमिकता"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"यो अनुप्रयोगले तपाईंको स्क्रिनका अन्य एपमाथि प्रदर्शन गर्नुका साथै माइक्रोफोन र क्यामेराको प्रयोग गर्दै छ।"</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"सेटिङहरू"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"ठिक छ"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"सिस्टमले यो सूचना आउँदा बज्ने ध्वनि बन्द गरेको छ।"</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"सिस्टमले यो सूचनालाई दिइने दर्जा बढाएको छ।"</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"सिस्टमले यो सूचनालाई दिइने दर्जा घटाएको छ।"</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"के यो सही थियो?"</string>
<string name="feedback_response" msgid="4671729244976641339">"तपाईंको प्रतिक्रियाका लागि धन्यवाद!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"ठिक छ"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index aa738c4..1871eef 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Batterij: drie streepjes."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Batterij is vol."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Batterijpercentage onbekend."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Geen telefoonsignaal."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefoon: één streepje."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefoon: twee streepjes."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefoon: drie streepjes."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Telefoonsignaal is op volle sterkte."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Geen gegevens."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Gegevens: één streepje."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Gegevens: twee streepjes."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Gegevens: drie streepjes."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Gegevenssignaal is op volle sterkte."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Verbonden met <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Verbonden met <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Verbonden met <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX: twee streepjes."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX: drie streepjes."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX-signaal is op volle sterkte."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernetverbinding verbroken."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet verbonden."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Geen signaal."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Niet verbonden."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Geen streepjes."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Uitgeschakeld."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Verbonden."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Verbinden."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wifi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Geen simkaart."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Mobiele data"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobiele data aan"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobiele data uit"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Gebruik van gegevens is niet ingesteld"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Uit"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth-tethering."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Vliegtuigmodus."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ingeschakeld."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Geen simkaart."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Netwerk van provider wordt gewijzigd"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Accudetails openen"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Batterij: <xliff:g id="NUMBER">%d</xliff:g> procent."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Batterij op <xliff:g id="PERCENTAGE">%1$s</xliff:g> procent, nog ongeveer <xliff:g id="TIME">%2$s</xliff:g> op basis van je gebruik"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Kan overgaan of trillen op basis van de telefooninstellingen. Gesprekken uit <xliff:g id="APP_NAME">%1$s</xliff:g> worden standaard als bubbels weergegeven."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Trekt de aandacht met een zwevende snelkoppeling naar deze content."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Het systeem laten bepalen of deze melding geluid moet maken of moet trillen"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Wordt bovenaan het gespreksgedeelte weergegeven, verschijnt als zwevende bubbel, geeft profielfoto weer op vergrendelscherm"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Instellingen"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioriteit"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Deze app geeft andere apps op je scherm weer en gebruikt de microfoon en camera."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Instellingen"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Deze melding is gedempt door het systeem."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Deze melding is gepromoveerd door het systeem."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Deze melding is verlaagd door het systeem."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Is dit juist?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Bedankt voor je feedback."</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 7e34067..601b8f4 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"ବ୍ୟାଟେରୀର ତିନୋଟି ବାର୍ ଅଛି।"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"ବ୍ୟାଟେରୀ ପୂର୍ଣ୍ଣ।"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"ବ୍ୟାଟେରୀ ଶତକଡ଼ା ଅଜଣା ଅଟେ।"</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"କୌଣସି ଫୋନ୍ ନାହିଁ।"</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"ଫୋନର ଗୋଟିଏ ବାର ଅଛି।"</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"ଫୋନର ଦୁଇଟି ବାର୍ ଅଛି।"</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"ଫୋନ୍ରେ ତିନୋଟି ବାର୍ ଅଛି।"</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"ଫୋନ୍ ସିଗ୍ନାଲ୍ ପୂର୍ଣ୍ଣ ଅଛି।"</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"କୌଣସି ଡାଟା ନାହିଁ।"</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"ଡାଟାର ଗୋଟିଏ ବାର ଅଛି।"</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"ଡାଟାର ଦୁଇଟି ବାର୍ ଅଛି।"</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"ଡାଟାର ତିନୋଟି ବାର୍ ଅଛି।"</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"ଡାଟା ସିଗ୍ନାଲ୍ ପୂର୍ଣ୍ଣ ଅଛି।"</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g> ସହିତ ସଂଯୁକ୍ତ।"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> ସହ ସଂଯୁକ୍ତ"</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> ସହିତ ସଂଯୁକ୍ତ।"</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAXର ଦୁଇଟି ବାର୍ ଅଛି।"</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAXର ତିନୋଟି ବାର୍ ଅଛି।"</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAXର ସିଗ୍ନାଲ୍ ସମ୍ପୂର୍ଣ୍ଣ ଅଛି।"</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"ଇଥରନେଟ୍ ବିଚ୍ଛିନ୍ନ ହୋଇଛି।"</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"ଇଥରନେଟ୍ ସଂଯୁକ୍ତ ହୋଇଛି।"</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"କୌଣସି ସିଗ୍ନାଲ୍ ନାହିଁ।"</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"ସଂଯୁକ୍ତ ହୋଇନାହିଁ।"</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"କୌଣସି ବାର୍ ନାହିଁ।"</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"ବନ୍ଦ।"</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"ସଂଯୁକ୍ତ।"</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"ସଂଯୋଗ କରୁଛି।"</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"ରୋମିଙ୍ଗ"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"ୱାଇ-ଫାଇ"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"କୌଣସି SIM ନାହିଁ।"</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"ମୋବାଇଲ୍ ଡାଟା"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"ମୋବାଇଲ୍ ଡାଟା ଅନ୍"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"ମୋବାଇଲ୍ ଡାଟା ବନ୍ଦ ଅଛି"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"ବ୍ୟବହୃତ ଡାଟା ପାଇଁ ସେଟ୍ ହୋଇନାହିଁ"</string>
<string name="cell_data_off" msgid="4886198950247099526">"ବନ୍ଦ"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"ବ୍ଲୁଟୁଥ ଟିଥରିଂ।"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"ଏରୋପ୍ଲେନ୍ ମୋଡ୍।"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ଅନ୍।"</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"କୌଣସି SIM କାର୍ଡ ନାହିଁ।"</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"କେରିଅର୍ ନେଟ୍ୱର୍କ ବଦଳୁଛି"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"ବ୍ୟାଟେରୀ ବିବରଣୀ ଖୋଲନ୍ତୁ"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"ବ୍ୟାଟେରୀ <xliff:g id="NUMBER">%d</xliff:g> ଶତକଡ଼ା।"</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ବ୍ୟାଟେରୀ <xliff:g id="PERCENTAGE">%1$s</xliff:g> ଶତକଡା, ଆପଣଙ୍କର ବ୍ୟବହାରକୁ ଆଧାର କରି ପାଖାପାଖି <xliff:g id="TIME">%2$s</xliff:g> ବାକି ଅଛି"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ଫୋନ୍ ସେଟିଂସ୍ ଆଧାରରେ ରିଙ୍ଗ କିମ୍ବା ଭାଇବ୍ରେଟ୍ ହୋଇପାରେ। <xliff:g id="APP_NAME">%1$s</xliff:g>ରୁ ବାର୍ତ୍ତାଳାପଗୁଡ଼ିକ ଡିଫଲ୍ଟ ଭାବରେ ବବଲ୍ ହୁଏ।"</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ଏହି ବିଷୟବସ୍ତୁ ପାଇଁ ଏକ ଭାସମାନ ସର୍ଟକଟ୍ ସହ ଆପଣଙ୍କର ଧ୍ୟାନ ଦିଅନ୍ତୁ।"</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"ଏହି ବିଜ୍ଞପ୍ତି ପ୍ରାପ୍ତ ହେବା ସମୟରେ ସାଉଣ୍ଡ ହେବା ଉଚିତ ନା ଭାଇବ୍ରେସନ୍ ତାହା ସିଷ୍ଟମକୁ ସ୍ଥିର କରିବାକୁ ଦିଅନ୍ତୁ"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"ବାର୍ତ୍ତାଳାପ ବିଭାଗର ଶୀର୍ଷରେ ଦେଖାଏ, ଫ୍ଲୋଟିଂ ବବଲ୍ ଭାବେ ଦେଖାଯାଏ, ଲକ୍ ସ୍କ୍ରିନରେ ପ୍ରୋଫାଇଲ୍ ଛବି ଡିସପ୍ଲେ କରେ"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"ସେଟିଂସ୍"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"ପ୍ରାଥମିକତା"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"ଏହି ଆପ୍, ଆପଣଙ୍କର ସ୍କ୍ରୀନ୍ ଉପରେ ଥିବା ଅନ୍ୟ ଆପ୍ ଉପରେ ପ୍ରଦର୍ଶିତ ହେଉଛି ଏବଂ ମାଇକ୍ରୋଫୋନ୍ ଓ କ୍ୟାମେରା ବ୍ୟବହାର କରୁଛି।"</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"ସେଟିଂସ୍"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"ଠିକ୍ ଅଛି"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"ଏହି ବିଜ୍ଞପ୍ତିକୁ ସିଷ୍ଟମ୍ ଦ୍ୱାରା ନୀରବ କରାଯାଇଥିଲା।"</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"ଏହି ବିଜ୍ଞପ୍ତିକୁ ସିଷ୍ଟମ୍ ଦ୍ୱାରା ପ୍ରମୋଟ୍ କରାଯାଇଥିଲା।"</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"ଏହି ବିଜ୍ଞପ୍ତିକୁ ସିଷ୍ଟମ୍ ଦ୍ୱାରା ଡିମୋଟ୍ କରାଯାଇଥିଲା।"</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"ଏହା ଠିକ୍ ଥିଲା କି?"</string>
<string name="feedback_response" msgid="4671729244976641339">"ଆପଣଙ୍କ ମତାମତ ପାଇଁ ଧନ୍ୟବାଦ!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"ଠିକ୍ ଅଛି"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index ca4b6ad..b374a6e 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"ਬੈਟਰੀ ਤਿੰਨ ਬਾਰਸ।"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"ਬੈਟਰੀ ਪੂਰੀ।"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"ਬੈਟਰੀ ਪ੍ਰਤੀਸ਼ਤ ਅਗਿਆਤ ਹੈ।"</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"ਕੋਈ ਫ਼ੋਨ ਨਹੀਂ।"</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"ਫ਼ੋਨ ਇੱਕ ਬਾਰ।"</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"ਫ਼ੋਨ ਦੋ ਬਾਰਸ।"</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"ਫ਼ੋਨ ਤਿੰਨ ਬਾਰਸ।"</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"ਫ਼ੋਨ ਸਿਗਨਲ ਪੂਰਾ।"</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"ਕੋਈ ਡਾਟਾ ਨਹੀਂ।"</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">" ਡਾਟਾ ਇੱਕ ਬਾਰ।"</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">" ਡਾਟਾ ਦੋ ਬਾਰਸ।"</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">" ਡਾਟਾ ਤਿੰਨ ਬਾਰ।"</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">" ਡਾਟਾ ਸਿਗਨਲ ਪੂਰਾ।"</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ।"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ।"</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ।"</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX ਦੋ ਬਾਰਸ।"</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX ਤਿੰਨ ਬਾਰਸ।"</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX ਸਿਗਨਲ ਪੂਰਾ।"</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"ਈਥਰਨੈੱਟ ਡਿਸਕਨੈਕਟ ਹੋ ਗਿਆ।"</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"ਈਥਰਨੈੱਟ ਕਨੈਕਟ ਹੋ ਗਿਆ।"</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"ਕੋਈ ਸਿਗਨਲ ਨਹੀਂ।"</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"ਕਨੈਕਟ ਨਹੀਂ ਕੀਤਾ।"</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"ਸਿਫ਼ਰ ਬਾਰਸ।"</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"ਬੰਦ।"</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"ਕਨੈਕਟ ਕੀਤਾ।"</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"ਕਨੈਕਟ ਕਰ ਰਿਹਾ ਹੈ।"</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"ਰੋਮਿੰਗ"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"ਵਾਈ-ਫਾਈ"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"ਕੋਈ SIM ਨਹੀਂ।"</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"ਮੋਬਾਈਲ ਡਾਟਾ"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"ਮੋਬਾਈਲ ਡਾਟਾ ਚਾਲੂ"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"ਮੋਬਾਈਲ ਡਾਟਾ ਬੰਦ"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"ਡਾਟਾ ਵਰਤਣ ਲਈ ਸੈੱਟ ਨਹੀਂ"</string>
<string name="cell_data_off" msgid="4886198950247099526">"ਬੰਦ"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"ਬਲੂਟੁੱਥ ਟੈਦਰਿੰਗ।"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"ਏਅਰਪਲੇਨ ਮੋਡ।"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ਚਾਲੂ ਹੈ।"</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"ਕੋਈ ਸਿਮ ਕਾਰਡ ਨਹੀਂ।"</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"ਕੈਰੀਅਰ ਨੈੱਟਵਰਕ ਦੀ ਬਦਲੀ"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"ਬੈਟਰੀ ਵੇਰਵੇ ਖੋਲ੍ਹੋ"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"ਬੈਟਰੀ <xliff:g id="NUMBER">%d</xliff:g> ਪ੍ਰਤੀਸ਼ਤ ਹੈ।"</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"ਬੈਟਰੀ <xliff:g id="PERCENTAGE">%1$s</xliff:g> ਫ਼ੀਸਦ, ਤੁਹਾਡੀ ਵਰਤੋਂ ਦੇ ਆਧਾਰ \'ਤੇ ਲਗਭਗ <xliff:g id="TIME">%2$s</xliff:g> ਬਾਕੀ"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ਫ਼ੋਨ ਸੈਟਿੰਗਾਂ ਦੇ ਆਧਾਰ \'ਤੇ ਘੰਟੀ ਵੱਜ ਸਕਦੀ ਹੈ ਜਾਂ ਥਰਥਰਾਹਟ ਹੋ ਸਕਦੀ ਹੈ। ਪੂਰਵ-ਨਿਰਧਾਰਤ ਤੌਰ \'ਤੇ <xliff:g id="APP_NAME">%1$s</xliff:g> ਬਬਲ ਤੋਂ ਗੱਲਾਂਬਾਤਾਂ।"</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ਇਸ ਸਮੱਗਰੀ ਦੇ ਅਸਥਿਰ ਸ਼ਾਰਟਕੱਟ ਨਾਲ ਆਪਣਾ ਧਿਆਨ ਕੇਂਦਰਿਤ ਰੱਖੋ।"</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"ਸਿਸਟਮ ਨੂੰ ਨਿਰਧਾਰਤ ਕਰਨ ਦਿਓ ਕਿ ਇਸ ਸੂਚਨਾ ਲਈ ਕੋਈ ਧੁਨੀ ਵਜਾਉਣੀ ਚਾਹੀਦੀ ਹੈ ਜਾਂ ਥਰਥਰਾਹਟ ਕਰਨੀ ਚਾਹੀਦੀ ਹੈ"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"ਗੱਲਬਾਤ ਸੈਕਸ਼ਨ ਦੇ ਸਿਖਰ \'ਤੇ ਦਿਖਾਈਆਂ ਜਾਂਦੀਆਂ ਹਨ, ਬਬਲ ਵਜੋਂ ਦਿਸਦੀਆਂ ਹਨ, ਲਾਕ ਸਕ੍ਰੀਨ \'ਤੇ ਪ੍ਰੋਫਾਈਲ ਤਸਵੀਰ ਦਿਖਾਈ ਜਾਂਦੀ ਹੈ"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"ਸੈਟਿੰਗਾਂ"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"ਤਰਜੀਹ"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"ਇਹ ਐਪ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਹੋਰਾਂ ਐਪਾਂ ਉੱਪਰ ਦਿਖਾਈ ਜਾ ਰਹੀ ਹੈ ਅਤੇ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਅਤੇ ਕੈਮਰੇ ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੀ ਹੈ।"</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"ਸੈਟਿੰਗਾਂ"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"ਠੀਕ ਹੈ"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"ਸਿਸਟਮ ਵੱਲੋਂ ਇਹ ਸੂਚਨਾ ਸ਼ਾਂਤ ਕਰ ਦਿੱਤੀ ਗਈ ਸੀ।"</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"ਸਿਸਟਮ ਵੱਲੋਂ ਇਸ ਸੂਚਨਾ ਦਾ ਦਰਜਾ ਵਧਾ ਦਿੱਤਾ ਗਿਆ ਸੀ।"</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"ਸਿਸਟਮ ਵੱਲੋਂ ਇਸ ਸੂਚਨਾ ਦਾ ਦਰਜਾ ਘਟਾ ਦਿੱਤਾ ਗਿਆ ਸੀ।"</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"ਕੀ ਇਹ ਸਹੀ ਸੀ?"</string>
<string name="feedback_response" msgid="4671729244976641339">"ਤੁਹਾਡੇ ਵਿਚਾਰ ਲਈ ਧੰਨਵਾਦ!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"ਠੀਕ ਹੈ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 142a507..3ff500e 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Bateria: trzy paski."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Bateria naładowana."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Poziom naładowania baterii jest nieznany."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Brak sygnału telefonu."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefon: jeden pasek."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefon: dwa paski."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefon: trzy paski."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Telefon: pełna moc sygnału."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Brak danych."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Dane: jeden pasek."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Dane: dwa paski."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Dane: trzy paski."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Dane: pełna moc sygnału."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Połączono z <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Połączono z <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Połączono z urządzeniem <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX: dwa paski"</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX: trzy paski"</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX: pełna moc sygnału"</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Rozłączono z siecią Ethernet."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Połączono z siecią Ethernet."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Brak sygnału."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Nie połączono."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Zero pasków."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Wył."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Połączono."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Łączę..."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Brak karty SIM."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Mobilna transmisja danych"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobilna transmisja danych włączona"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Wyłączona"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Nie skonfigurowano do transmisji danych"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Wył."</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Thethering przez Bluetooth."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Tryb samolotowy."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"Sieć VPN włączona."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Brak karty SIM."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Zmiana sieci operatora"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Zobacz szczegóły baterii"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Bateria: <xliff:g id="NUMBER">%d</xliff:g> procent."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Bateria <xliff:g id="PERCENTAGE">%1$s</xliff:g> procent, jeszcze <xliff:g id="TIME">%2$s</xliff:g> (na podstawie Twojego sposobu korzystania)"</string>
@@ -729,6 +704,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Może włączyć dzwonek lub wibracje w zależności od ustawień telefonu. Rozmowy z aplikacji <xliff:g id="APP_NAME">%1$s</xliff:g> są domyślnie wyświetlane jako dymki."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Przyciąga uwagę dzięki pływającym skrótom do treści."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Pozwól systemowi decydować, czy o powiadomieniu powinien informować dźwięk czy wibracja"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Wyświetla się jako pływający dymek u góry sekcji rozmów, pokazuje zdjęcie profilowe na ekranie blokady"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Ustawienia"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Priorytet"</string>
@@ -747,9 +730,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Ta aplikacja wyświetla się nad innymi aplikacjami na ekranie i używa mikrofonu oraz aparatu."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Ustawienia"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"System wyciszył to powiadomienie."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"System zmienił ważność tego powiadomienia na wyższą."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"System zmienił ważność tego powiadomienia na niższą."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Czy to było prawidłowe?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Dziękujemy za opinię"</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 82139f5..8529f40 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Três barras de bateria."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Bateria cheia."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Porcentagem da bateria desconhecida."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Sem telefone."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Uma barra de sinal do telefone."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Duas barras de sinal do telefone."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Três barras de sinal do telefone."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Sinal do telefone cheio."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Nenhum dado."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Uma barra de sinal de dados."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Duas barras de sinal de dados."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Três barras do sinal de dados."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Sinal de dados cheio."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Conectado a <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Conectado a <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Conectado a <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Duas barras do WiMAX."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Três barras do WiMAX."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Sinal WiMAX completo."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet desconectada."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet conectada."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Sem sinal."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Sem conexão."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Nenhuma barra."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Desligado."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Conectado."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Conectando."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Sem chip."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Dados móveis"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Dados móveis ativados"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Dados móveis desativados"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Sem configuração para uso de dados"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Desativados"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Tethering Bluetooth."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Modo avião."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ativada."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Sem chip."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Alteração de rede da operadora"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Abrir detalhes da bateria"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Bateria em <xliff:g id="NUMBER">%d</xliff:g> por cento."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Bateria com <xliff:g id="PERCENTAGE">%1$s</xliff:g> de carga, tempo restante aproximado, com base no seu uso: <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Pode vibrar ou tocar com base nas configurações do smartphone. As conversas do app <xliff:g id="APP_NAME">%1$s</xliff:g> aparecem em balões por padrão."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Mantém sua atenção com um atalho flutuante para esse conteúdo."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Faça com que o sistema determine se a notificação resultará em som ou vibração"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Aparecem na parte superior de uma seção de conversa, em forma de balões, mostrando a foto do perfil na tela de bloqueio"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Configurações"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritárias"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Este app está sobreposto a outros apps na sua tela e está usando o microfone e a câmera."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Configurações"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Esta notificação foi silenciada pelo sistema."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Esta notificação foi promovida pelo sistema."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Esta notificação foi rebaixada pelo sistema."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Isso está correto?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Agradecemos seu feedback."</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 8203bf6..e90e105 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Três barras de bateria."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Bateria carregada."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Percentagem da bateria desconhecida."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Sem telefone."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Uma barra de telefone."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Duas barras de telefone."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Três barras de telefone."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Sinal de telefone completo."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Sem dados."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Uma barra de dados."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Duas barras de dados."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Três barras de dados."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Sinal de dados completo."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Ligado a <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Ligado a <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Ligado a <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Duas barras de WiMAX."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Três barras de WiMAX."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Sinal WiMAX completo."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet desligada."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet ligada."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Sem sinal."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Sem ligação."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Zero barras."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Desativado."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Ligado."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"A ligar..."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Sem SIM."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Dados móveis"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Dados móveis ativados"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Dados móveis desativados"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Não definido para utilizar dados"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Desativado"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Ligação Bluetooth via telemóvel."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Modo de avião"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ativada."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Nenhum cartão SIM."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Rede do operador em mudança."</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Abrir detalhes da bateria"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Bateria a <xliff:g id="NUMBER">%d</xliff:g> por cento."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Bateria a <xliff:g id="PERCENTAGE">%1$s</xliff:g> por cento, resta(m) cerca de <xliff:g id="TIME">%2$s</xliff:g> com base na sua utilização."</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Pode tocar ou vibrar com base nas definições do telemóvel. As conversas da app <xliff:g id="APP_NAME">%1$s</xliff:g> aparecem como um balão por predefinição."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Mantém a sua atenção com um atalho flutuante para este conteúdo."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Faça com que o sistema determine se esta notificação deve emitir um som ou uma vibração"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Aparece no topo da secção de conversas, surge como balão flutuante e apresenta a imagem do perfil no ecrã de bloqueio."</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Definições"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioridade"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Esta app está a sobrepor-se a outras aplicações no ecrã e a utilizar o microfone e a câmara."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Definições"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"O sistema silenciou esta notificação."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"O sistema promoveu esta notificação."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"O sistema despromoveu esta notificação."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Estava correto?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Obrigado pelo seu feedback!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 82139f5..8529f40 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Três barras de bateria."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Bateria cheia."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Porcentagem da bateria desconhecida."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Sem telefone."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Uma barra de sinal do telefone."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Duas barras de sinal do telefone."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Três barras de sinal do telefone."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Sinal do telefone cheio."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Nenhum dado."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Uma barra de sinal de dados."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Duas barras de sinal de dados."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Três barras do sinal de dados."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Sinal de dados cheio."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Conectado a <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Conectado a <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Conectado a <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Duas barras do WiMAX."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Três barras do WiMAX."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Sinal WiMAX completo."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet desconectada."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet conectada."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Sem sinal."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Sem conexão."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Nenhuma barra."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Desligado."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Conectado."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Conectando."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Sem chip."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Dados móveis"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Dados móveis ativados"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Dados móveis desativados"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Sem configuração para uso de dados"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Desativados"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Tethering Bluetooth."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Modo avião."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ativada."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Sem chip."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Alteração de rede da operadora"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Abrir detalhes da bateria"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Bateria em <xliff:g id="NUMBER">%d</xliff:g> por cento."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Bateria com <xliff:g id="PERCENTAGE">%1$s</xliff:g> de carga, tempo restante aproximado, com base no seu uso: <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Pode vibrar ou tocar com base nas configurações do smartphone. As conversas do app <xliff:g id="APP_NAME">%1$s</xliff:g> aparecem em balões por padrão."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Mantém sua atenção com um atalho flutuante para esse conteúdo."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Faça com que o sistema determine se a notificação resultará em som ou vibração"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Aparecem na parte superior de uma seção de conversa, em forma de balões, mostrando a foto do perfil na tela de bloqueio"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Configurações"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritárias"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Este app está sobreposto a outros apps na sua tela e está usando o microfone e a câmera."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Configurações"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Esta notificação foi silenciada pelo sistema."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Esta notificação foi promovida pelo sistema."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Esta notificação foi rebaixada pelo sistema."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Isso está correto?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Agradecemos seu feedback."</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 123d672..9339dec 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Baterie: trei bare."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Baterie: complet."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Procentajul bateriei este necunoscut."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Nu există semnal pentru telefon."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Semnal pentru telefon: o bară."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Semnal pentru telefon: două bare."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Semnal pentru telefon: trei bare."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Semnal pentru telefon: complet."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Nu există semnal pentru date."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Semnal pentru date: o bară."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Semnal pentru date: două bare."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Semnal pentru date: trei bare."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Semnal pentru date: complet."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Conectat la <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Conectat la <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"S-a stabilit conexiunea la <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX două bare."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX trei bare."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX semnal complet."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet deconectat."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet conectat."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Fără semnal."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Neconectat."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Nicio bară."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Dezactivat."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Conectat."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Se conectează."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Niciun card SIM."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Date mobile"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Date mobile activate"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Date mobile dezactivate"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Nu este setat pentru a folosi datele"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Dezactivate"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Conectarea ca modem prin Bluetooth."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Mod Avion."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"Rețea VPN activată"</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Fără SIM."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Se schimbă rețeaua operatorului"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Deschideți detaliile privind bateria"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Baterie: <xliff:g id="NUMBER">%d</xliff:g> la sută."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Procentul rămas din baterie este <xliff:g id="PERCENTAGE">%1$s</xliff:g>. În baza utilizării, timpul rămas este de aproximativ <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -726,6 +701,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Poate să sune sau să vibreze, în funcție de setările telefonului. Conversațiile din balonul <xliff:g id="APP_NAME">%1$s</xliff:g> în mod prestabilit."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Vă atrage atenția printr-o comandă rapidă flotantă la acest conținut."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Solicitați-i sistemului să stabilească dacă această notificare este sonoră sau cu vibrații."</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Se afișează în partea de sus a secțiunii de conversație, apare ca un balon flotant, afișează fotografia de profil pe ecranul de blocare"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Setări"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritate"</string>
@@ -744,9 +727,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Această aplicație se afișează peste alte aplicații de pe ecran și folosește microfonul și camera foto."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Setări"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Notificarea a fost dezactivată de sistem."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Notificarea a fost promovată de sistem."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Notificarea a fost mutată în jos de sistem."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Este corect?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Mulțumim pentru feedback!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 03f1dfc..1fa9749 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Заряд батареи: три деления."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Батарея полностью заряжена."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Уровень заряда батареи в процентах неизвестен."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Сигнал телефонной сети отсутствует."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Сигнал телефонной сети: одно деление."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Сигнал телефонной сети: два деления."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Сигнал телефонной сети: три деления."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Надежный телефонный сигнал."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Сигнал передачи данных отсутствует."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Сигнал передачи данных: одно деление."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Сигнал передачи данных: два деления."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Сигнал передачи данных: три деления."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Надежный сигнал передачи данных."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g>: подключено."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>: подключено."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Подключено к: <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Сигнал WiMAX: два деления."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Сигнал WiMAX: три деления."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Надежный сигнал WiMAX."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Устройство отключено от Ethernet."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Устройство подключено к Ethernet."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Нет сигнала"</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Не подключено"</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Нет сигнала"</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Отключено"</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Подключено"</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Соединение."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Роуминг"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"SIM-карта отсутствует."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Мобильный Интернет"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Мобильный Интернет включен"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Мобильный Интернет отключен"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Мобильный Интернет по умолчанию не используется."</string>
<string name="cell_data_off" msgid="4886198950247099526">"Отключен"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth-модем"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Режим полета."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"Режим VPN включен."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Нет SIM-карты."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Сменить сеть"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Сведения о расходе заряда батареи"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Заряд батареи в процентах: <xliff:g id="NUMBER">%d</xliff:g>."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Заряд батареи в процентах: <xliff:g id="PERCENTAGE">%1$s</xliff:g>. Оценка оставшегося времени работы: <xliff:g id="TIME">%2$s</xliff:g>."</string>
@@ -729,6 +704,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Звонок или вибрация в зависимости от настроек телефона. Разговоры из приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" по умолчанию появляются в виде всплывающего чата."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Привлекает ваше внимание к контенту с помощью плавающего ярлыка"</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Система будет сама определять, включать ли звуковой сигнал или вибрацию для уведомления"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Появляется в верхней части списка разговоров и как всплывающий чат, фото профиля показывается на заблок. экране"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Настройки"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Приоритет"</string>
@@ -747,9 +730,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Это приложение располагается поверх других приложений, а также использует микрофон и камеру."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Настройки"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"ОК"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Это уведомление отключено системой."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Статус этого уведомления повышен системой."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Статус этого уведомления понижен системой."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Все верно?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Спасибо!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"ОК"</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index f5e2e70..d39bc52 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"බැටරිය තීරු තුනයි."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"බැටරිය පිරී ඇත."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"බැටරි ප්රතිශතය නොදනී."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"දුරකථනයක් නැත."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"දුරකථනය තීරු එකයි."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"දුරකථනය තීරු දෙකයි."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"දුරකථනය තීරු තුනයි."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"දුරකථනයේ සංඥාව පිරී ඇත."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"දත්ත නැත."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"දත්ත තීරු එකයි."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"දත්ත තීරු 2."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"දත්ත තීරු 3."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"දත්ත සංඥාව පිරී ඇත."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g> වෙත සම්බන්ධ කරන ලදි."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> වෙත සම්බන්ධ කරන ලදි."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> වෙත සම්බන්ධ විය."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX තීරු දෙකයි."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX තීරු තුනයි."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX සංඥාව පිරී ඇත."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"ඊතර්නෙට් විසන්ධි කරන ලදී."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"ඊතර්නෙට් සම්බන්ධ කරන ලදී."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"සංඥා නැත."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"සම්බන්ධ වී නැත."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"තීරු ශුන්යයි."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"අක්රිය කරන්න."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"සම්බන්ධිතයි."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"සම්බන්ධ වෙමින්."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"රෝමිං"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"SIM නැත."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"ජංගම දත්ත"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"ජංගම දත්ත ක්රියාත්මකයි"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"ජංගම දත්ත ක්රියාවිරහිතයි"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"දත්ත භාවිත කිරීමට සකසා නැත"</string>
<string name="cell_data_off" msgid="4886198950247099526">"ක්රියාවිරහිතයි"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"බ්ලූටූත් ටෙදරින්."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"අහස්යානා ආකාරය."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN ක්රියාත්මකයි."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"SIM කාඩ්පත නැත."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"වාහක ජාලය වෙනස් වෙමින්"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"බැටරි විස්තර විවෘත කරන්න"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"බැටරි ප්රතිශතය <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"බැටරි ප්රතිශතය <xliff:g id="PERCENTAGE">%1$s</xliff:g>, ඔබේ භාවිතයට අනුව <xliff:g id="TIME">%2$s</xliff:g> ක් පමණ ඉතුරුයි"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"දුරකථන සැකසීම් මත පදනම්ව නාද කිරීමට හෝ කම්පනය කිරීමට හැකිය. <xliff:g id="APP_NAME">%1$s</xliff:g> වෙතින් සංවාද පෙරනිමියෙන් බුබුළු දමයි"</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"පාවෙන කෙටිමගක් සමග ඔබේ අවධානය මෙම අන්තර්ගතය වෙත තබා ගන්න."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"මෙම දැනුම් දීම ශබ්දයක් හෝ කම්පනයක් ඇති කළ යුතු ද යන්න පද්ධතිය මගින් තීරණය කර තිබේද"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"සංවාද කොටසේ ඉහළම පෙන්වයි, බුබුළක් ලෙස දිස් වේ, අගුලු තිරයේ පැතිකඩ පින්තූරය සංදර්ශනය වේ"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"සැකසීම්"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"ප්රමුඛතාව"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"මෙම යෙදුම් ඔබගේ තිරය මත අනෙකුත් යෙදුම්වලට උඩින් සංදර්ශනය වන අතර මයික්රෆෝනය සහ කැමරාව භාවිතා කරයි."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"සැකසීම්"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"හරි"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"මෙම දැනුම් දීම පද්ධතිය මගින් නිහඬ කරන ලදී."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"මෙම දැනුම් දීම පද්ධතිය මගින් ඉහළ දමන ලදී."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"මෙම දැනුම් දීම පද්ධතිය මගින් පහත දමන ලදී."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"මෙය නිවැරදි වුයේද?"</string>
<string name="feedback_response" msgid="4671729244976641339">"ඔබේ ප්රතිපෝෂණයට ස්තූතියි!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"හරි"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 22673b9..a50da0e 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Tri čiarky batérie."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Batéria je nabitá."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Percento batérie nie je známe."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Žiadna telefónna sieť."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Jeden stĺpec signálu telefónnej siete."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Dve čiarky signálu telefónnej siete."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Tri čiarky signálu telefónnej siete."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Plný signál telefónnej siete."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Žiadna dátová sieť."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Jedna čiarka signálu dátovej siete."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Dve čiarky signálu dátovej siete."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Tri čiarky signálu dátovej siete."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Plný signál dátovej siete."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Pripojené k zariadeniu <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Pripojené k zariadeniu <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Pripojené k zariadeniu <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Dva stĺpce signálu siete WiMAX."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Tri stĺpce signálu siete WiMAX."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Plný signál siete WiMAX."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Sieť ethernet je odpojená"</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Sieť ethernet je pripojená"</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Žiadny signál."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Nepripojené."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Žiadna čiarka."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Vypnuté."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Pripojené."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Pripája sa"</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi‑Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Žiadna SIM karta."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Mobilné dáta"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobilné dáta sú zapnuté"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobilné dáta sú vypnuté"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Nie je nastavené na používanie dát"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Vypnuté"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Pripojenie cez Bluetooth."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Režim v lietadle."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN je zapnuté."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Žiadna SIM karta."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Mení sa sieť operátora"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Otvoriť podrobnosti o batérii"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Batéria <xliff:g id="NUMBER">%d</xliff:g> percent."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Percentá batérie: <xliff:g id="PERCENTAGE">%1$s</xliff:g>. Na základe vášho používania zostáva <xliff:g id="TIME">%2$s</xliff:g>."</string>
@@ -729,6 +704,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Môže zvoniť alebo vibrovať podľa nastavení telefónu. Predvolene sa zobrazia konverzácie z bubliny <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Upúta vás plávajúcim odkazom na tento obsah."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Nechajte systém určiť, či má toto upozornenie vydávať zvuk alebo vibrovať"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Nájdete ju hore v sekcii konverzácií ako plávajúcu bublinu, zobrazuje profilovú fotku na uzamknutej obrazovke"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Nastavenia"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Priorita"</string>
@@ -747,9 +730,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Táto aplikácia sa zobrazuje cez ďalšie aplikácie na obrazovke a používa mikrofón aj fotoaparát."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Nastavenia"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Zvuk tohto upozornenia bol vypnutý systémom."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Toto upozornenie bolo povýšené systémom."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Toto upozornenie bolo systémom preradené nižšie."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Bolo toto správne?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Ďakujeme za váš názor."</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 42a961c..7d9a5d9 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Baterija s tremi črticami."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Baterija je polna."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Neznan odstotek napolnjenosti baterije."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Ni telefona."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefon z eno črtico."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefon z dvema črticama."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefon s tremi črticami."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Signal telefona je poln."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Ni podatkov."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Podatkovni signal z eno črtico."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Podatki z dvema črticama."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Podatki s tremi črticami."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Podatkovni signal poln."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Povezava vzpostavljena z: <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Povezava vzpostavljena z: <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Vzpostavljena povezava: <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Signal WiMAX: dve črtici."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Signal WiMAX: tri črtice."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Poln signal WiMAX."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernetna povezava je prekinjena."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernetna povezava je vzpostavljena."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Ni signala."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Ni povezan."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Nič črtic."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Izklopljen."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Povezan."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Povezovanje."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Gostovanje"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Ni kartice SIM."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Prenos podatkov v mobilnem omrežju"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Prenos podatkov v mobilnem omrežju je vklopljen"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Prenos podatkov v mobilnem omrežju je izklopljen"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Ni nastavljeno za uporabo prenosa podatkov"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Izklopljeno"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Internet prek Bluetootha."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Način za letalo."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"Omrežje VPN je vklopljeno."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Ni kartice SIM."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Spreminjanje omrežja operaterja"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Odpiranje podrobnosti o bateriji"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Baterija <xliff:g id="NUMBER">%d</xliff:g> odstotkov."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Napolnjenost baterije je <xliff:g id="PERCENTAGE">%1$s</xliff:g>, glede na način uporabe imate na voljo še približno <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -729,6 +704,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Zvonjenje ali vibriranje je omogočeno na podlagi nastavitev telefona. Pogovori v aplikaciji <xliff:g id="APP_NAME">%1$s</xliff:g> so privzeto prikazani v oblačkih."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Zadrži vašo pozornost z lebdečo bližnjico do te vsebine."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Naj sistem določi, ali ob prejemu tega obvestila naprava predvaja zvok ali zavibrira"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Prikaz na vrhu razdelka s pogovorom in v plavajočem oblačku, prikaz profilne slike na zaklenjenem zaslonu"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Nastavitve"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prednost"</string>
@@ -747,9 +730,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Ta aplikacija prekriva druge aplikacije na zaslonu ter uporablja mikrofon in fotoaparat."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Nastavitve"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"V redu"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Sistem je utišal to obvestilo."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Sistem je zvišal prednost tega obvestila."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Sistem je znižal prednost tega obvestila."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Je bilo to prav?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Hvala za povratne informacije."</string>
<string name="feedback_ok" msgid="6481426753298857144">"V redu"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 1943823..a72f090 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Bateria ka edhe tre vija."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Bateria u mbush."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Përqindja e baterisë e panjohur."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Nuk ka telefon."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefoni ka edhe një vijë."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefoni ka dy vija."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefoni ka tre vija."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Sinjali i telefonit është i plotë."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Nuk ka të dhëna."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Sinjali është vetëm një vijë."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Të dhënat kanë dy vija."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Sinjali është me tre vija."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Sinjali i të dhënave është i plotë."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Lidhur me <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Lidhur me <xliff:g id="BLUETOOTH">%s</xliff:g>"</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Është lidhur me <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX ka dy vija."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX ka tre vija."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX ka sinjal të plotë."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Lidhja e eternetit u shkëput."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Lidhja e eternetit u lidh."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Nuk ka sinjal."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Nuk është i lidhur."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Zero vija."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Çaktivizuar."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"I lidhur."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Po lidhet."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Nuk ka kartë SIM."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Të dhënat celulare"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Të dhënat celulare janë aktive"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Të dhënat celulare janë joaktive"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Nuk është caktuar të përdorë të dhënat"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Joaktiv"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Po lidhet me \"bluetooth\"."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"modaliteti i aeroplanit"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN-ja është aktive."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Nuk ka kartë SIM."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Rrjeti i operatorit celular po ndryshohet"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Hap detajet e baterisë"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Bateria ka edhe <xliff:g id="NUMBER">%d</xliff:g> për qind."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Bateria <xliff:g id="PERCENTAGE">%1$s</xliff:g> përqind, rreth <xliff:g id="TIME">%2$s</xliff:g> të mbetura bazuar në përdorimin tënd"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Mund të bjerë zilja ose të dridhet në bazë të cilësimeve të telefonit. Bisedat nga flluska e <xliff:g id="APP_NAME">%1$s</xliff:g> si parazgjedhje."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Mban vëmendjen tënde me një shkurtore pluskuese te kjo përmbajtje."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Kërkoji sistemit të përcaktojë nëse ky njoftim duhet të lëshojë tingull apo dridhje"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Shfaqet në krye të seksionit të bisedës dhe shfaqet si flluskë pluskuese, shfaq fotografinë e profilit në ekranin e kyçjes"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Cilësimet"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Përparësia"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Ky aplikacion po shfaqet mbi aplikacionet e tjera në ekran dhe po përdor mikrofonin dhe kamerën."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Cilësimet"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"Në rregull"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Ky njoftim është vendosur në heshtje nga sistemi."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Ky njoftim është rritur në nivel nga sistemi."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Ky njoftim është ulur në nivel nga sistemi."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"A ishte e saktë kjo?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Faleminderit për komentin!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"Në rregull"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 50bbff2..3cc9f20 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Батерија од три црте."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Батерија је пуна."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Проценат напуњености батерије није познат."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Нема телефона."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Сигнал телефона има једну црту."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Сигнал телефона од две црте."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Сигнал телефона од три црте."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Сигнал телефона је пун."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Нема података."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Сигнал за податке има једну црту."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Сигнал за податке од две црте."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Сигнал за податке од три црте."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Сигнал за податке је најјачи."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Повезани сте са <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Повезани сте са <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Повезани смо са уређајем <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX сигнал има две црте."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX сигнал има три црте."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX сигнал је најјачи."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Веза са етернетом је прекинута."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Етернет је повезан."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Нема сигнала."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Није повезано."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Ниједна црта."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Искључено."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Повезано је."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Повезивање."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Роминг"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"WiFi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Нема SIM картице."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Мобилни подаци"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Мобилни подаци су укључени"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Мобилни подаци су искључени"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Није подешено за коришћење података"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Искључено"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth привезивање."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Режим рада у авиону."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN је укључен."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Нема SIM картице."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Промена мреже мобилног оператера"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Отвори детаље о батерији"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Батерија је на <xliff:g id="NUMBER">%d</xliff:g> посто."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Батерија је на <xliff:g id="PERCENTAGE">%1$s</xliff:g> посто, преостало време на основу коришћења је <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -726,6 +701,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Може да звони или вибрира у зависности од подешавања телефона. Конверзације из апликације <xliff:g id="APP_NAME">%1$s</xliff:g> се подразумевано приказују у облачићима."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Привлачи вам пажњу помоћу плутајуће пречице до овог садржаја."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Нека систем утврди да ли ово обавештење треба да емитује звук или да вибрира"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Приказује се у врху одељка за конверзације као плутајући облачић, приказује слику профила на закључаном екрану"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Подешавања"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Приоритет"</string>
@@ -744,9 +727,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Ова апликација се приказује преко других апликација на екрану и користи микрофон и камеру."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Подешавања"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"Потврди"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Систем је искључио ово обавештење."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Систем је промовисао ово обавештење."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Систем је поставио ово обавештење на дно."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Да ли је то тачно?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Хвала вам на повратним информацијама!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"Потврди"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 1aba0e3..5b8a526 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Batteri: tre staplar."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Batteriet är fulladdat."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Okänd batterinivå."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Ingen telefon."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefon: en stapel."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefon: två staplar."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefon: tre staplar."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Telefonsignalen är full."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Inga data."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Data: en stapel."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Data: två staplar."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Data: tre staplar."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Datasignalen är full."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Ansluten till <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Ansluten till <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Ansluten till <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX: två staplar."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX: tre staplar."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX-signalen är full."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet har kopplats från."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet har anslutits."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Ingen signal."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Inte ansluten."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Inga staplar."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Inaktiverad."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Ansluten."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Ansluter."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Inget SIM-kort."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Mobildata"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobildata har aktiverats"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobildata har inaktiverats"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Inte inställd på mobildata"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Av"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Internetdelning via Bluetooth"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Flygplansläge"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN har aktiverats."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Inget SIM-kort."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Byter leverantörsnätverk"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Visa uppgifter om batteri"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Batteri <xliff:g id="NUMBER">%d</xliff:g> procent."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Batteri: <xliff:g id="PERCENTAGE">%1$s</xliff:g> procent, cirka <xliff:g id="TIME">%2$s</xliff:g> kvar utifrån din användning"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Kan ringa eller vibrera beroende på inställningarna på telefonen. Konversationer från <xliff:g id="APP_NAME">%1$s</xliff:g> visas i bubblor som standard."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Behåller din uppmärksamhet med en flytande genväg till innehållet."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Låt systemet avgöra om den här aviseringen ska låta eller vibrera"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Visas högst upp bland konversationerna som en flytande bubbla, visar profilbilden på låsskärmen"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Inställningar"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritet"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Appen visas över andra appar på skärmen och den använder mikrofonen och kameran."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Inställningar"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Den här aviseringen har tystats av systemet."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Den här aviseringen har flyttats upp av systemet."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Den här aviseringen har flyttats ned av systemet."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Stämmer detta?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Tack för din feedback!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index f02cc91..b2b2c37 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Pau tatu za betri."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Betri imejaa."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Asilimia ya betri haijulikani."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Hakuna simu"</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Mwambaa mmoja wa simu."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Miambaa miwili ya simu"</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Miambaa mitatu ya simu."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Ishara ya simu imejaa."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Hakuna data."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Upapi mmoja wa habari"</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Miamba miwili ya data."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Fito tatu za habari."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Ishara ya data imejaa."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Imeunganishwa kwenye <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Imeunganishwa kwenye <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Imeunganishwa kwenye <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Pau mbili za WiMAX."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Pau tatu za WiMAX."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Ishara ya WiMAX imejaa."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethaneti imeondolewa."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethaneti imeunganishwa."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Hakuna mtandao"</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Haijaunganishwa."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Vipima mtandao sufuri."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Imezimwa."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Imeunganishwa."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Inaunganisha."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Mitandao ya ng\'ambo"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Hakuna SIM."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Data ya Simu"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Data ya Simu Imewashwa"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Umezima data ya mtandao wa simu"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Haijawekewa mipangilio ya kutumia data"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Zima"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Shiriki intaneti kwa Bluetooth."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Hali ya ndegeni."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN imewashwa."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Hakuna SIM kadi."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Mabadiliko katika mtandao wa mtoa huduma"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Fungua maelezo ya betri"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Asilimia <xliff:g id="NUMBER">%d</xliff:g> ya betri"</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Betri ina asilimia <xliff:g id="PERCENTAGE">%1$s</xliff:g>, zimesalia takribani <xliff:g id="TIME">%2$s</xliff:g> kulingana na jinsi unavyoitumia"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Huenda ikalia au kutetema kulingana na mipangilio ya simu. Mazungumzo kutoka kiputo cha <xliff:g id="APP_NAME">%1$s</xliff:g> kwa chaguomsingi."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Huweka umakinifu wako kwenye maudhui haya kwa kutumia njia ya mkato ya kuelea."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Ruhusu mfumo ubainishe iwapo arifa hii inapaswa kutoa sauti au mtetemo"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Huonyeshwa kwenye sehemu ya juu ya mazungumzo, huonekana kama kiputo, huonyesha picha ya wasifu kwenye skrini iliyofungwa"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Mipangilio"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Kipaumbele"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Programu hii inachomoza kwenye programu zingine zilizo katika skrini yako na inatumia maikrofoni na kamera."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Mipangilio"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"Sawa"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Arifa hii ilizimwa na mfumo."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Arifa hii ilipandishwa hadhi na mfumo."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Arifa hii ilishushwa hadhi na mfumo."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Je, hatua hii ilikuwa sahihi?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Asante kwa maoni yako!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"Sawa"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index a9a3b07..8833153 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"பேட்டரி சக்தி மூன்று பார் அளவில் உள்ளது."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"பேட்டரி முழுமையாக உள்ளது."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"பேட்டரி சதவீதம் தெரியவில்லை."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"சிக்னல் இல்லை."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"சிக்னல் ஒரு கோட்டில் உள்ளது."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"சிக்னல் இரண்டு கோட்டில் உள்ளது."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"சிக்னல் மூன்று கோட்டில் உள்ளது."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"சிக்னல் முழுமையாக உள்ளது."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"டேட்டா சிக்னல் இல்லை."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"தரவு சிக்னல் ஒரு கோட்டில் உள்ளது."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"தரவின் சிக்னல் இரண்டு கோடு வரை உள்ளது."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"தரவு சிக்னல் மூன்று கோட்டில் உள்ளது."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"தரவு சிக்னல் முழுமையாக உள்ளது."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g>க்கு இணைக்கப்பட்டது."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>க்கு இணைக்கப்பட்டது."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> உடன் இணைக்கப்பட்டுள்ளது."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX இரண்டு கோடுகள்."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX மூன்று கோடுகள்."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX சிக்னல் முழுமையாக உள்ளது."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"ஈத்தர்நெட் துண்டிக்கப்பட்டது."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"ஈத்தர்நெட் இணைக்கப்பட்டது."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"சிக்னல் இல்லை."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"இணைக்கப்படவில்லை."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"கோடுகள் இல்லை."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"ஆஃப்."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"இணைக்கப்பட்டது."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"இணைக்கிறது."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"ரோமிங்"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"வைஃபை"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"சிம் இல்லை."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"மொபைல் டேட்டா"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"மொபைல் டேட்டா இயக்கப்பட்டது"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"மொபைல் டேட்டா ஆஃப் செய்யப்பட்டது"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"தரவை உபயோகிக்க அமைக்கப்படவில்லை"</string>
<string name="cell_data_off" msgid="4886198950247099526">"ஆஃப்"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"புளூடூத் டெதெரிங்."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"விமானப் பயன்முறை."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN இயக்கத்தில் உள்ளது."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"சிம் கார்டு இல்லை."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"மொபைல் நிறுவன நெட்வொர்க்கை மாற்றும்"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"பேட்டரி விவரங்களைத் திறக்கும்"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"பேட்டரி சக்தி <xliff:g id="NUMBER">%d</xliff:g> சதவிகிதம் உள்ளது."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"பேட்டரி: <xliff:g id="PERCENTAGE">%1$s</xliff:g> சதவீதம், உபயோகத்தின் அடிப்படையில் <xliff:g id="TIME">%2$s</xliff:g> மீதமுள்ளது"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"மொபைல் அமைப்புகளின் அடிப்படையில் ஒலிக்கவோ அதிரவோ செய்யும். <xliff:g id="APP_NAME">%1$s</xliff:g> இலிருந்து வரும் உரையாடல்கள் இயல்பாகவே குமிழாகத் தோன்றும்."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"இந்த உள்ளடக்கத்திற்கான மிதக்கும் ஷார்ட்கட் மூலம் உங்கள் கவனத்தைப் பெற்றிருக்கும்."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"இந்த அறிவிப்பு ஒலி எழுப்ப வேண்டுமா அதிர வேண்டுமா என்பதை சிஸ்டம் தீர்மானிக்கும்"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"உரையாடல் பிரிவின் மேற்பகுதியில் மிதக்கும் குமிழாகத் தோன்றும். பூட்டுத் திரையின் மேல் சுயவிவரப் படத்தைக் காட்டும்"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"அமைப்புகள்"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"முன்னுரிமை"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"இந்த ஆப்ஸானது, உங்கள் திரையில் பிற ஆப்ஸின் இடைமுகத்தின் மேல் தோன்றுவதுடன், மைக்ரோஃபோனையும் கேமராவையும் உபயோகிக்கிறது."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"அமைப்புகள்"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"சரி"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"இந்த அறிவிப்பு சிஸ்டத்தால் ஒலியடக்கப்பட்டது."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"இந்த அறிவிப்பு சிஸ்டத்தால் முக்கியமானது என வரையறுக்கப்பட்டது."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"இந்த அறிவிப்பு சிஸ்டத்தால் முக்கியமில்லாதது என வரையறுக்கப்பட்டது."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"இது சரியானதா?"</string>
<string name="feedback_response" msgid="4671729244976641339">"உங்கள் கருத்துக்கு நன்றி!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"சரி"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 7e7dc37..ccb4fa7 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"బ్యాటరీ మూడు బార్లు."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"బ్యాటరీ నిండింది."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"బ్యాటరీ శాతం తెలియదు."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"ఫోన్ లేదు."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"ఫోన్ ఒక బారు."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"ఫోన్ రెండు బార్లు."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"ఫోన్ మూడు బార్లు."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"ఫోన్ సిగ్నల్ పూర్తిగా ఉంది."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"డేటా లేదు."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"డేటా ఒక బారు."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"డేటా రెండు బార్లు."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"డేటా మూడు బార్లు."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"డేటా సిగ్నల్ సంపూర్ణంగా ఉంది."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g>కి కనెక్ట్ చేయబడింది."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>కి కనెక్ట్ చేయబడింది."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g>కి కనెక్ట్ చేయబడింది."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX రెండు బార్లు కలిగి ఉంది."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX మూడు బార్లు కలిగి ఉంది."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX సిగ్నల్ పూర్తిగా ఉంది."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"ఈథర్నెట్ డిస్కనెక్ట్ చేయబడింది."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"ఈథర్నెట్ కనెక్ట్ చేయబడింది."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"సిగ్నల్ లేదు."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"కనెక్ట్ చేయబడలేదు."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"సున్నా బార్లు."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"ఆఫ్లో ఉంది."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"కనెక్ట్ చేయబడింది."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"కనెక్ట్ అవుతోంది."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"రోమింగ్"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"సిమ్ లేదు."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"మొబైల్ డేటా"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"మొబైల్ డేటా ఆన్ చేయబడింది"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"మొబైల్ డేటా ఆఫ్లో ఉంది"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"డేటాను ఉపయోగించే విధంగా సెట్ చేయలేదు"</string>
<string name="cell_data_off" msgid="4886198950247099526">"ఆఫ్ చేయండి"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"బ్లూటూత్ టెథెరింగ్."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"ఎయిర్ప్లేన్ మోడ్."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPNలో."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"SIM కార్డ్ లేదు."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"క్యారియర్ నెట్వర్క్ మారుతోంది"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"బ్యాటరీ వివరాలను తెరుస్తుంది"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"బ్యాటరీ <xliff:g id="NUMBER">%d</xliff:g> శాతం."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"బ్యాటరీ <xliff:g id="PERCENTAGE">%1$s</xliff:g> శాతం ఉంది, మీ వినియోగాన్ని బట్టి <xliff:g id="TIME">%2$s</xliff:g> పని చేస్తుంది"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ఫోన్ సెట్టింగ్ల ఆధారంగా రింగ్ లేదా వైబ్రేట్ కావచ్చు. <xliff:g id="APP_NAME">%1$s</xliff:g> నుండి సంభాషణలు ఆటోమేటిక్గా బబుల్గా కనిపిస్తాయి."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ఫ్లోటింగ్ షార్ట్కట్తో మీ దృష్టిని ఈ కంటెంట్పై నిలిపి ఉంచుతుంది."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"ఈ నోటిఫికేషన్ వచ్చినప్పుడు శబ్దం చేయాలా లేదా వైబ్రేట్ చేయాలా అనేది నిర్ణయించడానికి సిస్టమ్కు అనుమతి ఇవ్వండి"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"సంభాషణ విభాగం ఎగువన ఉంటుంది, తేలుతున్న బబుల్లాగా కనిపిస్తుంది, లాక్ స్క్రీన్పై ప్రొఫైల్ ఫోటోను ప్రదర్శిస్తుంది"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"సెట్టింగ్లు"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"ప్రాధాన్యత"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"ఈ యాప్ మీ స్క్రీన్లోని ఇతర యాప్లపై ప్రదర్శించబడుతోంది మరియు మైక్రోఫోన్, కెమెరాను ఉపయోగిస్తుంది."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"సెట్టింగ్లు"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"సరే"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"ఈ నోటిఫికేషన్ను సిస్టమ్ నిశ్శబ్దంగా ఉండేలా చేసింది."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"ఈ నోటిఫికేషన్ స్థాయిని సిస్టమ్ పెంచింది."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"ఈ నోటిఫికేషన్ స్థాయిని సిస్టమ్ తగ్గించింది."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"ఇది సరైనదేనా?"</string>
<string name="feedback_response" msgid="4671729244976641339">"మీ ఫీడ్బ్యాక్ను అందించినందుకు ధన్యవాదాలు!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"సరే"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index a18ec8a..9c408e1 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"แบตเตอรี่สามขีด"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"แบตเตอรี่เต็ม"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"ไม่ทราบเปอร์เซ็นต์แบตเตอรี่"</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"ไม่มีสัญญาณโทรศัพท์"</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"สัญญาณโทรศัพท์หนึ่งขีด"</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"สัญญาณโทรศัพท์สองขีด"</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"สัญญาณโทรศัพท์สามขีด"</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"สัญญาณโทรศัพท์เต็ม"</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"ไม่มีข้อมูล"</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"สัญญาณข้อมูลหนึ่งขีด"</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"สัญญาณข้อมูลสองขีด"</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"สัญญาณข้อมูลสามขีด"</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"สัญญาณข้อมูลเต็ม"</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"เชื่อมต่อ <xliff:g id="WIFI">%s</xliff:g> แล้ว"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"เชื่อมต่อกับ <xliff:g id="BLUETOOTH">%s</xliff:g> แล้ว"</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"เชื่อมต่อกับ <xliff:g id="CAST">%s</xliff:g>"</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"สัญญาณ WiMAX สองขีด"</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"สัญญาณ WiMAX สามขีด"</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"สัญญาณ WiMAX เต็ม"</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"ยกเลิกการเชื่อมต่ออีเทอร์เน็ตแล้ว"</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"เชื่อมต่ออีเทอร์เน็ตแล้ว"</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"ไม่มีสัญญาณ"</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"ไม่ได้เชื่อมต่อ"</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"ศูนย์ขีด"</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"ปิดอยู่"</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"เชื่อมต่อแล้ว"</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"กำลังเชื่อมต่อ"</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"โรมมิ่ง"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"WiFi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"ไม่มีซิมการ์ด"</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"เน็ตมือถือ"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"อินเทอร์เน็ตมือถือเปิดอยู่"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"เน็ตมือถือปิดอยู่"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"ไม่ได้ตั้งค่าให้ใช้อินเทอร์เน็ตมือถือ"</string>
<string name="cell_data_off" msgid="4886198950247099526">"ปิด"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"การปล่อยสัญญาณบลูทูธ"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"โหมดบนเครื่องบิน"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN เปิดอยู่"</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"ไม่มีซิมการ์ด"</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"การเปลี่ยนเครือข่ายผู้ให้บริการ"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"เปิดรายละเอียดแบตเตอรี่"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"แบตเตอรี่ <xliff:g id="NUMBER">%d</xliff:g> เปอร์เซ็นต์"</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"แบตเตอรี่ <xliff:g id="PERCENTAGE">%1$s</xliff:g> เปอร์เซ็นต์ ใช้ได้อีกประมาณ <xliff:g id="TIME">%2$s</xliff:g> ทั้งนี้ขึ้นอยู่กับการใช้งานของคุณ"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"อาจส่งเสียงหรือสั่นโดยขึ้นอยู่กับการตั้งค่าโทรศัพท์ การสนทนาจาก <xliff:g id="APP_NAME">%1$s</xliff:g> จะแสดงเป็นบับเบิลโดยค่าเริ่มต้น"</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ดึงดูดความสนใจของคุณไว้เสมอด้วยทางลัดแบบลอยที่มายังเนื้อหานี้"</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"ให้ระบบพิจารณาว่าจะให้การแจ้งเตือนนี้ส่งเสียงหรือสั่นหรือไม่"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"แสดงที่ด้านบนของส่วนการสนทนา ปรากฏเป็นบับเบิลแบบลอย แสดงรูปโปรไฟล์บนหน้าจอล็อก"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"การตั้งค่า"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"ลำดับความสำคัญ"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"แอปนี้กำลังแสดงทับแอปอื่นๆ ในหน้าจอและใช้ไมโครโฟนและกล้อง"</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"การตั้งค่า"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"ตกลง"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"การแจ้งเตือนนี้ถูกปิดเสียงโดยระบบ"</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"การแจ้งเตือนนี้ได้รับการเพิ่มระดับโดยระบบ"</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"การแจ้งเตือนนี้ถูกลดระดับโดยระบบ"</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"การดำเนินการนี้ถูกต้องไหม"</string>
<string name="feedback_response" msgid="4671729244976641339">"ขอบคุณที่แสดงความคิดเห็น"</string>
<string name="feedback_ok" msgid="6481426753298857144">"ตกลง"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index a68f5ad..9e8aa96 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Baterya na tatlong bar."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Puno na ang baterya."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Hindi alam ang porsyento ng baterya."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Walang telepono."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telepono na isang bar."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telepono na dalawang bar."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telepono na tatlong bar."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Puno ang signal ng telepono."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Walang data."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Data na isang bar."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Data na dalawang bar."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Data na tatlong bar."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Puno ang signal ng data."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Nakakonekta sa <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Nakakonekta sa <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Nakakonekta sa <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX na dalawang bar."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX na tatlong bar."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Puno ang signal ng WiMAX."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Nadiskonekta ang Ethernet."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Nakakonekta ang Ethernet."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Walang signal."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Hindi nakakonekta."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Walang mga bar."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Naka-off."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Nakakonekta."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Kumokonekta."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Roaming"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Walang SIM."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Mobile Data"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Naka-on ang Mobile Data"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Naka-off ang mobile data"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Hindi nakatakdang gumamit ng data"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Naka-off"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Pag-tether ng Bluetooth."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Mode na eroplano."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"Naka-on ang VPN."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Walang SIM card."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Nagpapalit ng carrier network"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Buksan ang mga detalye ng baterya"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Baterya <xliff:g id="NUMBER">%d</xliff:g> (na) porsyento."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> (na) porsyento ang baterya, nasa <xliff:g id="TIME">%2$s</xliff:g> ang natitira batay sa paggamit mo"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Puwedeng mag-ring o mag-vibrate batay sa mga setting ng telepono. Mga pag-uusap mula sa <xliff:g id="APP_NAME">%1$s</xliff:g> bubble bilang default."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Pinapanatili ang iyong atensyon sa pamamagitan ng lumulutang na shortcut sa content na ito."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Ipatukoy sa system kung dapat gumawa ng tunog o pag-vibrate ang notification na ito"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Makikita sa itaas ng seksyon ng pag-uusap, lumalabas bilang floating bubble, ipinapakita sa lock screen ang larawan sa profile"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Mga Setting"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Priyoridad"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Ipinapakita ang app na ito sa ibabaw ng iba pang app sa iyong screen at ginagamit nito ang mikropono at camera."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Mga Setting"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Ginawang silent ng system ang notification na ito."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Na-promote ng system ang notification na ito."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Na-demote ng system ang notification na ito."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Tama ba ito?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Salamat sa iyong feedback!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index d0d343c..2b89578 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Pil gücü üç çubuk."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Pil tam dolu."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Pil yüzdesi bilinmiyor."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Telefon sinyali yok."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefon sinyali bir çubuk."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefon sinyali iki çubuk."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefon sinyali üç çubuk."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Telefon sinyali tam."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Veri yok."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Veri sinyali bir çubuk."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Veri sinyali iki çubuk."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Veri sinyali üç çubuk."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Veri sinyali tam."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g> ile bağlı."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> ile bağlı."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> bağlantısı kuruldu."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX iki çubuk."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX üç çubuk."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX sinyali tam."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet bağlantısı kesildi."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet bağlandı."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Sinyal yok."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Bağlanmadı."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Sıfır çubuk."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Kapalı."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Bağlandı."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Bağlanıyor."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Dolaşım"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Kablosuz"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"SIM kart yok."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Mobil Veri"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobil Veri Açık"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobil veri kapalı"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Veri kullanmak üzere ayarlanmadı"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Kapalı"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth tethering"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Uçak modu."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN açık."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"SIM kart yok."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Operatör ağı değiştiriliyor"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Pil ayrıntılarını aç"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Pil yüzdesi: <xliff:g id="NUMBER">%d</xliff:g>"</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Pil yüzde <xliff:g id="PERCENTAGE">%1$s</xliff:g> dolu. Kullanımınıza göre yaklaşık <xliff:g id="TIME">%2$s</xliff:g> süresi kaldı"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Telefon ayarlarına bağlı olarak zili çalabilir veya titreyebilir <xliff:g id="APP_NAME">%1$s</xliff:g> adlı uygulamadan görüşmeler varsayılan olarak baloncukla gösterilir."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Kayan kısayolla dikkatinizi bu içerik üzerinde tutar."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Bu bildirimin ses çıkarması veya titreşmesi gerekip gerekmediğine sistem karar versin"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Görüşme bölümünün üstünde gösterilir, kayan baloncuk olarak görünür, kilit ekranında profil resmini görüntüler"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Ayarlar"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Öncelik"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Bu uygulama, ekranınızdaki diğer uygulamaların üzerinde görüntüleniyor ve mikrofon ile kamerayı kullanıyor."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Ayarlar"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"Tamam"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Bu bildirim sistem tarafından sessize alındı."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Bu bildirimin düzeyi sistem tarafından yükseltildi."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Bu bildirimin düzeyi sistem tarafından düşürüldü."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Bu doğru muydu?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Geri bildiriminiz için teşekkürler!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"Tamam"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 26bc662..ec7b85a 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Заряд акумулятора: три смужки."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Акумулятор заряджений."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Відсоток заряду акумулятора невідомий."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Немає сигналу телефону."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Одна смужка сигналу телефону."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Дві смужки сигналу телефону."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Три смужки сигналу телефону."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Максимальний сигнал телефону."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Немає сигналу даних."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Одна смужка сигналу даних."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Дві смужки сигналу даних."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Три смужки сигналу даних."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Максимальний сигнал даних."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Підключено до <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Підключено до <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Під’єднано до пристрою <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Дві смужки сигналу WiMAX."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Три смужки сигналу WiMAX."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Максимальний сигнал WiMAX."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Ethernet відключено."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Ethernet підключено."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Немає сигналу."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Не з’єднано."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Нуль смужок сигналу."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Вимкнено."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Під’єднано."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"З’єднання."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Роумінг"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Немає SIM-карти."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Мобільне передавання даних"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Мобільне передавання даних увімкнено"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Мобільне передавання даних вимкнено"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Не вибрано для використання даних"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Вимкнено"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth-модем"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Режим польоту."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"Мережу VPN увімкнено."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Немає SIM-карти."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Змінення мережі оператора"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Відкрити деталі акумулятора"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Заряд акумулятора у відсотках: <xliff:g id="NUMBER">%d</xliff:g>."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Згідно з даними про використання залишилося <xliff:g id="PERCENTAGE">%1$s</xliff:g> заряду акумулятора – близько <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -729,6 +704,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Може дзвонити або вібрувати залежно від налаштувань телефона. Показує спливаючі розмови з додатка <xliff:g id="APP_NAME">%1$s</xliff:g> за умовчанням."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Привертає увагу до контенту плаваючим ярликом."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Дозволити системі визначати, чи має сповіщення супроводжуватися звуком або вібрацією"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"З\'являється вгорі розділу розмов у спливаючому сповіщенні та показує зображення профілю на заблокованому екрані"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Налаштування"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Пріоритет"</string>
@@ -747,9 +730,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Цей додаток відображається поверх інших додатків на екрані та використовує мікрофон і камеру."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Налаштування"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Система заглушила це сповіщення."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Система підвищила статус цього сповіщення."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Система знизила статус цього сповіщення."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Правильно?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Дякуємо за відгук!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 5307249..15a4f30 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"بیٹری کے تین بارز۔"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"بیٹری بھری ہے۔"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"بیٹری کی فیصد نامعلوم ہے۔"</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"کوئی فون نہیں ہے۔"</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"فون کا ایک بار۔"</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"فون کے دو بارز۔"</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"فون کے تین بارز۔"</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"فون سگنل پورا ہے۔"</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"کوئی ڈیٹا نہیں ہے۔"</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"ڈیٹا کا ایک بار۔"</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"ڈیٹا کے دو بارز۔"</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"ڈیٹا کے تین بارز۔"</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"ڈیٹا سگنل بھرا ہوا ہے۔"</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g> سے منسلک ہیں۔"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> سے منسلک ہیں۔"</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"<xliff:g id="CAST">%s</xliff:g> سے منسلک ہے۔"</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX دو بارز۔"</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX تین بارز۔"</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX سگنل پورا ہے۔"</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"ایتھرنیٹ منقطع ہے۔"</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"ایتھرنیٹ منسلک ہے۔"</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"کوئی سگنل نہیں ہے۔"</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"مربوط نہیں ہے۔"</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"صفر بارز۔"</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"آف۔"</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"مربوط۔"</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"مربوط ہو رہا ہے۔"</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"رومنگ"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"کوئی SIM نہیں ہے۔"</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"موبائل ڈیٹا"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"موبائل ڈیٹا آن ہے"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"موبائل ڈیٹا آف ہے"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"ڈیٹا استعمال کرنے کے لیے سیٹ نہیں ہے"</string>
<string name="cell_data_off" msgid="4886198950247099526">"آف ہے"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"بلوٹوتھ ٹیدرنگ۔"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"ہوائی جہاز وضع۔"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN آن ہے۔"</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"کوئی SIM کارڈ نہیں ہے۔"</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"کیریئر نیٹ ورک کی تبدیلی"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"بیٹری کی تفصیلات کھولیں"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"بیٹری <xliff:g id="NUMBER">%d</xliff:g> فیصد۔"</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"آپ کے استعمال کی بنیاد پر بیٹری <xliff:g id="PERCENTAGE">%1$s</xliff:g> فیصد، تقریباً <xliff:g id="TIME">%2$s</xliff:g> باقی ہے"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"فون کی ترتیبات کے مطابق وائبریٹ یا گھنٹی بج سکتی ہے۔ بذریعہ ڈیفالٹ <xliff:g id="APP_NAME">%1$s</xliff:g> بلبلہ سے گفتگوئیں۔"</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"اس مواد کے فلوٹنگ شارٹ کٹ کے ساتھ آپ کی توجہ دیتی ہے۔"</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"سسٹم کو اس بات کا تعین کرنے دیں کہ آیا اس اطلاع کی آواز ہو یا وائبریٹ ہونا چاہیے"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"گفتگو کے سیکشن کے اوپری حصے پر دکھاتا ہے، تیرتے بلبلے کی طرح ظاہر ہوتا ہے، لاک اسکرین پر پروفائل تصویر دکھاتا ہے"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"ترتیبات"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"ترجیح"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"یہ ایپ آپ کی اسکرین پر دیگر ایپس پر ڈسپلے کر رہی ہے اور مائیکروفون اور کیمرے کا استعمال کر رہی ہے۔"</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"ترتیبات"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"ٹھیک ہے"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"سسٹم کے ذریعے اس اطلاع کو خاموش کیا گيا۔"</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"سسٹم کے ذریعے اس اطلاع کو پروموٹ کیا گيا۔"</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"سسٹم کے ذریعے اس اطلاع کو ڈیموٹ کیا گيا۔"</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"کیا یہ درست تھا؟"</string>
<string name="feedback_response" msgid="4671729244976641339">"آپ کے تاثرات کا شکریہ!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"ٹھیک ہے"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index b2ba26d..9e1387e 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Batareya uchta panelda."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Batareya to‘la."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Batareya quvvati foizi nomaʼlum."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Signal yo‘q."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefon bitta panelda."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefon ikkita panelda."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Telefon uchta panelda."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Telefon signali to‘liq."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Ma’lumotlar yo‘q."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Ma’lumotlar bitta panelda."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Ma’lumotlar ikkita panelda."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Ma’lumotlar uchta panelda."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Internet signali butun."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Ulangan: <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Ulangan: <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Bunga ulangan: <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Ikkita ustunli WiMAX."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Uchta ustunli WiMAX."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"To‘liq signalli WiMAX."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Qurilma Ethernet tarmog‘idan uzildi."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Qurilma Ethernet tarmog‘iga ulandi."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Signal yo‘q."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Ulanmagan."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Signal ustuni yo‘q."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Yoqilmagan"</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Ulangan."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Ulanmoqda…"</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Rouming"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"SIM kartasiz."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Mobil internet"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Mobil internet yoniq"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Mobil internet yoqilmagan"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Maʼlumotlardan foydalanish uchun sozlanmagan"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Yoqilmagan"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Bluetooth modem"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Parvoz rejimi"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN yoniq."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"SIM karta solinmagan."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Mobil tarmoqni o‘zgartirish"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Quvvat sarfi tafsilotlari"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Batareya <xliff:g id="NUMBER">%d</xliff:g> foiz."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Batareya quvvati <xliff:g id="PERCENTAGE">%1$s</xliff:g> foiz, joriy holatda yana <xliff:g id="TIME">%2$s</xliff:g> qoldi"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Telefon sozlamalari asosida jiringlashi yoki tebranishi mumkin. <xliff:g id="APP_NAME">%1$s</xliff:g> suhbatlari standart holatda bulutcha shaklida chiqadi."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Bu kontentni ochuvchi erkin yorliq diqqatingizda boʻladi."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Bu bildirishnoma jiringlashi yoki tebranishini hal qilsin"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Suhbatlar ruknining tepasida qalqib chiquvchi bulutcha shaklida chiqadi, ekran qulfida profil rasmi chiqadi"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Sozlamalar"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Muhim"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Bu ilova ekranda boshqa ilovalar ustidan ochilgan hamda mikrofon va kameradan foydalanmoqda."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Sozlamalar"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Bu bildirishnoma tizim tomonidan ovozsiz qilindi."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Bu bildirishnoma tizim tomonidan balandlatildi."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Bu bildirishnoma tizim tomonidan pasaytirildi."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Xatolar boʻlmadimi?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Fikr-mulohazangiz uchun tashakkur!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index a5d4900..92929b8 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Mức pin ba vạch."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Mức pin đầy."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Tỷ lệ phần trăm pin không xác định."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Không có điện thoại nào."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Tín hiệu điện thoại một vạch."</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Tín hiệu điện thoại hai vạch."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Tín hiệu điện thoại ba vạch."</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Tín hiệu điện thoại đầy đủ."</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Không có dữ liệu."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Tín hiệu dữ liệu một vạch."</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Tín hiệu dữ liệu hai vạch."</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Tín hiệu dữ liệu ba vạch."</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Tín hiệu dữ liệu đầy đủ."</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Đã kết nối với <xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Đã kết nối với <xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Đã kết nối với <xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX hai vạch."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX ba vạch."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Tín hiệu WiMAX đầy đủ."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"Đã ngắt kết nối Ethernet."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"Đã kết nối Ethernet."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Không có tín hiệu nào."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Chưa được kết nối."</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"0 vạch."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Tắt."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Đã kết nối."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Đang kết nối."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Chuyển vùng"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Không có SIM nào."</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Dữ liệu di động"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Dữ liệu di động đang bật"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Đã tắt dữ liệu di động"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Chưa được đặt để sử dụng dữ liệu"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Tắt"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Chia sẻ Internet qua Bluetooth"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Chế độ trên máy bay."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN đang bật."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Không có thẻ SIM nào."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Thay đổi mạng của nhà mạng"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Mở chi tiết về pin"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> phần trăm pin."</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> phần trăm pin, còn khoảng <xliff:g id="TIME">%2$s</xliff:g> dựa trên mức sử dụng của bạn"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Có thể đổ chuông hoặc rung tùy theo chế độ cài đặt trên điện thoại. Theo mặc định, các cuộc trò chuyện từ <xliff:g id="APP_NAME">%1$s</xliff:g> được phép hiển thị dưới dạng bong bóng."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Luôn chú ý vào nội dung này bằng phím tắt nổi."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Cho phép hệ thống quyết định xem thông báo này phát âm thanh hay rung"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Hiển thị cuộc trò chuyện ở đầu phần cuộc trò chuyện và dưới dạng bong bóng nổi, hiển thị ảnh hồ sơ trên màn hình khóa"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Cài đặt"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Mức độ ưu tiên"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Ứng dụng này đang hiển thị chồng lên các ứng dụng khác trên màn hình, đồng thời đang sử dụng micrô và máy ảnh."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Cài đặt"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"OK"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Hệ thống đã tắt tiếng thông báo này."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Hệ thống đã nâng mức ưu tiên của thông báo này."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Hệ thống đã giảm mức ưu tiên của thông báo này."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Thông tin này có chính xác không?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Cảm ơn bạn đã phản hồi!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"OK"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 10873c5..827ca5f 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"电池电量为三格。"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"电池电量满格。"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"电池电量百分比未知。"</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"没有手机信号。"</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"手机信号强度为一格。"</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"手机信号强度为两格。"</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"手机信号强度为三格。"</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"手机信号满格。"</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"没有数据网络信号。"</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"数据信号强度为一格。"</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"数据信号强度为两格。"</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"数据信号强度为三格。"</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"数据信号满格。"</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"已连接到“<xliff:g id="WIFI">%s</xliff:g>”。"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"已连接到<xliff:g id="BLUETOOTH">%s</xliff:g>。"</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"已连接到 <xliff:g id="CAST">%s</xliff:g>。"</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX 信号强度为两格。"</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX 信号强度为三格。"</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX 信号满格。"</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"以太网已断开连接。"</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"以太网已连接。"</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"无信号。"</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"未连接。"</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"信号强度为零格。"</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"关闭。"</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"已连接。"</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"正在连接。"</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"漫游"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"WLAN"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"无 SIM 卡。"</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"移动数据"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"移动数据已开启"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"移动数据网络已关闭"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"未设置为使用移动数据"</string>
<string name="cell_data_off" msgid="4886198950247099526">"关闭"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"蓝牙网络共享。"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"飞行模式。"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN 已开启。"</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"没有 SIM 卡。"</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"运营商网络正在更改"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"打开电量详情"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"电池电量为百分之 <xliff:g id="NUMBER">%d</xliff:g>。"</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"电池电量为 <xliff:g id="PERCENTAGE">%1$s</xliff:g>,根据您的使用情况,大约还可使用 <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"可能会响铃或振动(取决于手机设置)。默认情况下,来自<xliff:g id="APP_NAME">%1$s</xliff:g>的对话会以对话泡的形式显示。"</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"通过可链接到这项内容的浮动快捷方式吸引您的注意。"</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"让系统决定是否应让设备在收到此通知时发出提示音或振动"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"以悬浮对话泡形式显示在对话部分顶部,如果设备处于锁定状态,在锁定屏幕上显示个人资料照片"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"设置"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"优先"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"此应用正显示在屏幕上其他应用的上层,并且正在使用麦克风和摄像头。"</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"设置"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"确定"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"此通知已被系统静音。"</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"此通知已被系统升级。"</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"此通知已被系统降级。"</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"是否正确?"</string>
<string name="feedback_response" msgid="4671729244976641339">"感谢您提供反馈!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"确定"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 9abcf10..50bac07 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"電池電量為三格。"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"電池已滿。"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"電量百分比不明。"</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"沒有電話訊號。"</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"電話訊號強度為一格。"</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"電話訊號強度為兩格。"</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"電話訊號強度為三格。"</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"電話訊號滿格。"</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"沒有數據網絡。"</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"數據網絡訊號強度為一格。"</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"數據網絡訊號強度為兩格。"</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"數據網絡訊號強度為三格。"</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"數據網絡訊號滿格。"</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"已連線至<xliff:g id="WIFI">%s</xliff:g>。"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"已連線至<xliff:g id="BLUETOOTH">%s</xliff:g>。"</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"已連接至 <xliff:g id="CAST">%s</xliff:g>。"</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX 訊號強度兩格。"</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX 訊號強度三格。"</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX 訊號滿格。"</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"以太網連接中斷。"</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"已連接以太網。"</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"沒有訊號。"</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"未連線。"</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"訊號強度為零格。"</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"關閉。"</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"已連線。"</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"連線中。"</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"漫遊"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"無 SIM 卡。"</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"流動數據"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"開咗流動數據"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"流動數據已關閉"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"未設定至可使用資料"</string>
<string name="cell_data_off" msgid="4886198950247099526">"關閉"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"藍牙網絡共享。"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"飛航模式。"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"開咗 VPN。"</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"沒有 SIM 卡。"</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"流動網絡供應商網絡正在變更"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"開啟電池詳細資料"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"電池電量為百分之 <xliff:g id="NUMBER">%d</xliff:g>。"</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"電量仲剩番 <xliff:g id="PERCENTAGE">%1$s</xliff:g>。根據你嘅使用情況,仲可以用大約 <xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"可能會根據手機設定發出鈴聲或震動。「<xliff:g id="APP_NAME">%1$s</xliff:g>」的對話會預設以對話氣泡顯示。"</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"為此內容建立浮動捷徑以保持注意力。"</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"由系統判斷是否要讓此通知發出音效或震動"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"以浮動對話泡顯示在對話部分的頂部,並在上鎖畫面顯示個人檔案相片"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"設定"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"重要"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"此應用程式目前透過其他應用程式在畫面上顯示內容,且正在使用麥克風和相機。"</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"設定"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"確定"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"系統已將此通知設為靜音。"</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"系統已將此通知升級。"</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"系統已將此通知降級。"</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"是否正確?"</string>
<string name="feedback_response" msgid="4671729244976641339">"多謝您提供意見!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"確定"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index a33146b..0ff8ffa 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"電池電量三格。"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"電池電量已滿。"</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"電池電量不明。"</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"沒有電話訊號。"</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"電話訊號強度一格。"</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"電話訊號強度兩格。"</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"電話訊號強度三格。"</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"電話訊號滿格。"</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"沒有數據網路。"</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"數據網路訊號強度一格。"</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"數據網路訊號強度兩格。"</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"數據網路訊號強度三格。"</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"數據網路訊號滿格。"</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"已連線至<xliff:g id="WIFI">%s</xliff:g>。"</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"已連線至<xliff:g id="BLUETOOTH">%s</xliff:g>。"</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"已連線至 <xliff:g id="CAST">%s</xliff:g>。"</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"WiMAX 訊號兩格。"</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"WiMAX 訊號三格。"</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"WiMAX 訊號滿格。"</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"未連上乙太網路。"</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"已連上乙太網路。"</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"沒有訊號。"</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"尚未連線。"</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"訊號強度零格。"</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"關閉。"</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"已連線。"</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"連線中。"</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"漫遊"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"沒有 SIM 卡。"</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"行動數據"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"行動數據已開啟"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"行動數據已關閉"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"並未設為使用行動數據"</string>
<string name="cell_data_off" msgid="4886198950247099526">"已關閉"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"藍牙網路共用"</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"飛行模式。"</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"VPN 已開啟。"</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"沒有 SIM 卡。"</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"電信業者網路正在進行變更"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"開啟電量詳細資料"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"電池電量為百分之 <xliff:g id="NUMBER">%d</xliff:g>。"</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"目前的電量為 <xliff:g id="PERCENTAGE">%1$s</xliff:g>。根據你的使用情形,大約還能使用到<xliff:g id="TIME">%2$s</xliff:g>"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"可能會根據手機的設定響鈴或震動。根據預設,來自「<xliff:g id="APP_NAME">%1$s</xliff:g>」的對話會以對話框形式顯示。"</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"利用浮動式捷徑快速存取這項內容。"</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"由系統判斷要讓裝置在收到這則通知時震動還是發出音效"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"以浮動對話框的形式顯示在對話部分的頂端。如果裝置處於鎖定狀態,則在螢幕鎖定畫面上顯示個人資料相片"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"設定"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"優先"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"這個應用程式顯示在畫面上其他應用程式的上層,且正在使用麥克風和相機。"</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"設定"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"確定"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"系統已將這則通知設為靜音。"</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"系統已提升這則通知的優先順序。"</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"系統已降低這則通知的優先順序。"</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"是否正確?"</string>
<string name="feedback_response" msgid="4671729244976641339">"感謝你提供意見!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"確定"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 5c8b6cd..321fd20 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -187,16 +187,6 @@
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Amabha amathathu ebhethri"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Ibhethri igcwele."</string>
<string name="accessibility_battery_unknown" msgid="1807789554617976440">"Iphesenti lebhethri alaziwa."</string>
- <string name="accessibility_no_phone" msgid="8828412144430247025">"Ayikho ifoni."</string>
- <string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Ibha eyodwa yefoni"</string>
- <string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Amabha amabilil efoni."</string>
- <string name="accessibility_phone_three_bars" msgid="5670937367300884534">"Amabha amathathu efoni"</string>
- <string name="accessibility_phone_signal_full" msgid="1103449569988869971">"Isiginali yefoni igcwele"</string>
- <string name="accessibility_no_data" msgid="2124768255213392359">"Ayikho idatha."</string>
- <string name="accessibility_data_one_bar" msgid="3226985124149387055">"Idatha enye yebha"</string>
- <string name="accessibility_data_two_bars" msgid="4576231688545173059">"Amabha amabili edatha"</string>
- <string name="accessibility_data_three_bars" msgid="3036562180893930325">"Amabha amathathu edatha"</string>
- <string name="accessibility_data_signal_full" msgid="283507058258113551">"Igcwele i-signal yedatha"</string>
<string name="accessibility_wifi_name" msgid="4863440268606851734">"Xhuma ku-<xliff:g id="WIFI">%s</xliff:g>."</string>
<string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Xhuma ku-<xliff:g id="BLUETOOTH">%s</xliff:g>."</string>
<string name="accessibility_cast_name" msgid="7344437925388773685">"Ixhumeke ku-<xliff:g id="CAST">%s</xliff:g>."</string>
@@ -205,8 +195,6 @@
<string name="accessibility_wimax_two_bars" msgid="7335485192390018939">"Amabha amabili we-WiMAX."</string>
<string name="accessibility_wimax_three_bars" msgid="2773714362377629938">"Amabha amathathu we-WiMAX."</string>
<string name="accessibility_wimax_signal_full" msgid="3101861561730624315">"Isiginali ye-WiMAX egcwele."</string>
- <string name="accessibility_ethernet_disconnected" msgid="2097190491174968655">"I-Ethernet inqanyuliwe."</string>
- <string name="accessibility_ethernet_connected" msgid="3988347636883115213">"I-Ethernet ixhunyiwe."</string>
<string name="accessibility_no_signal" msgid="1115622734914921920">"Ayikho isignali."</string>
<string name="accessibility_not_connected" msgid="4061305616351042142">"Akuxhunyiwe"</string>
<string name="accessibility_zero_bars" msgid="1364823964848784827">"Amabha ayiqanda."</string>
@@ -218,30 +206,17 @@
<string name="accessibility_desc_off" msgid="8055389500285421408">"Vala."</string>
<string name="accessibility_desc_connected" msgid="3082590384032624233">"Ixhunyiwe."</string>
<string name="accessibility_desc_connecting" msgid="8011433412112903614">"Iyaxhuma."</string>
- <string name="data_connection_gprs" msgid="2752584037409568435">"I-GPRS"</string>
<string name="data_connection_hspa" msgid="6096234094857660873">"I-HSPA"</string>
- <string name="data_connection_3g" msgid="1215807817895516914">"3G"</string>
- <string name="data_connection_3_5g" msgid="4097346596394846450">"H"</string>
- <string name="data_connection_3_5g_plus" msgid="8938598386721354697">"H+"</string>
- <string name="data_connection_4g" msgid="5770196771037980730">"4G"</string>
- <string name="data_connection_4g_plus" msgid="780615287092000279">"4G+"</string>
- <string name="data_connection_lte" msgid="557021044282539923">"I-LTE"</string>
- <string name="data_connection_lte_plus" msgid="4799302403782283178">"I-LTE+"</string>
- <string name="data_connection_cdma" msgid="7678457855627313518">"1X"</string>
<string name="data_connection_roaming" msgid="375650836665414797">"Iyazulazula"</string>
- <string name="data_connection_edge" msgid="6316755666481405762">"I-EDGE"</string>
<string name="accessibility_data_connection_wifi" msgid="4422160347472742434">"I-Wi-Fi"</string>
<string name="accessibility_no_sim" msgid="1140839832913084973">"Ayikho i-SIM"</string>
<string name="accessibility_cell_data" msgid="172950885786007392">"Idatha Yeselula"</string>
<string name="accessibility_cell_data_on" msgid="691666434519443162">"Idatha yeselula ivuliwe"</string>
- <string name="cell_data_off_content_description" msgid="9165555931499878044">"Idatha yeselula ivaliwe"</string>
- <string name="not_default_data_content_description" msgid="6757881730711522517">"Akusethiwe ukuze kusetshenziswe idatha"</string>
<string name="cell_data_off" msgid="4886198950247099526">"Valiwe"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"Imodemu nge-Bluetooth."</string>
<string name="accessibility_airplane_mode" msgid="1899529214045998505">"Imodi yendiza."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"I-VPN ivuliwe."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"Alikho ikhadi le-SIM."</string>
- <string name="carrier_network_change_mode" msgid="5174141476991149918">"Inethiwekhi yenkampani yenethiwekhi iyashintsha"</string>
<string name="accessibility_battery_details" msgid="6184390274150865789">"Vula imininingwane yebhethri"</string>
<string name="accessibility_battery_level" msgid="5143715405241138822">"Iphesenti <xliff:g id="NUMBER">%d</xliff:g> lebhethri"</string>
<string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"Amaphesenti ebhethri ngu-<xliff:g id="PERCENTAGE">%1$s</xliff:g>, cishe kusele okungu-<xliff:g id="TIME">%2$s</xliff:g> kusukela ekusetshenzisweni kwakho"</string>
@@ -723,6 +698,14 @@
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Ingase ikhale noma idlidlize kuya ngamasethingi wefoni yakho. Izingxoxo ezivela ku-<xliff:g id="APP_NAME">%1$s</xliff:g> ziba yibhamuza ngokuzenzakalela."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Igcina ukunaka kwakho ngesinqamuleli esintantayo kulokhu okuqukethwe."</string>
<string name="notification_channel_summary_automatic" msgid="5813109268050235275">"Vumela isistimu inqume uma lesi saziso kufanele senze umsindo noma sidlidlize"</string>
+ <!-- no translation found for notification_channel_summary_automatic_alerted (954166812246932240) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_silenced (7403004439649872047) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_promoted (1301710305149590426) -->
+ <skip />
+ <!-- no translation found for notification_channel_summary_automatic_demoted (1831303964660807700) -->
+ <skip />
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Iboniswa ngenhla kwesigaba sengxoxo, ivela njengebhamuza elintantayo, ibonisa isithombe sephrofayela kukukhiya isikrini"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Izilungiselelo"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Okubalulekile"</string>
@@ -741,9 +724,14 @@
<string name="appops_camera_mic_overlay" msgid="5584311236445644095">"Lolu hlelo lokusebenza liboniswa ngaphezulu kwezinye izinhlelo zokusebenza kusikrini sakho futhi kusetshenziswa imakrofoni nekhamera."</string>
<string name="notification_appops_settings" msgid="5208974858340445174">"Izilungiselelo"</string>
<string name="notification_appops_ok" msgid="2177609375872784124">"KULUNGILE"</string>
- <string name="feedback_silenced" msgid="5382212321253328247">"Lesi saziso sithuliswe isistimu."</string>
- <string name="feedback_promoted" msgid="8075757485407091976">"Lesi saziso siphromothwe isistimu."</string>
- <string name="feedback_demoted" msgid="5848066008939031913">"Lesi saziso sehliswe isikhundla isistimu."</string>
+ <!-- no translation found for feedback_alerted (5192459808484271208) -->
+ <skip />
+ <!-- no translation found for feedback_silenced (9116540317466126457) -->
+ <skip />
+ <!-- no translation found for feedback_promoted (2125562787759780807) -->
+ <skip />
+ <!-- no translation found for feedback_demoted (951884763467110604) -->
+ <skip />
<string name="feedback_prompt" msgid="2278631214125128281">"Ingabe kade kulungile lokhu?"</string>
<string name="feedback_response" msgid="4671729244976641339">"Siyabonga ngempendulo!"</string>
<string name="feedback_ok" msgid="6481426753298857144">"KULUNGILE"</string>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 52b93ee..6f69483 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -677,6 +677,8 @@
<dimen name="keyguard_clock_top_margin">36dp</dimen>
<!-- The margin between top of clock and bottom of lock icon. -->
<dimen name="keyguard_clock_lock_margin">16dp</dimen>
+ <!-- The amount to shift the clocks during a small/large transition -->
+ <dimen name="keyguard_clock_switch_y_shift">10dp</dimen>
<item name="scrim_behind_alpha" format="float" type="dimen">0.62</item>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 6fa4aa1..0687d06 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -231,7 +231,7 @@
<!-- Notification text displayed when we fail to save a screenshot for unknown reasons. [CHAR LIMIT=100] -->
<string name="screenshot_failed_to_save_unknown_text">Try taking screenshot again</string>
<!-- Notification text displayed when we fail to save a screenshot. [CHAR LIMIT=100] -->
- <string name="screenshot_failed_to_save_text">Can\'t save screenshot due to limited storage space</string>
+ <string name="screenshot_failed_to_save_text">Can\'t save screenshot</string>
<!-- Notification text displayed when we fail to take a screenshot. [CHAR LIMIT=100] -->
<string name="screenshot_failed_to_capture_text">Taking screenshots isn\'t allowed by the app or
your organization</string>
@@ -2773,6 +2773,14 @@
<string name="basic_status" translatable="false">Open conversation</string>
<!-- Status for conversation without interaction data [CHAR LIMIT=120] -->
<string name="select_conversation_text" translatable="false">Select one conversation to show in your widget:</string>
+ <!-- Timestamp for notification with exact time [CHAR LIMIT=120] -->
+ <string name="timestamp" translatable="false"><xliff:g id="duration" example="5 hours">%1$s</xliff:g> ago</string>
+ <!-- Timestamp for notification when less than a certain time window [CHAR LIMIT=120] -->
+ <string name="less_than_timestamp" translatable="false">Less than <xliff:g id="duration" example="5 hours">%1$s</xliff:g> ago</string>
+ <!-- Timestamp for notification when over a certain time window [CHAR LIMIT=120] -->
+ <string name="over_timestamp" translatable="false">Over <xliff:g id="duration" example="1 week">%1$s</xliff:g> ago</string>
+ <!-- Status text for a birthday today [CHAR LIMIT=120] -->
+ <string name="birthday_status" translatable="false">Today is their birthday!</string>
<!-- Title to display in a notification when ACTION_BATTERY_CHANGED.EXTRA_PRESENT field is false
[CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
index d8fa90a..7dc537c 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
@@ -22,7 +22,7 @@
import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_UNDEFINED;
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Point;
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
index 229d20b..e5c4bf3 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
@@ -27,7 +27,7 @@
import android.app.ActivityManager;
import android.app.ActivityManager.RecentTaskInfo;
import android.app.ActivityManager.RunningTaskInfo;
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
import android.app.AppGlobals;
@@ -122,7 +122,7 @@
* @return the task snapshot for the given {@param taskId}.
*/
public @NonNull ThumbnailData getTaskThumbnail(int taskId, boolean isLowResolution) {
- ActivityManager.TaskSnapshot snapshot = null;
+ TaskSnapshot snapshot = null;
try {
snapshot = getService().getTaskSnapshot(taskId, isLowResolution);
} catch (RemoteException e) {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
index fa2f8b9..af7c5da 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
@@ -16,7 +16,7 @@
package com.android.systemui.shared.system;
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
import android.graphics.Rect;
import android.os.RemoteException;
import android.util.Log;
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
index 065d084..a907e66 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
@@ -17,8 +17,8 @@
package com.android.systemui.shared.system;
import android.app.ActivityManager.RunningTaskInfo;
-import android.app.ActivityManager.TaskSnapshot;
import android.app.ActivityTaskManager;
+import android.window.TaskSnapshot;
import android.app.TaskStackListener;
import android.content.ComponentName;
import android.os.Handler;
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ThreadedRendererCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ThreadedRendererCompat.java
index bf88a29..ffd8a08 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ThreadedRendererCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ThreadedRendererCompat.java
@@ -23,6 +23,7 @@
*/
public class ThreadedRendererCompat {
+ public static int EGL_CONTEXT_PRIORITY_REALTIME_NV = 0x3357;
public static int EGL_CONTEXT_PRIORITY_HIGH_IMG = 0x3101;
public static int EGL_CONTEXT_PRIORITY_MEDIUM_IMG = 0x3102;
public static int EGL_CONTEXT_PRIORITY_LOW_IMG = 0x3103;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index ab7ba8a..323449a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -1,6 +1,8 @@
package com.android.keyguard;
import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Paint;
@@ -48,6 +50,9 @@
*/
private static final float TO_BOLD_TRANSITION_FRACTION = 0.7f;
+ private static final long CLOCK_OUT_MILLIS = 150;
+ private static final long CLOCK_IN_MILLIS = 200;
+
/**
* Layout transition that scales the default clock face.
*/
@@ -112,6 +117,7 @@
private int[] mColorPalette;
private int mLockScreenMode = KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL;
+ private int mClockSwitchYAmount;
public KeyguardClockSwitch(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -131,6 +137,17 @@
}
/**
+ * Apply dp changes on font/scale change
+ */
+ public void onDensityOrFontScaleChanged() {
+ setTextSize(TypedValue.COMPLEX_UNIT_PX, mContext.getResources()
+ .getDimensionPixelSize(R.dimen.widget_big_font_size));
+
+ mClockSwitchYAmount = mContext.getResources().getDimensionPixelSize(
+ R.dimen.keyguard_clock_switch_y_shift);
+ }
+
+ /**
* Returns if this view is presenting a custom clock, or the default implementation.
*/
public boolean hasCustomClock() {
@@ -181,6 +198,8 @@
mNewLockscreenLargeClockFrame = findViewById(R.id.new_lockscreen_clock_view_large);
mSmallClockFrame = findViewById(R.id.clock_view);
mKeyguardStatusArea = findViewById(R.id.keyguard_status_area);
+
+ onDensityOrFontScaleChanged();
}
void setClockPlugin(ClockPlugin plugin, int statusBarState) {
@@ -296,31 +315,43 @@
mClockViewBold.setFormat24Hour(format);
}
- private void updateClockLayout(boolean useLargeClock) {
+ private void animateClockChange(boolean useLargeClock) {
if (mLockScreenMode != KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1) return;
- Fade fadeIn = new Fade();
- fadeIn.setDuration(KeyguardSliceView.DEFAULT_ANIM_DURATION);
- fadeIn.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
-
- Fade fadeOut = new Fade();
- fadeOut.setDuration(KeyguardSliceView.DEFAULT_ANIM_DURATION / 2);
- fadeOut.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
-
+ View in, out;
+ int direction = 1;
if (useLargeClock) {
- TransitionManager.beginDelayedTransition(mNewLockscreenClockFrame, fadeOut);
- TransitionManager.beginDelayedTransition(mNewLockscreenLargeClockFrame, fadeIn);
-
- mNewLockscreenClockFrame.setVisibility(View.INVISIBLE);
- addView(mNewLockscreenLargeClockFrame);
- mNewLockscreenLargeClockFrame.setVisibility(View.VISIBLE);
+ out = mNewLockscreenClockFrame;
+ in = mNewLockscreenLargeClockFrame;
+ addView(in);
+ direction = -1;
} else {
- TransitionManager.beginDelayedTransition(mNewLockscreenClockFrame, fadeIn);
- TransitionManager.beginDelayedTransition(mNewLockscreenLargeClockFrame, fadeOut);
+ in = mNewLockscreenClockFrame;
+ out = mNewLockscreenLargeClockFrame;
- removeView(mNewLockscreenLargeClockFrame);
- mNewLockscreenClockFrame.setVisibility(View.VISIBLE);
+ // Must remove in order for notifications to appear in the proper place
+ removeView(out);
}
+
+ AnimatorSet outAnim = new AnimatorSet();
+ outAnim.setDuration(CLOCK_OUT_MILLIS);
+ outAnim.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
+ outAnim.playTogether(
+ ObjectAnimator.ofFloat(out, View.ALPHA, 0f),
+ ObjectAnimator.ofFloat(out, View.TRANSLATION_Y, 0,
+ direction * -mClockSwitchYAmount));
+
+ in.setAlpha(0);
+ in.setVisibility(View.VISIBLE);
+ AnimatorSet inAnim = new AnimatorSet();
+ inAnim.setDuration(CLOCK_IN_MILLIS);
+ inAnim.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
+ inAnim.playTogether(ObjectAnimator.ofFloat(in, View.ALPHA, 1f),
+ ObjectAnimator.ofFloat(in, View.TRANSLATION_Y, direction * mClockSwitchYAmount, 0));
+ inAnim.setStartDelay(CLOCK_OUT_MILLIS / 2);
+
+ inAnim.start();
+ outAnim.start();
}
/**
@@ -343,7 +374,8 @@
if (hasVisibleNotifications == mHasVisibleNotifications) {
return;
}
- updateClockLayout(!hasVisibleNotifications);
+
+ animateClockChange(!hasVisibleNotifications);
mHasVisibleNotifications = hasVisibleNotifications;
if (mDarkAmount == 0f && mBigClockContainer != null) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index 4d6e8a9..e0de180 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -21,7 +21,6 @@
import android.content.res.Resources;
import android.provider.Settings;
import android.text.format.DateFormat;
-import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
@@ -146,11 +145,10 @@
}
/**
- * Updates clock's text
+ * Apply dp changes on font/scale change
*/
public void onDensityOrFontScaleChanged() {
- mView.setTextSize(TypedValue.COMPLEX_UNIT_PX,
- mResources.getDimensionPixelSize(R.dimen.widget_big_font_size));
+ mView.onDensityOrFontScaleChanged();
}
/**
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 2071cfa..b43496c 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -1901,6 +1901,15 @@
}
/**
+ * Whether to show the lock icon on lock screen and bouncer. This depends on the enrolled
+ * biometrics to the device.
+ */
+ public boolean shouldShowLockIcon() {
+ return isFaceAuthEnabledForUser(KeyguardUpdateMonitor.getCurrentUser())
+ && !isUdfpsEnrolled();
+ }
+
+ /**
* @return true if there's at least one udfps enrolled
*/
public boolean isUdfpsEnrolled() {
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java
new file mode 100644
index 0000000..c0f8cae
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java
@@ -0,0 +1,109 @@
+/*
+ * 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 04e26d3..d6cb114 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
@@ -50,6 +50,7 @@
ForegroundServiceController foregroundServiceController,
NotificationEntryManager notificationEntryManager,
NotifPipeline notifPipeline,
+ ForegroundServiceLifetimeExtender fgsLifetimeExtender,
SystemClock systemClock) {
mContext = context;
mForegroundServiceController = foregroundServiceController;
@@ -77,6 +78,7 @@
removeNotification(entry.getSbn());
}
});
+ mEntryManager.addNotificationLifetimeExtender(fgsLifetimeExtender);
notifPipeline.addCollectionListener(new NotifCollectionListener() {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index bf42a60..036fcf3 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -33,14 +33,15 @@
import android.provider.Settings;
import android.util.Log;
import android.util.TimingsTraceLog;
+import android.view.SurfaceControl;
import com.android.internal.protolog.common.ProtoLog;
import com.android.systemui.dagger.ContextComponentHelper;
import com.android.systemui.dagger.GlobalRootComponent;
import com.android.systemui.dagger.SysUIComponent;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.people.PeopleSpaceActivity;
import com.android.systemui.people.widget.PeopleSpaceWidgetProvider;
+import com.android.systemui.shared.system.ThreadedRendererCompat;
import com.android.systemui.util.NotificationChannels;
import java.lang.reflect.Constructor;
@@ -98,6 +99,18 @@
if (Process.myUserHandle().equals(UserHandle.SYSTEM)) {
IntentFilter bootCompletedFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
bootCompletedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+
+ // If SF GPU context priority is set to realtime, then SysUI should run at high.
+ // The priority is defaulted at medium.
+ int sfPriority = SurfaceControl.getGPUContextPriority();
+ Log.i(TAG, "Found SurfaceFlinger's GPU Priority: " + sfPriority);
+ if (sfPriority == ThreadedRendererCompat.EGL_CONTEXT_PRIORITY_REALTIME_NV) {
+ Log.i(TAG, "Setting SysUI's GPU Context priority to: "
+ + ThreadedRendererCompat.EGL_CONTEXT_PRIORITY_HIGH_IMG);
+ ThreadedRendererCompat.setContextPriority(
+ ThreadedRendererCompat.EGL_CONTEXT_PRIORITY_HIGH_IMG);
+ }
+
registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -112,26 +125,12 @@
mServices[i].onBootCompleted();
}
}
- // If flag SHOW_PEOPLE_SPACE is true, enable People Space launcher icon.
- // TODO(b/170396074): Remove this when we don't need an icon anymore.
- try {
- int showPeopleSpace = Settings.Global.getInt(context.getContentResolver(),
- Settings.Global.SHOW_PEOPLE_SPACE, 0);
- context.getPackageManager().setComponentEnabledSetting(
- new ComponentName(context, PeopleSpaceActivity.class),
- showPeopleSpace == 1
- ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
- : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
- PackageManager.DONT_KILL_APP);
- } catch (Exception e) {
- Log.w(TAG, "Error enabling People Space launch icon:", e);
- }
// If SHOW_PEOPLE_SPACE is true, enable People Space widget provider.
// TODO(b/170396074): Remove this when we don't need a widget anymore.
try {
int showPeopleSpace = Settings.Global.getInt(context.getContentResolver(),
- Settings.Global.SHOW_PEOPLE_SPACE, 0);
+ Settings.Global.SHOW_PEOPLE_SPACE, 1);
context.getPackageManager().setComponentEnabledSetting(
new ComponentName(context, PeopleSpaceWidgetProvider.class),
showPeopleSpace == 1
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 7bb8a84..65a6f29 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -91,7 +91,7 @@
private final String mHbmDisableCommand;
private final boolean mHbmSupported;
// Brightness in nits in the high-brightness mode.
- private final float mHbmNits;
+ private final float mMaxNits;
// A spline mapping from the device's backlight value, normalized to the range [0, 1.0], to a
// brightness in nits.
private final Spline mBacklightToNitsSpline;
@@ -135,7 +135,7 @@
@SuppressLint("ClickableViewAccessibility")
private final UdfpsView.OnTouchListener mOnTouchListener = (v, event) -> {
UdfpsView view = (UdfpsView) v;
- final boolean isFingerDown = view.isScrimShowing();
+ final boolean isFingerDown = view.isShowScrimAndDot();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
@@ -211,30 +211,51 @@
// non-high-brightness mode.
float[] nitsRange = toFloatArray(resources.obtainTypedArray(
com.android.internal.R.array.config_screenBrightnessNits));
+ if (nitsRange.length < 2) {
+ throw new IllegalArgumentException(
+ String.format("nitsRange.length: %d. Must be >= 2", nitsRange.length));
+ }
// The last value of this range corresponds to the high-brightness mode.
float[] nitsAutoBrightnessValues = toFloatArray(resources.obtainTypedArray(
com.android.internal.R.array.config_autoBrightnessDisplayValuesNits));
+ if (nitsAutoBrightnessValues.length < 2) {
+ throw new IllegalArgumentException(
+ String.format("nitsAutoBrightnessValues.length: %d. Must be >= 2",
+ nitsAutoBrightnessValues.length));
+ }
- mHbmNits = nitsAutoBrightnessValues[nitsAutoBrightnessValues.length - 1];
- float[] hbmNitsRange = {nitsRange[0], mHbmNits};
+ mMaxNits = nitsAutoBrightnessValues[nitsAutoBrightnessValues.length - 1];
+ float[] hbmNitsRange = nitsRange.clone();
+ hbmNitsRange[hbmNitsRange.length - 1] = mMaxNits;
// This range only consists of the minimum and maximum backlight values, which only apply
// in non-high-brightness mode.
float[] normalizedBacklightRange = normalizeBacklightRange(
resources.getIntArray(
com.android.internal.R.array.config_screenBrightnessBacklight));
+ if (normalizedBacklightRange.length < 2) {
+ throw new IllegalArgumentException(
+ String.format("normalizedBacklightRange.length: %d. Must be >= 2",
+ normalizedBacklightRange.length));
+ }
+ if (normalizedBacklightRange.length != nitsRange.length) {
+ throw new IllegalArgumentException(
+ "normalizedBacklightRange.length != nitsRange.length");
+ }
mBacklightToNitsSpline = Spline.createSpline(normalizedBacklightRange, nitsRange);
mNitsToHbmBacklightSpline = Spline.createSpline(hbmNitsRange, normalizedBacklightRange);
mDefaultBrightness = obtainDefaultBrightness(powerManager);
// TODO(b/160025856): move to the "dump" method.
- Log.v(TAG, String.format("ctor | mNitsRange: [%f, %f]", nitsRange[0], nitsRange[1]));
+ Log.v(TAG, String.format("ctor | mNitsRange: [%f, %f]", nitsRange[0],
+ nitsRange[nitsRange.length - 1]));
Log.v(TAG, String.format("ctor | mHbmNitsRange: [%f, %f]", hbmNitsRange[0],
- hbmNitsRange[1]));
+ hbmNitsRange[hbmNitsRange.length - 1]));
Log.v(TAG, String.format("ctor | mNormalizedBacklightRange: [%f, %f]",
- normalizedBacklightRange[0], normalizedBacklightRange[1]));
+ normalizedBacklightRange[0],
+ normalizedBacklightRange[normalizedBacklightRange.length - 1]));
mFingerprintManager.setUdfpsOverlayController(new UdfpsOverlayController());
mIsOverlayShowing = false;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java
index 5a61379..663a0da 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java
@@ -27,6 +27,7 @@
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.text.TextUtils;
import android.util.AttributeSet;
@@ -70,6 +71,7 @@
// mInsetsListener to restrict the touchable region and allow the touches outside of the sensor
// to propagate to the rest of the UI.
@NonNull private final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsListener;
+ @NonNull private final Drawable mFingerprintDrawable;
// Used to obtain the sensor location.
@NonNull private FingerprintSensorPropertiesInternal mSensorProps;
@@ -79,7 +81,7 @@
private float mBurnInOffsetX;
private float mBurnInOffsetY;
- private boolean mIsScrimShowing;
+ private boolean mShowScrimAndDot;
private boolean mIsHbmSupported;
@Nullable private String mDebugMessage;
@@ -112,15 +114,16 @@
mSensorPaint = new Paint(0 /* flags */);
mSensorPaint.setAntiAlias(true);
mSensorPaint.setColor(Color.WHITE);
- mSensorPaint.setStyle(Paint.Style.STROKE);
- mSensorPaint.setStrokeWidth(SENSOR_OUTLINE_WIDTH);
mSensorPaint.setShadowLayer(SENSOR_SHADOW_RADIUS, 0, 0, Color.BLACK);
+ mSensorPaint.setStyle(Paint.Style.FILL);
mDebugTextPaint = new Paint();
mDebugTextPaint.setAntiAlias(true);
mDebugTextPaint.setColor(Color.BLUE);
mDebugTextPaint.setTextSize(DEBUG_TEXT_SIZE_PX);
+ mFingerprintDrawable = getResources().getDrawable(R.drawable.ic_fingerprint, null);
+
mTouchableRegion = new Rect();
// When the device is rotated, it's important that mTouchableRegion is updated before
// this listener is called. This listener is usually called shortly after onLayout.
@@ -130,7 +133,7 @@
internalInsetsInfo.touchableRegion.set(mTouchableRegion);
};
- mIsScrimShowing = false;
+ mShowScrimAndDot = false;
}
void setSensorProperties(@NonNull FingerprintSensorPropertiesInternal properties) {
@@ -181,6 +184,13 @@
default:
// Do nothing to stay in portrait mode.
}
+
+ int margin = (int) (mSensorRect.bottom - mSensorRect.top) / 5;
+ mFingerprintDrawable.setBounds(
+ (int) mSensorRect.left + margin,
+ (int) mSensorRect.top + margin,
+ (int) mSensorRect.right - margin,
+ (int) mSensorRect.bottom - margin);
}
@Override
@@ -198,6 +208,8 @@
// is finished, mTouchableRegion will be used by mInsetsListener to compute the touch
// insets.
mSensorRect.roundOut(mTouchableRegion);
+
+
}
@Override
@@ -218,7 +230,7 @@
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
- if (mIsScrimShowing && mIsHbmSupported) {
+ if (mShowScrimAndDot && mIsHbmSupported) {
// Only draw the scrim if HBM is supported.
canvas.drawRect(mScrimRect, mScrimPaint);
}
@@ -229,7 +241,15 @@
if (!TextUtils.isEmpty(mDebugMessage)) {
canvas.drawText(mDebugMessage, 0, 160, mDebugTextPaint);
}
- canvas.drawOval(mSensorRect, mSensorPaint);
+
+ if (mShowScrimAndDot) {
+ // draw dot (white circle)
+ canvas.drawOval(mSensorRect, mSensorPaint);
+ } else {
+ // draw fingerprint icon
+ mFingerprintDrawable.draw(canvas);
+ }
+
canvas.restore();
}
@@ -264,19 +284,17 @@
mScrimPaint.setAlpha(alpha);
}
- boolean isScrimShowing() {
- return mIsScrimShowing;
+ boolean isShowScrimAndDot() {
+ return mShowScrimAndDot;
}
void showScrimAndDot() {
- mIsScrimShowing = true;
- mSensorPaint.setStyle(Paint.Style.FILL);
+ mShowScrimAndDot = true;
invalidate();
}
void hideScrimAndDot() {
- mIsScrimShowing = false;
- mSensorPaint.setStyle(Paint.Style.STROKE);
+ mShowScrimAndDot = false;
invalidate();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/FaceAuthScreenBrightnessController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/FaceAuthScreenBrightnessController.kt
index a7d17e1..b4137fa 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/FaceAuthScreenBrightnessController.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/FaceAuthScreenBrightnessController.kt
@@ -64,7 +64,8 @@
private val globalSettings: GlobalSettings,
private val systemSettings: SystemSettings,
private val mainHandler: Handler,
- private val dumpManager: DumpManager
+ private val dumpManager: DumpManager,
+ private val enabled: Boolean
) : Dumpable {
private var userDefinedBrightness: Float = 1f
@@ -86,7 +87,7 @@
return
}
// TODO enable only when receiving a low-light error
- overridingBrightness = running
+ overridingBrightness = if (enabled) running else false
}
}
private lateinit var whiteOverlay: View
@@ -188,6 +189,7 @@
println("brightnessAnimationDuration: $brightnessAnimationDuration")
println("maxScreenBrightness: $maxScreenBrightness")
println("userDefinedBrightness: $userDefinedBrightness")
+ println("enabled: $enabled")
}
}
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
index d7b5eea..626abfc 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -142,8 +142,9 @@
return Optional.empty();
}
+ // currently disabled (doesn't ramp up brightness or use scrim) see b/175918367
return Optional.of(new FaceAuthScreenBrightnessController(
notificationShadeWindowController, keyguardUpdateMonitor, resources,
- globalSetting, systemSettings, handler, dumpManager));
+ globalSetting, systemSettings, handler, dumpManager, false));
}
}
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 9e25389..4f85192 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
@@ -94,7 +94,8 @@
public MediaOutputController(@NonNull Context context, String packageName,
boolean aboveStatusbar, MediaSessionManager mediaSessionManager, LocalBluetoothManager
lbm, ShadeController shadeController, ActivityStarter starter,
- NotificationEntryManager notificationEntryManager, UiEventLogger uiEventLogger) {
+ NotificationEntryManager notificationEntryManager, UiEventLogger uiEventLogger,
+ MediaRouter2Manager routerManager) {
mContext = context;
mPackageName = packageName;
mMediaSessionManager = mediaSessionManager;
@@ -106,7 +107,7 @@
mLocalMediaManager = new LocalMediaManager(mContext, lbm, imm, packageName);
mMetricLogger = new MediaOutputMetricLogger(mContext, mPackageName);
mUiEventLogger = uiEventLogger;
- mRouterManager = MediaRouter2Manager.getInstance(mContext);
+ mRouterManager = routerManager;
}
void start(@NonNull Callback cb) {
@@ -137,7 +138,9 @@
mLocalMediaManager.stopScan();
mLocalMediaManager.registerCallback(this);
mLocalMediaManager.startScan();
- mRouterManager.startScan();
+ if (mRouterManager != null) {
+ mRouterManager.startScan();
+ }
}
void stop() {
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt
index 0f340a5..e1a504c 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt
@@ -18,6 +18,7 @@
import android.content.Context
import android.media.session.MediaSessionManager
+import android.media.MediaRouter2Manager
import com.android.internal.logging.UiEventLogger
import com.android.settingslib.bluetooth.LocalBluetoothManager
import com.android.systemui.plugins.ActivityStarter
@@ -35,7 +36,8 @@
private val shadeController: ShadeController,
private val starter: ActivityStarter,
private val notificationEntryManager: NotificationEntryManager,
- private val uiEventLogger: UiEventLogger
+ private val uiEventLogger: UiEventLogger,
+ private val routerManager: MediaRouter2Manager
) {
companion object {
var mediaOutputDialog: MediaOutputDialog? = null
@@ -46,7 +48,7 @@
mediaOutputDialog?.dismiss()
mediaOutputDialog = MediaOutputController(context, packageName, aboveStatusBar,
mediaSessionManager, lbm, shadeController, starter, notificationEntryManager,
- uiEventLogger).run {
+ uiEventLogger, routerManager).run {
MediaOutputDialog(context, aboveStatusBar, this, uiEventLogger)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
index e43eb9f..2ad12b9 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
@@ -38,11 +38,12 @@
import androidx.preference.PreferenceManager;
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.logging.UiEventLoggerImpl;
import com.android.systemui.R;
import com.android.systemui.people.widget.PeopleSpaceWidgetProvider;
import java.util.List;
-import java.util.Map;
/**
* Shows the user their tiles for their priority People (go/live-status).
@@ -60,6 +61,7 @@
private AppWidgetManager mAppWidgetManager;
private int mAppWidgetId;
private boolean mShowSingleConversation;
+ private UiEventLogger mUiEventLogger = new UiEventLoggerImpl();
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -93,13 +95,12 @@
*/
private void setTileViewsWithPriorityConversations() {
try {
- List<Map.Entry<Long, PeopleSpaceTile>> tiles = PeopleSpaceUtils.getTiles(
+ List<PeopleSpaceTile> tiles = PeopleSpaceUtils.getTiles(
mContext, mNotificationManager, mPeopleManager, mLauncherApps);
- for (Map.Entry<Long, PeopleSpaceTile> entry : tiles) {
- PeopleSpaceTile tile = entry.getValue();
+ for (PeopleSpaceTile tile : tiles) {
PeopleSpaceTileView tileView = new PeopleSpaceTileView(mContext, mPeopleSpaceLayout,
tile.getId());
- setTileView(tileView, tile, entry.getKey());
+ setTileView(tileView, tile);
}
} catch (Exception e) {
Log.e(TAG, "Couldn't retrieve conversations", e);
@@ -107,12 +108,12 @@
}
/** Sets {@code tileView} with the data in {@code conversation}. */
- private void setTileView(PeopleSpaceTileView tileView, PeopleSpaceTile tile,
- long lastInteraction) {
+ private void setTileView(PeopleSpaceTileView tileView, PeopleSpaceTile tile) {
try {
String pkg = tile.getPackageName();
String status =
- PeopleSpaceUtils.getLastInteractionString(mContext, lastInteraction);
+ PeopleSpaceUtils.getLastInteractionString(mContext,
+ tile.getLastInteractionTimestamp(), true);
tileView.setStatus(status);
tileView.setName(tile.getUserName().toString());
@@ -149,6 +150,8 @@
/** Finish activity with a successful widget configuration result. */
private void finishActivity() {
+ if (PeopleSpaceUtils.DEBUG) Log.d(TAG, "Widget added!");
+ mUiEventLogger.log(PeopleSpaceUtils.PeopleSpaceWidgetEvent.PEOPLE_SPACE_WIDGET_ADDED);
Intent resultValue = new Intent();
resultValue.putExtra(EXTRA_APPWIDGET_ID, mAppWidgetId);
setResult(RESULT_OK, resultValue);
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
index d682379..f1a57bf 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
@@ -29,6 +29,8 @@
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.LauncherApps;
+import android.database.Cursor;
+import android.database.SQLException;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
@@ -41,7 +43,7 @@
import android.os.Parcelable;
import android.os.ServiceManager;
import android.os.UserHandle;
-import android.preference.PreferenceManager;
+import android.provider.ContactsContract;
import android.provider.Settings;
import android.service.notification.ConversationChannelWrapper;
import android.service.notification.StatusBarNotification;
@@ -49,19 +51,30 @@
import android.view.View;
import android.widget.RemoteViews;
+import androidx.preference.PreferenceManager;
+
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.UiEvent;
+import com.android.internal.logging.UiEventLogger;
import com.android.internal.util.ArrayUtils;
+import com.android.settingslib.utils.ThreadUtils;
import com.android.systemui.R;
import com.android.systemui.people.widget.LaunchConversationActivity;
import com.android.systemui.people.widget.PeopleSpaceWidgetProvider;
+import java.text.SimpleDateFormat;
import java.time.Duration;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -75,14 +88,42 @@
private static final int ONE_DAY = 1;
public static final String OPTIONS_PEOPLE_SPACE_TILE = "options_people_space_tile";
+ private static final Pattern DOUBLE_EXCLAMATION_PATTERN = Pattern.compile("[!][!]+");
+ private static final Pattern DOUBLE_QUESTION_PATTERN = Pattern.compile("[?][?]+");
+ private static final Pattern ANY_DOUBLE_MARK_PATTERN = Pattern.compile("[!?][!?]+");
+ private static final Pattern MIXED_MARK_PATTERN = Pattern.compile("![?].*|.*[?]!");
+
/** Represents whether {@link StatusBarNotification} was posted or removed. */
public enum NotificationAction {
POSTED,
REMOVED
}
+ /**
+ * The UiEvent enums that this class can log.
+ */
+ public enum PeopleSpaceWidgetEvent implements UiEventLogger.UiEventEnum {
+ @UiEvent(doc = "People space widget deleted")
+ PEOPLE_SPACE_WIDGET_DELETED(666),
+ @UiEvent(doc = "People space widget added")
+ PEOPLE_SPACE_WIDGET_ADDED(667),
+ @UiEvent(doc = "People space widget clicked to launch conversation")
+ PEOPLE_SPACE_WIDGET_CLICKED(668);
+
+ private final int mId;
+
+ PeopleSpaceWidgetEvent(int id) {
+ mId = id;
+ }
+
+ @Override
+ public int getId() {
+ return mId;
+ }
+ }
+
/** Returns a list of map entries corresponding to user's conversations. */
- public static List<Map.Entry<Long, PeopleSpaceTile>> getTiles(
+ public static List<PeopleSpaceTile> getTiles(
Context context, INotificationManager notificationManager, IPeopleManager peopleManager,
LauncherApps launcherApps)
throws Exception {
@@ -90,70 +131,72 @@
Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0) == 1;
List<ConversationChannelWrapper> conversations = notificationManager.getConversations(
true).getList();
- List<Map.Entry<Long, PeopleSpaceTile>> tiles = getSortedTiles(peopleManager,
- conversations.stream().map(c ->
- new PeopleSpaceTile.Builder(c.getShortcutInfo(), launcherApps).build()));
+ List<PeopleSpaceTile> tiles = getSortedTiles(peopleManager,
+ conversations.stream().filter(c -> c.getShortcutInfo() != null).map(
+ c -> new PeopleSpaceTile.Builder(c.getShortcutInfo(),
+ launcherApps).build()));
if (!showOnlyPriority) {
if (DEBUG) Log.d(TAG, "Add recent conversations");
List<ConversationChannel> recentConversations =
peopleManager.getRecentConversations().getList();
- List<Map.Entry<Long, PeopleSpaceTile>> recentTiles =
- getSortedTiles(peopleManager, recentConversations.stream().map(c ->
- new PeopleSpaceTile
- .Builder(c.getShortcutInfo(), launcherApps)
- .build()));
+ List<PeopleSpaceTile> recentTiles =
+ getSortedTiles(peopleManager,
+ recentConversations
+ .stream()
+ .filter(
+ c -> c.getShortcutInfo() != null)
+ .map(
+ c -> new PeopleSpaceTile.Builder(c.getShortcutInfo(),
+ launcherApps).build()));
tiles.addAll(recentTiles);
}
return tiles;
}
- /** Updates {@code appWidgetIds} with their associated conversation stored. */
+ /**
+ * Updates {@code appWidgetIds} with their associated conversation stored, handling a
+ * notification being posted or removed.
+ */
public static void updateSingleConversationWidgets(Context context, int[] appWidgetIds,
AppWidgetManager appWidgetManager, INotificationManager notificationManager) {
IPeopleManager peopleManager = IPeopleManager.Stub.asInterface(
ServiceManager.getService(Context.PEOPLE_SERVICE));
LauncherApps launcherApps = context.getSystemService(LauncherApps.class);
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
+ Map<Integer, PeopleSpaceTile> widgetIdToTile = new HashMap<>();
try {
- List<Map.Entry<Long, PeopleSpaceTile>> tiles =
+ List<PeopleSpaceTile> tiles =
PeopleSpaceUtils.getTiles(context, notificationManager,
peopleManager, launcherApps);
-
for (int appWidgetId : appWidgetIds) {
String shortcutId = sp.getString(String.valueOf(appWidgetId), null);
if (DEBUG) {
- Log.d(TAG, "Set widget: " + appWidgetId + " with shortcut ID: " + shortcutId);
+ Log.d(TAG, "Widget ID: " + appWidgetId + " Shortcut ID: " + shortcutId);
}
- Optional<Map.Entry<Long, PeopleSpaceTile>> entry = tiles.stream().filter(
- e -> e.getValue().getId().equals(shortcutId)).findFirst();
+
+ Optional<PeopleSpaceTile> entry = tiles.stream().filter(
+ e -> e.getId().equals(shortcutId)).findFirst();
+
if (!entry.isPresent() || shortcutId == null) {
if (DEBUG) Log.d(TAG, "Matching conversation not found for shortcut ID");
//TODO: Delete app widget id when crash is fixed (b/175486868)
continue;
}
- PeopleSpaceTile tile =
- augmentTileFromStorage(entry.get().getValue(), appWidgetManager,
- appWidgetId);
-
- RemoteViews views = createRemoteViews(context, tile, entry.get().getKey(),
+ // Augment current tile based on stored fields.
+ PeopleSpaceTile tile = augmentTileFromStorage(entry.get(), appWidgetManager,
appWidgetId);
+ RemoteViews views = createRemoteViews(context, tile, appWidgetId);
+
// Tell the AppWidgetManager to perform an update on the current app widget.
appWidgetManager.updateAppWidget(appWidgetId, views);
+
+ widgetIdToTile.put(appWidgetId, tile);
}
} catch (Exception e) {
- Log.e(TAG, "Exception updating single conversation widgets: " + e);
+ Log.e(TAG, "Failed to retrieve conversations to set tiles: " + e);
}
- }
-
- /** Returns a list sorted by ascending last interaction time from {@code stream}. */
- private static List<Map.Entry<Long, PeopleSpaceTile>> getSortedTiles(
- IPeopleManager peopleManager, Stream<PeopleSpaceTile> stream) {
- return stream
- .filter(c -> shouldKeepConversation(c))
- .map(c -> Map.entry(getLastInteraction(peopleManager, c), c))
- .sorted((c1, c2) -> (c2.getKey().compareTo(c1.getKey())))
- .collect(Collectors.toList());
+ getBirthdaysOnBackgroundThread(context, appWidgetManager, widgetIdToTile, appWidgetIds);
}
/** Augment {@link PeopleSpaceTile} with fields from stored tile. */
@@ -166,6 +209,7 @@
return tile;
}
return tile.toBuilder()
+ .setStatusText(storedTile.getStatusText())
.setNotificationKey(storedTile.getNotificationKey())
.setNotificationContent(storedTile.getNotificationContent())
.setNotificationDataUri(storedTile.getNotificationDataUri())
@@ -202,37 +246,67 @@
.setNotificationDataUri(null)
.build();
}
+ updateAppWidgetOptions(appWidgetManager, appWidgetId, storedTile);
+ }
+
+ private static void updateAppWidgetOptions(AppWidgetManager appWidgetManager, int appWidgetId,
+ PeopleSpaceTile tile) {
Bundle newOptions = new Bundle();
- newOptions.putParcelable(OPTIONS_PEOPLE_SPACE_TILE, storedTile);
+ newOptions.putParcelable(OPTIONS_PEOPLE_SPACE_TILE, tile);
appWidgetManager.updateAppWidgetOptions(appWidgetId, newOptions);
}
- private static RemoteViews createRemoteViews(Context context, PeopleSpaceTile tile,
- long lastInteraction, int appWidgetId) throws Exception {
- // TODO: If key is null or if text and data uri are null.
- if (tile.getNotificationKey() == null) {
- return createLastInteractionRemoteViews(context, tile, lastInteraction, appWidgetId);
+ /** Creates a {@link RemoteViews} for {@code tile}. */
+ private static RemoteViews createRemoteViews(Context context,
+ PeopleSpaceTile tile, int appWidgetId) {
+ RemoteViews views;
+ if (tile.getNotificationKey() != null) {
+ views = createNotificationRemoteViews(context, tile);
+ } else if (tile.getStatusText() != null) {
+ views = createStatusRemoteViews(context, tile);
+ } else {
+ views = createLastInteractionRemoteViews(context, tile);
}
- return createNotificationRemoteViews(context, tile, lastInteraction, appWidgetId);
+ return setCommonRemoteViewsFields(context, views, tile, appWidgetId);
}
- private static RemoteViews createLastInteractionRemoteViews(Context context,
- PeopleSpaceTile tile, long lastInteraction, int appWidgetId)
- throws Exception {
- RemoteViews views = new RemoteViews(
- context.getPackageName(), R.layout.people_space_large_avatar_tile);
- String status = PeopleSpaceUtils.getLastInteractionString(
- context, lastInteraction);
- views.setTextViewText(R.id.status, status);
+ private static RemoteViews setCommonRemoteViewsFields(Context context, RemoteViews views,
+ PeopleSpaceTile tile, int appWidgetId) {
+ try {
+ views.setTextViewText(R.id.name, tile.getUserName().toString());
+ views.setImageViewBitmap(
+ R.id.package_icon,
+ PeopleSpaceUtils.convertDrawableToBitmap(
+ context.getPackageManager().getApplicationIcon(
+ tile.getPackageName())
+ )
+ );
+ views.setImageViewIcon(R.id.person_icon, tile.getUserIcon());
- views = setCommonRemoteViewsFields(context, views, tile, appWidgetId);
- return views;
+ Intent activityIntent = new Intent(context, LaunchConversationActivity.class);
+ activityIntent.addFlags(
+ Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_CLEAR_TASK
+ | Intent.FLAG_ACTIVITY_NO_HISTORY
+ | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ activityIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_TILE_ID, tile.getId());
+ activityIntent.putExtra(
+ PeopleSpaceWidgetProvider.EXTRA_PACKAGE_NAME, tile.getPackageName());
+ activityIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_UID, tile.getUid());
+ views.setOnClickPendingIntent(R.id.item, PendingIntent.getActivity(
+ context,
+ appWidgetId,
+ activityIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE));
+ return views;
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to set common fields: " + e);
+ }
+ return null;
}
private static RemoteViews createNotificationRemoteViews(Context context,
- PeopleSpaceTile tile, long lastInteraction, int appWidgetId)
- throws Exception {
-
+ PeopleSpaceTile tile) {
RemoteViews views = new RemoteViews(
context.getPackageName(), R.layout.people_space_small_avatar_tile);
Uri image = tile.getNotificationDataUri();
@@ -242,46 +316,85 @@
views.setViewVisibility(R.id.image, View.VISIBLE);
views.setViewVisibility(R.id.content, View.GONE);
} else {
- views.setTextViewText(R.id.content, tile.getNotificationContent());
+ CharSequence content = tile.getNotificationContent();
+ views = setPunctuationRemoteViewsFields(views, content);
+ views.setTextViewText(R.id.content, content);
views.setViewVisibility(R.id.content, View.VISIBLE);
views.setViewVisibility(R.id.image, View.GONE);
}
-
- views = setCommonRemoteViewsFields(context, views, tile, appWidgetId);
+ views.setTextViewText(R.id.time, PeopleSpaceUtils.getLastInteractionString(
+ context, tile.getLastInteractionTimestamp(), false));
return views;
}
- private static RemoteViews setCommonRemoteViewsFields(
- Context context, RemoteViews views, PeopleSpaceTile tile, int appWidgetId)
- throws Exception {
- views.setTextViewText(R.id.name, tile.getUserName().toString());
- views.setImageViewBitmap(
- R.id.package_icon,
- PeopleSpaceUtils.convertDrawableToBitmap(
- context.getPackageManager().getApplicationIcon(tile.getPackageName())
- )
- );
- views.setImageViewIcon(R.id.person_icon, tile.getUserIcon());
-
- Intent activityIntent = new Intent(context, LaunchConversationActivity.class);
- activityIntent.addFlags(
- Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_CLEAR_TASK
- | Intent.FLAG_ACTIVITY_NO_HISTORY
- | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
- activityIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_TILE_ID, tile.getId());
- activityIntent.putExtra(
- PeopleSpaceWidgetProvider.EXTRA_PACKAGE_NAME, tile.getPackageName());
- activityIntent.putExtra(PeopleSpaceWidgetProvider.EXTRA_UID, tile.getUid());
- views.setOnClickPendingIntent(R.id.item, PendingIntent.getActivity(
- context,
- appWidgetId,
- activityIntent,
- PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE));
+ private static RemoteViews createStatusRemoteViews(Context context,
+ PeopleSpaceTile tile) {
+ RemoteViews views = new RemoteViews(
+ context.getPackageName(), R.layout.people_space_large_avatar_tile);
+ views.setTextViewText(R.id.status, tile.getStatusText());
return views;
}
+ private static RemoteViews createLastInteractionRemoteViews(Context context,
+ PeopleSpaceTile tile) {
+ RemoteViews views = new RemoteViews(
+ context.getPackageName(), R.layout.people_space_large_avatar_tile);
+ String status = PeopleSpaceUtils.getLastInteractionString(
+ context, tile.getLastInteractionTimestamp(), true);
+ views.setTextViewText(R.id.status, status);
+ return views;
+ }
+
+ private static RemoteViews setPunctuationRemoteViewsFields(
+ RemoteViews views, CharSequence content) {
+ String punctuation = getBackgroundTextFromMessage(content.toString());
+ int visibility = View.GONE;
+ if (punctuation != null) {
+ visibility = View.VISIBLE;
+ }
+ views.setTextViewText(R.id.punctuation1, punctuation);
+ views.setTextViewText(R.id.punctuation2, punctuation);
+ views.setTextViewText(R.id.punctuation3, punctuation);
+ views.setTextViewText(R.id.punctuation4, punctuation);
+ views.setTextViewText(R.id.punctuation5, punctuation);
+ views.setTextViewText(R.id.punctuation6, punctuation);
+
+ views.setViewVisibility(R.id.punctuation1, visibility);
+ views.setViewVisibility(R.id.punctuation2, visibility);
+ views.setViewVisibility(R.id.punctuation3, visibility);
+ views.setViewVisibility(R.id.punctuation4, visibility);
+ views.setViewVisibility(R.id.punctuation5, visibility);
+ views.setViewVisibility(R.id.punctuation6, visibility);
+
+ return views;
+ }
+
+ /** Gets character for tile background decoration based on notification content. */
+ @VisibleForTesting
+ static String getBackgroundTextFromMessage(String message) {
+ if (!ANY_DOUBLE_MARK_PATTERN.matcher(message).find()) {
+ return null;
+ }
+ if (MIXED_MARK_PATTERN.matcher(message).find()) {
+ return "!?";
+ }
+ Matcher doubleQuestionMatcher = DOUBLE_QUESTION_PATTERN.matcher(message);
+ if (!doubleQuestionMatcher.find()) {
+ return "!";
+ }
+ Matcher doubleExclamationMatcher = DOUBLE_EXCLAMATION_PATTERN.matcher(message);
+ if (!doubleExclamationMatcher.find()) {
+ return "?";
+ }
+ // If we have both "!!" and "??", return the one that comes first.
+ if (doubleQuestionMatcher.start() < doubleExclamationMatcher.start()) {
+ return "?";
+ }
+ return "!";
+ }
+
/** Gets the most recent {@link Notification.MessagingStyle.Message} from the notification. */
+ @VisibleForTesting
public static Notification.MessagingStyle.Message getLastMessagingStyleMessage(
StatusBarNotification sbn) {
Notification notification = sbn.getNotification();
@@ -302,6 +415,18 @@
return null;
}
+ /** Returns a list sorted by ascending last interaction time from {@code stream}. */
+ private static List<PeopleSpaceTile> getSortedTiles(IPeopleManager peopleManager,
+ Stream<PeopleSpaceTile> stream) {
+ return stream
+ .filter(c -> shouldKeepConversation(c))
+ .map(c -> c.toBuilder().setLastInteractionTimestamp(
+ getLastInteraction(peopleManager, c)).build())
+ .sorted((c1, c2) -> new Long(c2.getLastInteractionTimestamp()).compareTo(
+ new Long(c1.getLastInteractionTimestamp())))
+ .collect(Collectors.toList());
+ }
+
/** Returns the last interaction time with the user specified by {@code PeopleSpaceTile}. */
private static Long getLastInteraction(IPeopleManager peopleManager,
PeopleSpaceTile tile) {
@@ -344,7 +469,8 @@
}
/** Returns a readable status describing the {@code lastInteraction}. */
- public static String getLastInteractionString(Context context, long lastInteraction) {
+ public static String getLastInteractionString(Context context, long lastInteraction,
+ boolean includeLastChatted) {
if (lastInteraction == 0L) {
Log.e(TAG, "Could not get valid last interaction");
return context.getString(R.string.basic_status);
@@ -354,18 +480,25 @@
MeasureFormat formatter = MeasureFormat.getInstance(Locale.getDefault(),
MeasureFormat.FormatWidth.WIDE);
if (durationSinceLastInteraction.toHours() < MIN_HOUR) {
- return context.getString(R.string.last_interaction_status_less_than,
+ return context.getString(includeLastChatted ? R.string.last_interaction_status_less_than
+ : R.string.less_than_timestamp,
formatter.formatMeasures(new Measure(MIN_HOUR, MeasureUnit.HOUR)));
} else if (durationSinceLastInteraction.toDays() < ONE_DAY) {
- return context.getString(R.string.last_interaction_status, formatter.formatMeasures(
- new Measure(durationSinceLastInteraction.toHours(), MeasureUnit.HOUR)));
+ return context.getString(
+ includeLastChatted ? R.string.last_interaction_status : R.string.timestamp,
+ formatter.formatMeasures(
+ new Measure(durationSinceLastInteraction.toHours(), MeasureUnit.HOUR)));
} else if (durationSinceLastInteraction.toDays() < DAYS_IN_A_WEEK) {
- return context.getString(R.string.last_interaction_status, formatter.formatMeasures(
- new Measure(durationSinceLastInteraction.toDays(), MeasureUnit.DAY)));
+ return context.getString(
+ includeLastChatted ? R.string.last_interaction_status : R.string.timestamp,
+ formatter.formatMeasures(
+ new Measure(durationSinceLastInteraction.toDays(), MeasureUnit.DAY)));
} else {
return context.getString(durationSinceLastInteraction.toDays() == DAYS_IN_A_WEEK
- ? R.string.last_interaction_status :
- R.string.last_interaction_status_over,
+ ? (includeLastChatted ? R.string.last_interaction_status :
+ R.string.timestamp) :
+ (includeLastChatted ? R.string.last_interaction_status_over
+ : R.string.over_timestamp),
formatter.formatMeasures(
new Measure(durationSinceLastInteraction.toDays() / DAYS_IN_A_WEEK,
MeasureUnit.WEEK)));
@@ -386,4 +519,139 @@
return tile != null && tile.getUserName().length() != 0;
}
+ private static boolean hasBirthdayStatus(PeopleSpaceTile tile, Context context) {
+ return tile.getStatusText() != null && tile.getStatusText().equals(
+ context.getString(R.string.birthday_status));
+ }
+
+
+ /** Calls to retrieve birthdays on a background thread. */
+ private static void getBirthdaysOnBackgroundThread(Context context,
+ AppWidgetManager appWidgetManager,
+ Map<Integer, PeopleSpaceTile> peopleSpaceTiles, int[] appWidgetIds) {
+ ThreadUtils.postOnBackgroundThread(
+ () -> getBirthdays(context, appWidgetManager, peopleSpaceTiles, appWidgetIds));
+ }
+
+ /** Queries the Contacts DB for any birthdays today. */
+ @VisibleForTesting
+ public static void getBirthdays(Context context, AppWidgetManager appWidgetManager,
+ Map<Integer, PeopleSpaceTile> widgetIdToTile, int[] appWidgetIds) {
+ if (DEBUG) Log.d(TAG, "Get birthdays");
+ if (appWidgetIds.length == 0) return;
+ List<String> lookupKeysWithBirthdaysToday = getContactLookupKeysWithBirthdaysToday(context);
+ for (int appWidgetId : appWidgetIds) {
+ PeopleSpaceTile storedTile = widgetIdToTile.get(appWidgetId);
+ if (storedTile == null || storedTile.getContactUri() == null) {
+ if (DEBUG) Log.d(TAG, "No contact uri for: " + storedTile);
+ removeBirthdayStatusIfPresent(appWidgetManager, context, storedTile, appWidgetId);
+ continue;
+ }
+ if (lookupKeysWithBirthdaysToday.isEmpty()) {
+ if (DEBUG) Log.d(TAG, "No birthdays today");
+ removeBirthdayStatusIfPresent(appWidgetManager, context, storedTile, appWidgetId);
+ continue;
+ }
+ updateTileWithBirthday(context, appWidgetManager, lookupKeysWithBirthdaysToday,
+ storedTile,
+ appWidgetId);
+ }
+ }
+
+ /** Removes the birthday status if present in {@code storedTile} and pushes the update. */
+ private static void removeBirthdayStatusIfPresent(AppWidgetManager appWidgetManager,
+ Context context, PeopleSpaceTile storedTile, int appWidgetId) {
+ if (hasBirthdayStatus(storedTile, context)) {
+ if (DEBUG) Log.d(TAG, "Remove " + storedTile.getUserName() + "'s birthday");
+ updateAppWidgetOptionsAndView(appWidgetManager, context, appWidgetId,
+ storedTile.toBuilder()
+ .setStatusText(null)
+ .build());
+ }
+ }
+
+ /**
+ * Update {@code storedTile} if the contact has a lookup key matched to any {@code
+ * lookupKeysWithBirthdays}.
+ */
+ private static void updateTileWithBirthday(Context context, AppWidgetManager appWidgetManager,
+ List<String> lookupKeysWithBirthdaysToday, PeopleSpaceTile storedTile,
+ int appWidgetId) {
+ Cursor cursor = null;
+ try {
+ cursor = context.getContentResolver().query(storedTile.getContactUri(),
+ null, null, null, null);
+ while (cursor != null && cursor.moveToNext()) {
+ String storedLookupKey = cursor.getString(
+ cursor.getColumnIndex(ContactsContract.CommonDataKinds.Event.LOOKUP_KEY));
+ if (!storedLookupKey.isEmpty() && lookupKeysWithBirthdaysToday.contains(
+ storedLookupKey)) {
+ if (DEBUG) Log.d(TAG, storedTile.getUserName() + "'s birthday today!");
+ updateAppWidgetOptionsAndView(appWidgetManager, context, appWidgetId,
+ storedTile.toBuilder()
+ .setStatusText(context.getString(R.string.birthday_status))
+ .build());
+ return;
+ }
+ }
+ } catch (SQLException e) {
+ Log.e(TAG, "Failed to query contact: " + e);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
+ }
+ removeBirthdayStatusIfPresent(appWidgetManager, context, storedTile, appWidgetId);
+ }
+
+ /** Update app widget options and the current view. */
+ private static void updateAppWidgetOptionsAndView(AppWidgetManager appWidgetManager,
+ Context context, int appWidgetId, PeopleSpaceTile tile) {
+ updateAppWidgetOptions(appWidgetManager, appWidgetId, tile);
+ RemoteViews views = createRemoteViews(context,
+ tile, appWidgetId);
+ appWidgetManager.updateAppWidget(appWidgetId, views);
+ }
+
+ /**
+ * Returns lookup keys for all contacts with a birthday today.
+ *
+ * <p>Birthdays are queried from a different table within the Contacts DB than the table for
+ * the Contact Uri provided by most messaging apps. Matching by the contact ID is then quite
+ * fragile as the row IDs across the different tables are not guaranteed to stay aligned, so we
+ * match the data by {@link ContactsContract.ContactsColumns#LOOKUP_KEY} key to ensure proper
+ * matching across all the Contacts DB tables.
+ */
+ private static List<String> getContactLookupKeysWithBirthdaysToday(Context context) {
+ List<String> lookupKeysWithBirthdaysToday = new ArrayList<>(1);
+ String today = new SimpleDateFormat("MM-dd").format(new Date());
+ String[] projection = new String[]{
+ ContactsContract.CommonDataKinds.Event.LOOKUP_KEY,
+ ContactsContract.CommonDataKinds.Event.START_DATE};
+ String where =
+ ContactsContract.Data.MIMETYPE
+ + "= ? AND " + ContactsContract.CommonDataKinds.Event.TYPE + "="
+ + ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY + " AND substr("
+ + ContactsContract.CommonDataKinds.Event.START_DATE + ",6) = ?";
+ String[] selection =
+ new String[]{ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE, today};
+ Cursor cursor = null;
+ try {
+ cursor = context.getContentResolver().query(ContactsContract.Data.CONTENT_URI,
+ projection, where, selection, null);
+ while (cursor != null && cursor.moveToNext()) {
+ String lookupKey = cursor.getString(
+ cursor.getColumnIndex(ContactsContract.CommonDataKinds.Event.LOOKUP_KEY));
+ lookupKeysWithBirthdaysToday.add(lookupKey);
+ }
+ } catch (SQLException e) {
+ Log.e(TAG, "Failed to query birthdays: " + e);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
+ }
+ return lookupKeysWithBirthdaysToday;
+ }
}
+
diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/LaunchConversationActivity.java b/packages/SystemUI/src/com/android/systemui/people/widget/LaunchConversationActivity.java
index 0b0308f..358f311 100644
--- a/packages/SystemUI/src/com/android/systemui/people/widget/LaunchConversationActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/LaunchConversationActivity.java
@@ -23,12 +23,15 @@
import android.os.UserHandle;
import android.util.Log;
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.logging.UiEventLoggerImpl;
import com.android.systemui.people.PeopleSpaceUtils;
/** Proxy activity to launch ShortcutInfo's conversation. */
public class LaunchConversationActivity extends Activity {
private static final String TAG = "PeopleSpaceLaunchConv";
private static final boolean DEBUG = PeopleSpaceUtils.DEBUG;
+ private UiEventLogger mUiEventLogger = new UiEventLoggerImpl();
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -44,6 +47,7 @@
if (DEBUG) {
Log.d(TAG, "Launching conversation with shortcutInfo id " + tileId);
}
+ mUiEventLogger.log(PeopleSpaceUtils.PeopleSpaceWidgetEvent.PEOPLE_SPACE_WIDGET_CLICKED);
try {
LauncherApps launcherApps =
getApplicationContext().getSystemService(LauncherApps.class);
diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java
index 1ee9e0e..7f204cc 100644
--- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetProvider.java
@@ -27,6 +27,8 @@
import android.util.Log;
import android.widget.RemoteViews;
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.logging.UiEventLoggerImpl;
import com.android.systemui.R;
import com.android.systemui.people.PeopleSpaceUtils;
@@ -39,7 +41,10 @@
public static final String EXTRA_PACKAGE_NAME = "extra_package_name";
public static final String EXTRA_UID = "extra_uid";
+ public UiEventLogger mUiEventLogger = new UiEventLoggerImpl();
+
/** Called when widget updates. */
+ @Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
@@ -79,4 +84,14 @@
appWidgetManager.updateAppWidget(appWidgetId, views);
}
}
+
+ @Override
+ public void onDeleted(Context context, int[] appWidgetIds) {
+ super.onDeleted(context, appWidgetIds);
+ for (int widgetId : appWidgetIds) {
+ if (DEBUG) Log.d(TAG, "Widget removed");
+ mUiEventLogger.log(PeopleSpaceUtils.PeopleSpaceWidgetEvent.PEOPLE_SPACE_WIDGET_DELETED);
+ }
+ }
+
}
diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetRemoteViewsFactory.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetRemoteViewsFactory.java
index 1e6c213..fb33aff 100644
--- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetRemoteViewsFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetRemoteViewsFactory.java
@@ -34,7 +34,6 @@
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
/** People Space Widget RemoteViewsFactory class. */
public class PeopleSpaceWidgetRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
@@ -45,7 +44,7 @@
private INotificationManager mNotificationManager;
private PackageManager mPackageManager;
private LauncherApps mLauncherApps;
- private List<Map.Entry<Long, PeopleSpaceTile>> mTiles = new ArrayList<>();
+ private List<PeopleSpaceTile> mTiles = new ArrayList<>();
private Context mContext;
public PeopleSpaceWidgetRemoteViewsFactory(Context context, Intent intent) {
@@ -100,11 +99,10 @@
RemoteViews personView = new RemoteViews(mContext.getPackageName(),
R.layout.people_space_widget_item);
try {
- Map.Entry<Long, PeopleSpaceTile> entry = mTiles.get(i);
- PeopleSpaceTile tile = entry.getValue();
- long lastInteraction = entry.getKey();
+ PeopleSpaceTile tile = mTiles.get(i);
- String status = PeopleSpaceUtils.getLastInteractionString(mContext, lastInteraction);
+ String status = PeopleSpaceUtils.getLastInteractionString(mContext,
+ tile.getLastInteractionTimestamp(), true);
personView.setTextViewText(R.id.status, status);
personView.setTextViewText(R.id.name, tile.getUserName().toString());
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
index d58895e..d3adc9b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
@@ -321,7 +321,7 @@
@Override
public void onTuningChanged(String key, String newValue) {
if (QS_REMOVE_LABELS.equals(key)) {
- boolean newShowLabels = "0".equals(newValue);
+ boolean newShowLabels = newValue == null || "0".equals(newValue);
if (mShowLabels == newShowLabels) return;
mShowLabels = newShowLabels;
for (TileRecord t : mRecords) {
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 d7933d3..73ab9b0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -77,11 +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);
- }
+ // Prototype menu item
+ toolbar.getMenu()
+ .add(Menu.NONE, MENU_REMOVE_LABELS, Menu.NONE, "Remove labels")
+ .setCheckable(true)
+ .setVisible(Build.IS_ENG || Build.IS_USERDEBUG);
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 9bf3b8c..2dfac1b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizerController.java
@@ -105,7 +105,8 @@
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)));
+ mToolbar.getMenu().findItem(MENU_REMOVE_LABELS)
+ .setChecked(newValue != null && !("0".equals(newValue)));
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 2076cbf..7ec2691 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -20,10 +20,8 @@
import static android.provider.Settings.Global.ZEN_MODE_OFF;
import android.app.Dialog;
-import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.pm.ApplicationInfo;
@@ -53,7 +51,6 @@
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.SysUIToast;
-import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
@@ -78,17 +75,12 @@
private static final Intent ZEN_PRIORITY_SETTINGS =
new Intent(Settings.ACTION_ZEN_MODE_PRIORITY_SETTINGS);
- private static final String ACTION_SET_VISIBLE = "com.android.systemui.dndtile.SET_VISIBLE";
- private static final String EXTRA_VISIBLE = "visible";
-
private final ZenModeController mController;
private final DndDetailAdapter mDetailAdapter;
private final SharedPreferences mSharedPreferences;
- private final BroadcastDispatcher mBroadcastDispatcher;
private boolean mListening;
private boolean mShowingDetail;
- private boolean mReceiverRegistered;
@Inject
public DndTile(
@@ -100,7 +92,6 @@
ActivityStarter activityStarter,
QSLogger qsLogger,
ZenModeController zenModeController,
- BroadcastDispatcher broadcastDispatcher,
@Main SharedPreferences sharedPreferences
) {
super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController,
@@ -108,21 +99,9 @@
mController = zenModeController;
mSharedPreferences = sharedPreferences;
mDetailAdapter = new DndDetailAdapter();
- mBroadcastDispatcher = broadcastDispatcher;
- broadcastDispatcher.registerReceiver(mReceiver, new IntentFilter(ACTION_SET_VISIBLE));
- mReceiverRegistered = true;
mController.observe(getLifecycle(), mZenCallback);
}
- @Override
- protected void handleDestroy() {
- super.handleDestroy();
- if (mReceiverRegistered) {
- mBroadcastDispatcher.unregisterReceiver(mReceiver);
- mReceiverRegistered = false;
- }
- }
-
public static void setVisible(Context context, boolean visible) {
Prefs.putBoolean(context, Prefs.Key.DND_TILE_VISIBLE, visible);
}
@@ -348,15 +327,6 @@
}
};
- private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final boolean visible = intent.getBooleanExtra(EXTRA_VISIBLE, false);
- setVisible(mContext, visible);
- refreshState();
- }
- };
-
private final class DndDetailAdapter implements DetailAdapter, OnAttachStateChangeListener {
private ZenModePanel mZenPanel;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
index 6afc756..c2ba344 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
@@ -17,6 +17,7 @@
package com.android.systemui.recents;
import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE;
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_NONE;
import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE;
import android.animation.ArgbEvaluator;
@@ -27,6 +28,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.graphics.drawable.ColorDrawable;
import android.os.Binder;
@@ -186,7 +188,7 @@
DisplayMetrics metrics = new DisplayMetrics();
mWindowManager.getDefaultDisplay().getMetrics(metrics);
float density = metrics.density;
- int rotation = RotationUtils.getRotation(mContext);
+ int rotation = getRotation(mContext);
inflateView(rotation);
int bgColor = mContext.getColor(
@@ -342,14 +344,23 @@
protected void onConfigurationChanged() {
removeAllViews();
- inflateView(RotationUtils.getRotation(mContext));
+ inflateView(getRotation(mContext));
+ }
+
+ private int getRotation(Context context) {
+ Configuration config = context.getResources().getConfiguration();
+ if (config.smallestScreenWidthDp >= 600) {
+ return ROTATION_NONE;
+ }
+
+ return RotationUtils.getRotation(context);
}
private final Runnable mUpdateLayoutRunnable = new Runnable() {
@Override
public void run() {
if (mLayout != null && mLayout.getParent() != null) {
- mLayout.setLayoutParams(getRequestLayoutParams(RotationUtils.getRotation(mContext)));
+ mLayout.setLayoutParams(getRequestLayoutParams(getRotation(mContext)));
}
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
index f4ce77a..3346935 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
@@ -34,7 +34,6 @@
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.Icon;
-import android.media.ExifInterface;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
@@ -52,10 +51,13 @@
import android.text.format.DateUtils;
import android.util.Log;
+import androidx.exifinterface.media.ExifInterface;
+
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.systemui.R;
import com.android.systemui.SystemUIFactory;
+import com.android.systemui.screenshot.ScreenshotController.SavedImageData.ShareTransition;
import java.io.File;
import java.io.IOException;
@@ -74,11 +76,12 @@
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
+import java.util.function.Supplier;
/**
* An AsyncTask that saves an image to the media store in the background.
*/
-class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
+class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
private static final String TAG = logTag(SaveImageInBackgroundTask.class);
private static final String SCREENSHOT_FILE_NAME_TEMPLATE = "Screenshot_%s.png";
@@ -95,12 +98,15 @@
private final String mScreenshotId;
private final boolean mSmartActionsEnabled;
private final Random mRandom = new Random();
+ private final Supplier<ShareTransition> mSharedElementTransition;
SaveImageInBackgroundTask(Context context, ScreenshotSmartActions screenshotSmartActions,
- ScreenshotController.SaveImageInBackgroundData data) {
+ ScreenshotController.SaveImageInBackgroundData data,
+ Supplier<ShareTransition> sharedElementTransition) {
mContext = context;
mScreenshotSmartActions = screenshotSmartActions;
mImageData = new ScreenshotController.SavedImageData();
+ mSharedElementTransition = sharedElementTransition;
// Prepare all the output metadata
mParams = data;
@@ -135,7 +141,6 @@
ContentResolver resolver = mContext.getContentResolver();
Bitmap image = mParams.image;
- Resources r = mContext.getResources();
try {
// Save the screenshot to the MediaStore
@@ -233,7 +238,7 @@
mImageData.uri = uri;
mImageData.smartActions = smartActions;
- mImageData.shareAction = createShareAction(mContext, mContext.getResources(), uri);
+ mImageData.shareTransition = createShareAction(mContext, mContext.getResources(), uri);
mImageData.editAction = createEditAction(mContext, mContext.getResources(), uri);
mImageData.deleteAction = createDeleteAction(mContext, mContext.getResources(), uri);
@@ -284,61 +289,68 @@
mParams.clearImage();
}
+ /**
+ * Assumes that the action intent is sent immediately after being supplied.
+ */
@VisibleForTesting
- Notification.Action createShareAction(Context context, Resources r, Uri uri) {
- // Note: Both the share and edit actions are proxied through ActionProxyReceiver in
- // order to do some common work like dismissing the keyguard and sending
- // closeSystemWindows
+ Supplier<ShareTransition> createShareAction(Context context, Resources r, Uri uri) {
+ return () -> {
+ ShareTransition transition = mSharedElementTransition.get();
- // Create a share intent, this will always go through the chooser activity first
- // which should not trigger auto-enter PiP
- String subjectDate = DateFormat.getDateTimeInstance().format(new Date(mImageTime));
- String subject = String.format(SCREENSHOT_SHARE_SUBJECT_TEMPLATE, subjectDate);
- Intent sharingIntent = new Intent(Intent.ACTION_SEND);
- sharingIntent.setType("image/png");
- sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
- // Include URI in ClipData also, so that grantPermission picks it up.
- // We don't use setData here because some apps interpret this as "to:".
- ClipData clipdata = new ClipData(new ClipDescription("content",
- new String[]{ClipDescription.MIMETYPE_TEXT_PLAIN}),
- new ClipData.Item(uri));
- sharingIntent.setClipData(clipdata);
- sharingIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
- sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ // Note: Both the share and edit actions are proxied through ActionProxyReceiver in
+ // order to do some common work like dismissing the keyguard and sending
+ // closeSystemWindows
- // Make sure pending intents for the system user are still unique across users
- // by setting the (otherwise unused) request code to the current user id.
- int requestCode = context.getUserId();
+ // Create a share intent, this will always go through the chooser activity first
+ // which should not trigger auto-enter PiP
+ String subjectDate = DateFormat.getDateTimeInstance().format(new Date(mImageTime));
+ String subject = String.format(SCREENSHOT_SHARE_SUBJECT_TEMPLATE, subjectDate);
+ Intent sharingIntent = new Intent(Intent.ACTION_SEND);
+ sharingIntent.setType("image/png");
+ sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
+ // Include URI in ClipData also, so that grantPermission picks it up.
+ // We don't use setData here because some apps interpret this as "to:".
+ ClipData clipdata = new ClipData(new ClipDescription("content",
+ new String[]{ClipDescription.MIMETYPE_TEXT_PLAIN}),
+ new ClipData.Item(uri));
+ sharingIntent.setClipData(clipdata);
+ sharingIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
+ sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- Intent sharingChooserIntent =
- Intent.createChooser(sharingIntent, null)
- .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK)
- .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ // Make sure pending intents for the system user are still unique across users
+ // by setting the (otherwise unused) request code to the current user id.
+ int requestCode = context.getUserId();
- // cancel current pending intent (if any) since clipData isn't used for matching
- PendingIntent pendingIntent = PendingIntent.getActivityAsUser(
- context, 0, sharingChooserIntent,
- PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE,
- null, UserHandle.CURRENT);
+ Intent sharingChooserIntent = Intent.createChooser(sharingIntent, null)
+ .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK)
+ .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- // Create a share action for the notification
- PendingIntent shareAction = PendingIntent.getBroadcastAsUser(context, requestCode,
- new Intent(context, ActionProxyReceiver.class)
- .putExtra(ScreenshotController.EXTRA_ACTION_INTENT, pendingIntent)
- .putExtra(ScreenshotController.EXTRA_DISALLOW_ENTER_PIP, true)
- .putExtra(ScreenshotController.EXTRA_ID, mScreenshotId)
- .putExtra(ScreenshotController.EXTRA_SMART_ACTIONS_ENABLED,
- mSmartActionsEnabled)
- .setAction(Intent.ACTION_SEND)
- .addFlags(Intent.FLAG_RECEIVER_FOREGROUND),
- PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE,
- UserHandle.SYSTEM);
+ // cancel current pending intent (if any) since clipData isn't used for matching
+ PendingIntent pendingIntent = PendingIntent.getActivityAsUser(
+ context, 0, sharingChooserIntent,
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE,
+ transition.bundle, UserHandle.CURRENT);
- Notification.Action.Builder shareActionBuilder = new Notification.Action.Builder(
- Icon.createWithResource(r, R.drawable.ic_screenshot_share),
- r.getString(com.android.internal.R.string.share), shareAction);
+ // Create a share action for the notification
+ PendingIntent shareAction = PendingIntent.getBroadcastAsUser(context, requestCode,
+ new Intent(context, ActionProxyReceiver.class)
+ .putExtra(ScreenshotController.EXTRA_ACTION_INTENT, pendingIntent)
+ .putExtra(ScreenshotController.EXTRA_DISALLOW_ENTER_PIP, true)
+ .putExtra(ScreenshotController.EXTRA_ID, mScreenshotId)
+ .putExtra(ScreenshotController.EXTRA_SMART_ACTIONS_ENABLED,
+ mSmartActionsEnabled)
+ .setAction(Intent.ACTION_SEND)
+ .addFlags(Intent.FLAG_RECEIVER_FOREGROUND),
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE,
+ UserHandle.SYSTEM);
- return shareActionBuilder.build();
+ Notification.Action.Builder shareActionBuilder = new Notification.Action.Builder(
+ Icon.createWithResource(r, R.drawable.ic_screenshot_share),
+ r.getString(com.android.internal.R.string.share), shareAction);
+
+ transition.shareAction = shareActionBuilder.build();
+ return transition;
+ };
}
@VisibleForTesting
@@ -354,8 +366,7 @@
if (!TextUtils.isEmpty(editorPackage)) {
editIntent.setComponent(ComponentName.unflattenFromString(editorPackage));
}
- editIntent.setType("image/png");
- editIntent.setData(uri);
+ editIntent.setDataAndType(uri, "image/png");
editIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
editIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
editIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index 3f163d3..d2fe5d2 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -34,6 +34,9 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.Nullable;
+import android.app.ActivityOptions;
+import android.app.ExitTransitionCoordinator;
+import android.app.ExitTransitionCoordinator.ExitTransitionCallbacks;
import android.app.Notification;
import android.content.ComponentName;
import android.content.Context;
@@ -46,6 +49,7 @@
import android.media.MediaActionSound;
import android.net.Uri;
import android.os.Binder;
+import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -54,6 +58,7 @@
import android.provider.Settings;
import android.util.DisplayMetrics;
import android.util.Log;
+import android.util.Pair;
import android.view.Display;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -67,15 +72,18 @@
import android.view.accessibility.AccessibilityManager;
import android.widget.Toast;
+import com.android.internal.app.ChooserActivity;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.policy.PhoneWindow;
import com.android.settingslib.applications.InterestingConfigChanges;
import com.android.systemui.R;
+import com.android.systemui.screenshot.ScreenshotController.SavedImageData.ShareTransition;
import com.android.systemui.util.DeviceConfigProxy;
import java.util.List;
import java.util.function.Consumer;
+import java.util.function.Supplier;
import javax.inject.Inject;
@@ -103,17 +111,26 @@
*/
static class SavedImageData {
public Uri uri;
- public Notification.Action shareAction;
+ public Supplier<ShareTransition> shareTransition;
public Notification.Action editAction;
public Notification.Action deleteAction;
public List<Notification.Action> smartActions;
/**
+ * POD for shared element transition to share sheet.
+ */
+ static class ShareTransition {
+ public Bundle bundle;
+ public Notification.Action shareAction;
+ public Runnable onCancelRunnable;
+ }
+
+ /**
* Used to reset the return data on error
*/
public void reset() {
uri = null;
- shareAction = null;
+ shareTransition = null;
editAction = null;
deleteAction = null;
smartActions = null;
@@ -587,7 +604,8 @@
mSaveInBgTask.setActionsReadyListener(this::logSuccessOnActionsReady);
}
- mSaveInBgTask = new SaveImageInBackgroundTask(mContext, mScreenshotSmartActions, data);
+ mSaveInBgTask = new SaveImageInBackgroundTask(mContext, mScreenshotSmartActions, data,
+ getShareTransitionSupplier());
mSaveInBgTask.execute();
}
@@ -638,6 +656,35 @@
}
/**
+ * Supplies the necessary bits for the shared element transition to share sheet.
+ * Note that once supplied, the action intent to share must be sent immediately after.
+ */
+ private Supplier<ShareTransition> getShareTransitionSupplier() {
+ return () -> {
+ ExitTransitionCallbacks cb = new ExitTransitionCallbacks() {
+ @Override
+ public boolean isReturnTransitionAllowed() {
+ return false;
+ }
+
+ @Override
+ public void onFinish() { }
+ };
+
+ Pair<ActivityOptions, ExitTransitionCoordinator> transition =
+ ActivityOptions.startSharedElementAnimation(mWindow, cb, null,
+ Pair.create(mScreenshotView.getScreenshotPreview(),
+ ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME));
+ transition.second.startExit();
+
+ ShareTransition supply = new ShareTransition();
+ supply.bundle = transition.first.toBundle();
+ supply.onCancelRunnable = () -> ActivityOptions.stopSharedElementAnimation(mWindow);
+ return supply;
+ };
+ }
+
+ /**
* Logs success/failure of the screenshot saving task, and shows an error if it failed.
*/
private void logSuccessOnActionsReady(ScreenshotController.SavedImageData imageData) {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
index 4ca3dcc..357702a 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
@@ -73,6 +73,7 @@
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.R;
+import com.android.systemui.screenshot.ScreenshotController.SavedImageData.ShareTransition;
import com.android.systemui.shared.system.QuickStepContract;
import java.util.ArrayList;
@@ -104,6 +105,7 @@
private static final long SCREENSHOT_DISMISS_Y_DURATION_MS = 350;
private static final long SCREENSHOT_DISMISS_ALPHA_DURATION_MS = 183;
private static final long SCREENSHOT_DISMISS_ALPHA_OFFSET_MS = 50; // delay before starting fade
+ private static final long SCREENSHOT_DISMISS_SHARE_OFFSET_MS = 300; // delay after share clicked
private static final float SCREENSHOT_ACTIONS_START_SCALE_X = .7f;
private static final float ROUNDED_CORNER_RADIUS = .05f;
private static final int SWIPE_PADDING_DP = 12; // extra padding around views to allow swipe
@@ -138,6 +140,7 @@
private UiEventLogger mUiEventLogger;
private ScreenshotViewCallback mCallbacks;
private Animator mDismissAnimation;
+ private boolean mIgnoreDismiss;
private final ArrayList<ScreenshotActionChip> mSmartChips = new ArrayList<>();
private PendingInteraction mPendingInteraction;
@@ -526,13 +529,31 @@
});
return animator;
}
+ protected View getScreenshotPreview() {
+ return mScreenshotPreview;
+ }
void setChipIntents(ScreenshotController.SavedImageData imageData) {
- mShareChip.setPendingIntent(imageData.shareAction.actionIntent,
- () -> {
- mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SHARE_TAPPED);
+ mShareChip.setOnClickListener(v -> {
+ ShareTransition transition = imageData.shareTransition.get();
+ try {
+ mIgnoreDismiss = true;
+ transition.shareAction.actionIntent.send();
+ mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_SHARE_TAPPED);
+
+ // Ensures that we delay dismissing until transition has started.
+ postDelayed(() -> {
+ mIgnoreDismiss = false;
animateDismissal();
- });
+ }, SCREENSHOT_DISMISS_SHARE_OFFSET_MS);
+ } catch (PendingIntent.CanceledException e) {
+ mIgnoreDismiss = false;
+ if (transition.onCancelRunnable != null) {
+ transition.onCancelRunnable.run();
+ }
+ Log.e(TAG, "Share intent cancelled", e);
+ }
+ });
mEditChip.setPendingIntent(imageData.editAction.actionIntent,
() -> {
mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_EDIT_TAPPED);
@@ -589,6 +610,9 @@
}
private void animateDismissal(Animator dismissAnimation) {
+ if (mIgnoreDismiss) {
+ return;
+ }
if (DEBUG_WINDOW) {
Log.d(TAG, "removing OnComputeInternalInsetsListener");
}
@@ -759,7 +783,7 @@
}
@Override
- public boolean onTouch(View v, MotionEvent event) {
+ public boolean onTouch(View view, MotionEvent event) {
boolean gestureResult = mGestureDetector.onTouchEvent(event);
mCallbacks.onUserInteraction();
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
@@ -789,6 +813,10 @@
createSwipeReturnAnimation().start();
}
return true;
+ } else {
+ if (view == mScreenshotPreview) {
+ mScreenshotPreview.performClick();
+ }
}
}
return gestureResult;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 7bac007..20efa32 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -197,7 +197,6 @@
viewState.hasItemsInStableShelf = lastViewState.inShelf;
viewState.hidden = !mAmbientState.isShadeExpanded()
|| mAmbientState.isQsCustomizerShowing();
- viewState.maxShelfEnd = maxShelfEnd;
} else {
viewState.hidden = true;
viewState.location = ExpandableViewState.LOCATION_GONE;
@@ -823,10 +822,6 @@
return - (getIntrinsicHeight() - mStatusBarHeight) / 2;
}
- public int getNotificationMergeSize() {
- return getIntrinsicHeight();
- }
-
@Override
public boolean hasNoContentHeight() {
return true;
@@ -1018,7 +1013,6 @@
private class ShelfState extends ExpandableViewState {
private float openedAmount;
private boolean hasItemsInStableShelf;
- private float maxShelfEnd;
@Override
public void applyToView(View view) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index 4b6d66e..3c549f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -485,7 +485,7 @@
}
}
row.showFeedbackIcon(mAssistantFeedbackController.showFeedbackIndicator(entry),
- mAssistantFeedbackController.getFeedbackImageResource(entry));
+ mAssistantFeedbackController.getFeedbackResources(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 a350c5d..0465ebf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java
@@ -27,6 +27,7 @@
import android.os.Looper;
import android.os.UserHandle;
import android.provider.Settings;
+import android.util.Pair;
import androidx.annotation.Nullable;
@@ -129,24 +130,28 @@
}
/**
- * Get the feedback indicator image resource according to assistant's changes on this
- * notification's rank or importance.
+ * Get the feedback indicator image and content description resources 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) {
+ public Pair<Integer, Integer> getFeedbackResources(NotificationEntry entry) {
int feedbackStatus = getFeedbackStatus(entry);
switch (feedbackStatus) {
case STATUS_ALERTED:
- return R.drawable.ic_feedback_alerted;
+ return new Pair(R.drawable.ic_feedback_alerted,
+ R.string.notification_feedback_indicator_alerted);
case STATUS_SILENCED:
- return R.drawable.ic_feedback_silenced;
+ return new Pair(R.drawable.ic_feedback_silenced,
+ R.string.notification_feedback_indicator_silenced);
case STATUS_PROMOTED:
- return R.drawable.ic_feedback_uprank;
+ return new Pair(R.drawable.ic_feedback_uprank,
+ R.string.notification_feedback_indicator_promoted);
case STATUS_DEMOTED:
- return R.drawable.ic_feedback_downrank;
+ return new Pair(R.drawable.ic_feedback_downrank,
+ R.string.notification_feedback_indicator_demoted);
default:
- return 0;
+ return new Pair(0, 0);
}
}
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 998ae9e..c7ac403 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,8 +30,12 @@
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;
/**
@@ -71,6 +75,9 @@
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);
@@ -112,6 +119,64 @@
};
/**
+ * 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 11b829c..3c437d1 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
@@ -49,6 +49,7 @@
import android.util.FloatProperty;
import android.util.Log;
import android.util.MathUtils;
+import android.util.Pair;
import android.util.Property;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -1672,12 +1673,12 @@
requestLayout();
}
- public void showFeedbackIcon(boolean show, int resId) {
+ public void showFeedbackIcon(boolean show, Pair<Integer, Integer> resIds) {
if (mIsSummaryWithChildren) {
- mChildrenContainer.showFeedbackIcon(show, resId);
+ mChildrenContainer.showFeedbackIcon(show, resIds);
}
- mPrivateLayout.showFeedbackIcon(show, resId);
- mPublicLayout.showFeedbackIcon(show, resId);
+ mPrivateLayout.showFeedbackIcon(show, resIds);
+ mPublicLayout.showFeedbackIcon(show, resIds);
}
/** Sets the last time the notification being displayed audibly alerted the user. */
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 475f627..d2774df 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
@@ -33,6 +33,7 @@
import android.util.ArrayMap;
import android.util.AttributeSet;
import android.util.Log;
+import android.util.Pair;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.NotificationHeaderView;
@@ -1586,15 +1587,15 @@
return null;
}
- public void showFeedbackIcon(boolean show, int resId) {
+ public void showFeedbackIcon(boolean show, Pair<Integer, Integer> resIds) {
if (mContractedChild != null) {
- mContractedWrapper.showFeedbackIcon(show, resId);
+ mContractedWrapper.showFeedbackIcon(show, resIds);
}
if (mExpandedChild != null) {
- mExpandedWrapper.showFeedbackIcon(show, resId);
+ mExpandedWrapper.showFeedbackIcon(show, resIds);
}
if (mHeadsUpChild != null) {
- mHeadsUpWrapper.showFeedbackIcon(show, resId);
+ mHeadsUpWrapper.showFeedbackIcon(show, resIds);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
index 1034b1f..596aea0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.notification.row;
import static android.provider.Settings.Secure.SHOW_NOTIFICATION_SNOOZE;
+import static android.view.HapticFeedbackConstants.CLOCK_TICK;
import static com.android.systemui.SwipeHelper.SWIPED_FAR_ENOUGH_SIZE_FRACTION;
@@ -113,6 +114,8 @@
private boolean mIsUserTouching;
+ private boolean mSnappingToDismiss;
+
private final PeopleNotificationIdentifier mPeopleNotificationIdentifier;
public NotificationMenuRow(Context context,
@@ -175,6 +178,11 @@
return mSnapping;
}
+ @VisibleForTesting
+ protected boolean isSnappingToDismiss() {
+ return mSnappingToDismiss;
+ }
+
@Override
public void setMenuClickListener(OnMenuEventListener listener) {
mMenuListener = listener;
@@ -346,6 +354,14 @@
mCheckForDrag = new CheckForDrag();
mHandler.postDelayed(mCheckForDrag, SHOW_MENU_DELAY);
}
+ if (canBeDismissed()) {
+ final float dismissThreshold = getDismissThreshold();
+ final boolean snappingToDismiss = delta < -dismissThreshold || delta > dismissThreshold;
+ if (mSnappingToDismiss != snappingToDismiss) {
+ getMenuView().performHapticFeedback(CLOCK_TICK);
+ }
+ mSnappingToDismiss = snappingToDismiss;
+ }
}
@VisibleForTesting
@@ -361,7 +377,8 @@
@Override
public void onTouchStart() {
- beginDrag();
+ beginDrag();
+ mSnappingToDismiss = false;
}
@Override
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 152527f..28ee935 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
@@ -22,6 +22,7 @@
import android.content.Context;
import android.content.res.ColorStateList;
import android.util.ArraySet;
+import android.util.Pair;
import android.view.NotificationHeaderView;
import android.view.NotificationTopLineView;
import android.view.View;
@@ -132,10 +133,13 @@
/** Shows or hides feedback indicator */
@Override
- public void showFeedbackIcon(boolean show, int resId) {
+ public void showFeedbackIcon(boolean show, Pair<Integer, Integer> resIds) {
mFeedbackIcon.setVisibility(show ? View.VISIBLE : View.GONE);
- if (show && mFeedbackIcon instanceof ImageButton) {
- ((ImageButton) mFeedbackIcon).setImageResource(resId);
+ if (show) {
+ if (mFeedbackIcon instanceof ImageButton) {
+ ((ImageButton) mFeedbackIcon).setImageResource(resIds.first);
+ }
+ mFeedbackIcon.setContentDescription(mView.getContext().getString(resIds.second));
}
}
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 04cbe87c..7b5c5f6 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
@@ -29,6 +29,7 @@
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
+import android.util.Pair;
import android.view.ContextThemeWrapper;
import android.view.NotificationHeaderView;
import android.view.View;
@@ -103,7 +104,7 @@
/**
* Shows or hides feedback icon.
*/
- public void showFeedbackIcon(boolean show, int resId) {
+ public void showFeedbackIcon(boolean show, Pair<Integer, Integer> resIds) {
}
public void onReinflated() {
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 a56ae7d..3833637 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
@@ -23,6 +23,7 @@
import android.graphics.drawable.ColorDrawable;
import android.service.notification.StatusBarNotification;
import android.util.AttributeSet;
+import android.util.Pair;
import android.view.LayoutInflater;
import android.view.NotificationHeaderView;
import android.view.View;
@@ -1300,12 +1301,12 @@
/**
* Shows or hides feedback icon.
*/
- public void showFeedbackIcon(boolean show, int resId) {
+ public void showFeedbackIcon(boolean show, Pair<Integer, Integer> resIds) {
if (mNotificationHeaderWrapper != null) {
- mNotificationHeaderWrapper.showFeedbackIcon(show, resId);
+ mNotificationHeaderWrapper.showFeedbackIcon(show, resIds);
}
if (mNotificationHeaderWrapperLowPriority != null) {
- mNotificationHeaderWrapperLowPriority.showFeedbackIcon(show, resId);
+ mNotificationHeaderWrapperLowPriority.showFeedbackIcon(show, resIds);
}
}
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 0dc824f..9e8385b 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
@@ -632,10 +632,15 @@
if (DEBUG) {
int y = mTopPadding;
+ mDebugPaint.setColor(Color.RED);
canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
+
y = getLayoutHeight();
+ mDebugPaint.setColor(Color.YELLOW);
canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
+
y = getHeight() - getEmptyBottomMargin();
+ mDebugPaint.setColor(Color.GREEN);
canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 4ca9c5d..db0713c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -289,8 +289,6 @@
SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__HIDDEN);
mDismissCallbackRegistry.notifyDismissCancelled();
}
- mExpansion = EXPANSION_HIDDEN;
- dispatchExpansionChanged();
mIsScrimmed = false;
mFalsingCollector.onBouncerHidden();
mCallback.onBouncerVisiblityChanged(false /* shown */);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index b9e8d74..6da5d1b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -164,10 +164,10 @@
public void setup(int statusBarMinHeight, int maxShadeBottom, int notificationStackHeight,
float panelExpansion, int parentHeight, int keyguardStatusHeight, int clockPreferredY,
boolean hasCustomClock, boolean hasVisibleNotifs, float dark, float emptyDragAmount,
- boolean bypassEnabled, int unlockedStackScrollerPadding, boolean udfpsEnrolled,
+ boolean bypassEnabled, int unlockedStackScrollerPadding, boolean showLockIcon,
float qsExpansion) {
- mMinTopMargin = statusBarMinHeight + (udfpsEnrolled ? mContainerTopPaddingWithoutLockIcon :
- mContainerTopPaddingWithLockIcon);
+ mMinTopMargin = statusBarMinHeight + (showLockIcon
+ ? mContainerTopPaddingWithLockIcon : mContainerTopPaddingWithoutLockIcon);
mMaxShadeBottom = maxShadeBottom;
mNotificationStackHeight = notificationStackHeight;
mPanelExpansion = panelExpansion;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java
index 6bdc303..ab0366e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java
@@ -501,7 +501,7 @@
if (mBlockUpdates && canBlockUpdates()) {
shouldUpdate = false;
}
- if (shouldUpdate && mLockIcon != null) {
+ if (shouldUpdate && mLockIcon != null && mLockIcon.getVisibility() != GONE) {
mLockIcon.update(state,
mStatusBarStateController.isDozing(), mKeyguardJustShown);
}
@@ -549,16 +549,14 @@
return false;
}
- if (mKeyguardUpdateMonitor.isUdfpsEnrolled()) {
- boolean changed = mLockIcon.getVisibility() == GONE;
+ if (!mKeyguardUpdateMonitor.shouldShowLockIcon()) {
+ boolean changed = mLockIcon.getVisibility() != GONE;
mLockIcon.setVisibility(GONE);
return changed;
}
boolean onAodOrDocked = mStatusBarStateController.isDozing() || mDocked;
- boolean invisible = onAodOrDocked || mWakeAndUnlockRunning || mShowingLaunchAffordance
- || (mKeyguardSecurityModel.getSecurityMode(KeyguardUpdateMonitor.getCurrentUser())
- == KeyguardSecurityModel.SecurityMode.None);
+ boolean invisible = onAodOrDocked || mWakeAndUnlockRunning || mShowingLaunchAffordance;
boolean fingerprintOrBypass = mFingerprintUnlock
|| mKeyguardBypassController.getBypassEnabled();
if (fingerprintOrBypass && !mBouncerShowingScrimmed) {
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 8d3b128..ba08e76 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -912,7 +912,8 @@
clockPreferredY, hasCustomClock(),
hasVisibleNotifications, mInterpolatedDarkAmount, mEmptyDragAmount,
bypassEnabled, getUnlockedStackScrollerPadding(),
- mUpdateMonitor.isUdfpsEnrolled(), getQsExpansionFraction());
+ mUpdateMonitor.shouldShowLockIcon(),
+ getQsExpansionFraction());
mClockPositionAlgorithm.run(mClockPositionResult);
mKeyguardStatusViewController.updatePosition(
mClockPositionResult.clockX, mClockPositionResult.clockY,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java
index 272c494..22fd93e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java
@@ -25,11 +25,15 @@
import androidx.annotation.NonNull;
+import com.android.systemui.Dumpable;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dump.DumpManager;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Date;
import javax.inject.Inject;
@@ -38,7 +42,7 @@
*/
@SysUISingleton
public class NextAlarmControllerImpl extends BroadcastReceiver
- implements NextAlarmController {
+ implements NextAlarmController, Dumpable {
private final ArrayList<NextAlarmChangeCallback> mChangeCallbacks = new ArrayList<>();
@@ -48,18 +52,34 @@
/**
*/
@Inject
- public NextAlarmControllerImpl(Context context) {
- mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+ public NextAlarmControllerImpl(
+ AlarmManager alarmManager,
+ BroadcastDispatcher broadcastDispatcher,
+ DumpManager dumpManager) {
+ dumpManager.registerDumpable("NextAlarmController", this);
+ mAlarmManager = alarmManager;
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_USER_SWITCHED);
filter.addAction(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED);
- context.registerReceiverAsUser(this, UserHandle.ALL, filter, null, null);
+ broadcastDispatcher.registerReceiver(this, filter, null, UserHandle.ALL);
updateNextAlarm();
}
+ @Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println("NextAlarmController state:");
- pw.print(" mNextAlarm="); pw.println(mNextAlarm);
+ pw.print("mNextAlarm=");
+ if (mNextAlarm != null) {
+ pw.println(new Date(mNextAlarm.getTriggerTime()));
+ pw.print(" PendingIntentPkg=");
+ pw.println(mNextAlarm.getShowIntent().getCreatorPackage());
+ } else {
+ pw.println("null");
+ }
+
+ pw.println("Registered Callbacks:");
+ for (NextAlarmChangeCallback callback : mChangeCallbacks) {
+ pw.print(" "); pw.println(callback.toString());
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
index a287e57..d9f4744 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
@@ -267,6 +267,12 @@
ColorUtils.RGBToHSL(Color.red(color), Color.green(color), Color.blue(color), hslMain);
hslMain[0] /= 360f;
+ // To close to white or black, let's use the default system theme instead of
+ // applying a colorized one.
+ if (hslMain[2] < 0.05 || hslMain[2] > 0.95) {
+ return Color.TRANSPARENT;
+ }
+
float minDistance = Float.MAX_VALUE;
int closestColor = Color.TRANSPARENT;
for (int candidate: candidates) {
@@ -294,7 +300,7 @@
final String overlayPackageJson = mSecureSettings.getStringForUser(
Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES,
currentUser);
- if (DEBUG) Log.d(TAG, "updateThemeOverlays: " + overlayPackageJson);
+ if (DEBUG) Log.d(TAG, "updateThemeOverlays. Setting: " + overlayPackageJson);
boolean hasSystemPalette = false;
boolean hasAccentColor = false;
final Map<String, String> categoryToPackage = new ArrayMap<>();
@@ -343,6 +349,10 @@
while (colorString.length() < 6) {
colorString = "0" + colorString;
}
+ // Remove alpha component
+ if (colorString.length() > 6) {
+ colorString = colorString.substring(colorString.length() - 6);
+ }
return colorString;
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/RotationUtils.java b/packages/SystemUI/src/com/android/systemui/util/leak/RotationUtils.java
index 11c72c4..e44981e 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/RotationUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/RotationUtils.java
@@ -15,7 +15,6 @@
package com.android.systemui.util.leak;
import android.content.Context;
-import android.content.res.Configuration;
import android.view.Surface;
public class RotationUtils {
@@ -26,30 +25,26 @@
public static final int ROTATION_UPSIDE_DOWN = 3;
public static int getRotation(Context context) {
- Configuration config = context.getResources().getConfiguration();
int rot = context.getDisplay().getRotation();
- if (config.smallestScreenWidthDp < 600) {
- if (rot == Surface.ROTATION_90) {
- return ROTATION_LANDSCAPE;
- } else if (rot == Surface.ROTATION_270) {
- return ROTATION_SEASCAPE;
- }
+ if (rot == Surface.ROTATION_90) {
+ return ROTATION_LANDSCAPE;
+ } else if (rot == Surface.ROTATION_270) {
+ return ROTATION_SEASCAPE;
+ } else {
+ return ROTATION_NONE;
}
- return ROTATION_NONE;
}
public static int getExactRotation(Context context) {
- Configuration config = context.getResources().getConfiguration();
int rot = context.getDisplay().getRotation();
- if (config.smallestScreenWidthDp < 600) {
- if (rot == Surface.ROTATION_90) {
- return ROTATION_LANDSCAPE;
- } else if (rot == Surface.ROTATION_270) {
- return ROTATION_SEASCAPE;
- } else if (rot == Surface.ROTATION_180) {
- return ROTATION_UPSIDE_DOWN;
- }
+ if (rot == Surface.ROTATION_90) {
+ return ROTATION_LANDSCAPE;
+ } else if (rot == Surface.ROTATION_270) {
+ return ROTATION_SEASCAPE;
+ } else if (rot == Surface.ROTATION_180) {
+ return ROTATION_UPSIDE_DOWN;
+ } else {
+ return ROTATION_NONE;
}
- return ROTATION_NONE;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 735338f..df54eab 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -259,6 +259,7 @@
| WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
| WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
+ mWindow.addPrivateFlags(WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY);
mWindow.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
mWindow.setWindowAnimations(com.android.internal.R.style.Animation_Toast);
WindowManager.LayoutParams lp = mWindow.getAttributes();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
index 6c3b37e..e967a5d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
@@ -24,7 +24,10 @@
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;
@@ -51,6 +54,8 @@
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;
@@ -79,7 +84,8 @@
MockitoAnnotations.initMocks(this);
mFsc = new ForegroundServiceController(mAppOpsController, mMainHandler);
mListener = new ForegroundServiceNotificationListener(
- mContext, mFsc, mEntryManager, mNotifPipeline, mClock);
+ mContext, mFsc, mEntryManager, mNotifPipeline,
+ mock(ForegroundServiceLifetimeExtender.class), 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
new file mode 100644
index 0000000..9a40421
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceNotificationListenerTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index 648c319..7f8372e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -175,7 +175,7 @@
@Test
public void fingerDown() throws RemoteException {
// Configure UdfpsView to accept the ACTION_DOWN event
- when(mUdfpsView.isScrimShowing()).thenReturn(false);
+ when(mUdfpsView.isShowScrimAndDot()).thenReturn(false);
when(mUdfpsView.isValidTouch(anyFloat(), anyFloat(), anyFloat())).thenReturn(true);
// GIVEN that the overlay is showing
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/FaceAuthScreenBrightnessControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/FaceAuthScreenBrightnessControllerTest.kt
index 73a7ca9..cb05a6b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/FaceAuthScreenBrightnessControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/FaceAuthScreenBrightnessControllerTest.kt
@@ -83,7 +83,7 @@
MockitoAnnotations.initMocks(this)
faceAuthScreenBrightnessController = object : FaceAuthScreenBrightnessController(
notificationShadeWindowController, keyguardUpdateMonitor, resources, globalSettings,
- systemSettings, mainHandler, dumpManager) {
+ systemSettings, mainHandler, dumpManager, true) {
override fun createAnimator(start: Float, end: Float) = animator
}
`when`(systemSettings.getFloat(eq(SCREEN_BRIGHTNESS_FLOAT))).thenReturn(INITIAL_BRIGHTNESS)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
index fd5d996..c00b394 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
@@ -24,6 +24,7 @@
import static org.mockito.Mockito.when;
import android.content.Context;
+import android.media.MediaRouter2Manager;
import android.media.session.MediaSessionManager;
import android.os.Bundle;
import android.testing.AndroidTestingRunner;
@@ -63,6 +64,7 @@
private NotificationEntryManager mNotificationEntryManager =
mock(NotificationEntryManager.class);
private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class);
+ private final MediaRouter2Manager mRouterManager = mock(MediaRouter2Manager.class);
private MediaOutputBaseDialogImpl mMediaOutputBaseDialogImpl;
private MediaOutputController mMediaOutputController;
@@ -75,7 +77,7 @@
public void setUp() {
mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false,
mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
- mNotificationEntryManager, mUiEventLogger);
+ mNotificationEntryManager, mUiEventLogger, mRouterManager);
mMediaOutputBaseDialogImpl = new MediaOutputBaseDialogImpl(mContext,
mMediaOutputController);
mMediaOutputBaseDialogImpl.onCreate(new Bundle());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
index d1a617b..c1a3994 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
@@ -32,6 +32,7 @@
import android.graphics.drawable.Icon;
import android.media.MediaDescription;
import android.media.MediaMetadata;
+import android.media.MediaRouter2Manager;
import android.media.RoutingSessionInfo;
import android.media.session.MediaController;
import android.media.session.MediaSessionManager;
@@ -91,6 +92,7 @@
private NotificationEntryManager mNotificationEntryManager =
mock(NotificationEntryManager.class);
private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class);
+ private final MediaRouter2Manager mRouter2Manager = mock(MediaRouter2Manager.class);
private Context mSpyContext;
private MediaOutputController mMediaOutputController;
@@ -113,7 +115,7 @@
mMediaOutputController = new MediaOutputController(mSpyContext, TEST_PACKAGE_NAME, false,
mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
- mNotificationEntryManager, mUiEventLogger);
+ mNotificationEntryManager, mUiEventLogger, mRouter2Manager);
mLocalMediaManager = spy(mMediaOutputController.mLocalMediaManager);
mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
MediaDescription.Builder builder = new MediaDescription.Builder();
@@ -157,7 +159,7 @@
public void start_withoutPackageName_verifyMediaControllerInit() {
mMediaOutputController = new MediaOutputController(mSpyContext, null, false,
mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
- mNotificationEntryManager, mUiEventLogger);
+ mNotificationEntryManager, mUiEventLogger, mRouter2Manager);
mMediaOutputController.start(mCb);
@@ -178,7 +180,7 @@
public void stop_withoutPackageName_verifyMediaControllerDeinit() {
mMediaOutputController = new MediaOutputController(mSpyContext, null, false,
mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
- mNotificationEntryManager, mUiEventLogger);
+ mNotificationEntryManager, mUiEventLogger, mRouter2Manager);
mMediaOutputController.start(mCb);
@@ -449,7 +451,7 @@
public void getNotificationLargeIcon_withoutPackageName_returnsNull() {
mMediaOutputController = new MediaOutputController(mSpyContext, null, false,
mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
- mNotificationEntryManager, mUiEventLogger);
+ mNotificationEntryManager, mUiEventLogger, mRouter2Manager);
assertThat(mMediaOutputController.getNotificationIcon()).isNull();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
index 86f6bde..e47a5e7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
@@ -24,6 +24,7 @@
import static org.mockito.Mockito.when;
import android.media.MediaRoute2Info;
+import android.media.MediaRouter2Manager;
import android.media.session.MediaSessionManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -65,6 +66,7 @@
private final NotificationEntryManager mNotificationEntryManager =
mock(NotificationEntryManager.class);
private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class);
+ private final MediaRouter2Manager mRouterManager = mock(MediaRouter2Manager.class);
private MediaOutputDialog mMediaOutputDialog;
private MediaOutputController mMediaOutputController;
@@ -74,7 +76,7 @@
public void setUp() {
mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false,
mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
- mNotificationEntryManager, mUiEventLogger);
+ mNotificationEntryManager, mUiEventLogger, mRouterManager);
mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
mMediaOutputDialog = new MediaOutputDialog(mContext, false,
mMediaOutputController, mUiEventLogger);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java
index c296ff5..6111099 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java
@@ -21,6 +21,7 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import android.media.MediaRouter2Manager;
import android.media.session.MediaSessionManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -64,6 +65,7 @@
private NotificationEntryManager mNotificationEntryManager =
mock(NotificationEntryManager.class);
private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class);
+ private final MediaRouter2Manager mRouterManager = mock(MediaRouter2Manager.class);
private MediaOutputGroupDialog mMediaOutputGroupDialog;
private MediaOutputController mMediaOutputController;
@@ -73,7 +75,7 @@
public void setUp() {
mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false,
mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
- mNotificationEntryManager, mUiEventLogger);
+ mNotificationEntryManager, mUiEventLogger, mRouterManager);
mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
mMediaOutputGroupDialog = new MediaOutputGroupDialog(mContext, false,
mMediaOutputController);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java
index e934f84..644373c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleSpaceUtilsTest.java
@@ -21,7 +21,13 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Notification;
@@ -29,11 +35,16 @@
import android.app.people.PeopleSpaceTile;
import android.appwidget.AppWidgetManager;
import android.content.ContentResolver;
+import android.content.Context;
import android.content.Intent;
+import android.content.pm.LauncherApps;
+import android.content.pm.ShortcutInfo;
+import android.database.Cursor;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteException;
+import android.provider.ContactsContract;
import android.provider.Settings;
import android.service.notification.StatusBarNotification;
import android.testing.AndroidTestingRunner;
@@ -52,6 +63,8 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.Map;
+
@SmallTest
@RunWith(AndroidTestingRunner.class)
public class PeopleSpaceUtilsTest extends SysuiTestCase {
@@ -61,6 +74,32 @@
private static final String SHORTCUT_ID = "101";
private static final String NOTIFICATION_KEY = "notification_key";
private static final String NOTIFICATION_CONTENT = "notification_content";
+ private static final String TEST_LOOKUP_KEY = "lookup_key";
+ private static final int TEST_COLUMN_INDEX = 1;
+ private static final Uri URI = Uri.parse("fake_uri");
+ private static final Icon ICON = Icon.createWithResource("package", R.drawable.ic_android);
+ private static final Person PERSON = new Person.Builder()
+ .setName("name")
+ .setKey("abc")
+ .setUri(URI.toString())
+ .setBot(false)
+ .build();
+ private static final PeopleSpaceTile PERSON_TILE =
+ new PeopleSpaceTile
+ .Builder(SHORTCUT_ID, "username", ICON, new Intent())
+ .setNotificationKey(NOTIFICATION_KEY)
+ .setNotificationContent(NOTIFICATION_CONTENT)
+ .setNotificationDataUri(URI)
+ .build();
+
+ private final ShortcutInfo mShortcutInfo = new ShortcutInfo.Builder(mContext,
+ SHORTCUT_ID).setLongLabel(
+ "name").setPerson(PERSON)
+ .build();
+ private final ShortcutInfo mShortcutInfoWithoutPerson = new ShortcutInfo.Builder(mContext,
+ SHORTCUT_ID).setLongLabel(
+ "name")
+ .build();
@Mock
private NotificationListener mListenerService;
@@ -68,26 +107,12 @@
private IAppWidgetService mIAppWidgetService;
@Mock
private AppWidgetManager mAppWidgetManager;
-
- private static Icon sIcon = Icon.createWithResource("package", R.drawable.ic_android);
- private static Uri sUri = new Uri.Builder()
- .scheme(ContentResolver.SCHEME_CONTENT)
- .authority("something")
- .path("test")
- .build();
- private static Person sPerson = new Person.Builder()
- .setName("name")
- .setKey("abc")
- .setUri("uri")
- .setBot(false)
- .build();
- private static PeopleSpaceTile sPeopleSpaceTile =
- new PeopleSpaceTile
- .Builder(SHORTCUT_ID, "username", sIcon, new Intent())
- .setNotificationKey(NOTIFICATION_KEY)
- .setNotificationContent(NOTIFICATION_CONTENT)
- .setNotificationDataUri(sUri)
- .build();
+ @Mock
+ private Cursor mMockCursor;
+ @Mock
+ private ContentResolver mMockContentResolver;
+ @Mock
+ private Context mMockContext;
@Before
public void setUp() throws RemoteException {
@@ -97,13 +122,19 @@
int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT, WIDGET_ID_WITHOUT_SHORTCUT};
Bundle options = new Bundle();
- options.putParcelable(OPTIONS_PEOPLE_SPACE_TILE, sPeopleSpaceTile);
+ options.putParcelable(OPTIONS_PEOPLE_SPACE_TILE, PERSON_TILE);
when(mIAppWidgetService.getAppWidgetIds(any())).thenReturn(widgetIdsArray);
when(mAppWidgetManager.getAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT)))
.thenReturn(options);
when(mAppWidgetManager.getAppWidgetOptions(eq(WIDGET_ID_WITHOUT_SHORTCUT)))
.thenReturn(new Bundle());
+
+ when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver);
+ when(mMockContentResolver.query(any(Uri.class), any(), anyString(), any(),
+ isNull())).thenReturn(mMockCursor);
+ when(mMockContext.getString(R.string.birthday_status)).thenReturn(
+ mContext.getString(R.string.birthday_status));
}
@Test
@@ -124,15 +155,104 @@
}
@Test
+ public void testGetBackgroundTextFromMessageNoPunctuation() {
+ String backgroundText = PeopleSpaceUtils.getBackgroundTextFromMessage("test");
+
+ assertThat(backgroundText).isNull();
+ }
+
+ @Test
+ public void testGetBackgroundTextFromMessageSingleExclamation() {
+ String backgroundText = PeopleSpaceUtils.getBackgroundTextFromMessage("test!");
+
+ assertThat(backgroundText).isNull();
+ }
+
+ @Test
+ public void testGetBackgroundTextFromMessageSingleQuestion() {
+ String backgroundText = PeopleSpaceUtils.getBackgroundTextFromMessage("?test");
+
+ assertThat(backgroundText).isNull();
+ }
+
+ @Test
+ public void testGetBackgroundTextFromMessageSeparatedMarks() {
+ String backgroundText = PeopleSpaceUtils.getBackgroundTextFromMessage("test! right!");
+
+ assertThat(backgroundText).isNull();
+ }
+
+ @Test
+ public void testGetBackgroundTextFromMessageDoubleExclamation() {
+ String backgroundText = PeopleSpaceUtils.getBackgroundTextFromMessage("!!test");
+
+ assertThat(backgroundText).isEqualTo("!");
+ }
+
+ @Test
+ public void testGetBackgroundTextFromMessageDoubleQuestion() {
+ String backgroundText = PeopleSpaceUtils.getBackgroundTextFromMessage("test??");
+
+ assertThat(backgroundText).isEqualTo("?");
+ }
+
+ @Test
+ public void testGetBackgroundTextFromMessageMixed() {
+ String backgroundText = PeopleSpaceUtils.getBackgroundTextFromMessage("test?!");
+
+ assertThat(backgroundText).isEqualTo("!?");
+ }
+
+ @Test
+ public void testGetBackgroundTextFromMessageMixedInTheMiddle() {
+ String backgroundText = PeopleSpaceUtils.getBackgroundTextFromMessage(
+ "test!? in the middle");
+
+ assertThat(backgroundText).isEqualTo("!?");
+ }
+
+ @Test
+ public void testGetBackgroundTextFromMessageMixedDifferentOrder() {
+ String backgroundText = PeopleSpaceUtils.getBackgroundTextFromMessage(
+ "test!? in the middle");
+
+ assertThat(backgroundText).isEqualTo("!?");
+ }
+
+ @Test
+ public void testGetBackgroundTextFromMessageMultiple() {
+ String backgroundText = PeopleSpaceUtils.getBackgroundTextFromMessage(
+ "test!?!!? in the middle");
+
+ assertThat(backgroundText).isEqualTo("!?");
+ }
+
+ @Test
+ public void testGetBackgroundTextFromMessageQuestionFirst() {
+ String backgroundText = PeopleSpaceUtils.getBackgroundTextFromMessage(
+ "test?? in the middle!!");
+
+ assertThat(backgroundText).isEqualTo("?");
+ }
+
+ @Test
+ public void testGetBackgroundTextFromMessageExclamationFirst() {
+ String backgroundText = PeopleSpaceUtils.getBackgroundTextFromMessage(
+ "test!! in the middle??");
+
+ assertThat(backgroundText).isEqualTo("!");
+ }
+
+ @Test
public void testGetLastMessagingStyleMessage() {
Notification notification = new Notification.Builder(mContext, "test")
.setContentTitle("TEST_TITLE")
.setContentText("TEST_TEXT")
.setShortcutId(SHORTCUT_ID)
- .setStyle(new Notification.MessagingStyle(sPerson)
- .addMessage(new Notification.MessagingStyle.Message("text1", 0, sPerson))
- .addMessage(new Notification.MessagingStyle.Message("text2", 20, sPerson))
- .addMessage(new Notification.MessagingStyle.Message("text3", 10, sPerson))
+ .setStyle(new Notification.MessagingStyle(PERSON)
+ .addMessage(new Notification.MessagingStyle.Message("text1", 0, PERSON))
+ .addMessage(new Notification.MessagingStyle.Message("text2", 20, PERSON))
+ .addMessage(new Notification.MessagingStyle.Message("text3", 10, PERSON))
)
.build();
StatusBarNotification sbn = new SbnBuilder()
@@ -149,21 +269,21 @@
public void testAugmentTileFromStorageWithNotification() {
PeopleSpaceTile tile =
new PeopleSpaceTile
- .Builder("id", "userName", sIcon, new Intent())
+ .Builder("id", "userName", ICON, new Intent())
.build();
PeopleSpaceTile actual = PeopleSpaceUtils
.augmentTileFromStorage(tile, mAppWidgetManager, WIDGET_ID_WITH_SHORTCUT);
assertThat(actual.getNotificationKey()).isEqualTo(NOTIFICATION_KEY);
assertThat(actual.getNotificationContent()).isEqualTo(NOTIFICATION_CONTENT);
- assertThat(actual.getNotificationDataUri()).isEqualTo(sUri);
+ assertThat(actual.getNotificationDataUri()).isEqualTo(URI);
}
@Test
public void testAugmentTileFromStorageWithoutNotification() {
PeopleSpaceTile tile =
new PeopleSpaceTile
- .Builder("id", "userName", sIcon, new Intent())
+ .Builder("id", "userName", ICON, new Intent())
.build();
PeopleSpaceTile actual = PeopleSpaceUtils
.augmentTileFromStorage(tile, mAppWidgetManager, WIDGET_ID_WITHOUT_SHORTCUT);
@@ -172,4 +292,98 @@
assertThat(actual.getNotificationKey()).isEqualTo(null);
assertThat(actual.getNotificationDataUri()).isEqualTo(null);
}
+
+ @Test
+ public void testDoNotUpdateSingleConversationAppWidgetWhenNotBirthday() {
+ int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT};
+ when(mMockCursor.moveToNext()).thenReturn(true, false);
+ when(mMockCursor.getString(eq(TEST_COLUMN_INDEX))).thenReturn(TEST_LOOKUP_KEY);
+ when(mMockCursor.getColumnIndex(eq(ContactsContract.CommonDataKinds.Event.LOOKUP_KEY)
+ )).thenReturn(TEST_COLUMN_INDEX);
+
+ // Existing tile does not have birthday status.
+ Map<Integer, PeopleSpaceTile> widgetIdToTile = Map.of(WIDGET_ID_WITH_SHORTCUT,
+ new PeopleSpaceTile.Builder(mShortcutInfoWithoutPerson,
+ mContext.getSystemService(LauncherApps.class)).build());
+ PeopleSpaceUtils.getBirthdays(mMockContext, mAppWidgetManager,
+ widgetIdToTile, widgetIdsArray);
+
+ verify(mAppWidgetManager, never()).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
+ any());
+ }
+
+ @Test
+ public void testUpdateSingleConversationAppWidgetWithoutPersonContactUriToRemoveBirthday() {
+ int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT};
+ when(mMockCursor.moveToNext()).thenReturn(true, false);
+ when(mMockCursor.getString(eq(TEST_COLUMN_INDEX))).thenReturn(TEST_LOOKUP_KEY);
+ when(mMockCursor.getColumnIndex(eq(ContactsContract.CommonDataKinds.Event.LOOKUP_KEY)
+ )).thenReturn(TEST_COLUMN_INDEX);
+
+ // Existing tile has a birthday status.
+ Map<Integer, PeopleSpaceTile> widgetIdToTile = Map.of(WIDGET_ID_WITH_SHORTCUT,
+ new PeopleSpaceTile.Builder(mShortcutInfoWithoutPerson,
+ mContext.getSystemService(LauncherApps.class)).setStatusText(
+ mContext.getString(R.string.birthday_status)).build());
+ PeopleSpaceUtils.getBirthdays(mMockContext, mAppWidgetManager,
+ widgetIdToTile, widgetIdsArray);
+
+ verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
+ any());
+ }
+
+ @Test
+ public void testUpdateSingleConversationAppWidgetToRemoveBirthdayWhenNoLongerBirthday() {
+ int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT};
+ Cursor mockPersonUriCursor = mock(Cursor.class);
+ Cursor mockBirthdaysUriCursor = mock(Cursor.class);
+ when(mockPersonUriCursor.moveToNext()).thenReturn(true, false);
+ when(mockBirthdaysUriCursor.moveToNext()).thenReturn(true, false);
+ when(mockBirthdaysUriCursor.getColumnIndex(
+ eq(ContactsContract.CommonDataKinds.Event.LOOKUP_KEY)
+ )).thenReturn(TEST_COLUMN_INDEX);
+ when(mockPersonUriCursor.getColumnIndex(
+ eq(ContactsContract.CommonDataKinds.Event.LOOKUP_KEY)
+ )).thenReturn(TEST_COLUMN_INDEX);
+ // Return different cursors based on the Uri queried.
+ when(mMockContentResolver.query(eq(URI), any(), any(), any(),
+ any())).thenReturn(mockPersonUriCursor);
+ when(mMockContentResolver.query(eq(ContactsContract.Data.CONTENT_URI), any(), any(), any(),
+ any())).thenReturn(mockBirthdaysUriCursor);
+ // Each cursor returns a different lookup key.
+ when(mockBirthdaysUriCursor.getString(eq(TEST_COLUMN_INDEX))).thenReturn(TEST_LOOKUP_KEY);
+ when(mockPersonUriCursor.getString(eq(TEST_COLUMN_INDEX))).thenReturn(
+ TEST_LOOKUP_KEY + "differentlookup");
+
+ // Existing tile has a birthday status.
+ Map<Integer, PeopleSpaceTile> widgetIdToTile = Map.of(WIDGET_ID_WITH_SHORTCUT,
+ new PeopleSpaceTile.Builder(mShortcutInfo,
+ mContext.getSystemService(LauncherApps.class)).setStatusText(
+ mContext.getString(R.string.birthday_status)).build());
+ PeopleSpaceUtils.getBirthdays(mMockContext, mAppWidgetManager,
+ widgetIdToTile, widgetIdsArray);
+
+ verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
+ any());
+ }
+
+ @Test
+ public void testUpdateSingleConversationAppWidgetWhenBirthday() {
+ int[] widgetIdsArray = {WIDGET_ID_WITH_SHORTCUT};
+ when(mMockCursor.moveToNext()).thenReturn(true, false, true, false);
+ when(mMockCursor.getString(eq(TEST_COLUMN_INDEX))).thenReturn(TEST_LOOKUP_KEY);
+ when(mMockCursor.getColumnIndex(eq(ContactsContract.CommonDataKinds.Event.LOOKUP_KEY)
+ )).thenReturn(TEST_COLUMN_INDEX);
+
+ // Existing tile has a birthday status.
+ Map<Integer, PeopleSpaceTile> widgetIdToTile = Map.of(WIDGET_ID_WITH_SHORTCUT,
+ new PeopleSpaceTile.Builder(mShortcutInfo,
+ mContext.getSystemService(LauncherApps.class)).setStatusText(
+ mContext.getString(R.string.birthday_status)).build());
+ PeopleSpaceUtils.getBirthdays(mMockContext, mAppWidgetManager,
+ widgetIdToTile, widgetIdsArray);
+
+ verify(mAppWidgetManager, times(1)).updateAppWidget(eq(WIDGET_ID_WITH_SHORTCUT),
+ any());
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java
index cd4f51e..df07b12 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/people/widget/PeopleSpaceWidgetManagerTest.java
@@ -37,7 +37,6 @@
import android.app.Person;
import android.app.people.PeopleSpaceTile;
import android.appwidget.AppWidgetManager;
-import android.content.ContentResolver;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ParceledListSlice;
@@ -95,6 +94,21 @@
private static final String OTHER_SHORTCUT_ID = "102";
private static final String NOTIFICATION_KEY = "notification_key";
private static final String NOTIFICATION_CONTENT = "notification_content";
+ private static final Uri URI = Uri.parse("fake_uri");
+ private static final Icon ICON = Icon.createWithResource("package", R.drawable.ic_android);
+ private static final Person PERSON = new Person.Builder()
+ .setName("name")
+ .setKey("abc")
+ .setUri(URI.toString())
+ .setBot(false)
+ .build();
+ private static final PeopleSpaceTile PERSON_TILE =
+ new PeopleSpaceTile
+ .Builder(SHORTCUT_ID, "username", ICON, new Intent())
+ .setNotificationKey(NOTIFICATION_KEY)
+ .setNotificationContent(NOTIFICATION_CONTENT)
+ .setNotificationDataUri(URI)
+ .build();
private PeopleSpaceWidgetManager mManager;
@@ -110,26 +124,6 @@
@Captor
private ArgumentCaptor<NotificationHandler> mListenerCaptor;
- private static Icon sIcon = Icon.createWithResource("package", R.drawable.ic_android);
- private static Uri sUri = new Uri.Builder()
- .scheme(ContentResolver.SCHEME_CONTENT)
- .authority("something")
- .path("test")
- .build();
- private static Person sPerson = new Person.Builder()
- .setName("name")
- .setKey("abc")
- .setUri("uri")
- .setBot(false)
- .build();
- private static PeopleSpaceTile sPeopleSpaceTile =
- new PeopleSpaceTile
- .Builder(SHORTCUT_ID, "username", sIcon, new Intent())
- .setNotificationKey(NOTIFICATION_KEY)
- .setNotificationContent(NOTIFICATION_CONTENT)
- .setNotificationDataUri(sUri)
- .build();
-
private final NoManSimulator mNoMan = new NoManSimulator();
private final FakeSystemClock mClock = new FakeSystemClock();
@@ -150,9 +144,9 @@
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
SharedPreferences.Editor editor = sp.edit();
editor.putString(String.valueOf(WIDGET_ID_WITH_SHORTCUT), SHORTCUT_ID);
- editor.commit();
+ editor.apply();
Bundle options = new Bundle();
- options.putParcelable(OPTIONS_PEOPLE_SPACE_TILE, sPeopleSpaceTile);
+ options.putParcelable(OPTIONS_PEOPLE_SPACE_TILE, PERSON_TILE);
when(mAppWidgetManager.getAppWidgetOptions(eq(WIDGET_ID_WITH_SHORTCUT)))
.thenReturn(options);
@@ -304,7 +298,6 @@
UserHandle.getUserHandleForUid(0), channel, IMPORTANCE_HIGH);
mClock.advanceTime(MIN_LINGER_DURATION);
- verify(mIAppWidgetService, never()).getAppWidgetIds(any());
verify(mIAppWidgetService, never()).notifyAppWidgetViewDataChanged(any(), any(), anyInt());
verify(mAppWidgetManager, never()).updateAppWidget(anyInt(),
any(RemoteViews.class));
@@ -456,8 +449,8 @@
.setContentTitle("TEST_TITLE")
.setContentText("TEST_TEXT")
.setShortcutId(shortcutId)
- .setStyle(new Notification.MessagingStyle(sPerson)
- .addMessage(new Notification.MessagingStyle.Message("text3", 10, sPerson))
+ .setStyle(new Notification.MessagingStyle(PERSON)
+ .addMessage(new Notification.MessagingStyle.Message("text3", 10, PERSON))
)
.build();
return new SbnBuilder()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
index 2374b82..6759c90 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
@@ -43,6 +43,7 @@
import com.android.systemui.SystemUIFactory;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.screenshot.ScreenshotController.SavedImageData.ShareTransition;
import org.junit.Before;
import org.junit.Test;
@@ -175,10 +176,11 @@
data.finisher = null;
data.mActionsReadyListener = null;
SaveImageInBackgroundTask task =
- new SaveImageInBackgroundTask(mContext, mScreenshotSmartActions, data);
+ new SaveImageInBackgroundTask(mContext, mScreenshotSmartActions, data,
+ ShareTransition::new);
Notification.Action shareAction = task.createShareAction(mContext, mContext.getResources(),
- Uri.parse("Screenshot_123.png"));
+ Uri.parse("Screenshot_123.png")).get().shareAction;
Intent intent = shareAction.actionIntent.getIntent();
assertNotNull(intent);
@@ -202,7 +204,8 @@
data.finisher = null;
data.mActionsReadyListener = null;
SaveImageInBackgroundTask task =
- new SaveImageInBackgroundTask(mContext, mScreenshotSmartActions, data);
+ new SaveImageInBackgroundTask(mContext, mScreenshotSmartActions, data,
+ ShareTransition::new);
Notification.Action editAction = task.createEditAction(mContext, mContext.getResources(),
Uri.parse("Screenshot_123.png"));
@@ -229,7 +232,8 @@
data.finisher = null;
data.mActionsReadyListener = null;
SaveImageInBackgroundTask task =
- new SaveImageInBackgroundTask(mContext, mScreenshotSmartActions, data);
+ new SaveImageInBackgroundTask(mContext, mScreenshotSmartActions, data,
+ ShareTransition::new);
Notification.Action deleteAction = task.createDeleteAction(mContext,
mContext.getResources(),
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 3f1cf83..d131dce 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
@@ -41,6 +41,7 @@
import android.service.notification.StatusBarNotification;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
+import android.util.Pair;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -120,9 +121,9 @@
}
@Test
- public void testGetFeedbackImageResource_settingDisabled() {
+ public void testGetFeedbackResources_settingDisabled() {
switchSetting(OFF);
- Assert.assertEquals(0, mAssistantFeedbackController.getFeedbackImageResource(
+ Assert.assertEquals(new Pair(0, 0), mAssistantFeedbackController.getFeedbackResources(
getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_DEFAULT, RANKING_UNCHANGED)));
}
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 0954621..639e791 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,6 +31,7 @@
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;
@@ -45,6 +46,7 @@
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;
@@ -69,6 +71,7 @@
private NotificationEntryBuilder mEntryBuilder;
private AppOpsCoordinator mAppOpsCoordinator;
private NotifFilter mForegroundFilter;
+ private NotifLifetimeExtender mForegroundNotifLifetimeExtender;
private NotifSectioner mFgsSection;
private FakeSystemClock mClock = new FakeSystemClock();
@@ -95,6 +98,13 @@
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();
}
@@ -150,6 +160,55 @@
}
@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 ca982a6..2e0827f 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
@@ -39,10 +39,12 @@
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
+import android.util.Pair;
import android.view.View;
import androidx.test.filters.SmallTest;
+import com.android.internal.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -210,7 +212,7 @@
// public notification is custom layout - no header
mGroupRow.setSensitive(true, true);
mGroupRow.setOnFeedbackClickListener(null);
- mGroupRow.showFeedbackIcon(false, 0);
+ mGroupRow.showFeedbackIcon(false, null);
}
@Test
@@ -224,12 +226,13 @@
mGroupRow.setChildrenContainer(mockContainer);
final boolean show = true;
- final int resId = 1;
- mGroupRow.showFeedbackIcon(show, resId);
+ final Pair<Integer, Integer> resIds = new Pair(R.drawable.ic_feedback_alerted,
+ R.string.notification_feedback_indicator_alerted);
+ mGroupRow.showFeedbackIcon(show, resIds);
- verify(mockContainer, times(1)).showFeedbackIcon(show, resId);
- verify(privateLayout, times(1)).showFeedbackIcon(show, resId);
- verify(publicLayout, times(1)).showFeedbackIcon(show, resId);
+ verify(mockContainer, times(1)).showFeedbackIcon(show, resIds);
+ verify(privateLayout, times(1)).showFeedbackIcon(show, resIds);
+ verify(publicLayout, times(1)).showFeedbackIcon(show, resIds);
}
@Test
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 377a69d..4183508 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
@@ -25,6 +25,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.util.Pair;
import android.view.NotificationHeaderView;
import android.view.View;
import android.view.ViewPropertyAnimator;
@@ -33,6 +34,7 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.internal.R;
import com.android.internal.widget.NotificationExpandButton;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.media.dialog.MediaOutputDialogFactory;
@@ -95,7 +97,8 @@
mView.setExpandedChild(mockExpanded);
mView.setHeadsUpChild(mockHeadsUp);
- mView.showFeedbackIcon(true, 1);
+ mView.showFeedbackIcon(true, new Pair(R.drawable.ic_feedback_alerted,
+ R.string.notification_feedback_indicator_alerted));
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/NotificationMenuRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java
index c426c87..e3516f97 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java
@@ -14,8 +14,9 @@
package com.android.systemui.statusbar.notification.row;
-import static android.provider.Settings.Secure.SHOW_NOTIFICATION_SNOOZE;
import static android.provider.Settings.Global.SHOW_NEW_NOTIF_DISMISS;
+import static android.provider.Settings.Secure.SHOW_NOTIFICATION_SNOOZE;
+import static android.view.HapticFeedbackConstants.CLOCK_TICK;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
@@ -33,6 +34,7 @@
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
import android.testing.ViewUtils;
+import android.view.View;
import android.view.ViewGroup;
import androidx.test.filters.SmallTest;
@@ -54,12 +56,14 @@
public class NotificationMenuRowTest extends LeakCheckedTest {
private ExpandableNotificationRow mRow;
+ private View mView;
private PeopleNotificationIdentifier mPeopleNotificationIdentifier;
@Before
public void setup() {
injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
mRow = mock(ExpandableNotificationRow.class);
+ mView = mock(View.class);
mPeopleNotificationIdentifier = mock(PeopleNotificationIdentifier.class);
NotificationEntry entry = new NotificationEntryBuilder().build();
when(mRow.getEntry()).thenReturn(entry);
@@ -409,4 +413,61 @@
row.setMenuAlpha(0.5f);
assertTrue("when alpha is .5, menu is visible", row.isMenuVisible());
}
+
+ @Test
+ public void testOnTouchMove() {
+ NotificationMenuRow row = Mockito.spy(
+ new NotificationMenuRow(mContext, mPeopleNotificationIdentifier));
+ row.createMenu(mRow, null);
+ doReturn(50f).when(row).getDismissThreshold();
+ doReturn(true).when(row).canBeDismissed();
+ doReturn(mView).when(row).getMenuView();
+ row.onTouchMove(30f);
+
+ assertFalse("When moving not farther than threshold, menu is not snapping to dismiss",
+ row.isSnappingToDismiss());
+ verify(mView, times(0)).performHapticFeedback(CLOCK_TICK);
+
+ row.onTouchMove(60f);
+
+ assertTrue("When moving farther than threshold, menu is snapping to dismiss",
+ row.isSnappingToDismiss());
+ verify(mView, times(1)).performHapticFeedback(CLOCK_TICK);
+
+ row.onTouchMove(70f);
+
+ assertTrue("When moving farther than threshold, menu is snapping to dismiss",
+ row.isSnappingToDismiss());
+ verify(mView, times(1)).performHapticFeedback(CLOCK_TICK);
+
+ row.onTouchMove(30f);
+
+ assertFalse("When moving not farther than threshold, menu is not snapping to dismiss",
+ row.isSnappingToDismiss());
+ verify(mView, times(2)).performHapticFeedback(CLOCK_TICK);
+
+ row.onTouchMove(-30f);
+
+ assertFalse("When moving not farther than threshold, menu is not snapping to dismiss",
+ row.isSnappingToDismiss());
+ verify(mView, times(2)).performHapticFeedback(CLOCK_TICK);
+
+ row.onTouchMove(-60f);
+
+ assertTrue("When moving farther than threshold, menu is snapping to dismiss",
+ row.isSnappingToDismiss());
+ verify(mView, times(3)).performHapticFeedback(CLOCK_TICK);
+
+ row.onTouchMove(-70f);
+
+ assertTrue("When moving farther than threshold, menu is snapping to dismiss",
+ row.isSnappingToDismiss());
+ verify(mView, times(3)).performHapticFeedback(CLOCK_TICK);
+
+ row.onTouchMove(-30f);
+
+ assertFalse("When moving not farther than threshold, menu is not snapping to dismiss",
+ row.isSnappingToDismiss());
+ verify(mView, times(4)).performHapticFeedback(CLOCK_TICK);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LockscreenIconControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LockscreenIconControllerTest.java
index 1ac7937..95a3505 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LockscreenIconControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LockscreenIconControllerTest.java
@@ -91,6 +91,7 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
+ when(mKeyguardUpdateMonitor.shouldShowLockIcon()).thenReturn(true);
when(mLockIcon.getContext()).thenReturn(mContext);
mLockIconController = new LockscreenLockIconController(
mLockscreenGestureLogger, mKeyguardUpdateMonitor, mLockPatternUtils,
@@ -145,12 +146,10 @@
}
@Test
- public void testVisibility_noBouncer() {
- // no security (ie: no lock screen OR swipe to unlock)
- when(mKeyguardSecurityModel.getSecurityMode(anyInt())).thenReturn(
- KeyguardSecurityModel.SecurityMode.None);
+ public void testVisibility_doNotShowLockIcon() {
+ when(mKeyguardUpdateMonitor.shouldShowLockIcon()).thenReturn(false);
mOnAttachStateChangeListener.onViewAttachedToWindow(mLockIcon);
- verify(mLockIcon).updateIconVisibility(false);
+ verify(mLockIcon).setVisibility(View.GONE);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
index c826cbc..d33fac0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
@@ -107,7 +107,7 @@
eq(UserHandle.USER_ALL));
verify(mDumpManager).registerDumpable(any(), any());
- List<Integer> colorList = List.of(Color.RED, Color.BLUE, 0x0CCCCC, 0x000111);
+ List<Integer> colorList = List.of(Color.RED, Color.BLUE, 0x0CCCCC, 0x000CCC);
when(mThemeOverlayApplier.getAvailableAccentColors()).thenReturn(colorList);
when(mThemeOverlayApplier.getAvailableSystemColors()).thenReturn(colorList);
}
@@ -136,11 +136,9 @@
// Assert that we received the colors that we were expecting
assertThat(themeOverlays.getValue().get(OVERLAY_CATEGORY_SYSTEM_PALETTE))
- .isEqualTo(MONET_SYSTEM_PALETTE_PACKAGE
- + Integer.toHexString(Color.RED).toUpperCase());
+ .isEqualTo(MONET_SYSTEM_PALETTE_PACKAGE + "FF0000");
assertThat(themeOverlays.getValue().get(OVERLAY_CATEGORY_ACCENT_COLOR))
- .isEqualTo(MONET_ACCENT_COLOR_PACKAGE
- + Integer.toHexString(Color.BLUE).toUpperCase());
+ .isEqualTo(MONET_ACCENT_COLOR_PACKAGE + "0000FF");
// Should not ask again if changed to same value
mColorsListener.getValue().onColorsChanged(mainColors, WallpaperManager.FLAG_SYSTEM);
@@ -148,10 +146,36 @@
}
@Test
+ public void onWallpaperColorsChanged_whiteTheme() {
+ WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.WHITE),
+ Color.valueOf(Color.BLUE), null);
+ mColorsListener.getValue().onColorsChanged(mainColors, WallpaperManager.FLAG_SYSTEM);
+ ArgumentCaptor<Map<String, String>> themeOverlays = ArgumentCaptor.forClass(Map.class);
+
+ verify(mThemeOverlayApplier).applyCurrentUserOverlays(themeOverlays.capture(), any());
+
+ // Assert that we received the colors that we were expecting
+ assertThat(themeOverlays.getValue().containsKey(OVERLAY_CATEGORY_SYSTEM_PALETTE)).isFalse();
+ }
+
+ @Test
+ public void onWallpaperColorsChanged_blackTheme() {
+ WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.BLACK),
+ Color.valueOf(Color.BLUE), null);
+ mColorsListener.getValue().onColorsChanged(mainColors, WallpaperManager.FLAG_SYSTEM);
+ ArgumentCaptor<Map<String, String>> themeOverlays = ArgumentCaptor.forClass(Map.class);
+
+ verify(mThemeOverlayApplier).applyCurrentUserOverlays(themeOverlays.capture(), any());
+
+ // Assert that we received the colors that we were expecting
+ assertThat(themeOverlays.getValue().containsKey(OVERLAY_CATEGORY_SYSTEM_PALETTE)).isFalse();
+ }
+
+ @Test
public void onWallpaperColorsChanged_addsLeadingZerosToColors() {
// Should ask for a new theme when wallpaper colors change
WallpaperColors mainColors = new WallpaperColors(Color.valueOf(0x0CCCCC),
- Color.valueOf(0x000111), null);
+ Color.valueOf(0x000CCC), null);
mColorsListener.getValue().onColorsChanged(mainColors, WallpaperManager.FLAG_SYSTEM);
ArgumentCaptor<Map<String, String>> themeOverlays = ArgumentCaptor.forClass(Map.class);
@@ -161,7 +185,7 @@
assertThat(themeOverlays.getValue().get(OVERLAY_CATEGORY_SYSTEM_PALETTE))
.isEqualTo(MONET_SYSTEM_PALETTE_PACKAGE + "0CCCCC");
assertThat(themeOverlays.getValue().get(OVERLAY_CATEGORY_ACCENT_COLOR))
- .isEqualTo(MONET_ACCENT_COLOR_PACKAGE + "000111");
+ .isEqualTo(MONET_ACCENT_COLOR_PACKAGE + "000CCC");
}
@Test
diff --git a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
index 52a82dd..5ee30fb7 100644
--- a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
+++ b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
@@ -51,7 +51,6 @@
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.nio.charset.StandardCharsets;
public class WallpaperBackupAgent extends BackupAgent {
private static final String TAG = "WallpaperBackup";
@@ -323,8 +322,7 @@
private Rect parseCropHint(File wallpaperInfo, String sectionTag) {
Rect cropHint = new Rect();
try (FileInputStream stream = new FileInputStream(wallpaperInfo)) {
- XmlPullParser parser = Xml.newPullParser();
- parser.setInput(stream, StandardCharsets.UTF_8.name());
+ XmlPullParser parser = Xml.resolvePullParser(stream);
int type;
do {
@@ -351,8 +349,7 @@
private ComponentName parseWallpaperComponent(File wallpaperInfo, String sectionTag) {
ComponentName name = null;
try (FileInputStream stream = new FileInputStream(wallpaperInfo)) {
- final XmlPullParser parser = Xml.newPullParser();
- parser.setInput(stream, StandardCharsets.UTF_8.name());
+ final XmlPullParser parser = Xml.resolvePullParser(stream);
int type;
do {
diff --git a/packages/overlays/NavigationBarModeGesturalOverlay/res/values/config.xml b/packages/overlays/NavigationBarModeGesturalOverlay/res/values/config.xml
index 06cb33b..cd53227 100644
--- a/packages/overlays/NavigationBarModeGesturalOverlay/res/values/config.xml
+++ b/packages/overlays/NavigationBarModeGesturalOverlay/res/values/config.xml
@@ -54,4 +54,6 @@
show. -->
<bool name="config_navBarAlwaysShowOnSideEdgeGesture">true</bool>
+ <!-- If true, attach the navigation bar to the app during app transition -->
+ <bool name="config_attachNavBarToAppDuringTransition">true</bool>
</resources>
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/config.xml b/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/config.xml
index d5991f3..88cb74d 100644
--- a/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/config.xml
+++ b/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/config.xml
@@ -54,4 +54,6 @@
show. -->
<bool name="config_navBarAlwaysShowOnSideEdgeGesture">true</bool>
+ <!-- If true, attach the navigation bar to the app during app transition -->
+ <bool name="config_attachNavBarToAppDuringTransition">true</bool>
</resources>
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/config.xml b/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/config.xml
index ff507ee..70c41d0 100644
--- a/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/config.xml
+++ b/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/config.xml
@@ -54,4 +54,6 @@
show. -->
<bool name="config_navBarAlwaysShowOnSideEdgeGesture">true</bool>
+ <!-- If true, attach the navigation bar to the app during app transition -->
+ <bool name="config_attachNavBarToAppDuringTransition">true</bool>
</resources>
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/config.xml b/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/config.xml
index 378756a..de26394 100644
--- a/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/config.xml
+++ b/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/config.xml
@@ -54,4 +54,6 @@
show. -->
<bool name="config_navBarAlwaysShowOnSideEdgeGesture">true</bool>
+ <!-- If true, attach the navigation bar to the app during app transition -->
+ <bool name="config_attachNavBarToAppDuringTransition">true</bool>
</resources>
diff --git a/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java b/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java
index bafb641..a2c7e4f 100644
--- a/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java
+++ b/services/accessibility/java/com/android/server/accessibility/ActionReplacingCallback.java
@@ -40,10 +40,14 @@
private final IAccessibilityInteractionConnectionCallback mServiceCallback;
private final IAccessibilityInteractionConnection mConnectionWithReplacementActions;
private final int mInteractionId;
+ private final int mNodeWithReplacementActionsInteractionId;
private final Object mLock = new Object();
@GuardedBy("mLock")
- List<AccessibilityNodeInfo> mNodesWithReplacementActions;
+ private boolean mRequestForNodeWithReplacementActionFailed;
+
+ @GuardedBy("mLock")
+ AccessibilityNodeInfo mNodeWithReplacementActions;
@GuardedBy("mLock")
List<AccessibilityNodeInfo> mNodesFromOriginalWindow;
@@ -51,18 +55,8 @@
@GuardedBy("mLock")
AccessibilityNodeInfo mNodeFromOriginalWindow;
- // Keep track of whether or not we've been called back for a single node
@GuardedBy("mLock")
- boolean mSingleNodeCallbackHappened;
-
- // Keep track of whether or not we've been called back for multiple node
- @GuardedBy("mLock")
- boolean mMultiNodeCallbackHappened;
-
- // We shouldn't get any more callbacks after we've called back the original service, but
- // keep track to make sure we catch such strange things
- @GuardedBy("mLock")
- boolean mDone;
+ List<AccessibilityNodeInfo> mPrefetchedNodesFromOriginalWindow;
public ActionReplacingCallback(IAccessibilityInteractionConnectionCallback serviceCallback,
IAccessibilityInteractionConnection connectionWithReplacementActions,
@@ -70,19 +64,20 @@
mServiceCallback = serviceCallback;
mConnectionWithReplacementActions = connectionWithReplacementActions;
mInteractionId = interactionId;
+ mNodeWithReplacementActionsInteractionId = interactionId + 1;
// Request the root node of the replacing window
final long identityToken = Binder.clearCallingIdentity();
try {
mConnectionWithReplacementActions.findAccessibilityNodeInfoByAccessibilityId(
- AccessibilityNodeInfo.ROOT_NODE_ID, null, interactionId + 1, this, 0,
+ AccessibilityNodeInfo.ROOT_NODE_ID, null,
+ mNodeWithReplacementActionsInteractionId, this, 0,
interrogatingPid, interrogatingTid, null, null);
} catch (RemoteException re) {
if (DEBUG) {
Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()");
}
- // Pretend we already got a (null) list of replacement nodes
- mMultiNodeCallbackHappened = true;
+ mRequestForNodeWithReplacementActionFailed = true;
} finally {
Binder.restoreCallingIdentity(identityToken);
}
@@ -90,46 +85,73 @@
@Override
public void setFindAccessibilityNodeInfoResult(AccessibilityNodeInfo info, int interactionId) {
- boolean readyForCallback;
- synchronized(mLock) {
+ synchronized (mLock) {
if (interactionId == mInteractionId) {
mNodeFromOriginalWindow = info;
+ } else if (interactionId == mNodeWithReplacementActionsInteractionId) {
+ mNodeWithReplacementActions = info;
} else {
Slog.e(LOG_TAG, "Callback with unexpected interactionId");
return;
}
-
- mSingleNodeCallbackHappened = true;
- readyForCallback = mMultiNodeCallbackHappened;
}
- if (readyForCallback) {
- replaceInfoActionsAndCallService();
- }
+ replaceInfoActionsAndCallServiceIfReady();
}
@Override
public void setFindAccessibilityNodeInfosResult(List<AccessibilityNodeInfo> infos,
int interactionId) {
- boolean callbackForSingleNode;
- boolean callbackForMultipleNodes;
- synchronized(mLock) {
+ synchronized (mLock) {
if (interactionId == mInteractionId) {
mNodesFromOriginalWindow = infos;
- } else if (interactionId == mInteractionId + 1) {
- mNodesWithReplacementActions = infos;
+ } else if (interactionId == mNodeWithReplacementActionsInteractionId) {
+ setNodeWithReplacementActionsFromList(infos);
} else {
Slog.e(LOG_TAG, "Callback with unexpected interactionId");
return;
}
- callbackForSingleNode = mSingleNodeCallbackHappened;
- callbackForMultipleNodes = mMultiNodeCallbackHappened;
- mMultiNodeCallbackHappened = true;
}
- if (callbackForSingleNode) {
+ replaceInfoActionsAndCallServiceIfReady();
+ }
+
+ @Override
+ public void setPrefetchAccessibilityNodeInfoResult(List<AccessibilityNodeInfo> infos,
+ int interactionId)
+ throws RemoteException {
+ synchronized (mLock) {
+ if (interactionId == mInteractionId) {
+ mPrefetchedNodesFromOriginalWindow = infos;
+ } else {
+ Slog.e(LOG_TAG, "Callback with unexpected interactionId");
+ return;
+ }
+ }
+ replaceInfoActionsAndCallServiceIfReady();
+ }
+
+ private void replaceInfoActionsAndCallServiceIfReady() {
+ boolean originalAndReplacementCallsHaveHappened = false;
+ synchronized (mLock) {
+ originalAndReplacementCallsHaveHappened = mNodeWithReplacementActions != null
+ && (mNodeFromOriginalWindow != null
+ || mNodesFromOriginalWindow != null
+ || mPrefetchedNodesFromOriginalWindow != null);
+ originalAndReplacementCallsHaveHappened
+ |= mRequestForNodeWithReplacementActionFailed;
+ }
+ if (originalAndReplacementCallsHaveHappened) {
replaceInfoActionsAndCallService();
- }
- if (callbackForMultipleNodes) {
replaceInfosActionsAndCallService();
+ replacePrefetchInfosActionsAndCallService();
+ }
+ }
+
+ private void setNodeWithReplacementActionsFromList(List<AccessibilityNodeInfo> infos) {
+ for (int i = 0; i < infos.size(); i++) {
+ AccessibilityNodeInfo info = infos.get(i);
+ if (info.getSourceNodeId() == AccessibilityNodeInfo.ROOT_NODE_ID) {
+ mNodeWithReplacementActions = info;
+ }
}
}
@@ -143,18 +165,10 @@
private void replaceInfoActionsAndCallService() {
final AccessibilityNodeInfo nodeToReturn;
synchronized (mLock) {
- if (mDone) {
- if (DEBUG) {
- Slog.e(LOG_TAG, "Extra callback");
- }
- return;
- }
if (mNodeFromOriginalWindow != null) {
replaceActionsOnInfoLocked(mNodeFromOriginalWindow);
}
- recycleReplaceActionNodesLocked();
nodeToReturn = mNodeFromOriginalWindow;
- mDone = true;
}
try {
mServiceCallback.setFindAccessibilityNodeInfoResult(nodeToReturn, mInteractionId);
@@ -168,21 +182,7 @@
private void replaceInfosActionsAndCallService() {
final List<AccessibilityNodeInfo> nodesToReturn;
synchronized (mLock) {
- if (mDone) {
- if (DEBUG) {
- Slog.e(LOG_TAG, "Extra callback");
- }
- return;
- }
- if (mNodesFromOriginalWindow != null) {
- for (int i = 0; i < mNodesFromOriginalWindow.size(); i++) {
- replaceActionsOnInfoLocked(mNodesFromOriginalWindow.get(i));
- }
- }
- recycleReplaceActionNodesLocked();
- nodesToReturn = (mNodesFromOriginalWindow == null)
- ? null : new ArrayList<>(mNodesFromOriginalWindow);
- mDone = true;
+ nodesToReturn = replaceActionsLocked(mNodesFromOriginalWindow);
}
try {
mServiceCallback.setFindAccessibilityNodeInfosResult(nodesToReturn, mInteractionId);
@@ -193,6 +193,31 @@
}
}
+ private void replacePrefetchInfosActionsAndCallService() {
+ final List<AccessibilityNodeInfo> nodesToReturn;
+ synchronized (mLock) {
+ nodesToReturn = replaceActionsLocked(mPrefetchedNodesFromOriginalWindow);
+ }
+ try {
+ mServiceCallback.setPrefetchAccessibilityNodeInfoResult(nodesToReturn, mInteractionId);
+ } catch (RemoteException re) {
+ if (DEBUG) {
+ Slog.e(LOG_TAG, "Failed to setFindAccessibilityNodeInfosResult");
+ }
+ }
+ }
+
+ @GuardedBy("mLock")
+ private List<AccessibilityNodeInfo> replaceActionsLocked(List<AccessibilityNodeInfo> infos) {
+ if (infos != null) {
+ for (int i = 0; i < infos.size(); i++) {
+ replaceActionsOnInfoLocked(infos.get(i));
+ }
+ }
+ return (infos == null)
+ ? null : new ArrayList<>(infos);
+ }
+
@GuardedBy("mLock")
private void replaceActionsOnInfoLocked(AccessibilityNodeInfo info) {
info.removeAllActions();
@@ -204,40 +229,22 @@
info.setDismissable(false);
// We currently only replace actions for the root node
if ((info.getSourceNodeId() == AccessibilityNodeInfo.ROOT_NODE_ID)
- && mNodesWithReplacementActions != null) {
- // This list should always contain a single node with the root ID
- for (int i = 0; i < mNodesWithReplacementActions.size(); i++) {
- AccessibilityNodeInfo nodeWithReplacementActions =
- mNodesWithReplacementActions.get(i);
- if (nodeWithReplacementActions.getSourceNodeId()
- == AccessibilityNodeInfo.ROOT_NODE_ID) {
- List<AccessibilityAction> actions = nodeWithReplacementActions.getActionList();
- if (actions != null) {
- for (int j = 0; j < actions.size(); j++) {
- info.addAction(actions.get(j));
- }
- // The PIP needs to be able to take accessibility focus
- info.addAction(AccessibilityAction.ACTION_ACCESSIBILITY_FOCUS);
- info.addAction(AccessibilityAction.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
- }
- info.setClickable(nodeWithReplacementActions.isClickable());
- info.setFocusable(nodeWithReplacementActions.isFocusable());
- info.setContextClickable(nodeWithReplacementActions.isContextClickable());
- info.setScrollable(nodeWithReplacementActions.isScrollable());
- info.setLongClickable(nodeWithReplacementActions.isLongClickable());
- info.setDismissable(nodeWithReplacementActions.isDismissable());
+ && mNodeWithReplacementActions != null) {
+ List<AccessibilityAction> actions = mNodeWithReplacementActions.getActionList();
+ if (actions != null) {
+ for (int j = 0; j < actions.size(); j++) {
+ info.addAction(actions.get(j));
}
+ // The PIP needs to be able to take accessibility focus
+ info.addAction(AccessibilityAction.ACTION_ACCESSIBILITY_FOCUS);
+ info.addAction(AccessibilityAction.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
}
+ info.setClickable(mNodeWithReplacementActions.isClickable());
+ info.setFocusable(mNodeWithReplacementActions.isFocusable());
+ info.setContextClickable(mNodeWithReplacementActions.isContextClickable());
+ info.setScrollable(mNodeWithReplacementActions.isScrollable());
+ info.setLongClickable(mNodeWithReplacementActions.isLongClickable());
+ info.setDismissable(mNodeWithReplacementActions.isDismissable());
}
}
-
- @GuardedBy("mLock")
- private void recycleReplaceActionNodesLocked() {
- if (mNodesWithReplacementActions == null) return;
- for (int i = mNodesWithReplacementActions.size() - 1; i >= 0; i--) {
- AccessibilityNodeInfo nodeWithReplacementAction = mNodesWithReplacementActions.get(i);
- nodeWithReplacementAction.recycle();
- }
- mNodesWithReplacementActions = null;
- }
}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index c7fd209..9d8901a 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -422,15 +422,12 @@
@GuardedBy("mLock")
private FillRequest mPendingFillRequest;
- void newAutofillRequestLocked(boolean isInlineRequest) {
+ @Nullable Consumer<InlineSuggestionsRequest> newAutofillRequestLocked(ViewState viewState,
+ boolean isInlineRequest) {
mPendingFillRequest = null;
mWaitForInlineRequest = isInlineRequest;
mPendingInlineSuggestionsRequest = null;
- }
-
- @NonNull Consumer<InlineSuggestionsRequest> newInlineRequestConsumerLocked(
- ViewState viewState) {
- return (inlineSuggestionsRequest) -> {
+ return isInlineRequest ? (inlineSuggestionsRequest) -> {
synchronized (mLock) {
if (!mWaitForInlineRequest || mPendingInlineSuggestionsRequest != null) {
return;
@@ -439,7 +436,7 @@
maybeRequestFillLocked();
viewState.resetState(ViewState.STATE_PENDING_CREATE_INLINE_REQUEST);
}
- };
+ } : null;
}
void maybeRequestFillLocked() {
@@ -811,12 +808,32 @@
// structure is taken. This causes only one fill request per burst of focus changes.
cancelCurrentRequestLocked();
- final Consumer<InlineSuggestionsRequest> inlineSuggestionsRequestConsumer =
- mAssistReceiver.newInlineRequestConsumerLocked(viewState);
- final boolean isInlineRequest = maybeRequestCreateInlineSuggestionsRequestLocked(
- /* isAugmented= */ false, inlineSuggestionsRequestConsumer, viewState,
- mCurrentViewId, flags);
- mAssistReceiver.newAutofillRequestLocked(isInlineRequest);
+ // 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);
+ }
// Now request the assist structure data.
try {
@@ -836,60 +853,6 @@
}
}
- @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,
@@ -2607,27 +2570,23 @@
}
/**
- * Invokes either regular or augmented autofill process upon entering a view.
+ * Starts (if necessary) a new fill request upon entering a view.
*
- * <p> A new standard autofill request will be started in 2 scenarios:
+ * <p>A new 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 either regular or augmented autofill is invoked.
+ * @return {@code true} if a new fill response is requested.
*/
@GuardedBy("mLock")
- private boolean maybeRequestFillOnViewEnteredLocked(@NonNull AutofillId id,
- @NonNull ViewState viewState, boolean isSameViewEntered, int flags) {
+ private boolean requestNewFillResponseOnViewEnteredIfNecessaryLocked(@NonNull AutofillId id,
+ @NonNull ViewState viewState, 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);
@@ -2635,24 +2594,7 @@
return true;
}
- 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 it's not, then check if it it should start a partition.
if (shouldStartNewPartitionLocked(id)) {
if (sDebug) {
Slog.d(TAG, "Starting partition or augmented request for view id " + id + ": "
@@ -2847,7 +2789,27 @@
return;
}
- if (maybeRequestFillOnViewEnteredLocked(id, viewState, isSameViewEntered, flags)) {
+ 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)) {
return;
}
@@ -3445,12 +3407,34 @@
}
};
- if (!maybeRequestCreateInlineSuggestionsRequestLocked(/* isAugmented= */ true,
- requestAugmentedAutofill, viewState, focusedId, flags)) {
+ // 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 {
requestAugmentedAutofill.accept(
mInlineSessionController.getInlineSuggestionsRequestLocked().orElse(null));
}
-
if (mAugmentedAutofillDestroyer == null) {
mAugmentedAutofillDestroyer = remoteService::onDestroyAutofillWindowsRequest;
}
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index e6e52de..70b2672 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -18,6 +18,7 @@
package com.android.server.companion;
import static com.android.internal.util.CollectionUtils.emptyIfNull;
+import static com.android.internal.util.CollectionUtils.find;
import static com.android.internal.util.CollectionUtils.forEach;
import static com.android.internal.util.FunctionalUtils.uncheckExceptions;
import static com.android.internal.util.Preconditions.checkArgument;
@@ -131,9 +132,6 @@
CompanionDeviceManager.COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME,
".DeviceDiscoveryService");
- // 10 min
- public static final int DEVICE_DISCONNECT_PROFILE_REVOKE_DELAY_MS = 10 * 60 * 1000;
-
private static final boolean DEBUG = false;
private static final String LOG_TAG = "CompanionDeviceManagerService";
@@ -593,12 +591,50 @@
void removeAssociation(int userId, String pkg, String deviceMacAddress) {
updateAssociations(associations -> CollectionUtils.filter(associations, association -> {
- return association.getUserId() != userId
+ boolean notMatch = association.getUserId() != userId
|| !Objects.equals(association.getDeviceMacAddress(), deviceMacAddress)
|| !Objects.equals(association.getPackageName(), pkg);
+ if (!notMatch) {
+ onAssociationPreRemove(association);
+ }
+ return notMatch;
}));
}
+ void onAssociationPreRemove(Association association) {
+ String deviceProfile = association.getDeviceProfile();
+ if (deviceProfile != null) {
+ Association otherAssociationWithDeviceProfile = find(
+ getAllAssociations(association.getUserId()),
+ a -> !a.equals(association) && deviceProfile.equals(a.getDeviceProfile()));
+ if (otherAssociationWithDeviceProfile != null) {
+ Log.i(LOG_TAG, "Not revoking " + deviceProfile
+ + " for " + association
+ + " - profile still present in " + otherAssociationWithDeviceProfile);
+ } else {
+ long identity = Binder.clearCallingIdentity();
+ try {
+ mRoleManager.removeRoleHolderAsUser(
+ association.getDeviceProfile(),
+ association.getPackageName(),
+ RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP,
+ UserHandle.of(association.getUserId()),
+ getContext().getMainExecutor(),
+ success -> {
+ if (!success) {
+ Log.e(LOG_TAG, "Failed to revoke device profile role "
+ + association.getDeviceProfile()
+ + " to " + association.getPackageName()
+ + " for user " + association.getUserId());
+ }
+ });
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ }
+ }
+
private void updateSpecialAccessPermissionForAssociatedPackage(Association association) {
PackageInfo packageInfo = getPackageInfo(
association.getPackageName(),
@@ -636,6 +672,10 @@
}
exemptFromAutoRevoke(packageInfo.packageName, packageInfo.applicationInfo.uid);
+
+ if (mCurrentlyConnectedDevices.contains(association.getDeviceMacAddress())) {
+ grantDeviceProfile(association);
+ }
}
private void exemptFromAutoRevoke(String packageName, int uid) {
@@ -817,72 +857,39 @@
void onDeviceConnected(String address) {
mCurrentlyConnectedDevices.add(address);
- Handler.getMain().removeCallbacksAndMessages(getDisconnectJobHandlerId(address));
-
for (UserInfo user : getAllUsers()) {
for (Association association : getAllAssociations(user.id)) {
if (Objects.equals(address, association.getDeviceMacAddress())) {
if (association.getDeviceProfile() != null) {
Log.i(LOG_TAG, "Granting role " + association.getDeviceProfile()
+ " to " + association.getPackageName()
- + " due to device connected: " + address);
- mRoleManager.addRoleHolderAsUser(
- association.getDeviceProfile(),
- association.getPackageName(),
- RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP,
- UserHandle.of(association.getUserId()),
- getContext().getMainExecutor(),
- success -> {
- if (!success) {
- Log.e(LOG_TAG, "Failed to grant device profile role "
- + association.getDeviceProfile()
- + " to " + association.getPackageName()
- + " for user " + association.getUserId());
- }
- });
+ + " due to device connected: " + association.getDeviceMacAddress());
+ grantDeviceProfile(association);
}
}
}
}
}
- void onDeviceDisconnected(String address) {
- mCurrentlyConnectedDevices.remove(address);
-
- Handler.getMain().postDelayed(() -> {
- if (!mCurrentlyConnectedDevices.contains(address)) {
- for (UserInfo user : getAllUsers()) {
- for (Association association : getAllAssociations(user.id)) {
- if (association.getDeviceProfile() != null
- && Objects.equals(address, association.getDeviceMacAddress())
- && !association.isKeepProfilePrivilegesWhenDeviceAway()) {
- Log.i(LOG_TAG, "Revoking role " + association.getDeviceProfile()
- + " to " + association.getPackageName()
- + " due to device disconnected: " + address);
- mRoleManager.removeRoleHolderAsUser(
- association.getDeviceProfile(),
- association.getPackageName(),
- RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP,
- UserHandle.of(association.getUserId()),
- getContext().getMainExecutor(),
- success -> {
- if (!success) {
- Log.e(LOG_TAG, "Failed to revoke device profile role "
- + association.getDeviceProfile()
- + " to " + association.getPackageName()
- + " for user " + association.getUserId());
- }
- });
- }
+ private void grantDeviceProfile(Association association) {
+ mRoleManager.addRoleHolderAsUser(
+ association.getDeviceProfile(),
+ association.getPackageName(),
+ RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP,
+ UserHandle.of(association.getUserId()),
+ getContext().getMainExecutor(),
+ success -> {
+ if (!success) {
+ Log.e(LOG_TAG, "Failed to grant device profile role "
+ + association.getDeviceProfile()
+ + " to " + association.getPackageName()
+ + " for user " + association.getUserId());
}
- }
- }
- }, getDisconnectJobHandlerId(address), DEVICE_DISCONNECT_PROFILE_REVOKE_DELAY_MS);
+ });
}
- @NonNull
- private String getDisconnectJobHandlerId(String address) {
- return "CDM_onDisconnected_" + address;
+ void onDeviceDisconnected(String address) {
+ mCurrentlyConnectedDevices.remove(address);
}
private class ShellCmd extends ShellCommand {
@@ -898,34 +905,49 @@
@Override
public int onCommand(String cmd) {
- switch (cmd) {
- case "list": {
- forEach(
- getAllAssociations(getNextArgInt()),
- a -> getOutPrintWriter()
- .println(a.getPackageName() + " " + a.getDeviceMacAddress()));
- } break;
+ try {
+ switch (cmd) {
+ case "list": {
+ forEach(
+ getAllAssociations(getNextArgInt()),
+ a -> getOutPrintWriter()
+ .println(a.getPackageName() + " "
+ + a.getDeviceMacAddress()));
+ }
+ break;
- case "associate": {
- addAssociation(new Association(getNextArgInt(), getNextArgRequired(),
- getNextArgRequired(), null, false));
- } break;
+ case "associate": {
+ String pkg = getNextArgRequired();
+ String address = getNextArgRequired();
+ addAssociation(new Association(getNextArgInt(), address, pkg, null, false));
+ }
+ break;
- case "disassociate": {
- removeAssociation(getNextArgInt(), getNextArgRequired(), getNextArgRequired());
- } break;
+ case "disassociate": {
+ removeAssociation(getNextArgInt(), getNextArgRequired(),
+ getNextArgRequired());
+ }
+ break;
- case "simulate_connect": {
- onDeviceConnected(getNextArgRequired());
- } break;
+ case "simulate_connect": {
+ onDeviceConnected(getNextArgRequired());
+ }
+ break;
- case "simulate_disconnect": {
- onDeviceDisconnected(getNextArgRequired());
- } break;
+ case "simulate_disconnect": {
+ onDeviceDisconnected(getNextArgRequired());
+ }
+ break;
- default: return handleDefaultCommands(cmd);
+ default:
+ return handleDefaultCommands(cmd);
+ }
+ return 0;
+ } catch (Throwable t) {
+ Log.e(LOG_TAG, "Error running a command: $ " + cmd, t);
+ getErrPrintWriter().println(Log.getStackTraceString(t));
+ return 1;
}
- return 0;
}
private int getNextArgInt() {
diff --git a/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java b/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java
index 86ea1e4..00c91fe 100644
--- a/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java
+++ b/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java
@@ -21,7 +21,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.ActivityManager;
import android.app.contentsuggestions.ClassificationsRequest;
import android.app.contentsuggestions.ContentSuggestionsManager;
import android.app.contentsuggestions.IClassificationsCallback;
@@ -40,6 +39,7 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Slog;
+import android.window.TaskSnapshot;
import com.android.internal.os.IResultReceiver;
import com.android.server.LocalServices;
@@ -162,7 +162,7 @@
// Skip taking TaskSnapshot when bitmap is provided.
if (!imageContextRequestExtras.containsKey(ContentSuggestionsManager.EXTRA_BITMAP)) {
// Can block, so call before acquiring the lock.
- ActivityManager.TaskSnapshot snapshot =
+ TaskSnapshot snapshot =
mActivityTaskManagerInternal.getTaskSnapshotBlocking(taskId, false);
if (snapshot != null) {
snapshotBuffer = snapshot.getHardwareBuffer();
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 55c1e08..2e1fbb7 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -144,6 +144,7 @@
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
+import android.os.INetworkActivityListener;
import android.os.INetworkManagementService;
import android.os.Looper;
import android.os.Message;
@@ -876,6 +877,10 @@
*/
@VisibleForTesting
public static class Dependencies {
+ public int getCallingUid() {
+ return Binder.getCallingUid();
+ }
+
/**
* Get system properties to use in ConnectivityService.
*/
@@ -1376,8 +1381,11 @@
return;
}
final String action = blocked ? "BLOCKED" : "UNBLOCKED";
+ final NetworkRequest satisfiedRequest = nri.getSatisfiedRequest();
+ final int requestId = satisfiedRequest != null
+ ? satisfiedRequest.requestId : nri.mRequests.get(0).requestId;
mNetworkInfoBlockingLogs.log(String.format(
- "%s %d(%d) on netId %d", action, nri.mUid, nri.request.requestId, net.getNetId()));
+ "%s %d(%d) on netId %d", action, nri.mUid, requestId, net.getNetId()));
}
/**
@@ -1408,7 +1416,7 @@
@Override
public NetworkInfo getActiveNetworkInfo() {
enforceAccessPermission();
- final int uid = Binder.getCallingUid();
+ final int uid = mDeps.getCallingUid();
final NetworkState state = getUnfilteredActiveNetworkState(uid);
filterNetworkStateForUid(state, uid, false);
maybeLogBlockedNetworkInfo(state.networkInfo, uid);
@@ -1418,7 +1426,7 @@
@Override
public Network getActiveNetwork() {
enforceAccessPermission();
- return getActiveNetworkForUidInternal(Binder.getCallingUid(), false);
+ return getActiveNetworkForUidInternal(mDeps.getCallingUid(), false);
}
@Override
@@ -1458,7 +1466,7 @@
// Public because it's used by mLockdownTracker.
public NetworkInfo getActiveNetworkInfoUnfiltered() {
enforceAccessPermission();
- final int uid = Binder.getCallingUid();
+ final int uid = mDeps.getCallingUid();
NetworkState state = getUnfilteredActiveNetworkState(uid);
return state.networkInfo;
}
@@ -1474,7 +1482,7 @@
@Override
public NetworkInfo getNetworkInfo(int networkType) {
enforceAccessPermission();
- final int uid = Binder.getCallingUid();
+ final int uid = mDeps.getCallingUid();
if (getVpnUnderlyingNetworks(uid) != null) {
// A VPN is active, so we may need to return one of its underlying networks. This
// information is not available in LegacyTypeTracker, so we have to get it from
@@ -1519,7 +1527,7 @@
@Override
public Network getNetworkForType(int networkType) {
enforceAccessPermission();
- final int uid = Binder.getCallingUid();
+ final int uid = mDeps.getCallingUid();
NetworkState state = getFilteredNetworkState(networkType, uid);
if (!isNetworkWithLinkPropertiesBlocked(state.linkProperties, uid, false)) {
return state.network;
@@ -1566,7 +1574,7 @@
result.put(
nai.network,
maybeSanitizeLocationInfoForCaller(
- nc, Binder.getCallingUid(), callingPackageName));
+ nc, mDeps.getCallingUid(), callingPackageName));
}
synchronized (mVpns) {
@@ -1581,7 +1589,7 @@
result.put(
network,
maybeSanitizeLocationInfoForCaller(
- nc, Binder.getCallingUid(), callingPackageName));
+ nc, mDeps.getCallingUid(), callingPackageName));
}
}
}
@@ -1611,7 +1619,7 @@
@Override
public LinkProperties getActiveLinkProperties() {
enforceAccessPermission();
- final int uid = Binder.getCallingUid();
+ final int uid = mDeps.getCallingUid();
NetworkState state = getUnfilteredActiveNetworkState(uid);
if (state.linkProperties == null) return null;
return linkPropertiesRestrictedForCallerPermissions(state.linkProperties,
@@ -1625,7 +1633,7 @@
final LinkProperties lp = getLinkProperties(nai);
if (lp == null) return null;
return linkPropertiesRestrictedForCallerPermissions(
- lp, Binder.getCallingPid(), Binder.getCallingUid());
+ lp, Binder.getCallingPid(), mDeps.getCallingUid());
}
// TODO - this should be ALL networks
@@ -1635,7 +1643,7 @@
final LinkProperties lp = getLinkProperties(getNetworkAgentInfoForNetwork(network));
if (lp == null) return null;
return linkPropertiesRestrictedForCallerPermissions(
- lp, Binder.getCallingPid(), Binder.getCallingUid());
+ lp, Binder.getCallingPid(), mDeps.getCallingUid());
}
@Nullable
@@ -1657,17 +1665,17 @@
synchronized (nai) {
if (nai.networkCapabilities == null) return null;
return networkCapabilitiesRestrictedForCallerPermissions(
- nai.networkCapabilities, Binder.getCallingPid(), Binder.getCallingUid());
+ nai.networkCapabilities, Binder.getCallingPid(), mDeps.getCallingUid());
}
}
@Override
public NetworkCapabilities getNetworkCapabilities(Network network, String callingPackageName) {
- mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackageName);
+ mAppOpsManager.checkPackage(mDeps.getCallingUid(), callingPackageName);
enforceAccessPermission();
return maybeSanitizeLocationInfoForCaller(
getNetworkCapabilitiesInternal(network),
- Binder.getCallingUid(), callingPackageName);
+ mDeps.getCallingUid(), callingPackageName);
}
@VisibleForTesting
@@ -1705,16 +1713,17 @@
return newNc;
}
- Binder.withCleanCallingIdentity(
- () -> {
- if (!mLocationPermissionChecker.checkLocationPermission(
- callerPkgName, null /* featureId */, callerUid, null /* message */)) {
- // Caller does not have the requisite location permissions. Reset the
- // owner's UID in the NetworkCapabilities.
- newNc.setOwnerUid(INVALID_UID);
- }
- }
- );
+ final long token = Binder.clearCallingIdentity();
+ try {
+ if (!mLocationPermissionChecker.checkLocationPermission(
+ callerPkgName, null /* featureId */, callerUid, null /* message */)) {
+ // Caller does not have the requisite location permissions. Reset the
+ // owner's UID in the NetworkCapabilities.
+ newNc.setOwnerUid(INVALID_UID);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
return newNc;
}
@@ -1755,7 +1764,7 @@
}
private void restrictBackgroundRequestForCaller(NetworkCapabilities nc) {
- if (!mPermissionMonitor.hasUseBackgroundNetworksPermission(Binder.getCallingUid())) {
+ if (!mPermissionMonitor.hasUseBackgroundNetworksPermission(mDeps.getCallingUid())) {
nc.addCapability(NET_CAPABILITY_FOREGROUND);
}
}
@@ -1808,7 +1817,7 @@
// requestRouteToHost. In Q, GnssLocationProvider is changed to not call requestRouteToHost
// for devices launched with Q and above. However, existing devices upgrading to Q and
// above must continued to be supported for few more releases.
- if (isSystem(Binder.getCallingUid()) && SystemProperties.getInt(
+ if (isSystem(mDeps.getCallingUid()) && SystemProperties.getInt(
"ro.product.first_api_level", 0) > Build.VERSION_CODES.P) {
log("This method exists only for app backwards compatibility"
+ " and must not be called by system services.");
@@ -1874,7 +1883,7 @@
return false;
}
- final int uid = Binder.getCallingUid();
+ final int uid = mDeps.getCallingUid();
final long token = Binder.clearCallingIdentity();
try {
LinkProperties lp;
@@ -2294,7 +2303,7 @@
*/
@Override
public void systemReady() {
- if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ if (mDeps.getCallingUid() != Process.SYSTEM_UID) {
throw new SecurityException("Calling Uid is not system uid.");
}
systemReadyInternal();
@@ -2332,6 +2341,31 @@
}
/**
+ * Start listening for default data network activity state changes.
+ */
+ @Override
+ public void registerNetworkActivityListener(@NonNull INetworkActivityListener l) {
+ // TODO: Replace network activity listener registry in ConnectivityManager from NMS to here
+ }
+
+ /**
+ * Stop listening for default data network activity state changes.
+ */
+ @Override
+ public void unregisterNetworkActivityListener(@NonNull INetworkActivityListener l) {
+ // TODO: Replace network activity listener registry in ConnectivityManager from NMS to here
+ }
+
+ /**
+ * Check whether the default network radio is currently active.
+ */
+ @Override
+ public boolean isDefaultNetworkActive() {
+ // TODO: Replace isNetworkActive() in NMS.
+ return false;
+ }
+
+ /**
* Setup data activity tracking for the given network.
*
* Every {@code setupDataActivityTracking} should be paired with a
@@ -2520,7 +2554,7 @@
if (context.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
pw.println("Permission Denial: can't dump " + tag + " from from pid="
- + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
+ + Binder.getCallingPid() + ", uid=" + mDeps.getCallingUid()
+ " due to missing android.permission.DUMP permission");
return false;
} else {
@@ -2701,7 +2735,7 @@
* Return an array of all current NetworkRequest sorted by request id.
*/
@VisibleForTesting
- protected NetworkRequestInfo[] requestsSortedById() {
+ NetworkRequestInfo[] requestsSortedById() {
NetworkRequestInfo[] requests = new NetworkRequestInfo[0];
requests = mNetworkRequests.values().toArray(requests);
// Sort the array based off the NRI containing the min requestId in its requests.
@@ -3551,30 +3585,58 @@
return false;
}
for (NetworkRequestInfo nri : mNetworkRequests.values()) {
- if (reason == UnneededFor.LINGER && nri.request.isBackgroundRequest()) {
+ if (reason == UnneededFor.LINGER
+ && !nri.isMultilayerRequest()
+ && nri.mRequests.get(0).isBackgroundRequest()) {
// Background requests don't affect lingering.
continue;
}
- // If this Network is already the highest scoring Network for a request, or if
- // there is hope for it to become one if it validated, then it is needed.
- if (nri.request.isRequest() && nai.satisfies(nri.request) &&
- (nai.isSatisfyingRequest(nri.request.requestId) ||
- // Note that this catches two important cases:
- // 1. Unvalidated cellular will not be reaped when unvalidated WiFi
- // is currently satisfying the request. This is desirable when
- // cellular ends up validating but WiFi does not.
- // 2. Unvalidated WiFi will not be reaped when validated cellular
- // is currently satisfying the request. This is desirable when
- // WiFi ends up validating and out scoring cellular.
- nri.mSatisfier.getCurrentScore()
- < nai.getCurrentScoreAsValidated())) {
+ if (isNetworkPotentialSatisfier(nai, nri)) {
return false;
}
}
return true;
}
+ private boolean isNetworkPotentialSatisfier(
+ @NonNull final NetworkAgentInfo candidate, @NonNull final NetworkRequestInfo nri) {
+ // listen requests won't keep up a network satisfying it. If this is not a multilayer
+ // request, we can return immediately. For multilayer requests, we have to check to see if
+ // any of the multilayer requests may have a potential satisfier.
+ if (!nri.isMultilayerRequest() && nri.mRequests.get(0).isListen()) {
+ return false;
+ }
+ for (final NetworkRequest req : nri.mRequests) {
+ // As non-multilayer listen requests have already returned, the below would only happen
+ // for a multilayer request therefore continue to the next request if available.
+ if (req.isListen()) {
+ continue;
+ }
+ // If this Network is already the highest scoring Network for a request, or if
+ // there is hope for it to become one if it validated, then it is needed.
+ if (candidate.satisfies(req)) {
+ // As soon as a network is found that satisfies a request, return. Specifically for
+ // multilayer requests, returning as soon as a NetworkAgentInfo satisfies a request
+ // is important so as to not evaluate lower priority requests further in
+ // nri.mRequests.
+ final boolean isNetworkNeeded = candidate.isSatisfyingRequest(req.requestId)
+ // Note that this catches two important cases:
+ // 1. Unvalidated cellular will not be reaped when unvalidated WiFi
+ // is currently satisfying the request. This is desirable when
+ // cellular ends up validating but WiFi does not.
+ // 2. Unvalidated WiFi will not be reaped when validated cellular
+ // is currently satisfying the request. This is desirable when
+ // WiFi ends up validating and out scoring cellular.
+ || nri.mSatisfier.getCurrentScore()
+ < candidate.getCurrentScoreAsValidated();
+ return isNetworkNeeded;
+ }
+ }
+
+ return false;
+ }
+
private NetworkRequestInfo getNriForAppRequest(
NetworkRequest request, int callingUid, String requestedOperation) {
final NetworkRequestInfo nri = mNetworkRequests.get(request);
@@ -3871,8 +3933,12 @@
new CaptivePortal(new CaptivePortalImpl(network).asBinder()));
appIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
- Binder.withCleanCallingIdentity(() ->
- mContext.startActivityAsUser(appIntent, UserHandle.CURRENT));
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mContext.startActivityAsUser(appIntent, UserHandle.CURRENT);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
private class CaptivePortalImpl extends ICaptivePortal.Stub {
@@ -3900,7 +3966,7 @@
if (request == CaptivePortal.APP_REQUEST_REEVALUATION_REQUIRED) {
checkNetworkStackPermission();
- nm.forceReevaluation(Binder.getCallingUid());
+ nm.forceReevaluation(mDeps.getCallingUid());
}
}
@@ -4367,7 +4433,7 @@
public void reportNetworkConnectivity(Network network, boolean hasConnectivity) {
enforceAccessPermission();
enforceInternetPermission();
- final int uid = Binder.getCallingUid();
+ final int uid = mDeps.getCallingUid();
final int connectivityInfo = encodeBool(hasConnectivity);
// Handle ConnectivityDiagnostics event before attempting to revalidate the network. This
@@ -4437,13 +4503,13 @@
if (globalProxy != null) return globalProxy;
if (network == null) {
// Get the network associated with the calling UID.
- final Network activeNetwork = getActiveNetworkForUidInternal(Binder.getCallingUid(),
+ final Network activeNetwork = getActiveNetworkForUidInternal(mDeps.getCallingUid(),
true);
if (activeNetwork == null) {
return null;
}
return getLinkPropertiesProxyInfo(activeNetwork);
- } else if (mDeps.queryUserAccess(Binder.getCallingUid(), network.getNetId())) {
+ } else if (mDeps.queryUserAccess(mDeps.getCallingUid(), network.getNetId())) {
// Don't call getLinkProperties() as it requires ACCESS_NETWORK_STATE permission, which
// caller may not have.
return getLinkPropertiesProxyInfo(network);
@@ -4612,7 +4678,7 @@
*/
@Override
public ParcelFileDescriptor establishVpn(VpnConfig config) {
- int user = UserHandle.getUserId(Binder.getCallingUid());
+ int user = UserHandle.getUserId(mDeps.getCallingUid());
synchronized (mVpns) {
throwIfLockdownEnabled();
return mVpns.get(user).establish(config);
@@ -4633,7 +4699,7 @@
*/
@Override
public boolean provisionVpnProfile(@NonNull VpnProfile profile, @NonNull String packageName) {
- final int user = UserHandle.getUserId(Binder.getCallingUid());
+ final int user = UserHandle.getUserId(mDeps.getCallingUid());
synchronized (mVpns) {
return mVpns.get(user).provisionVpnProfile(packageName, profile, mKeyStore);
}
@@ -4651,7 +4717,7 @@
*/
@Override
public void deleteVpnProfile(@NonNull String packageName) {
- final int user = UserHandle.getUserId(Binder.getCallingUid());
+ final int user = UserHandle.getUserId(mDeps.getCallingUid());
synchronized (mVpns) {
mVpns.get(user).deleteVpnProfile(packageName, mKeyStore);
}
@@ -4668,7 +4734,7 @@
*/
@Override
public void startVpnProfile(@NonNull String packageName) {
- final int user = UserHandle.getUserId(Binder.getCallingUid());
+ final int user = UserHandle.getUserId(mDeps.getCallingUid());
synchronized (mVpns) {
throwIfLockdownEnabled();
mVpns.get(user).startVpnProfile(packageName, mKeyStore);
@@ -4685,7 +4751,7 @@
*/
@Override
public void stopVpnProfile(@NonNull String packageName) {
- final int user = UserHandle.getUserId(Binder.getCallingUid());
+ final int user = UserHandle.getUserId(mDeps.getCallingUid());
synchronized (mVpns) {
mVpns.get(user).stopVpnProfile(packageName);
}
@@ -4697,7 +4763,7 @@
*/
@Override
public void startLegacyVpn(VpnProfile profile) {
- int user = UserHandle.getUserId(Binder.getCallingUid());
+ int user = UserHandle.getUserId(mDeps.getCallingUid());
final LinkProperties egress = getActiveLinkProperties();
if (egress == null) {
throw new IllegalStateException("Missing active network connection");
@@ -4846,7 +4912,7 @@
@Override
public boolean updateLockdownVpn() {
- if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ if (mDeps.getCallingUid() != Process.SYSTEM_UID) {
logw("Lockdown VPN only available to AID_SYSTEM");
return false;
}
@@ -4868,7 +4934,7 @@
setLockdownTracker(null);
return true;
}
- int user = UserHandle.getUserId(Binder.getCallingUid());
+ int user = UserHandle.getUserId(mDeps.getCallingUid());
Vpn vpn = mVpns.get(user);
if (vpn == null) {
logw("VPN for user " + user + " not ready yet. Skipping lockdown");
@@ -5433,7 +5499,7 @@
messenger = null;
mBinder = null;
mPid = getCallingPid();
- mUid = getCallingUid();
+ mUid = mDeps.getCallingUid();
enforceRequestCountLimit();
}
@@ -5445,7 +5511,7 @@
ensureAllNetworkRequestsHaveType(mRequests);
mBinder = binder;
mPid = getCallingPid();
- mUid = getCallingUid();
+ mUid = mDeps.getCallingUid();
mPendingIntent = null;
enforceRequestCountLimit();
@@ -5460,6 +5526,10 @@
this(r, null);
}
+ boolean isMultilayerRequest() {
+ return mRequests.size() > 1;
+ }
+
private List<NetworkRequest> initializeRequests(NetworkRequest r) {
final ArrayList<NetworkRequest> tempRequests = new ArrayList<>();
tempRequests.add(new NetworkRequest(r));
@@ -5501,7 +5571,7 @@
public void binderDied() {
log("ConnectivityService NetworkRequestInfo binderDied(" +
mRequests + ", " + mBinder + ")");
- releaseNetworkRequest(mRequests);
+ releaseNetworkRequests(mRequests);
}
@Override
@@ -5534,13 +5604,15 @@
mAppOpsManager.checkPackage(callerUid, callerPackageName);
}
- private ArrayList<Integer> getSignalStrengthThresholds(NetworkAgentInfo nai) {
+ private ArrayList<Integer> getSignalStrengthThresholds(@NonNull final NetworkAgentInfo nai) {
final SortedSet<Integer> thresholds = new TreeSet<>();
synchronized (nai) {
- for (NetworkRequestInfo nri : mNetworkRequests.values()) {
- if (nri.request.networkCapabilities.hasSignalStrength() &&
- nai.satisfiesImmutableCapabilitiesOf(nri.request)) {
- thresholds.add(nri.request.networkCapabilities.getSignalStrength());
+ for (final NetworkRequestInfo nri : mNetworkRequests.values()) {
+ for (final NetworkRequest req : nri.mRequests) {
+ if (req.networkCapabilities.hasSignalStrength()
+ && nai.satisfiesImmutableCapabilitiesOf(req)) {
+ thresholds.add(req.networkCapabilities.getSignalStrength());
+ }
}
}
}
@@ -5588,7 +5660,7 @@
}
private boolean checkUnsupportedStartingFrom(int version, String callingPackageName) {
- final UserHandle user = UserHandle.getUserHandleForUid(Binder.getCallingUid());
+ final UserHandle user = UserHandle.getUserHandleForUid(mDeps.getCallingUid());
final PackageManager pm =
mContext.createContextAsUser(user, 0 /* flags */).getPackageManager();
try {
@@ -5608,7 +5680,7 @@
throw new SecurityException("Insufficient permissions to specify legacy type");
}
}
- final int callingUid = Binder.getCallingUid();
+ final int callingUid = mDeps.getCallingUid();
final NetworkRequest.Type type = (networkCapabilities == null)
? NetworkRequest.Type.TRACK_DEFAULT
: NetworkRequest.Type.REQUEST;
@@ -5678,7 +5750,7 @@
if (nai != null) {
nai.asyncChannel.sendMessage(android.net.NetworkAgent.CMD_REQUEST_BANDWIDTH_UPDATE);
synchronized (mBandwidthRequests) {
- final int uid = Binder.getCallingUid();
+ final int uid = mDeps.getCallingUid();
Integer uidReqs = mBandwidthRequests.get(uid);
if (uidReqs == null) {
uidReqs = 0;
@@ -5695,7 +5767,7 @@
}
private void enforceMeteredApnPolicy(NetworkCapabilities networkCapabilities) {
- final int uid = Binder.getCallingUid();
+ final int uid = mDeps.getCallingUid();
if (isSystem(uid)) {
// Exemption for system uid.
return;
@@ -5715,7 +5787,7 @@
PendingIntent operation, @NonNull String callingPackageName,
@Nullable String callingAttributionTag) {
Objects.requireNonNull(operation, "PendingIntent cannot be null.");
- final int callingUid = Binder.getCallingUid();
+ final int callingUid = mDeps.getCallingUid();
networkCapabilities = new NetworkCapabilities(networkCapabilities);
enforceNetworkRequestPermissions(networkCapabilities, callingPackageName,
callingAttributionTag);
@@ -5774,7 +5846,7 @@
@Override
public NetworkRequest listenForNetwork(NetworkCapabilities networkCapabilities,
Messenger messenger, IBinder binder, @NonNull String callingPackageName) {
- final int callingUid = Binder.getCallingUid();
+ final int callingUid = mDeps.getCallingUid();
if (!hasWifiNetworkListenPermission(networkCapabilities)) {
enforceAccessPermission();
}
@@ -5804,7 +5876,7 @@
public void pendingListenForNetwork(NetworkCapabilities networkCapabilities,
PendingIntent operation, @NonNull String callingPackageName) {
Objects.requireNonNull(operation, "PendingIntent cannot be null.");
- final int callingUid = Binder.getCallingUid();
+ final int callingUid = mDeps.getCallingUid();
if (!hasWifiNetworkListenPermission(networkCapabilities)) {
enforceAccessPermission();
}
@@ -5827,7 +5899,7 @@
return mNextNetworkProviderId.getAndIncrement();
}
- private void releaseNetworkRequest(List<NetworkRequest> networkRequests) {
+ private void releaseNetworkRequests(List<NetworkRequest> networkRequests) {
for (int i = 0; i < networkRequests.size(); i++) {
releaseNetworkRequest(networkRequests.get(i));
}
@@ -5905,7 +5977,7 @@
} else {
enforceNetworkFactoryPermission();
}
- mHandler.post(() -> handleReleaseNetworkRequest(request, Binder.getCallingUid(), true));
+ mHandler.post(() -> handleReleaseNetworkRequest(request, mDeps.getCallingUid(), true));
}
// NOTE: Accessed on multiple threads, must be synchronized on itself.
@@ -5999,7 +6071,7 @@
enforceNetworkFactoryPermission();
}
- final int uid = Binder.getCallingUid();
+ final int uid = mDeps.getCallingUid();
final long token = Binder.clearCallingIdentity();
try {
return registerNetworkAgentInternal(messenger, networkInfo, linkProperties,
@@ -7653,7 +7725,7 @@
@Override
public boolean addVpnAddress(String address, int prefixLength) {
- int user = UserHandle.getUserId(Binder.getCallingUid());
+ int user = UserHandle.getUserId(mDeps.getCallingUid());
synchronized (mVpns) {
throwIfLockdownEnabled();
return mVpns.get(user).addAddress(address, prefixLength);
@@ -7662,7 +7734,7 @@
@Override
public boolean removeVpnAddress(String address, int prefixLength) {
- int user = UserHandle.getUserId(Binder.getCallingUid());
+ int user = UserHandle.getUserId(mDeps.getCallingUid());
synchronized (mVpns) {
throwIfLockdownEnabled();
return mVpns.get(user).removeAddress(address, prefixLength);
@@ -7671,7 +7743,7 @@
@Override
public boolean setUnderlyingNetworksForVpn(Network[] networks) {
- int user = UserHandle.getUserId(Binder.getCallingUid());
+ int user = UserHandle.getUserId(mDeps.getCallingUid());
final boolean success;
synchronized (mVpns) {
throwIfLockdownEnabled();
@@ -7759,10 +7831,13 @@
final int userId = UserHandle.getCallingUserId();
- Binder.withCleanCallingIdentity(() -> {
+ final long token = Binder.clearCallingIdentity();
+ try {
final IpMemoryStore ipMemoryStore = IpMemoryStore.getMemoryStore(mContext);
ipMemoryStore.factoryReset();
- });
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
// Turn airplane mode off
setAirplaneMode(false);
@@ -7898,7 +7973,7 @@
@GuardedBy("mVpns")
private Vpn getVpnIfOwner() {
- return getVpnIfOwner(Binder.getCallingUid());
+ return getVpnIfOwner(mDeps.getCallingUid());
}
@GuardedBy("mVpns")
@@ -8376,7 +8451,7 @@
throw new IllegalArgumentException("ConnectivityManager.TYPE_* are deprecated."
+ " Please use NetworkCapabilities instead.");
}
- final int callingUid = Binder.getCallingUid();
+ final int callingUid = mDeps.getCallingUid();
mAppOpsManager.checkPackage(callingUid, callingPackageName);
// This NetworkCapabilities is only used for matching to Networks. Clear out its owner uid
@@ -8411,7 +8486,7 @@
mConnectivityDiagnosticsHandler.obtainMessage(
ConnectivityDiagnosticsHandler
.EVENT_UNREGISTER_CONNECTIVITY_DIAGNOSTICS_CALLBACK,
- Binder.getCallingUid(),
+ mDeps.getCallingUid(),
0,
callback));
}
@@ -8427,7 +8502,7 @@
}
final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
- if (nai == null || nai.creatorUid != Binder.getCallingUid()) {
+ if (nai == null || nai.creatorUid != mDeps.getCallingUid()) {
throw new SecurityException("Data Stall simulation is only possible for network "
+ "creators");
}
diff --git a/services/core/java/com/android/server/IntentResolver.java b/services/core/java/com/android/server/IntentResolver.java
index dbf179a..ea1ac0c 100644
--- a/services/core/java/com/android/server/IntentResolver.java
+++ b/services/core/java/com/android/server/IntentResolver.java
@@ -839,6 +839,17 @@
}
};
+ // Make <this> a copy of <orig>. The presumption is that <this> is empty.
+ protected void doCopy(IntentResolver orig) {
+ mFilters.addAll(orig.mFilters);
+ mTypeToFilter.putAll(orig.mTypeToFilter);
+ mBaseTypeToFilter.putAll(orig.mBaseTypeToFilter);
+ mWildTypeToFilter.putAll(orig.mWildTypeToFilter);
+ mSchemeToFilter.putAll(orig.mSchemeToFilter);
+ mActionToFilter.putAll(orig.mActionToFilter);
+ mTypedActionToFilter.putAll(orig.mTypedActionToFilter);
+ }
+
/**
* All filters that have been registered.
*/
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 6b45b48..c951fd4 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -4475,6 +4475,15 @@
return mMediaStoreAuthorityAppId == UserHandle.getAppId(uid);
}
+ @Override
+ public void freeCache(String volumeUuid, long freeBytes) {
+ try {
+ mStorageSessionController.freeCache(volumeUuid, freeBytes);
+ } catch (ExternalStorageServiceException e) {
+ Log.e(TAG, "Failed to free cache of vol : " + volumeUuid, e);
+ }
+ }
+
public boolean hasExternalStorage(int uid, String packageName) {
// No need to check for system uid. This avoids a deadlock between
// PackageManagerService and AppOpsService.
diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java
index 655d8ab..e8687e5 100644
--- a/services/core/java/com/android/server/TestNetworkService.java
+++ b/services/core/java/com/android/server/TestNetworkService.java
@@ -107,23 +107,23 @@
String ifacePrefix = isTun ? TEST_TUN_PREFIX : TEST_TAP_PREFIX;
String iface = ifacePrefix + sTestTunIndex.getAndIncrement();
- return Binder.withCleanCallingIdentity(
- () -> {
- try {
- ParcelFileDescriptor tunIntf =
- ParcelFileDescriptor.adoptFd(jniCreateTunTap(isTun, iface));
- for (LinkAddress addr : linkAddrs) {
- mNetd.interfaceAddAddress(
- iface,
- addr.getAddress().getHostAddress(),
- addr.getPrefixLength());
- }
+ final long token = Binder.clearCallingIdentity();
+ try {
+ ParcelFileDescriptor tunIntf =
+ ParcelFileDescriptor.adoptFd(jniCreateTunTap(isTun, iface));
+ for (LinkAddress addr : linkAddrs) {
+ mNetd.interfaceAddAddress(
+ iface,
+ addr.getAddress().getHostAddress(),
+ addr.getPrefixLength());
+ }
- return new TestNetworkInterface(tunIntf, iface);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- });
+ return new TestNetworkInterface(tunIntf, iface);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
/**
@@ -317,7 +317,12 @@
try {
// This requires NETWORK_STACK privileges.
- Binder.withCleanCallingIdentity(() -> mNMS.setInterfaceUp(iface));
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNMS.setInterfaceUp(iface);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
// Synchronize all accesses to mTestNetworkTracker to prevent the case where:
// 1. TestNetworkAgent successfully binds to death of binder
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index 165b6a1..74e3851 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -25,24 +25,44 @@
import android.net.NetworkRequest;
import android.net.vcn.IVcnManagementService;
import android.net.vcn.VcnConfig;
+import android.os.Binder;
+import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.ParcelUuid;
+import android.os.PersistableBundle;
+import android.os.Process;
+import android.os.ServiceSpecificException;
+import android.os.UserHandle;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.util.ArrayMap;
+import android.util.Slog;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting.Visibility;
+import com.android.server.vcn.util.PersistableBundleUtils;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
/**
* VcnManagementService manages Virtual Carrier Network profiles and lifecycles.
*
* <pre>The internal structure of the VCN Management subsystem is as follows:
*
- * +------------------------+ 1:1 +--------------------------------+
- * | VcnManagementService | ------------ Creates -------------> | TelephonySubscriptionManager |
- * | | | |
- * | Manages configs and | | Tracks subscriptions, carrier |
- * | VcnInstance lifecycles | <--- Notifies of subscription & --- | privilege changes, caches maps |
- * +------------------------+ carrier privilege changes +--------------------------------+
+ * +-------------------------+ 1:1 +--------------------------------+
+ * | VcnManagementService | ------------ Creates ------------> | TelephonySubscriptionManager |
+ * | | | |
+ * | Manages configs and | | Tracks subscriptions, carrier |
+ * | Vcn instance lifecycles | <--- Notifies of subscription & -- | privilege changes, caches maps |
+ * +-------------------------+ carrier privilege changes +--------------------------------+
* | 1:N ^
* | |
* | +-------------------------------+
@@ -54,19 +74,19 @@
* | mode state changes
* v |
* +-----------------------------------------------------------------------+
- * | VcnInstance |
+ * | Vcn |
* | |
- * | Manages tunnel lifecycles based on fulfillable NetworkRequest(s) |
- * | and overall safe-mode |
+ * | Manages GatewayConnection lifecycles based on fulfillable |
+ * | NetworkRequest(s) and overall safe-mode |
* +-----------------------------------------------------------------------+
* | 1:N ^
* Creates to fulfill |
- * NetworkRequest(s), tears Notifies of VcnTunnel
+ * NetworkRequest(s), tears Notifies of VcnGatewayConnection
* down when no longer needed teardown (e.g. Network reaped)
* | and safe-mode timer changes
* v |
* +-----------------------------------------------------------------------+
- * | VcnTunnel |
+ * | VcnGatewayConnection |
* | |
* | Manages a single (IKEv2) tunnel session and NetworkAgent, |
* | handles mobility events, (IPsec) Tunnel setup and safe-mode timers |
@@ -92,20 +112,72 @@
public static final boolean VDBG = false; // STOPSHIP: if true
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ static final String VCN_CONFIG_FILE = "/data/system/vcn/configs.xml";
+
/* Binder context for this service */
@NonNull private final Context mContext;
@NonNull private final Dependencies mDeps;
@NonNull private final Looper mLooper;
+ @NonNull private final Handler mHandler;
@NonNull private final VcnNetworkProvider mNetworkProvider;
+ @GuardedBy("mLock")
+ @NonNull
+ private final Map<ParcelUuid, VcnConfig> mConfigs = new ArrayMap<>();
+
+ @NonNull private final Object mLock = new Object();
+
+ @NonNull private final PersistableBundleUtils.LockingReadWriteHelper mConfigDiskRwHelper;
+
@VisibleForTesting(visibility = Visibility.PRIVATE)
VcnManagementService(@NonNull Context context, @NonNull Dependencies deps) {
mContext = requireNonNull(context, "Missing context");
mDeps = requireNonNull(deps, "Missing dependencies");
mLooper = mDeps.getLooper();
+ mHandler = new Handler(mLooper);
mNetworkProvider = new VcnNetworkProvider(mContext, mLooper);
+
+ mConfigDiskRwHelper = mDeps.newPersistableBundleLockingReadWriteHelper(VCN_CONFIG_FILE);
+
+ // Run on handler to ensure I/O does not block system server startup
+ mHandler.post(() -> {
+ PersistableBundle configBundle = null;
+ try {
+ configBundle = mConfigDiskRwHelper.readFromDisk();
+ } catch (IOException e1) {
+ Slog.e(TAG, "Failed to read configs from disk; retrying", e1);
+
+ // Retry immediately. The IOException may have been transient.
+ try {
+ configBundle = mConfigDiskRwHelper.readFromDisk();
+ } catch (IOException e2) {
+ Slog.wtf(TAG, "Failed to read configs from disk", e2);
+ return;
+ }
+ }
+
+ if (configBundle != null) {
+ final Map<ParcelUuid, VcnConfig> configs =
+ PersistableBundleUtils.toMap(
+ configBundle,
+ PersistableBundleUtils::toParcelUuid,
+ VcnConfig::new);
+
+ synchronized (mLock) {
+ for (Entry<ParcelUuid, VcnConfig> entry : configs.entrySet()) {
+ // Ensure no new configs are overwritten; a carrier app may have added a new
+ // config.
+ if (!mConfigs.containsKey(entry.getKey())) {
+ mConfigs.put(entry.getKey(), entry.getValue());
+ }
+ }
+ // TODO: Trigger re-evaluation of active VCNs; start/stop VCNs as needed.
+ }
+ }
+ });
}
// Package-visibility for SystemServer to create instances.
@@ -130,16 +202,81 @@
}
return mHandlerThread.getLooper();
}
+
+ /**
+ * Retrieves the caller's UID
+ *
+ * <p>This call MUST be made before calling {@link Binder#clearCallingIdentity}, otherwise
+ * this will not work properly.
+ *
+ * @return
+ */
+ public int getBinderCallingUid() {
+ return Binder.getCallingUid();
+ }
+
+ /**
+ * Creates and returns a new {@link PersistableBundle.LockingReadWriteHelper}
+ *
+ * @param path the file path to read/write from/to.
+ * @return the {@link PersistableBundleUtils.LockingReadWriteHelper} instance
+ */
+ public PersistableBundleUtils.LockingReadWriteHelper
+ newPersistableBundleLockingReadWriteHelper(@NonNull String path) {
+ return new PersistableBundleUtils.LockingReadWriteHelper(path);
+ }
}
/** Notifies the VcnManagementService that external dependencies can be set up. */
public void systemReady() {
- // TODO: Retrieve existing profiles from KeyStore
-
mContext.getSystemService(ConnectivityManager.class)
.registerNetworkProvider(mNetworkProvider);
}
+ private void enforcePrimaryUser() {
+ final int uid = mDeps.getBinderCallingUid();
+ if (uid == Process.SYSTEM_UID) {
+ throw new IllegalStateException(
+ "Calling identity was System Server. Was Binder calling identity cleared?");
+ }
+
+ if (!UserHandle.getUserHandleForUid(uid).isSystem()) {
+ throw new SecurityException(
+ "VcnManagementService can only be used by callers running as the primary user");
+ }
+ }
+
+ private void enforceCallingUserAndCarrierPrivilege(ParcelUuid subscriptionGroup) {
+ // Only apps running in the primary (system) user are allowed to configure the VCN. This is
+ // in line with Telephony's behavior with regards to binding to a Carrier App provided
+ // CarrierConfigService.
+ enforcePrimaryUser();
+
+ // TODO (b/172619301): Check based on events propagated from CarrierPrivilegesTracker
+ final SubscriptionManager subMgr = mContext.getSystemService(SubscriptionManager.class);
+ final List<SubscriptionInfo> subscriptionInfos = new ArrayList<>();
+ Binder.withCleanCallingIdentity(
+ () -> {
+ subscriptionInfos.addAll(subMgr.getSubscriptionsInGroup(subscriptionGroup));
+ });
+
+ final TelephonyManager telMgr = mContext.getSystemService(TelephonyManager.class);
+ for (SubscriptionInfo info : subscriptionInfos) {
+ // Check subscription is active first; much cheaper/faster check, and an app (currently)
+ // cannot be carrier privileged for inactive subscriptions.
+ if (subMgr.isValidSlotIndex(info.getSimSlotIndex())
+ && telMgr.hasCarrierPrivileges(info.getSubscriptionId())) {
+ // TODO (b/173717728): Allow configuration for inactive, but manageable
+ // subscriptions.
+ // TODO (b/173718661): Check for whole subscription groups at a time.
+ return;
+ }
+ }
+
+ throw new SecurityException(
+ "Carrier privilege required for subscription group to set VCN Config");
+ }
+
/**
* Sets a VCN config for a given subscription group.
*
@@ -150,7 +287,17 @@
requireNonNull(subscriptionGroup, "subscriptionGroup was null");
requireNonNull(config, "config was null");
- // TODO: Store VCN configuration, trigger startup as necessary
+ enforceCallingUserAndCarrierPrivilege(subscriptionGroup);
+
+ synchronized (mLock) {
+ mConfigs.put(subscriptionGroup, config);
+
+ // Must be done synchronously to ensure that writes do not happen out-of-order.
+ writeConfigsToDiskLocked();
+ }
+
+ // TODO: Clear Binder calling identity
+ // TODO: Trigger startup as necessary
}
/**
@@ -162,7 +309,40 @@
public void clearVcnConfig(@NonNull ParcelUuid subscriptionGroup) {
requireNonNull(subscriptionGroup, "subscriptionGroup was null");
- // TODO: Clear VCN configuration, trigger teardown as necessary
+ enforceCallingUserAndCarrierPrivilege(subscriptionGroup);
+
+ synchronized (mLock) {
+ mConfigs.remove(subscriptionGroup);
+
+ // Must be done synchronously to ensure that writes do not happen out-of-order.
+ writeConfigsToDiskLocked();
+ }
+
+ // TODO: Clear Binder calling identity
+ // TODO: Trigger teardown as necessary
+ }
+
+ @GuardedBy("mLock")
+ private void writeConfigsToDiskLocked() {
+ try {
+ PersistableBundle bundle =
+ PersistableBundleUtils.fromMap(
+ mConfigs,
+ PersistableBundleUtils::fromParcelUuid,
+ VcnConfig::toPersistableBundle);
+ mConfigDiskRwHelper.writeToDisk(bundle);
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to save configs to disk", e);
+ throw new ServiceSpecificException(0, "Failed to save configs");
+ }
+ }
+
+ /** Get current configuration list for testing purposes */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ Map<ParcelUuid, VcnConfig> getConfigs() {
+ synchronized (mLock) {
+ return Collections.unmodifiableMap(mConfigs);
+ }
}
/**
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index a2b6304..5fde046 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -168,6 +168,7 @@
public static final int FGS_FEATURE_ALLOWED_BY_FGS_BINDING = 17;
public static final int FGS_FEATURE_ALLOWED_BY_DEVICE_DEMO_MODE = 18;
public static final int FGS_FEATURE_ALLOWED_BY_PROCESS_RECORD = 19;
+ public static final int FGS_FEATURE_ALLOWED_BY_EXEMPTED_PACKAGES = 20;
@IntDef(flag = true, prefix = { "FGS_FEATURE_" }, value = {
FGS_FEATURE_DENIED,
@@ -188,7 +189,8 @@
FGS_FEATURE_ALLOWED_BY_SYSTEM_ALERT_WINDOW_PERMISSION,
FGS_FEATURE_ALLOWED_BY_FGS_BINDING,
FGS_FEATURE_ALLOWED_BY_DEVICE_DEMO_MODE,
- FGS_FEATURE_ALLOWED_BY_PROCESS_RECORD
+ FGS_FEATURE_ALLOWED_BY_PROCESS_RECORD,
+ FGS_FEATURE_ALLOWED_BY_EXEMPTED_PACKAGES,
})
@Retention(RetentionPolicy.SOURCE)
public @interface FgsFeatureRetCode {}
@@ -275,6 +277,13 @@
static final long FGS_BG_START_RESTRICTION_CHANGE_ID = 170668199L;
/**
+ * If set to false for a package, the system will *not* exempt it from FGS-BG-start,
+ * even if it's in {#code ActiveServices.sFgsBgStartExemptedPackages}.
+ */
+ @ChangeId
+ static final long FGS_BG_START_USE_EXEMPTION_LIST_CHANGE_ID = 175801883;
+
+ /**
* If a service can not become foreground service due to BG-FGS-launch restriction or other
* reasons, throws an IllegalStateException.
*/
@@ -282,6 +291,25 @@
@EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.S)
static final long FGS_START_EXCEPTION_CHANGE_ID = 174041399L;
+ /**
+ * Special allowlist that contains packages that are allowed to start FGS even if they target S,
+ * without using START_FOREGROUND_SERVICES_FROM_BACKGROUND.
+ *
+ * Note: we exempt FGS starts if either the "callee" or "caller" match any of the emempted
+ * packages. This means:
+ * - Exempted apps could call Context.startForegroundService() for services owned by any other
+ * apps.
+ * - Any apps could call Context.startForegroundService() for services owned by any exempted
+ * apps.
+ * And the call would succeed.
+ */
+ private static final ArraySet<String> sFgsBgStartExemptedPackages = new ArraySet<>();
+
+ static {
+ sFgsBgStartExemptedPackages.add("com.google.pixel.exo.bootstrapping"); //STOPSHIP Remove it.
+ sFgsBgStartExemptedPackages.add("com.android.chrome"); // STOPSHIP Remove it.
+ }
+
final Runnable mLastAnrDumpClearer = new Runnable() {
@Override public void run() {
synchronized (mAm) {
@@ -1672,13 +1700,12 @@
// TODO: remove as part of fixing b/173627642
@SuppressWarnings("AndroidFrameworkCompatChange")
private void postFgsNotificationLocked(ServiceRecord r) {
- final boolean isLegacyApp = (r.appInfo.targetSdkVersion < Build.VERSION_CODES.S);
boolean showNow = !mAm.mConstants.mFlagFgsNotificationDeferralEnabled;
if (!showNow) {
// Legacy apps' FGS notifications are not deferred unless the relevant
// DeviceConfig element has been set
showNow = mAm.mConstants.mFlagFgsNotificationDeferralApiGated
- && isLegacyApp;
+ && r.appInfo.targetSdkVersion < Build.VERSION_CODES.S;
}
if (!showNow) {
// is the notification such that it should show right away?
@@ -1733,11 +1760,6 @@
Slog.d(TAG_SERVICE, "FGS " + r
+ " notification in " + (when - now) + " ms");
}
- if (isLegacyApp) {
- Slog.i(TAG_SERVICE, "Deferring FGS notification in legacy app "
- + r.appInfo.packageName + "/" + UserHandle.formatUid(r.appInfo.uid)
- + " : " + r.foregroundNoti);
- }
mAm.mHandler.postAtTime(mPostDeferredFGSNotifications, when);
}
@@ -1761,7 +1783,7 @@
// The service might have been stopped or exited foreground state
// in the interval, so we lazy check whether we still need to show
// the notification.
- if (r.isForeground) {
+ if (r.isForeground && r.app != null) {
r.postNotification();
} else if (DEBUG_FOREGROUND_SERVICE) {
Slog.d(TAG_SERVICE, " - service no longer running/fg, ignoring");
@@ -5310,6 +5332,14 @@
}
}
+ // NOTE this should always be the last check.
+ if (ret == FGS_FEATURE_DENIED) {
+ if (isPackageExemptedFromFgsRestriction(r.appInfo.packageName, r.appInfo.uid)
+ || isPackageExemptedFromFgsRestriction(callingPackage, callingUid)) {
+ ret = FGS_FEATURE_ALLOWED_BY_EXEMPTED_PACKAGES;
+ }
+ }
+
final String debugInfo =
"[callingPackage: " + callingPackage
+ "; callingUid: " + callingUid
@@ -5327,6 +5357,13 @@
return ret;
}
+ private boolean isPackageExemptedFromFgsRestriction(String packageName, int uid) {
+ if (!sFgsBgStartExemptedPackages.contains(packageName)) {
+ return false;
+ }
+ return CompatChanges.isChangeEnabled(FGS_BG_START_USE_EXEMPTION_LIST_CHANGE_ID, uid);
+ }
+
private static String fgsCodeToString(@FgsFeatureRetCode int code) {
switch (code) {
case FGS_FEATURE_DENIED:
@@ -5367,6 +5404,8 @@
return "ALLOWED_BY_DEVICE_DEMO_MODE";
case FGS_FEATURE_ALLOWED_BY_PROCESS_RECORD:
return "ALLOWED_BY_PROCESS_RECORD";
+ case FGS_FEATURE_ALLOWED_BY_EXEMPTED_PACKAGES:
+ return "FGS_FEATURE_ALLOWED_BY_EXEMPTED_PACKAGES";
default:
return "";
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index 6892ef7..b0f296f 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -370,9 +370,9 @@
volatile boolean mFlagFgsNotificationDeferralEnabled = true;
// Restrict FGS notification deferral policy to only those apps that target
- // API version S or higher. Disabled by default; set to "true" to force
- // legacy app FGS notifications to display immediately in all cases.
- volatile boolean mFlagFgsNotificationDeferralApiGated = false;
+ // API version S or higher. Enabled by default; set to "false" to defer FGS
+ // notifications from legacy apps as well.
+ volatile boolean mFlagFgsNotificationDeferralApiGated = true;
// Time in milliseconds to defer FGS notifications after their transition to
// the foreground state.
@@ -806,7 +806,7 @@
mFlagFgsNotificationDeferralApiGated = DeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
KEY_DEFERRED_FGS_NOTIFICATIONS_API_GATED,
- /*default value*/ false);
+ /*default value*/ true);
}
private void updateFgsNotificationDeferralInterval() {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 10102cd..1841d67 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -5675,11 +5675,6 @@
}
@Override
- public ActivityManager.TaskSnapshot getTaskSnapshot(int taskId, boolean isLowResolution) {
- return mActivityTaskManager.getTaskSnapshot(taskId, isLowResolution);
- }
-
- @Override
public void resizeTask(int taskId, Rect bounds, int resizeMode) {
mActivityTaskManager.resizeTask(taskId, bounds, resizeMode);
}
@@ -11252,6 +11247,10 @@
// set on ION VMAs, therefore consider the entire ION heap as used kernel memory
kernelUsed += ionHeap;
}
+ final long gpuUsage = Debug.getGpuTotalUsageKb();
+ if (gpuUsage >= 0) {
+ pw.print(" GPU: "); pw.println(stringifyKBSize(gpuUsage));
+ }
final long lostRAM = memInfo.getTotalSizeKb()
- (ss[INDEX_TOTAL_PSS] - ss[INDEX_TOTAL_SWAP_PSS])
- memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
@@ -12046,6 +12045,12 @@
// set on ION VMAs, therefore consider the entire ION heap as used kernel memory
kernelUsed += ionHeap;
}
+ final long gpuUsage = Debug.getGpuTotalUsageKb();
+ if (gpuUsage >= 0) {
+ memInfoBuilder.append(" GPU: ");
+ memInfoBuilder.append(stringifyKBSize(gpuUsage));
+ memInfoBuilder.append("\n");
+ }
memInfoBuilder.append(" Used RAM: ");
memInfoBuilder.append(stringifyKBSize(
totalPss - cachedPss + kernelUsed));
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 12fe3ed..fffa814 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -2928,6 +2928,7 @@
final PlatformCompat platformCompat = (PlatformCompat)
ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE);
String toggleValue = getNextArgRequired();
+ boolean killPackage = !"--no-kill".equals(getNextOption());
boolean toggleAll = false;
int targetSdkVersion = -1;
long changeId = -1;
@@ -2979,7 +2980,11 @@
CompatibilityChangeConfig overrides =
new CompatibilityChangeConfig(
new Compatibility.ChangeConfig(enabled, disabled));
- platformCompat.setOverrides(overrides, packageName);
+ if (killPackage) {
+ platformCompat.setOverrides(overrides, packageName);
+ } else {
+ platformCompat.setOverridesForTest(overrides, packageName);
+ }
pw.println("Enabled change " + changeId + " for " + packageName + ".");
}
return 0;
@@ -2998,13 +3003,21 @@
CompatibilityChangeConfig overrides =
new CompatibilityChangeConfig(
new Compatibility.ChangeConfig(enabled, disabled));
- platformCompat.setOverrides(overrides, packageName);
+ if (killPackage) {
+ platformCompat.setOverrides(overrides, packageName);
+ } else {
+ platformCompat.setOverridesForTest(overrides, packageName);
+ }
pw.println("Disabled change " + changeId + " for " + packageName + ".");
}
return 0;
case "reset":
if (toggleAll) {
- platformCompat.clearOverrides(packageName);
+ if (killPackage) {
+ platformCompat.clearOverrides(packageName);
+ } else {
+ platformCompat.clearOverridesForTest(packageName);
+ }
pw.println("Reset all changes for " + packageName + " to default value.");
return 0;
}
@@ -3410,15 +3423,18 @@
pw.println(" write");
pw.println(" Write all pending state to storage.");
pw.println(" compat [COMMAND] [...]: sub-commands for toggling app-compat changes.");
- pw.println(" enable|disable|reset <CHANGE_ID|CHANGE_NAME> <PACKAGE_NAME>");
+ pw.println(" enable|disable [--no-kill] <CHANGE_ID|CHANGE_NAME> <PACKAGE_NAME>");
+ pw.println(" Toggles a change either by id or by name for <PACKAGE_NAME>.");
+ pw.println(" It kills <PACKAGE_NAME> (to allow the toggle to take effect) unless --no-kill is provided.");
+ pw.println(" reset <CHANGE_ID|CHANGE_NAME> <PACKAGE_NAME>");
pw.println(" Toggles a change either by id or by name for <PACKAGE_NAME>.");
pw.println(" It kills <PACKAGE_NAME> (to allow the toggle to take effect).");
- pw.println(" enable-all|disable-all <targetSdkVersion> <PACKAGE_NAME");
+ pw.println(" enable-all|disable-all <targetSdkVersion> <PACKAGE_NAME>");
pw.println(" Toggles all changes that are gated by <targetSdkVersion>.");
- pw.println(" reset-all <PACKAGE_NAME>");
+ pw.println(" reset-all [--no-kill] <PACKAGE_NAME>");
pw.println(" Removes all existing overrides for all changes for ");
pw.println(" <PACKAGE_NAME> (back to default behaviour).");
- pw.println(" It kills <PACKAGE_NAME> (to allow the toggle to take effect).");
+ pw.println(" It kills <PACKAGE_NAME> (to allow the toggle to take effect) unless --no-kill is provided.");
pw.println(" memory-factor [command] [...]: sub-commands for overriding memory pressure factor");
pw.println(" set <NORMAL|MODERATE|LOW|CRITICAL>");
pw.println(" Overrides memory pressure factor. May also supply a raw int level");
diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
index ca20224..6fe934e 100644
--- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
@@ -15,6 +15,8 @@
*/
package com.android.server.am;
+import static com.android.internal.power.MeasuredEnergyArray.SUBSYSTEM_DISPLAY;
+
import android.annotation.Nullable;
import android.bluetooth.BluetoothActivityEnergyInfo;
import android.bluetooth.BluetoothAdapter;
@@ -34,6 +36,7 @@
import android.telephony.TelephonyManager;
import android.util.IntArray;
import android.util.Slog;
+import android.util.SparseLongArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BatteryStatsImpl;
@@ -43,6 +46,8 @@
import libcore.util.EmptyArray;
+import java.util.ArrayList;
+import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
@@ -129,9 +134,13 @@
// WiFi keeps an accumulated total of stats, unlike Bluetooth.
// Keep the last WiFi stats so we can compute a delta.
@GuardedBy("mWorkerLock")
- private WifiActivityEnergyInfo mLastInfo =
+ private WifiActivityEnergyInfo mLastWifiInfo =
new WifiActivityEnergyInfo(0, 0, 0, 0, 0, 0);
+ /** Snapshot of measured energies, or null if no measured energies are supported. */
+ @GuardedBy("mWorkerLock")
+ private final @Nullable MeasuredEnergySnapshot mMeasuredEnergySnapshot;
+
/**
* Timestamp at which all external stats were last collected in
* {@link SystemClock#elapsedRealtime()} time base.
@@ -139,9 +148,13 @@
@GuardedBy("this")
private long mLastCollectionTimeStamp;
- BatteryExternalStatsWorker(Context context, BatteryStatsImpl stats) {
+ BatteryExternalStatsWorker(Context context, BatteryStatsImpl stats,
+ @Nullable MeasuredEnergyArray initialMeasuredEnergies) {
mContext = context;
mStats = stats;
+
+ mMeasuredEnergySnapshot = initialMeasuredEnergies == null ?
+ null : new MeasuredEnergySnapshot(initialMeasuredEnergies);
}
@Override
@@ -417,7 +430,6 @@
SynchronousResultReceiver bluetoothReceiver = null;
CompletableFuture<ModemActivityInfo> modemFuture = CompletableFuture.completedFuture(null);
boolean railUpdated = false;
- MeasuredEnergyArray energyArray = null;
if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_WIFI) != 0) {
// We were asked to fetch WiFi data.
@@ -495,13 +507,6 @@
}
}
- if ((updateFlags & UPDATE_ENERGY) != 0) {
- synchronized (mStats) {
- // TODO(b/172934873) evaluate a safe way to query the HAL without holding mStats
- energyArray = mStats.getEnergyConsumptionDataLocked();
- }
- }
-
final WifiActivityEnergyInfo wifiInfo = awaitControllerInfo(wifiReceiver);
final BluetoothActivityEnergyInfo bluetoothInfo = awaitControllerInfo(bluetoothReceiver);
ModemActivityInfo modemInfo = null;
@@ -513,6 +518,9 @@
} catch (ExecutionException e) {
Slog.w(TAG, "exception reading modem stats: " + e.getCause());
}
+ final SparseLongArray energyDeltas = mMeasuredEnergySnapshot == null ? null :
+ mMeasuredEnergySnapshot.updateAndGetDelta(getMeasuredEnergyLocked(updateFlags));
+
final long elapsedRealtime = SystemClock.elapsedRealtime();
final long uptime = SystemClock.uptimeMillis();
final long elapsedRealtimeUs = elapsedRealtime * 1000;
@@ -542,6 +550,13 @@
mStats.updateRpmStatsLocked(elapsedRealtimeUs);
}
+ // Inform mStats about each applicable measured energy.
+ if (energyDeltas != null) {
+ final long displayEnergy = energyDeltas.get(SUBSYSTEM_DISPLAY, 0L);
+ // Always pass in what BatteryExternalStatsWorker thinks screenState is.
+ mStats.updateDisplayEnergyLocked(displayEnergy, screenState, elapsedRealtime);
+ }
+
if (bluetoothInfo != null) {
if (bluetoothInfo.isValid()) {
mStats.updateBluetoothStateLocked(bluetoothInfo, elapsedRealtime, uptime);
@@ -549,11 +564,6 @@
Slog.w(TAG, "bluetooth info is invalid: " + bluetoothInfo);
}
}
-
- if ((updateFlags & UPDATE_ENERGY) != 0 && energyArray != null) {
- // Always use what BatteryExternalStatsWorker thinks screenState is.
- mStats.updateMeasuredEnergyStatsLocked(energyArray, screenState);
- }
}
// WiFi and Modem state are updated without the mStats lock held, because they
@@ -561,7 +571,9 @@
if (wifiInfo != null) {
if (wifiInfo.isValid()) {
- mStats.updateWifiState(extractDeltaLocked(wifiInfo), elapsedRealtime, uptime);
+ // TODO: wifiEnergyDelta = energyDeltas.get(MeasuredEnergyArray.SUBSYSTEM_WIFI, 0L);
+ mStats.updateWifiState(extractDeltaLocked(wifiInfo)
+ /*, TODO: wifiEnergyDelta */, elapsedRealtime, uptime);
} else {
Slog.w(TAG, "wifi info is invalid: " + wifiInfo);
}
@@ -570,6 +582,11 @@
if (modemInfo != null) {
mStats.updateMobileRadioState(modemInfo, elapsedRealtime, uptime);
}
+
+ if (updateFlags == UPDATE_ALL) {
+ // This helps mStats deal with ignoring data from prior to resets.
+ mStats.informThatAllExternalStatsAreFlushed();
+ }
}
/**
@@ -604,12 +621,12 @@
@GuardedBy("mWorkerLock")
private WifiActivityEnergyInfo extractDeltaLocked(WifiActivityEnergyInfo latest) {
final long timePeriodMs = latest.getTimeSinceBootMillis()
- - mLastInfo.getTimeSinceBootMillis();
- final long lastScanMs = mLastInfo.getControllerScanDurationMillis();
- final long lastIdleMs = mLastInfo.getControllerIdleDurationMillis();
- final long lastTxMs = mLastInfo.getControllerTxDurationMillis();
- final long lastRxMs = mLastInfo.getControllerRxDurationMillis();
- final long lastEnergy = mLastInfo.getControllerEnergyUsedMicroJoules();
+ - mLastWifiInfo.getTimeSinceBootMillis();
+ final long lastScanMs = mLastWifiInfo.getControllerScanDurationMillis();
+ final long lastIdleMs = mLastWifiInfo.getControllerIdleDurationMillis();
+ final long lastTxMs = mLastWifiInfo.getControllerTxDurationMillis();
+ final long lastRxMs = mLastWifiInfo.getControllerRxDurationMillis();
+ final long lastEnergy = mLastWifiInfo.getControllerEnergyUsedMicroJoules();
final long deltaTimeSinceBootMillis = latest.getTimeSinceBootMillis();
final int deltaStackState = latest.getStackState();
@@ -657,7 +674,7 @@
wasReset = false;
}
- mLastInfo = latest;
+ mLastWifiInfo = latest;
WifiActivityEnergyInfo delta = new WifiActivityEnergyInfo(
deltaTimeSinceBootMillis,
deltaStackState,
@@ -671,4 +688,39 @@
}
return delta;
}
+
+ // TODO(b/172934873): Evaluate a safe way to query the HAL without holding mStats
+ /** Fetch MeasuredEnergyArray for supported subsystems based on the given updateFlags. */
+ @GuardedBy("mWorkerLock")
+ private @Nullable MeasuredEnergyArray getMeasuredEnergyLocked(@ExternalUpdateFlag int flags) {
+ if (mMeasuredEnergySnapshot == null) return null;
+
+ if (flags == UPDATE_ALL) {
+ // Gotta catch 'em all... including custom (non-specific) subsystems
+ synchronized (mStats) {
+ return mStats.getEnergyConsumptionDataLocked();
+ }
+ }
+
+ final List<Integer> energyConsumerIds = new ArrayList<>();
+ if ((flags & UPDATE_DISPLAY) != 0) {
+ addEnergyConsumerIdLocked(energyConsumerIds, SUBSYSTEM_DISPLAY);
+ }
+ // TODO: Wifi, Bluetooth, etc., go here
+ if (energyConsumerIds.isEmpty()) {
+ return null;
+ }
+ synchronized (mStats) {
+ // TODO: Query *specific* subsystems from HAL based on energyConsumerIds.toArray()
+ return mStats.getEnergyConsumptionDataLocked();
+ }
+ }
+
+ @GuardedBy("mWorkerLock")
+ private void addEnergyConsumerIdLocked(List<Integer> energyConsumerIds,
+ @MeasuredEnergyArray.MeasuredEnergySubsystem int consumerId) {
+ if (mMeasuredEnergySnapshot.hasSubsystem(consumerId)) {
+ energyConsumerIds.add(consumerId);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 0ab3c9e..2f7c523 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -16,6 +16,7 @@
package com.android.server.am;
+import android.annotation.Nullable;
import android.bluetooth.BluetoothActivityEnergyInfo;
import android.content.ContentResolver;
import android.content.Context;
@@ -26,6 +27,7 @@
import android.os.BatteryStats;
import android.os.BatteryStatsInternal;
import android.os.BatteryUsageStats;
+import android.os.BatteryUsageStatsQuery;
import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
@@ -64,6 +66,8 @@
import com.android.internal.os.RailStats;
import com.android.internal.os.RpmStats;
import com.android.internal.power.MeasuredEnergyArray;
+import com.android.internal.power.MeasuredEnergyArray.MeasuredEnergySubsystem;
+import com.android.internal.power.MeasuredEnergyStats;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.ParseUtils;
@@ -196,7 +200,7 @@
}
@Override
- public MeasuredEnergyArray getEnergyConsumptionData() {
+ public @Nullable MeasuredEnergyArray getEnergyConsumptionData() {
final EnergyConsumerResult[] results = mPowerStatsHALWrapper.getEnergyConsumed(new int[0]);
if (results == null) return null;
final int size = results.length;
@@ -250,22 +254,44 @@
mHandler = new Handler(mHandlerThread.getLooper());
// TODO(b/173077356): Replace directly calling the HAL with PowerStatsService queries
- // Make sure to init Hal Wrapper before creating BatteryStatsImpl.
- mPowerStatsHALWrapper = new PowerStatsHALWrapper.PowerStatsHALWrapperImpl();
- mPowerStatsHALWrapper.initialize();
+ mPowerStatsHALWrapper = PowerStatsHALWrapper.getPowerStatsHalImpl();
+ final MeasuredEnergyArray initialEnergies = getEnergyConsumptionData();
+ final boolean[] supportedBuckets = getSupportedEnergyBuckets(initialEnergies);
mStats = new BatteryStatsImpl(systemDir, handler, this,
- this, mUserManagerUserInfoProvider);
- mWorker = new BatteryExternalStatsWorker(context, mStats);
+ this, supportedBuckets, mUserManagerUserInfoProvider);
+ mWorker = new BatteryExternalStatsWorker(context, mStats, initialEnergies);
mStats.setExternalStatsSyncLocked(mWorker);
mStats.setRadioScanningTimeoutLocked(mContext.getResources().getInteger(
com.android.internal.R.integer.config_radioScanningTimeout) * 1000L);
mStats.setPowerProfileLocked(new PowerProfile(context));
- mStats.startTrackingSystemServerCpuTime();
-
mBatteryUsageStatsProvider = new BatteryUsageStatsProvider(context, mStats);
}
+ /**
+ * Map the {@link MeasuredEnergySubsystem}s in the given energyArray to their corresponding
+ * {@link MeasuredEnergyStats.EnergyBucket}s.
+ *
+ * @return array with true for index i if energy bucket i is supported.
+ */
+ private static @Nullable boolean[] getSupportedEnergyBuckets(MeasuredEnergyArray energyArray) {
+ if (energyArray == null) {
+ return null;
+ }
+ final boolean[] buckets = new boolean[MeasuredEnergyStats.NUMBER_ENERGY_BUCKETS];
+ final int size = energyArray.size();
+ for (int energyIdx = 0; energyIdx < size; energyIdx++) {
+ switch (energyArray.getSubsystem(energyIdx)) {
+ case MeasuredEnergyArray.SUBSYSTEM_DISPLAY:
+ buckets[MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_ON] = true;
+ buckets[MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_DOZE] = true;
+ buckets[MeasuredEnergyStats.ENERGY_BUCKET_SCREEN_OTHER] = true;
+ break;
+ }
+ }
+ return buckets;
+ }
+
public void publish() {
LocalServices.addService(BatteryStatsInternal.class, new LocalService());
ServiceManager.addService(BatteryStats.SERVICE_NAME, asBinder());
@@ -560,10 +586,10 @@
* Returns BatteryUsageStats, which contains power attribution data on a per-subsystem
* and per-UID basis.
*/
- public BatteryUsageStats getBatteryUsageStats() {
+ public BatteryUsageStats getBatteryUsageStats(BatteryUsageStatsQuery query) {
mContext.enforceCallingPermission(
android.Manifest.permission.BATTERY_STATS, null);
- return mBatteryUsageStatsProvider.getBatteryUsageStats();
+ return mBatteryUsageStatsProvider.getBatteryUsageStats(query);
}
public byte[] getStatistics() {
@@ -2035,7 +2061,7 @@
private void dumpMeasuredEnergyStats(PrintWriter pw) {
// Wait for the completion of pending works if there is any
awaitCompletion();
- syncStats("dump", BatteryExternalStatsWorker.UPDATE_ENERGY);
+ syncStats("dump", BatteryExternalStatsWorker.UPDATE_ALL);
synchronized (mStats) {
mStats.dumpMeasuredEnergyStatsLocked(pw);
}
@@ -2135,7 +2161,6 @@
pw.println("Battery stats reset.");
noOutput = true;
}
- mWorker.scheduleSync("dump", BatteryExternalStatsWorker.UPDATE_ALL);
} else if ("--write".equals(arg)) {
awaitCompletion();
syncStats("dump", BatteryExternalStatsWorker.UPDATE_ALL);
@@ -2245,6 +2270,7 @@
in.setDataPosition(0);
BatteryStatsImpl checkinStats = new BatteryStatsImpl(
null, mStats.mHandler, null, null,
+ null /* energy buckets not currently in checkin anyway */,
mUserManagerUserInfoProvider);
checkinStats.readSummaryFromParcel(in);
in.recycle();
@@ -2285,6 +2311,7 @@
in.setDataPosition(0);
BatteryStatsImpl checkinStats = new BatteryStatsImpl(
null, mStats.mHandler, null, null,
+ null /* energy buckets not currently in checkin anyway */,
mUserManagerUserInfoProvider);
checkinStats.readSummaryFromParcel(in);
in.recycle();
diff --git a/services/core/java/com/android/server/am/MeasuredEnergySnapshot.java b/services/core/java/com/android/server/am/MeasuredEnergySnapshot.java
new file mode 100644
index 0000000..b915c0c
--- /dev/null
+++ b/services/core/java/com/android/server/am/MeasuredEnergySnapshot.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+
+import android.annotation.Nullable;
+import android.util.Slog;
+import android.util.SparseLongArray;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.power.MeasuredEnergyArray;
+import com.android.internal.power.MeasuredEnergyArray.MeasuredEnergySubsystem;
+
+import java.io.PrintWriter;
+import java.util.Arrays;
+
+/**
+ * Keeps snapshots of data from previously pulled MeasuredEnergyArrays.
+ */
+@VisibleForTesting
+public class MeasuredEnergySnapshot {
+ private static final String TAG = "MeasuredEnergySnapshot";
+
+ private static final long UNAVAILABLE = -1;
+
+ /**
+ * Energy snapshots from the last time each {@link MeasuredEnergySubsystem} was updated.
+ *
+ * Note that the snapshots for different subsystems may have been taken at different times.
+ *
+ * A snapshot is {@link #UNAVAILABLE} if the subsystem has never been updated (ie. unsupported).
+ */
+ private final long[] mMeasuredEnergySnapshots;
+
+ /**
+ * Constructor that initializes to the given energyArray;
+ * all subsystems not mentioned in initialEnergyArray are set to UNAVAILABLE.
+ */
+ public MeasuredEnergySnapshot(MeasuredEnergyArray initialEnergyArray) {
+ this(MeasuredEnergyArray.NUMBER_SUBSYSTEMS, initialEnergyArray);
+ }
+
+ /**
+ * Constructor (for testing) that initializes to the given energyArray and numSubsystems;
+ * all subsystems not mentioned in initialEnergyArray are set to UNAVAILABLE.
+ */
+ @VisibleForTesting
+ MeasuredEnergySnapshot(int numSubsystems, MeasuredEnergyArray initialEnergyArray) {
+ if (initialEnergyArray.size() > numSubsystems) {
+ throw new IllegalArgumentException("Energy array contains " + initialEnergyArray.size()
+ + " subsystems, which exceeds the maximum allowed of " + numSubsystems);
+ }
+ mMeasuredEnergySnapshots = new long[numSubsystems];
+ Arrays.fill(mMeasuredEnergySnapshots, UNAVAILABLE);
+ fillGivenSubsystems(initialEnergyArray);
+ }
+
+ /**
+ * For the subsystems present in energyArray, overwrites mMeasuredEnergySnapshots with their
+ * energy values from energyArray.
+ */
+ private void fillGivenSubsystems(MeasuredEnergyArray energyArray) {
+ final int size = energyArray.size();
+ for (int i = 0; i < size; i++) {
+ final int subsystem = energyArray.getSubsystem(i);
+ mMeasuredEnergySnapshots[subsystem] = energyArray.getEnergy(i);
+ }
+ }
+
+ /**
+ * Update with the some freshly measured energies and return the difference (delta)
+ * between the previously stored values and the passed-in values.
+ *
+ * @param energyArray measured energy array for some (possibly not all) subsystems.
+ *
+ * @return a map from the updated subsystems to their corresponding energy deltas.
+ * Subsystems not present in energyArray will not appear.
+ * Subsystems with no difference in energy will not appear.
+ * Returns null, if energyArray is null.
+ */
+ public @Nullable SparseLongArray updateAndGetDelta(MeasuredEnergyArray energyArray) {
+ if (energyArray == null) {
+ return null;
+ }
+ final SparseLongArray delta = new SparseLongArray();
+ final int size = energyArray.size();
+ for (int i = 0; i < size; i++) {
+ final int updatedSubsystem = energyArray.getSubsystem(i);
+ final long newEnergyUJ = energyArray.getEnergy(i);
+ final long oldEnergyUJ = mMeasuredEnergySnapshots[updatedSubsystem];
+
+ // If this is the first valid energy, there is no delta to take.
+ if (oldEnergyUJ < 0) continue;
+ final long deltaUJ = newEnergyUJ - oldEnergyUJ;
+ if (deltaUJ == 0) continue;
+ if (deltaUJ < 0) {
+ Slog.e(TAG, "For subsystem " + updatedSubsystem + ", new energy (" + newEnergyUJ
+ + ") is less than old energy (" + oldEnergyUJ + "). Skipping. ");
+ continue;
+ }
+ delta.put(updatedSubsystem, deltaUJ);
+ }
+
+ fillGivenSubsystems(energyArray);
+
+ return delta;
+ }
+
+ /**
+ * Check if a subsystem's measured energy is available.
+ * @param subsystem which subsystem.
+ * @return true if subsystem is available.
+ */
+ public boolean hasSubsystem(@MeasuredEnergySubsystem int subsystem) {
+ return mMeasuredEnergySnapshots[subsystem] != UNAVAILABLE;
+ }
+
+ /** Dump debug data. */
+ public void dump(PrintWriter pw) {
+ pw.println("Measured energy snapshot (microjoules):");
+ pw.print(" ");
+ for (int i = 0; i < MeasuredEnergyArray.NUMBER_SUBSYSTEMS; i++) {
+ final long energyUJ = mMeasuredEnergySnapshots[i];
+ if (energyUJ == UNAVAILABLE) continue;
+ pw.print(MeasuredEnergyArray.SUBSYSTEM_NAMES[i]);
+ pw.print(" : ");
+ pw.print(energyUJ);
+ if (i != MeasuredEnergyArray.NUMBER_SUBSYSTEMS - 1) {
+ pw.print(", ");
+ }
+ }
+ pw.println();
+ }
+}
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 4da7825..360ed9d 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -93,6 +93,7 @@
import android.app.AsyncNotedAppOp;
import android.app.RuntimeAppOpAccessMessage;
import android.app.SyncNotedAppOp;
+import android.app.admin.DevicePolicyManagerInternal;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -273,6 +274,8 @@
private final AppOpsManagerInternalImpl mAppOpsManagerInternal
= new AppOpsManagerInternalImpl();
+ @Nullable private final DevicePolicyManagerInternal dpmi =
+ LocalServices.getService(DevicePolicyManagerInternal.class);
private final IPlatformCompat mPlatformCompat = IPlatformCompat.Stub.asInterface(
ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
@@ -2690,6 +2693,10 @@
Ops pkgOps = ent.getValue();
for (int j=pkgOps.size()-1; j>=0; j--) {
Op curOp = pkgOps.valueAt(j);
+ if (shouldDeferResetOpToDpm(curOp.op)) {
+ deferResetOpToDpm(curOp.op, reqPackageName, reqUserId);
+ continue;
+ }
if (AppOpsManager.opAllowsReset(curOp.op)
&& curOp.mode != AppOpsManager.opToDefaultMode(curOp.op)) {
int previousMode = curOp.mode;
@@ -2739,16 +2746,27 @@
}
}
- if (allChanges != null) {
- int numChanges = allChanges.size();
- for (int i = 0; i < numChanges; i++) {
- ChangeRec change = allChanges.get(i);
- notifyOpChangedSync(change.op, change.uid, change.pkg,
- AppOpsManager.opToDefaultMode(change.op), change.previous_mode);
- }
+ int numChanges = allChanges.size();
+ for (int i = 0; i < numChanges; i++) {
+ ChangeRec change = allChanges.get(i);
+ notifyOpChangedSync(change.op, change.uid, change.pkg,
+ AppOpsManager.opToDefaultMode(change.op), change.previous_mode);
}
}
+ private boolean shouldDeferResetOpToDpm(int op) {
+ // TODO(b/174582385): avoid special-casing app-op resets by migrating app-op permission
+ // pre-grants to a role-based mechanism or another general-purpose mechanism.
+ return dpmi != null && dpmi.supportsResetOp(op);
+ }
+
+ /** Assumes {@link #shouldDeferResetOpToDpm(int)} is true. */
+ private void deferResetOpToDpm(int op, String packageName, @UserIdInt int userId) {
+ // TODO(b/174582385): avoid special-casing app-op resets by migrating app-op permission
+ // pre-grants to a role-based mechanism or another general-purpose mechanism.
+ dpmi.resetOp(op, packageName, userId);
+ }
+
private void evalAllForegroundOpsLocked() {
for (int uidi = mUidStates.size() - 1; uidi >= 0; uidi--) {
final UidState uidState = mUidStates.valueAt(uidi);
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 3b407f1..26f5c4c 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -16,6 +16,7 @@
package com.android.server.audio;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
@@ -31,14 +32,17 @@
import android.media.AudioSystem;
import android.media.IAudioRoutesObserver;
import android.media.ICapturePresetDevicesRoleDispatcher;
+import android.media.ICommunicationDeviceDispatcher;
import android.media.IStrategyPreferredDevicesDispatcher;
import android.media.MediaMetrics;
+import android.media.audiopolicy.AudioProductStrategy;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
+import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -49,6 +53,7 @@
import com.android.internal.annotations.GuardedBy;
import java.io.PrintWriter;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
@@ -75,7 +80,8 @@
private final @NonNull Context mContext;
/** Forced device usage for communications sent to AudioSystem */
- private int mForcedUseForComm;
+ private AudioDeviceAttributes mPreferredDeviceforComm;
+ private int mCommunicationStrategyId = -1;
// Manages all connected devices, only ever accessed on the message loop
private final AudioDeviceInventory mDeviceInventory;
@@ -131,10 +137,23 @@
init();
}
+ private void initCommunicationStrategyId() {
+ List<AudioProductStrategy> strategies = AudioProductStrategy.getAudioProductStrategies();
+ for (AudioProductStrategy strategy : strategies) {
+ if (strategy.getAudioAttributesForLegacyStreamType(AudioSystem.STREAM_VOICE_CALL)
+ != null) {
+ mCommunicationStrategyId = strategy.getId();
+ return;
+ }
+ }
+ mCommunicationStrategyId = -1;
+ }
+
private void init() {
setupMessaging(mContext);
- mForcedUseForComm = AudioSystem.FORCE_NONE;
+ mPreferredDeviceforComm = null;
+ initCommunicationStrategyId();
}
/*package*/ Context getContext() {
@@ -219,8 +238,7 @@
synchronized (mDeviceStateLock) {
AudioDeviceAttributes device = null;
if (on) {
- device = new AudioDeviceAttributes(AudioDeviceAttributes.ROLE_OUTPUT,
- AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, "");
+ device = new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_SPEAKER, "");
} else {
CommunicationRouteClient client = getCommunicationRouteClientForPid(pid);
if (client == null || !client.requestsSpeakerphone()) {
@@ -233,6 +251,38 @@
}
}
+ /**
+ * Select device for use for communication use cases.
+ * @param cb Client binder for death detection
+ * @param pid Client pid
+ * @param device Device selected or null to unselect.
+ * @param eventSource for logging purposes
+ */
+ /*package*/ boolean setDeviceForCommunication(
+ IBinder cb, int pid, AudioDeviceInfo device, String eventSource) {
+
+ if (AudioService.DEBUG_COMM_RTE) {
+ Log.v(TAG, "setDeviceForCommunication, device: " + device + ", pid: " + pid);
+ }
+
+ synchronized (mSetModeLock) {
+ synchronized (mDeviceStateLock) {
+ AudioDeviceAttributes deviceAttr = null;
+ if (device != null) {
+ deviceAttr = new AudioDeviceAttributes(device);
+ } else {
+ CommunicationRouteClient client = getCommunicationRouteClientForPid(pid);
+ if (client == null) {
+ return false;
+ }
+ }
+ setCommunicationRouteForClient(
+ cb, pid, deviceAttr, BtHelper.SCO_MODE_UNDEFINED, eventSource);
+ }
+ }
+ return true;
+ }
+
@GuardedBy("mDeviceStateLock")
/*package*/ void setCommunicationRouteForClient(
IBinder cb, int pid, AudioDeviceAttributes device,
@@ -241,6 +291,10 @@
if (AudioService.DEBUG_COMM_RTE) {
Log.v(TAG, "setCommunicationRouteForClient: device: " + device);
}
+ AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
+ "setCommunicationRouteForClient for pid: " + pid
+ + " device: " + device
+ + " from API: " + eventSource)).printLog(TAG));
final boolean wasBtScoRequested = isBluetoothScoRequested();
final boolean wasSpeakerphoneRequested = isSpeakerphoneRequested();
@@ -278,6 +332,7 @@
} else {
removeCommunicationRouteClient(cb, true);
}
+ postBroadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
}
} else if (!isBtScoRequested && wasBtScoRequested) {
mBtHelper.stopBluetoothSco(eventSource);
@@ -325,6 +380,20 @@
}
/**
+ * Returns the device currently requested for communication use case.
+ * @return AudioDeviceInfo the requested device for communication.
+ */
+ AudioDeviceInfo getDeviceForCommunication() {
+ synchronized (mDeviceStateLock) {
+ AudioDeviceAttributes device = requestedCommunicationDevice();
+ if (device == null) {
+ return null;
+ }
+ return AudioManager.getDeviceInfoFromType(device.getType());
+ }
+ }
+
+ /**
* Helper method on top of requestedCommunicationDevice() indicating if
* speakerphone ON is currently requested or not.
* @return true if speakerphone ON requested, false otherwise.
@@ -344,7 +413,11 @@
* @return true if speakerphone is active, false otherwise.
*/
/*package*/ boolean isSpeakerphoneOn() {
- return getForcedUseForComm() == AudioSystem.FORCE_SPEAKER;
+ AudioDeviceAttributes device = getPreferredDeviceForComm();
+ if (device == null) {
+ return false;
+ }
+ return device.getInternalType() == AudioSystem.DEVICE_OUT_SPEAKER;
}
/**
@@ -511,7 +584,11 @@
* @return true if Bluetooth SCO is active , false otherwise.
*/
/*package*/ boolean isBluetoothScoOn() {
- return getForcedUseForComm() == AudioSystem.FORCE_BT_SCO;
+ AudioDeviceAttributes device = getPreferredDeviceForComm();
+ if (device == null) {
+ return false;
+ }
+ return AudioSystem.DEVICE_OUT_ALL_SCO_SET.contains(device.getInternalType());
}
/*package*/ AudioRoutesInfo startWatchingRoutes(IAudioRoutesObserver observer) {
@@ -563,14 +640,9 @@
synchronized (mSetModeLock) {
synchronized (mDeviceStateLock) {
- AudioDeviceAttributes device = new AudioDeviceAttributes(
- AudioDeviceAttributes.ROLE_OUTPUT, AudioDeviceInfo.TYPE_BLUETOOTH_SCO, "");
+ AudioDeviceAttributes device =
+ new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, "");
setCommunicationRouteForClient(cb, pid, device, scoAudioMode, eventSource);
- if (!isBluetoothScoRequested()) {
- Log.w(TAG, "startBluetoothScoForClient_Sync: rejected for pid: "
- + pid + " mode owner pid: " + mModeOwnerPid);
- postBroadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
- }
}
}
}
@@ -599,10 +671,19 @@
return mDeviceInventory.setPreferredDevicesForStrategySync(strategy, devices);
}
+ /*package*/ void postSetPreferredDevicesForStrategy(int strategy,
+ @NonNull List<AudioDeviceAttributes> devices) {
+ sendILMsgNoDelay(MSG_IL_SET_PREF_DEVICES_FOR_STRATEGY, SENDMSG_REPLACE, strategy, devices);
+ }
+
/*package*/ int removePreferredDevicesForStrategySync(int strategy) {
return mDeviceInventory.removePreferredDevicesForStrategySync(strategy);
}
+ /*package*/ void postRemovePreferredDevicesForStrategy(int strategy) {
+ sendIMsgNoDelay(MSG_I_REMOVE_PREF_DEVICES_FOR_STRATEGY, SENDMSG_REPLACE, strategy);
+ }
+
/*package*/ void registerStrategyPreferredDevicesDispatcher(
@NonNull IStrategyPreferredDevicesDispatcher dispatcher) {
mDeviceInventory.registerStrategyPreferredDevicesDispatcher(dispatcher);
@@ -632,6 +713,45 @@
mDeviceInventory.unregisterCapturePresetDevicesRoleDispatcher(dispatcher);
}
+ /*package*/ void registerCommunicationDeviceDispatcher(
+ @NonNull ICommunicationDeviceDispatcher dispatcher) {
+ mCommDevDispatchers.register(dispatcher);
+ }
+
+ /*package*/ void unregisterCommunicationDeviceDispatcher(
+ @NonNull ICommunicationDeviceDispatcher dispatcher) {
+ mCommDevDispatchers.unregister(dispatcher);
+ }
+
+ // Monitoring of communication device
+ final RemoteCallbackList<ICommunicationDeviceDispatcher> mCommDevDispatchers =
+ new RemoteCallbackList<ICommunicationDeviceDispatcher>();
+
+ // portId of the device currently selected for communication: avoids broadcasting changes
+ // when same communication route is applied
+ @GuardedBy("mDeviceStateLock")
+ int mCurCommunicationPortId = -1;
+
+ @GuardedBy("mDeviceStateLock")
+ private void dispatchCommunicationDevice() {
+ AudioDeviceInfo device = getDeviceForCommunication();
+ int portId = (getDeviceForCommunication() == null) ? 0 : device.getId();
+ if (portId == mCurCommunicationPortId) {
+ return;
+ }
+ mCurCommunicationPortId = portId;
+
+ final int nbDispatchers = mCommDevDispatchers.beginBroadcast();
+ for (int i = 0; i < nbDispatchers; i++) {
+ try {
+ mCommDevDispatchers.getBroadcastItem(i)
+ .dispatchCommunicationDeviceChanged(portId);
+ } catch (RemoteException e) {
+ }
+ }
+ mCommDevDispatchers.finishBroadcast();
+ }
+
//---------------------------------------------------------------------
// Communication with (to) AudioService
//TODO check whether the AudioService methods are candidates to move here
@@ -888,9 +1008,12 @@
pw.println(" " + prefix + "pid: " + cl.getPid() + " device: "
+ cl.getDevice() + " cb: " + cl.getBinder()); });
- pw.println("\n" + prefix + "mForcedUseForComm: "
- + AudioSystem.forceUseConfigToString(mForcedUseForComm));
- pw.println(prefix + "mModeOwnerPid: " + mModeOwnerPid);
+ pw.println("\n" + prefix + "mPreferredDeviceforComm: "
+ + mPreferredDeviceforComm);
+ pw.println(prefix + "mCommunicationStrategyId: "
+ + mCommunicationStrategyId);
+
+ pw.println("\n" + prefix + "mModeOwnerPid: " + mModeOwnerPid);
mBtHelper.dump(pw, prefix);
}
@@ -985,6 +1108,7 @@
case MSG_RESTORE_DEVICES:
synchronized (mSetModeLock) {
synchronized (mDeviceStateLock) {
+ initCommunicationStrategyId();
mDeviceInventory.onRestoreDevices();
mBtHelper.onAudioServerDiedRestoreA2dp();
onUpdateCommunicationRoute("MSG_RESTORE_DEVICES");
@@ -1194,6 +1318,17 @@
final int strategy = msg.arg1;
mDeviceInventory.onSaveRemovePreferredDevices(strategy);
} break;
+ case MSG_IL_SET_PREF_DEVICES_FOR_STRATEGY: {
+ final int strategy = msg.arg1;
+ final List<AudioDeviceAttributes> devices =
+ (List<AudioDeviceAttributes>) msg.obj;
+ setPreferredDevicesForStrategySync(strategy, devices);
+
+ } break;
+ case MSG_I_REMOVE_PREF_DEVICES_FOR_STRATEGY: {
+ final int strategy = msg.arg1;
+ removePreferredDevicesForStrategySync(strategy);
+ } break;
case MSG_CHECK_MUTE_MUSIC:
checkMessagesMuteMusic(0);
break;
@@ -1286,7 +1421,8 @@
private static final int MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET = 38;
private static final int MSG_L_UPDATE_COMMUNICATION_ROUTE = 39;
-
+ private static final int MSG_IL_SET_PREF_DEVICES_FOR_STRATEGY = 40;
+ private static final int MSG_I_REMOVE_PREF_DEVICES_FOR_STRATEGY = 41;
private static boolean isMessageHandledUnderWakelock(int msgId) {
switch(msgId) {
@@ -1526,16 +1662,25 @@
* @return selected forced usage for communication.
*/
@GuardedBy("mDeviceStateLock")
- private int getForcedUseForComm() {
+ @Nullable private AudioDeviceAttributes getPreferredDeviceForComm() {
boolean btSCoOn = mBluetoothScoOn && mBtHelper.isBluetoothScoOn();
-
if (btSCoOn) {
- return AudioSystem.FORCE_BT_SCO;
+ // Use the SCO device known to BtHelper so that it matches exactly
+ // what has been communicated to audio policy manager. The device
+ // returned by requestedCommunicationDevice() can be a dummy SCO device if legacy
+ // APIs are used to start SCO audio.
+ AudioDeviceAttributes device = mBtHelper.getHeadsetAudioDevice();
+ if (device != null) {
+ return device;
+ }
}
- if (isSpeakerphoneRequested()) {
- return AudioSystem.FORCE_SPEAKER;
+ AudioDeviceAttributes device = requestedCommunicationDevice();
+ if (device == null
+ || AudioSystem.DEVICE_OUT_ALL_SCO_SET.contains(device.getInternalType())) {
+ // Do not indicate BT SCO selection if SCO is requested but SCO is not ON
+ return null;
}
- return AudioSystem.FORCE_NONE;
+ return device;
}
/**
@@ -1545,32 +1690,27 @@
// @GuardedBy("mSetModeLock")
@GuardedBy("mDeviceStateLock")
private void onUpdateCommunicationRoute(String eventSource) {
- mForcedUseForComm = getForcedUseForComm();
-
+ mPreferredDeviceforComm = getPreferredDeviceForComm();
if (AudioService.DEBUG_COMM_RTE) {
- Log.v(TAG, "onUpdateCommunicationRoute, mForcedUseForComm: " + mForcedUseForComm
- + " eventSource: " + eventSource);
+ Log.v(TAG, "onUpdateCommunicationRoute, mPreferredDeviceforComm: "
+ + mPreferredDeviceforComm + " eventSource: " + eventSource);
}
- if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) {
- AudioSystem.setParameters("BT_SCO=on");
- setForceUse_Async(
- AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_BT_SCO, eventSource);
- setForceUse_Async(
- AudioSystem.FOR_RECORD, AudioSystem.FORCE_BT_SCO, eventSource);
- } else {
+ if (mPreferredDeviceforComm == null
+ || !AudioSystem.DEVICE_OUT_ALL_SCO_SET.contains(
+ mPreferredDeviceforComm.getInternalType())) {
AudioSystem.setParameters("BT_SCO=off");
- setForceUse_Async(
- AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE, eventSource);
- if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER) {
- setForceUse_Async(
- AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_SPEAKER, eventSource);
- } else {
- setForceUse_Async(
- AudioSystem.FOR_COMMUNICATION, AudioSystem.FORCE_NONE, eventSource);
- }
+ } else {
+ AudioSystem.setParameters("BT_SCO=on");
+ }
+ if (mPreferredDeviceforComm == null) {
+ postRemovePreferredDevicesForStrategy(mCommunicationStrategyId);
+ } else {
+ postSetPreferredDevicesForStrategy(
+ mCommunicationStrategyId, Arrays.asList(mPreferredDeviceforComm));
}
mAudioService.postUpdateRingerModeServiceInt();
+ dispatchCommunicationDevice();
}
private CommunicationRouteClient removeCommunicationRouteClient(
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 33a8a30..82586b8 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -648,6 +648,10 @@
/*package*/ int setPreferredDevicesForStrategySync(int strategy,
@NonNull List<AudioDeviceAttributes> devices) {
final long identity = Binder.clearCallingIdentity();
+
+ AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
+ "setPreferredDevicesForStrategySync, strategy: " + strategy
+ + " devices: " + devices)).printLog(TAG));
final int status = mAudioSystem.setDevicesRoleForStrategy(
strategy, AudioSystem.DEVICE_ROLE_PREFERRED, devices);
Binder.restoreCallingIdentity(identity);
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 6bc927a..ada67b1 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -85,6 +85,7 @@
import android.media.IAudioServerStateDispatcher;
import android.media.IAudioService;
import android.media.ICapturePresetDevicesRoleDispatcher;
+import android.media.ICommunicationDeviceDispatcher;
import android.media.IPlaybackConfigDispatcher;
import android.media.IRecordingConfigDispatcher;
import android.media.IRingtonePlayer;
@@ -2108,10 +2109,22 @@
return getDevicesForAttributesInt(attributes);
}
- /** @see AudioManager#isMusicActive() */
- public boolean isMusicActive() {
+ /**
+ * @see AudioManager#isMusicActive()
+ * @param remotely true if query is for remote playback (cast), false for local playback.
+ */
+ public boolean isMusicActive(boolean remotely) {
// no permission required
- return AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0);
+ final long token = Binder.clearCallingIdentity();
+ try {
+ if (remotely) {
+ return AudioSystem.isStreamActiveRemotely(AudioSystem.STREAM_MUSIC, 0);
+ } else {
+ return AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
protected @NonNull ArrayList<AudioDeviceAttributes> getDevicesForAttributesInt(
@@ -4405,6 +4418,115 @@
restoreDeviceVolumeBehavior();
}
+ private static final int[] VALID_COMMUNICATION_DEVICE_TYPES = {
+ AudioDeviceInfo.TYPE_BUILTIN_SPEAKER,
+ AudioDeviceInfo.TYPE_BLUETOOTH_SCO,
+ AudioDeviceInfo.TYPE_WIRED_HEADSET,
+ AudioDeviceInfo.TYPE_USB_HEADSET,
+ AudioDeviceInfo.TYPE_BUILTIN_EARPIECE,
+ AudioDeviceInfo.TYPE_WIRED_HEADPHONES,
+ AudioDeviceInfo.TYPE_HEARING_AID,
+ AudioDeviceInfo.TYPE_BLE_HEADSET,
+ AudioDeviceInfo.TYPE_USB_DEVICE,
+ AudioDeviceInfo.TYPE_BLE_SPEAKER,
+ AudioDeviceInfo.TYPE_LINE_ANALOG,
+ AudioDeviceInfo.TYPE_HDMI,
+ AudioDeviceInfo.TYPE_AUX_LINE
+ };
+
+ private boolean isValidCommunicationDevice(AudioDeviceInfo device) {
+ for (int type : VALID_COMMUNICATION_DEVICE_TYPES) {
+ if (device.getType() == type) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /** @see AudioManager#setDeviceForCommunication(int) */
+ public boolean setDeviceForCommunication(IBinder cb, int portId) {
+ final int uid = Binder.getCallingUid();
+ final int pid = Binder.getCallingPid();
+
+ AudioDeviceInfo device = null;
+ if (portId != 0) {
+ device = AudioManager.getDeviceForPortId(portId, AudioManager.GET_DEVICES_OUTPUTS);
+ if (device == null) {
+ throw new IllegalArgumentException("invalid portID " + portId);
+ }
+ if (!isValidCommunicationDevice(device)) {
+ throw new IllegalArgumentException("invalid device type " + device.getType());
+ }
+ }
+ final String eventSource = new StringBuilder("setDeviceForCommunication(")
+ .append(") from u/pid:").append(uid).append("/")
+ .append(pid).toString();
+
+ int deviceType = AudioSystem.DEVICE_OUT_DEFAULT;
+ String deviceAddress = null;
+ if (device != null) {
+ deviceType = device.getPort().type();
+ deviceAddress = device.getAddress();
+ } else {
+ AudioDeviceInfo curDevice = mDeviceBroker.getDeviceForCommunication();
+ if (curDevice != null) {
+ deviceType = curDevice.getPort().type();
+ deviceAddress = curDevice.getAddress();
+ }
+ }
+ // do not log metrics if clearing communication device while no communication device
+ // was selected
+ if (deviceType != AudioSystem.DEVICE_OUT_DEFAULT) {
+ new MediaMetrics.Item(MediaMetrics.Name.AUDIO_DEVICE
+ + MediaMetrics.SEPARATOR + "setDeviceForCommunication")
+ .set(MediaMetrics.Property.DEVICE,
+ AudioSystem.getDeviceName(deviceType))
+ .set(MediaMetrics.Property.ADDRESS, deviceAddress)
+ .set(MediaMetrics.Property.STATE, device != null
+ ? MediaMetrics.Value.CONNECTED : MediaMetrics.Value.DISCONNECTED)
+ .record();
+ }
+
+ final long ident = Binder.clearCallingIdentity();
+ boolean status =
+ mDeviceBroker.setDeviceForCommunication(cb, pid, device, eventSource);
+ Binder.restoreCallingIdentity(ident);
+ return status;
+ }
+
+ /** @see AudioManager#getDeviceForCommunication() */
+ public int getDeviceForCommunication() {
+ final long ident = Binder.clearCallingIdentity();
+ AudioDeviceInfo device = mDeviceBroker.getDeviceForCommunication();
+ Binder.restoreCallingIdentity(ident);
+ if (device == null) {
+ return 0;
+ }
+ return device.getId();
+ }
+
+ /** @see AudioManager#addOnCommunicationDeviceChangedListener(
+ * Executor, AudioManager.OnCommunicationDeviceChangedListener)
+ */
+ public void registerCommunicationDeviceDispatcher(
+ @Nullable ICommunicationDeviceDispatcher dispatcher) {
+ if (dispatcher == null) {
+ return;
+ }
+ mDeviceBroker.registerCommunicationDeviceDispatcher(dispatcher);
+ }
+
+ /** @see AudioManager#removeOnCommunicationDeviceChangedListener(
+ * AudioManager.OnCommunicationDeviceChangedListener)
+ */
+ public void unregisterCommunicationDeviceDispatcher(
+ @Nullable ICommunicationDeviceDispatcher dispatcher) {
+ if (dispatcher == null) {
+ return;
+ }
+ mDeviceBroker.unregisterCommunicationDeviceDispatcher(dispatcher);
+ }
+
/** @see AudioManager#setSpeakerphoneOn(boolean) */
public void setSpeakerphoneOn(IBinder cb, boolean on) {
if (!checkAudioSettingsPermission("setSpeakerphoneOn()")) {
@@ -4999,8 +5121,7 @@
switch (mPlatformType) {
case AudioSystem.PLATFORM_VOICE:
if (isInCommunication()) {
- if (mAudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
- == AudioSystem.FORCE_BT_SCO) {
+ if (mDeviceBroker.isBluetoothScoOn()) {
// Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO...");
return AudioSystem.STREAM_BLUETOOTH_SCO;
} else {
@@ -5036,8 +5157,7 @@
}
default:
if (isInCommunication()) {
- if (mAudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
- == AudioSystem.FORCE_BT_SCO) {
+ if (mDeviceBroker.isBluetoothScoOn()) {
if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO");
return AudioSystem.STREAM_BLUETOOTH_SCO;
} else {
@@ -5181,7 +5301,7 @@
/** only public for mocking/spying, do not call outside of AudioService */
@VisibleForTesting
public int getDeviceForStream(int stream) {
- int device = getDevicesForStream(stream);
+ int device = getDevicesForStreamInt(stream);
if ((device & (device - 1)) != 0) {
// Multiple device selection is either:
// - speaker + one other device: give priority to speaker in this case.
@@ -5210,14 +5330,23 @@
return device;
}
- private int getDevicesForStream(int stream) {
- return getDevicesForStream(stream, true /*checkOthers*/);
+ /**
+ * @see AudioManager#getDevicesForStream(int)
+ */
+ public int getDevicesForStream(int streamType) {
+ ensureValidStreamType(streamType);
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return mAudioSystem.getDevicesForStream(streamType);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
- private int getDevicesForStream(int stream, boolean checkOthers) {
+ private int getDevicesForStreamInt(int stream) {
ensureValidStreamType(stream);
synchronized (VolumeStreamState.class) {
- return mStreamStates[stream].observeDevicesForStream_syncVSS(checkOthers);
+ return mStreamStates[stream].observeDevicesForStream_syncVSS(true);
}
}
@@ -6402,10 +6531,10 @@
}
pw.println();
pw.print(" Devices: ");
- final int devices = getDevicesForStream(mStreamType);
+ final int devices = getDevicesForStreamInt(mStreamType);
int device, i = 0, n = 0;
// iterate all devices from 1 to DEVICE_OUT_DEFAULT exclusive
- // (the default device is not returned by getDevicesForStream)
+ // (the default device is not returned by getDevicesForStreamInt)
while ((device = 1 << i) != AudioSystem.DEVICE_OUT_DEFAULT) {
if ((devices & device) != 0) {
if (n++ > 0) {
@@ -7637,7 +7766,7 @@
mDeviceBroker.setForceUse_Async(AudioSystem.FOR_HDMI_SYSTEM_AUDIO, config,
"setHdmiSystemAudioSupported");
}
- device = getDevicesForStream(AudioSystem.STREAM_MUSIC);
+ device = getDevicesForStreamInt(AudioSystem.STREAM_MUSIC);
}
}
return device;
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index ae0e805..c57d5af 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -27,6 +27,7 @@
import android.bluetooth.BluetoothHearingAid;
import android.bluetooth.BluetoothProfile;
import android.content.Intent;
+import android.media.AudioDeviceAttributes;
import android.media.AudioManager;
import android.media.AudioSystem;
import android.os.Binder;
@@ -530,46 +531,64 @@
mDeviceBroker.postBroadcastScoConnectionState(state);
}
- private boolean handleBtScoActiveDeviceChange(BluetoothDevice btDevice, boolean isActive) {
- if (btDevice == null) {
- return true;
+ @Nullable AudioDeviceAttributes getHeadsetAudioDevice() {
+ if (mBluetoothHeadsetDevice == null) {
+ return null;
}
+ return btHeadsetDeviceToAudioDevice(mBluetoothHeadsetDevice);
+ }
+
+ private AudioDeviceAttributes btHeadsetDeviceToAudioDevice(BluetoothDevice btDevice) {
String address = btDevice.getAddress();
+ if (!BluetoothAdapter.checkBluetoothAddress(address)) {
+ address = "";
+ }
BluetoothClass btClass = btDevice.getBluetoothClass();
- int inDevice = AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET;
- int[] outDeviceTypes = {
- AudioSystem.DEVICE_OUT_BLUETOOTH_SCO,
- AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
- AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT
- };
+ int nativeType = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO;
if (btClass != null) {
switch (btClass.getDeviceClass()) {
case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET:
case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE:
- outDeviceTypes = new int[] { AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET };
+ nativeType = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
break;
case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
- outDeviceTypes = new int[] { AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT };
+ nativeType = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
break;
}
}
- if (!BluetoothAdapter.checkBluetoothAddress(address)) {
- address = "";
+ if (AudioService.DEBUG_DEVICES) {
+ Log.i(TAG, "btHeadsetDeviceToAudioDevice btDevice: " + btDevice
+ + " btClass: " + (btClass == null ? "Unknown" : btClass)
+ + " nativeType: " + nativeType + " address: " + address);
}
+ return new AudioDeviceAttributes(nativeType, address);
+ }
+
+ private boolean handleBtScoActiveDeviceChange(BluetoothDevice btDevice, boolean isActive) {
+ if (btDevice == null) {
+ return true;
+ }
+ int inDevice = AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET;
+ AudioDeviceAttributes audioDevice = btHeadsetDeviceToAudioDevice(btDevice);
String btDeviceName = getName(btDevice);
boolean result = false;
if (isActive) {
- result |= mDeviceBroker.handleDeviceConnection(
- isActive, outDeviceTypes[0], address, btDeviceName);
+ result |= mDeviceBroker.handleDeviceConnection(isActive, audioDevice.getInternalType(),
+ audioDevice.getAddress(), btDeviceName);
} else {
+ int[] outDeviceTypes = {
+ AudioSystem.DEVICE_OUT_BLUETOOTH_SCO,
+ AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET,
+ AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT
+ };
for (int outDeviceType : outDeviceTypes) {
result |= mDeviceBroker.handleDeviceConnection(
- isActive, outDeviceType, address, btDeviceName);
+ isActive, outDeviceType, audioDevice.getAddress(), btDeviceName);
}
}
// handleDeviceConnection() && result to make sure the method get executed
result = mDeviceBroker.handleDeviceConnection(
- isActive, inDevice, address, btDeviceName) && result;
+ isActive, inDevice, audioDevice.getAddress(), btDeviceName) && result;
return result;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceUserState.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceUserState.java
index 78e875b..a26662d 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceUserState.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceUserState.java
@@ -133,7 +133,7 @@
if (tagName.equals(TAG_FACE)) {
String name = parser.getAttributeValue(null, ATTR_NAME);
int faceId = parser.getAttributeInt(null, ATTR_FACE_ID);
- int deviceId = parser.getAttributeInt(null, ATTR_DEVICE_ID);
+ long deviceId = parser.getAttributeLong(null, ATTR_DEVICE_ID);
mBiometrics.add(new Face(name, faceId, deviceId));
}
}
diff --git a/services/core/java/com/android/server/compat/CompatChange.java b/services/core/java/com/android/server/compat/CompatChange.java
index ff31931..a8aa9aa 100644
--- a/services/core/java/com/android/server/compat/CompatChange.java
+++ b/services/core/java/com/android/server/compat/CompatChange.java
@@ -143,6 +143,9 @@
* @return {@code true} if the change should be enabled for the package.
*/
boolean isEnabled(ApplicationInfo app) {
+ if (app == null) {
+ return defaultValue();
+ }
if (mPackageOverrides != null && mPackageOverrides.containsKey(app.packageName)) {
return mPackageOverrides.get(app.packageName);
}
@@ -156,6 +159,15 @@
}
/**
+ * Returns the default value for the change id, assuming there are no overrides.
+ *
+ * @return {@code false} if it's a default disabled change, {@code true} otherwise.
+ */
+ boolean defaultValue() {
+ return !getDisabled();
+ }
+
+ /**
* Checks whether a change has an override for a package.
* @param packageName name of the package
* @return true if there is such override
diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java
index d80c58b..8511118 100644
--- a/services/core/java/com/android/server/compat/CompatConfig.java
+++ b/services/core/java/com/android/server/compat/CompatConfig.java
@@ -392,6 +392,14 @@
return alreadyKnown;
}
+ boolean defaultChangeIdValue(long changeId) {
+ CompatChange c = mChanges.get(changeId);
+ if (c == null) {
+ return true;
+ }
+ return c.defaultValue();
+ }
+
@VisibleForTesting
void clearChanges() {
synchronized (mChanges) {
diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java
index 77d5411..4bd01d4 100644
--- a/services/core/java/com/android/server/compat/PlatformCompat.java
+++ b/services/core/java/com/android/server/compat/PlatformCompat.java
@@ -120,10 +120,12 @@
* permission check.
*/
public boolean isChangeEnabledInternal(long changeId, ApplicationInfo appInfo) {
- boolean value = isChangeEnabledInternalNoLogging(changeId, appInfo);
- reportChange(changeId, appInfo.uid,
- value ? ChangeReporter.STATE_ENABLED : ChangeReporter.STATE_DISABLED);
- return value;
+ boolean enabled = isChangeEnabledInternalNoLogging(changeId, appInfo);
+ if (appInfo != null) {
+ reportChange(changeId, appInfo.uid,
+ enabled ? ChangeReporter.STATE_ENABLED : ChangeReporter.STATE_DISABLED);
+ }
+ return enabled;
}
@Override
@@ -131,9 +133,6 @@
@UserIdInt int userId) {
checkCompatChangeReadAndLogPermission();
ApplicationInfo appInfo = getApplicationInfo(packageName, userId);
- if (appInfo == null) {
- return true;
- }
return isChangeEnabled(changeId, appInfo);
}
@@ -142,7 +141,7 @@
checkCompatChangeReadAndLogPermission();
String[] packages = mContext.getPackageManager().getPackagesForUid(uid);
if (packages == null || packages.length == 0) {
- return true;
+ return mCompatConfig.defaultChangeIdValue(changeId);
}
boolean enabled = true;
for (String packageName : packages) {
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index cabfbc0..228ad588 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -246,7 +246,12 @@
void checkInterruptAndDelay(boolean sleepLonger) throws InterruptedException;
}
- static class Dependencies {
+ @VisibleForTesting
+ public static class Dependencies {
+ public boolean isCallerSystem() {
+ return Binder.getCallingUid() == Process.SYSTEM_UID;
+ }
+
public void startService(final String serviceName) {
SystemService.start(serviceName);
}
@@ -267,6 +272,10 @@
return new File("/data/misc/vpn/state");
}
+ public DeviceIdleInternal getDeviceIdleInternal() {
+ return LocalServices.getService(DeviceIdleInternal.class);
+ }
+
public void sendArgumentsToDaemon(
final String daemon, final LocalSocket socket, final String[] arguments,
final RetryScheduler retryScheduler) throws IOException, InterruptedException {
@@ -373,6 +382,14 @@
}
@VisibleForTesting
+ public Vpn(Looper looper, Context context, Dependencies deps,
+ INetworkManagementService netService, INetd netd, @UserIdInt int userId,
+ @NonNull KeyStore keyStore) {
+ this(looper, context, deps, netService, netd, userId, keyStore,
+ new SystemServices(context), new Ikev2SessionCreator());
+ }
+
+ @VisibleForTesting
protected Vpn(Looper looper, Context context, Dependencies deps,
INetworkManagementService netService, INetd netd,
int userId, @NonNull KeyStore keyStore, SystemServices systemServices,
@@ -772,8 +789,7 @@
// Tell the OS that background services in this app need to be allowed for
// a short time, so we can bootstrap the VPN service.
- DeviceIdleInternal idleController =
- LocalServices.getService(DeviceIdleInternal.class);
+ DeviceIdleInternal idleController = mDeps.getDeviceIdleInternal();
idleController.addPowerSaveTempWhitelistApp(Process.myUid(), alwaysOnPackage,
VPN_LAUNCH_IDLE_ALLOWLIST_DURATION_MS, mUserId, false, "vpn");
@@ -1959,10 +1975,6 @@
return mContext.createContextAsUser(
UserHandle.of(userId), 0 /* flags */).getContentResolver();
}
-
- public boolean isCallerSystem() {
- return Binder.getCallingUid() == Process.SYSTEM_UID;
- }
}
private native int jniCreate(int mtu);
@@ -3112,7 +3124,7 @@
@VisibleForTesting
@Nullable
VpnProfile getVpnProfilePrivileged(@NonNull String packageName, @NonNull KeyStore keyStore) {
- if (!mSystemServices.isCallerSystem()) {
+ if (!mDeps.isCallerSystem()) {
Log.wtf(TAG, "getVpnProfilePrivileged called as non-System UID ");
return null;
}
diff --git a/services/core/java/com/android/server/display/AmbientBrightnessStatsTracker.java b/services/core/java/com/android/server/display/AmbientBrightnessStatsTracker.java
index 0f1e666..d74c702 100644
--- a/services/core/java/com/android/server/display/AmbientBrightnessStatsTracker.java
+++ b/services/core/java/com/android/server/display/AmbientBrightnessStatsTracker.java
@@ -217,7 +217,6 @@
}
final LocalDate cutOffDate = mInjector.getLocalDate().minusDays(MAX_DAYS_TO_TRACK);
- parser.next();
int outerDepth = parser.getDepth();
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
diff --git a/services/core/java/com/android/server/display/BrightnessTracker.java b/services/core/java/com/android/server/display/BrightnessTracker.java
index 7a8ba9f..2375f74 100644
--- a/services/core/java/com/android/server/display/BrightnessTracker.java
+++ b/services/core/java/com/android/server/display/BrightnessTracker.java
@@ -622,7 +622,6 @@
final long timeCutOff = mInjector.currentTimeMillis() - MAX_EVENT_AGE;
- parser.next();
int outerDepth = parser.getDepth();
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index a8e56a1..574d8c6 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -21,6 +21,7 @@
import android.view.DisplayAddress;
import com.android.server.display.config.DisplayConfiguration;
+import com.android.server.display.config.DisplayQuirks;
import com.android.server.display.config.NitsMap;
import com.android.server.display.config.Point;
import com.android.server.display.config.XmlParser;
@@ -32,6 +33,7 @@
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -45,6 +47,8 @@
public static final float HIGH_BRIGHTNESS_MODE_UNSUPPORTED = Float.NaN;
+ public static final String QUIRK_CAN_SET_BRIGHTNESS_VIA_HWC = "canSetBrightnessViaHwc";
+
private static final String ETC_DIR = "etc";
private static final String DISPLAY_CONFIG_DIR = "displayconfig";
private static final String CONFIG_FILE_FORMAT = "display_%s.xml";
@@ -55,6 +59,7 @@
private float[] mNits;
private float[] mBrightness;
+ private List<String> mQuirks;
private DisplayDeviceConfig() {
}
@@ -134,11 +139,21 @@
return mBrightness;
}
+ /**
+ * @param quirkValue The quirk to test.
+ * @return {@code true} if the specified quirk is present in this configuration,
+ * {@code false} otherwise.
+ */
+ public boolean hasQuirk(String quirkValue) {
+ return mQuirks != null && mQuirks.contains(quirkValue);
+ }
+
@Override
public String toString() {
String str = "DisplayDeviceConfig{"
+ "mBrightness=" + Arrays.toString(mBrightness)
+ ", mNits=" + Arrays.toString(mNits)
+ + ", mQuirks=" + mQuirks
+ "}";
return str;
}
@@ -173,6 +188,7 @@
try (InputStream in = new BufferedInputStream(new FileInputStream(configFile))) {
final DisplayConfiguration config = XmlParser.read(in);
loadBrightnessMap(config);
+ loadQuirks(config);
} catch (IOException | DatatypeConfigurationException | XmlPullParserException e) {
Slog.e(TAG, "Encountered an error while reading/parsing display config file: "
+ configFile, e);
@@ -210,4 +226,11 @@
mNits = nits;
mBrightness = backlight;
}
+
+ private void loadQuirks(DisplayConfiguration config) {
+ final DisplayQuirks quirks = config.getQuirks();
+ if (quirks != null) {
+ mQuirks = new ArrayList<>(quirks.getQuirk());
+ }
+ }
}
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 155b246..9b8ed3a 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -185,6 +185,7 @@
private DisplayDeviceInfo mInfo;
private boolean mHavePendingChanges;
private int mState = Display.STATE_UNKNOWN;
+ // This is only set in the runnable returned from requestDisplayStateLocked.
private float mBrightnessState = PowerManager.BRIGHTNESS_INVALID_FLOAT;
private int mDefaultModeId;
private int mDefaultConfigGroup;
@@ -227,7 +228,7 @@
mDisplayDeviceConfig = null;
// Defer configuration file loading
BackgroundThread.getHandler().sendMessage(PooledLambda.obtainMessage(
- LocalDisplayDevice::loadDisplayConfigurationBrightnessMapping, this));
+ LocalDisplayDevice::loadDisplayConfiguration, this));
}
@Override
@@ -409,7 +410,7 @@
return mDisplayDeviceConfig;
}
- private void loadDisplayConfigurationBrightnessMapping() {
+ private void loadDisplayConfiguration() {
Spline nitsToHal = null;
Spline sysToNits = null;
@@ -419,6 +420,9 @@
return;
}
+ mBacklightAdapter.setForceSurfaceControl(mDisplayDeviceConfig.hasQuirk(
+ DisplayDeviceConfig.QUIRK_CAN_SET_BRIGHTNESS_VIA_HWC));
+
final float[] halNits = mDisplayDeviceConfig.getNits();
final float[] halBrightness = mDisplayDeviceConfig.getBrightness();
if (halNits == null || halBrightness == null) {
@@ -648,10 +652,6 @@
updateDeviceInfoLocked();
}
- if (brightnessChanged) {
- mBrightnessState = brightnessState;
- }
-
// Defer actually setting the display state until after we have exited
// the critical section since it can take hundreds of milliseconds
// to complete.
@@ -691,6 +691,7 @@
// Apply brightness changes given that we are in a non-suspended state.
if (brightnessChanged || vrModeChange) {
setDisplayBrightness(brightnessState);
+ mBrightnessState = brightnessState;
}
// Enter the final desired state, possibly suspended.
@@ -1208,6 +1209,14 @@
private final LogicalLight mBacklight;
private final boolean mUseSurfaceControlBrightness;
+ private boolean mForceSurfaceControl = false;
+
+ /**
+ * @param displayToken Token for display associated with this backlight.
+ * @param isDefaultDisplay {@code true} if it is the default display.
+ * @param forceSurfaceControl {@code true} if brightness should always be
+ * set via SurfaceControl API.
+ */
BacklightAdapter(IBinder displayToken, boolean isDefaultDisplay) {
mDisplayToken = displayToken;
@@ -1222,23 +1231,28 @@
}
}
- public void setBrightness(float brightness) {
- if (mUseSurfaceControlBrightness) {
+ void setBrightness(float brightness) {
+ if (mUseSurfaceControlBrightness || mForceSurfaceControl) {
SurfaceControl.setDisplayBrightness(mDisplayToken, brightness);
} else if (mBacklight != null) {
mBacklight.setBrightness(brightness);
}
}
- public void setVrMode(boolean isVrModeEnabled) {
+ void setVrMode(boolean isVrModeEnabled) {
if (mBacklight != null) {
mBacklight.setVrMode(isVrModeEnabled);
}
}
+ void setForceSurfaceControl(boolean forceSurfaceControl) {
+ mForceSurfaceControl = forceSurfaceControl;
+ }
+
@Override
public String toString() {
return "BacklightAdapter [useSurfaceControl=" + mUseSurfaceControlBrightness
+ + " (force_anyway? " + mForceSurfaceControl + ")"
+ ", backlight=" + mBacklight + "]";
}
}
diff --git a/services/core/java/com/android/server/display/color/ColorDisplayService.java b/services/core/java/com/android/server/display/color/ColorDisplayService.java
index 92a3ccf..727944d 100644
--- a/services/core/java/com/android/server/display/color/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/color/ColorDisplayService.java
@@ -77,7 +77,6 @@
import com.android.server.DisplayThread;
import com.android.server.LocalServices;
import com.android.server.SystemService;
-import com.android.server.SystemService.TargetUser;
import com.android.server.twilight.TwilightListener;
import com.android.server.twilight.TwilightManager;
import com.android.server.twilight.TwilightState;
@@ -119,6 +118,7 @@
private static final int MSG_APPLY_NIGHT_DISPLAY_ANIMATED = 3;
private static final int MSG_APPLY_GLOBAL_SATURATION = 4;
private static final int MSG_APPLY_DISPLAY_WHITE_BALANCE = 5;
+ private static final int MSG_APPLY_REDUCE_BRIGHT_COLORS = 6;
/**
* Return value if a setting has not been set.
@@ -129,17 +129,6 @@
* Evaluator used to animate color matrix transitions.
*/
private static final ColorMatrixEvaluator COLOR_MATRIX_EVALUATOR = new ColorMatrixEvaluator();
-
- private final NightDisplayTintController mNightDisplayTintController =
- new NightDisplayTintController();
-
- @VisibleForTesting
- final DisplayWhiteBalanceTintController mDisplayWhiteBalanceTintController =
- new DisplayWhiteBalanceTintController();
-
- private final TintController mGlobalSaturationTintController =
- new GlobalSaturationTintController();
-
/**
* Matrix and offset used for converting color to grayscale.
*/
@@ -163,6 +152,16 @@
1f, 1f, 1f, 1f
};
+ @VisibleForTesting
+ final DisplayWhiteBalanceTintController mDisplayWhiteBalanceTintController =
+ new DisplayWhiteBalanceTintController();
+ private final NightDisplayTintController mNightDisplayTintController =
+ new NightDisplayTintController();
+ private final TintController mGlobalSaturationTintController =
+ new GlobalSaturationTintController();
+ private final ReduceBrightColorsTintController mReduceBrightColorsTintController =
+ new ReduceBrightColorsTintController();
+
private final Handler mHandler;
private final AppSaturationController mAppSaturationController = new AppSaturationController();
@@ -354,6 +353,14 @@
case Secure.DISPLAY_WHITE_BALANCE_ENABLED:
updateDisplayWhiteBalanceStatus();
break;
+ case Secure.REDUCE_BRIGHT_COLORS_ACTIVATED:
+ onReduceBrightColorsActivationChanged();
+ mHandler.sendEmptyMessage(MSG_APPLY_REDUCE_BRIGHT_COLORS);
+ break;
+ case Secure.REDUCE_BRIGHT_COLORS_LEVEL:
+ onReduceBrightColorsStrengthLevelChanged();
+ mHandler.sendEmptyMessage(MSG_APPLY_REDUCE_BRIGHT_COLORS);
+ break;
}
}
}
@@ -372,17 +379,19 @@
false /* notifyForDescendants */, mContentObserver, mCurrentUser);
cr.registerContentObserver(System.getUriFor(System.DISPLAY_COLOR_MODE),
false /* notifyForDescendants */, mContentObserver, mCurrentUser);
- cr.registerContentObserver(
- Secure.getUriFor(Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED),
+ cr.registerContentObserver(Secure.getUriFor(Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED),
false /* notifyForDescendants */, mContentObserver, mCurrentUser);
cr.registerContentObserver(
Secure.getUriFor(Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED),
false /* notifyForDescendants */, mContentObserver, mCurrentUser);
- cr.registerContentObserver(
- Secure.getUriFor(Secure.ACCESSIBILITY_DISPLAY_DALTONIZER),
+ cr.registerContentObserver(Secure.getUriFor(Secure.ACCESSIBILITY_DISPLAY_DALTONIZER),
false /* notifyForDescendants */, mContentObserver, mCurrentUser);
cr.registerContentObserver(Secure.getUriFor(Secure.DISPLAY_WHITE_BALANCE_ENABLED),
false /* notifyForDescendants */, mContentObserver, mCurrentUser);
+ cr.registerContentObserver(Secure.getUriFor(Secure.REDUCE_BRIGHT_COLORS_ACTIVATED),
+ false /* notifyForDescendants */, mContentObserver, mCurrentUser);
+ cr.registerContentObserver(Secure.getUriFor(Secure.REDUCE_BRIGHT_COLORS_LEVEL),
+ false /* notifyForDescendants */, mContentObserver, mCurrentUser);
// Apply the accessibility settings first, since they override most other settings.
onAccessibilityInversionChanged();
@@ -420,6 +429,17 @@
updateDisplayWhiteBalanceStatus();
}
+
+ if (mReduceBrightColorsTintController.isAvailable(getContext())) {
+ mReduceBrightColorsTintController
+ .setUp(getContext(), DisplayTransformManager.needsLinearColorMatrix());
+ onReduceBrightColorsStrengthLevelChanged();
+ final boolean reset = resetReduceBrightColors();
+ if (!reset) {
+ onReduceBrightColorsActivationChanged();
+ mHandler.sendEmptyMessage(MSG_APPLY_REDUCE_BRIGHT_COLORS);
+ }
+ }
}
private void tearDown() {
@@ -444,6 +464,27 @@
if (mGlobalSaturationTintController.isAvailable(getContext())) {
mGlobalSaturationTintController.setActivated(null);
}
+
+ if (mReduceBrightColorsTintController.isAvailable(getContext())) {
+ mReduceBrightColorsTintController.setActivated(null);
+ }
+ }
+
+ private boolean resetReduceBrightColors() {
+ if (mCurrentUser == UserHandle.USER_NULL) {
+ return false;
+ }
+
+ final boolean isSettingActivated = Secure.getIntForUser(getContext().getContentResolver(),
+ Secure.REDUCE_BRIGHT_COLORS_ACTIVATED, 0, mCurrentUser) == 1;
+ final boolean shouldResetOnReboot = Secure.getIntForUser(getContext().getContentResolver(),
+ Secure.REDUCE_BRIGHT_COLORS_PERSIST_ACROSS_REBOOTS, 0, mCurrentUser) == 0;
+ if (isSettingActivated && mReduceBrightColorsTintController.isActivatedStateNotSet()
+ && shouldResetOnReboot) {
+ return Secure.putIntForUser(getContext().getContentResolver(),
+ Secure.REDUCE_BRIGHT_COLORS_ACTIVATED, 0, mCurrentUser);
+ }
+ return false;
}
private void onNightDisplayAutoModeChanged(int autoMode) {
@@ -572,6 +613,24 @@
isAccessiblityInversionEnabled() ? MATRIX_INVERT_COLOR : null);
}
+ private void onReduceBrightColorsActivationChanged() {
+ if (mCurrentUser == UserHandle.USER_NULL) {
+ return;
+ }
+ mReduceBrightColorsTintController.setActivated(
+ Secure.getIntForUser(getContext().getContentResolver(),
+ Secure.REDUCE_BRIGHT_COLORS_ACTIVATED, 0, mCurrentUser) == 1);
+ }
+
+ private void onReduceBrightColorsStrengthLevelChanged() {
+ if (mCurrentUser == UserHandle.USER_NULL) {
+ return;
+ }
+ mReduceBrightColorsTintController.setMatrix(
+ Secure.getIntForUser(getContext().getContentResolver(),
+ Secure.REDUCE_BRIGHT_COLORS_LEVEL, 0, mCurrentUser));
+ }
+
/**
* Applies current color temperature matrix, or removes it if deactivated.
*
@@ -937,6 +996,14 @@
pw.println(" Not available");
}
+ pw.println("Reduce bright colors:");
+ if (mReduceBrightColorsTintController.isAvailable(getContext())) {
+ pw.println(" Activated: " + mReduceBrightColorsTintController.isActivated());
+ mReduceBrightColorsTintController.dump(pw);
+ } else {
+ pw.println(" Not available");
+ }
+
pw.println("Color mode: " + getColorModeInternal());
}
@@ -1438,6 +1505,9 @@
mGlobalSaturationTintController.setMatrix(msg.arg1);
applyTint(mGlobalSaturationTintController, false);
break;
+ case MSG_APPLY_REDUCE_BRIGHT_COLORS:
+ applyTint(mReduceBrightColorsTintController, true);
+ break;
case MSG_APPLY_NIGHT_DISPLAY_IMMEDIATE:
applyTint(mNightDisplayTintController, true);
break;
diff --git a/services/core/java/com/android/server/display/color/DisplayTransformManager.java b/services/core/java/com/android/server/display/color/DisplayTransformManager.java
index 3b0069c..5c68c51 100644
--- a/services/core/java/com/android/server/display/color/DisplayTransformManager.java
+++ b/services/core/java/com/android/server/display/color/DisplayTransformManager.java
@@ -59,6 +59,10 @@
*/
public static final int LEVEL_COLOR_MATRIX_GRAYSCALE = 200;
/**
+ * Color transform level used by A11y services to reduce bright colors.
+ */
+ public static final int LEVEL_COLOR_MATRIX_REDUCE_BRIGHT_COLORS = 250;
+ /**
* Color transform level used by A11y services to invert the display colors.
*/
public static final int LEVEL_COLOR_MATRIX_INVERT_COLOR = 300;
@@ -97,7 +101,7 @@
* Map of level -> color transformation matrix.
*/
@GuardedBy("mColorMatrix")
- private final SparseArray<float[]> mColorMatrix = new SparseArray<>(5);
+ private final SparseArray<float[]> mColorMatrix = new SparseArray<>(6);
/**
* Temporary matrix used internally by {@link #computeColorMatrixLocked()}.
*/
diff --git a/services/core/java/com/android/server/display/color/ReduceBrightColorsTintController.java b/services/core/java/com/android/server/display/color/ReduceBrightColorsTintController.java
new file mode 100644
index 0000000..7e120c9
--- /dev/null
+++ b/services/core/java/com/android/server/display/color/ReduceBrightColorsTintController.java
@@ -0,0 +1,113 @@
+/*
+ * 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.display.color;
+
+import static com.android.server.display.color.DisplayTransformManager.LEVEL_COLOR_MATRIX_REDUCE_BRIGHT_COLORS;
+
+import android.content.Context;
+import android.hardware.display.ColorDisplayManager;
+import android.opengl.Matrix;
+import android.util.Slog;
+
+import com.android.internal.R;
+
+import java.io.PrintWriter;
+import java.util.Arrays;
+
+/**
+ * Control the color transform for bright color reduction.
+ */
+public class ReduceBrightColorsTintController extends TintController {
+
+ private final float[] mMatrix = new float[16];
+ private final float[] mCoefficients = new float[9];
+
+ private int mStrength;
+
+ @Override
+ public void setUp(Context context, boolean needsLinear) {
+ final String[] coefficients = context.getResources().getStringArray(
+ needsLinear ? R.array.config_reduceBrightColorsCoefficients
+ : R.array.config_reduceBrightColorsCoefficientsNative);
+ for (int i = 0; i < 9 && i < coefficients.length; i++) {
+ mCoefficients[i] = Float.parseFloat(coefficients[i]);
+ }
+ }
+
+ @Override
+ public float[] getMatrix() {
+ return isActivated() ? Arrays.copyOf(mMatrix, mMatrix.length)
+ : ColorDisplayService.MATRIX_IDENTITY;
+ }
+
+ @Override
+ public void setMatrix(int strengthLevel) {
+ // Clamp to valid range.
+ if (strengthLevel < 0) {
+ strengthLevel = 0;
+ } else if (strengthLevel > 100) {
+ strengthLevel = 100;
+ }
+ Slog.d(ColorDisplayService.TAG, "Setting bright color reduction level: " + strengthLevel);
+ mStrength = strengthLevel;
+
+ Matrix.setIdentityM(mMatrix, 0);
+
+ final float percentageStrength = strengthLevel / 100f;
+ final float squaredPercentageStrength = percentageStrength * percentageStrength;
+ final float red =
+ squaredPercentageStrength * mCoefficients[0] + percentageStrength * mCoefficients[1]
+ + mCoefficients[2];
+ final float green =
+ squaredPercentageStrength * mCoefficients[3] + percentageStrength * mCoefficients[4]
+ + mCoefficients[5];
+ final float blue =
+ squaredPercentageStrength * mCoefficients[6] + percentageStrength * mCoefficients[7]
+ + mCoefficients[8];
+ mMatrix[0] = clamp(red);
+ mMatrix[5] = clamp(green);
+ mMatrix[10] = clamp(blue);
+ }
+
+ private float clamp(float value) {
+ if (value > 1f) {
+ return 1f;
+ } else if (value < 0f) {
+ return 0f;
+ }
+ return value;
+ }
+
+ @Override
+ public void dump(PrintWriter pw) {
+ pw.println(" mStrength = " + mStrength);
+ }
+
+ @Override
+ public int getLevel() {
+ return LEVEL_COLOR_MATRIX_REDUCE_BRIGHT_COLORS;
+ }
+
+ @Override
+ public boolean isAvailable(Context context) {
+ return ColorDisplayManager.isColorTransformAccelerated(context);
+ }
+
+ public int getStrength() {
+ return mStrength;
+ }
+}
diff --git a/services/core/java/com/android/server/hdmi/DevicePowerStatusAction.java b/services/core/java/com/android/server/hdmi/DevicePowerStatusAction.java
index b52ab76..1a0a639 100644
--- a/services/core/java/com/android/server/hdmi/DevicePowerStatusAction.java
+++ b/services/core/java/com/android/server/hdmi/DevicePowerStatusAction.java
@@ -20,6 +20,7 @@
import android.hardware.hdmi.HdmiPlaybackClient;
import android.hardware.hdmi.HdmiPlaybackClient.DisplayStatusCallback;
import android.hardware.hdmi.IHdmiControlCallback;
+import android.hardware.tv.cec.V1_0.SendMessageResult;
import android.os.RemoteException;
import android.util.Slog;
@@ -42,6 +43,10 @@
private final int mTargetAddress;
private final List<IHdmiControlCallback> mCallbacks = new ArrayList<>();
+ // Retry the power status query as it might happen when the target device is waking up. In
+ // that case a device may be quite busy and can fail to respond within the 2s timeout.
+ private int mRetriesOnTimeout = 1;
+
static DevicePowerStatusAction create(HdmiCecLocalDevice source,
int targetAddress, IHdmiControlCallback callback) {
if (source == null || callback == null) {
@@ -68,13 +73,21 @@
private void queryDevicePowerStatus() {
sendCommand(HdmiCecMessageBuilder.buildGiveDevicePowerStatus(getSourceAddress(),
- mTargetAddress));
+ mTargetAddress), error -> {
+ // Don't retry on timeout if the remote device didn't even ACK the message. Assume
+ // the device is not present or not capable of CEC.
+ if (error == SendMessageResult.NACK) {
+ // Got no response from TV. Report status 'unknown'.
+ invokeCallback(HdmiControlManager.POWER_STATUS_UNKNOWN);
+ finish();
+ }
+ });
}
@Override
boolean processCommand(HdmiCecMessage cmd) {
if (mState != STATE_WAITING_FOR_REPORT_POWER_STATUS
- || mTargetAddress != cmd.getSource()) {
+ || mTargetAddress != cmd.getSource()) {
return false;
}
if (cmd.getOpcode() == Constants.MESSAGE_REPORT_POWER_STATUS) {
@@ -92,6 +105,12 @@
return;
}
if (state == STATE_WAITING_FOR_REPORT_POWER_STATUS) {
+ if (mRetriesOnTimeout > 0) {
+ mRetriesOnTimeout--;
+ start();
+ return;
+ }
+
// Got no response from TV. Report status 'unknown'.
invokeCallback(HdmiControlManager.POWER_STATUS_UNKNOWN);
finish();
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index bbd5ac3..ddb0141 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -26,6 +26,8 @@
import android.hardware.tv.cec.V1_0.IHdmiCecCallback;
import android.hardware.tv.cec.V1_0.Result;
import android.hardware.tv.cec.V1_0.SendMessageResult;
+import android.icu.util.IllformedLocaleException;
+import android.icu.util.ULocale;
import android.os.Handler;
import android.os.IHwBinder;
import android.os.Looper;
@@ -33,6 +35,7 @@
import android.stats.hdmi.HdmiStatsEnums;
import android.util.Slog;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.hdmi.HdmiAnnotations.IoThreadOnly;
@@ -49,8 +52,6 @@
import java.util.concurrent.ArrayBlockingQueue;
import java.util.function.Predicate;
-import sun.util.locale.LanguageTag;
-
/**
* Manages HDMI-CEC command and behaviors. It converts user's command into CEC command
* and pass it to CEC HAL so that it sends message to other device. For incoming
@@ -352,13 +353,31 @@
@ServiceThreadOnly
void setLanguage(String language) {
assertRunOnServiceThread();
- if (!LanguageTag.isLanguage(language)) {
+ if (!isLanguage(language)) {
return;
}
mNativeWrapperImpl.nativeSetLanguage(language);
}
/**
+ * Returns true if the language code is well-formed.
+ */
+ @VisibleForTesting static boolean isLanguage(String language) {
+ // Handle null and empty string because because ULocale.Builder#setLanguage accepts them.
+ if (language == null || language.isEmpty()) {
+ return false;
+ }
+
+ ULocale.Builder builder = new ULocale.Builder();
+ try {
+ builder.setLanguage(language);
+ return true;
+ } catch (IllformedLocaleException e) {
+ return false;
+ }
+ }
+
+ /**
* Configure ARC circuit in the hardware logic to start or stop the feature.
*
* @param port ID of HDMI port to which AVR is connected
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index c943fbc..c15fdca 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -66,6 +66,8 @@
import android.os.PowerManager;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
@@ -1653,6 +1655,12 @@
}
@Override
+ public boolean shouldHandleTvPowerKey() {
+ enforceAccessPermission();
+ return HdmiControlService.this.shouldHandleTvPowerKey();
+ }
+
+ @Override
public void queryDisplayStatus(final IHdmiControlCallback callback) {
enforceAccessPermission();
runOnServiceThread(new Runnable() {
@@ -2143,6 +2151,16 @@
}
@Override
+ public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
+ @Nullable FileDescriptor err, String[] args,
+ @Nullable ShellCallback callback, ResultReceiver resultReceiver)
+ throws RemoteException {
+ enforceAccessPermission();
+ new HdmiControlShellCommand(this)
+ .exec(this, in, out, err, args, callback, resultReceiver);
+ }
+
+ @Override
protected void dump(FileDescriptor fd, final PrintWriter writer, String[] args) {
if (!DumpUtils.checkDumpPermission(getContext(), TAG, writer)) return;
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
@@ -2334,6 +2352,24 @@
source.toggleAndFollowTvPower();
}
+ @VisibleForTesting
+ protected boolean shouldHandleTvPowerKey() {
+ if (isTvDevice()) {
+ return false;
+ }
+ String powerControlMode = getHdmiCecConfig().getStringValue(
+ HdmiControlManager.CEC_SETTING_NAME_POWER_CONTROL_MODE);
+ if (powerControlMode.equals(HdmiControlManager.POWER_CONTROL_MODE_NONE)) {
+ return false;
+ }
+ int hdmiCecEnabled = getHdmiCecConfig().getIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED);
+ if (hdmiCecEnabled != HdmiControlManager.HDMI_CEC_CONTROL_ENABLED) {
+ return false;
+ }
+ return true;
+ }
+
@ServiceThreadOnly
protected void queryDisplayStatus(final IHdmiControlCallback callback) {
assertRunOnServiceThread();
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java b/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java
new file mode 100644
index 0000000..ee3427f
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/HdmiControlShellCommand.java
@@ -0,0 +1,160 @@
+/*
+ * 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.hdmi;
+
+
+import android.hardware.hdmi.HdmiControlManager;
+import android.hardware.hdmi.IHdmiControlCallback;
+import android.hardware.hdmi.IHdmiControlService;
+import android.os.RemoteException;
+import android.os.ShellCommand;
+import android.util.Slog;
+
+import java.io.PrintWriter;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+final class HdmiControlShellCommand extends ShellCommand {
+
+ private static final String TAG = "HdmiShellCommand";
+
+ private final IHdmiControlService.Stub mBinderService;
+
+
+ HdmiControlShellCommand(IHdmiControlService.Stub binderService) {
+ mBinderService = binderService;
+ }
+
+ @Override
+ public int onCommand(String cmd) {
+ if (cmd == null) {
+ return handleDefaultCommands(cmd);
+ }
+
+ try {
+ return handleShellCommand(cmd);
+ } catch (Exception e) {
+ getErrPrintWriter().println(
+ "Caught error for command '" + cmd + "': " + e.getMessage());
+ Slog.e(TAG, "Error handling hdmi_control shell command: " + cmd, e);
+ return 1;
+ }
+ }
+
+ @Override
+ public void onHelp() {
+ PrintWriter pw = getOutPrintWriter();
+
+ pw.println("HdmiControlManager (hdmi_control) commands:");
+ pw.println(" help");
+ pw.println(" Print this help text.");
+ pw.println(" onetouchplay, otp");
+ pw.println(" Send the \"One Touch Play\" feature from a source to the TV");
+ pw.println(" vendorcommand --device_type <originating device type>");
+ pw.println(" --destination <destination device>");
+ pw.println(" --args <vendor specific arguments>");
+ pw.println(" [--id <true if vendor command should be sent with vendor id>]");
+ pw.println(" Send a Vendor Command to the given target device");
+ }
+
+ private int handleShellCommand(String cmd) throws RemoteException {
+ PrintWriter pw = getOutPrintWriter();
+
+ switch (cmd) {
+ case "otp":
+ case "onetouchplay":
+ return oneTouchPlay(pw);
+ case "vendorcommand":
+ return vendorCommand(pw);
+ }
+
+ getErrPrintWriter().println("Unhandled command: " + cmd);
+ return 1;
+ }
+
+ private int oneTouchPlay(PrintWriter pw) throws RemoteException {
+ final CountDownLatch latch = new CountDownLatch(1);
+ AtomicInteger cecResult = new AtomicInteger();
+ pw.print("Sending One Touch Play...");
+ mBinderService.oneTouchPlay(new IHdmiControlCallback.Stub() {
+ @Override
+ public void onComplete(int result) {
+ pw.println(" done (" + result + ")");
+ latch.countDown();
+ cecResult.set(result);
+ }
+ });
+
+ try {
+ if (!latch.await(HdmiConfig.TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+ getErrPrintWriter().println("One Touch Play timed out.");
+ return 1;
+ }
+ } catch (InterruptedException e) {
+ getErrPrintWriter().println("Caught InterruptedException");
+ Thread.currentThread().interrupt();
+ }
+ return cecResult.get() == HdmiControlManager.RESULT_SUCCESS ? 0 : 1;
+ }
+
+ private int vendorCommand(PrintWriter pw) throws RemoteException {
+ if (6 > getRemainingArgsCount()) {
+ throw new IllegalArgumentException("Expected 3 arguments.");
+ }
+
+ int deviceType = -1;
+ int destination = -1;
+ String parameters = "";
+ boolean hasVendorId = false;
+
+ String arg = getNextOption();
+ while (arg != null) {
+ switch (arg) {
+ case "-t":
+ case "--device_type":
+ deviceType = Integer.parseInt(getNextArgRequired());
+ break;
+ case "-d":
+ case "--destination":
+ destination = Integer.parseInt(getNextArgRequired());
+ break;
+ case "-a":
+ case "--args":
+ parameters = getNextArgRequired();
+ break;
+ case "-i":
+ case "--id":
+ hasVendorId = Boolean.parseBoolean(getNextArgRequired());
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown argument: " + arg);
+ }
+ arg = getNextArg();
+ }
+
+ String[] parts = parameters.split(":");
+ byte[] params = new byte[parts.length];
+ for (int i = 0; i < params.length; i++) {
+ params[i] = (byte) Integer.parseInt(parts[i], 16);
+ }
+
+ pw.println("Sending <Vendor Command>");
+ mBinderService.sendVendorCommand(deviceType, destination, params, hasVendorId);
+ return 0;
+ }
+}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 46ccf1e..bff81e6 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -41,11 +41,13 @@
import android.hardware.display.DisplayViewport;
import android.hardware.input.IInputDevicesChangedListener;
import android.hardware.input.IInputManager;
+import android.hardware.input.IInputSensorEventListener;
import android.hardware.input.ITabletModeChangedListener;
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.InputManager;
import android.hardware.input.InputManagerInternal;
import android.hardware.input.InputManagerInternal.LidSwitchCallback;
+import android.hardware.input.InputSensorInfo;
import android.hardware.input.KeyboardLayout;
import android.hardware.input.TouchCalibration;
import android.media.AudioManager;
@@ -117,6 +119,7 @@
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -181,12 +184,24 @@
private final List<TabletModeChangedListenerRecord> mTempTabletModeChangedListenersToNotify =
new ArrayList<>();
+ private final Object mSensorEventLock = new Object();
+ // List of currently registered sensor event listeners by process id
+ @GuardedBy("mSensorEventLock")
+ private final SparseArray<SensorEventListenerRecord> mSensorEventListeners =
+ new SparseArray<>();
+ private final List<SensorEventListenerRecord> mSensorEventListenersToNotify =
+ new ArrayList<>();
+ private final List<SensorEventListenerRecord> mSensorAccuracyListenersToNotify =
+ new ArrayList<>();
+
// Persistent data store. Must be locked each time during use.
private final PersistentDataStore mDataStore = new PersistentDataStore();
// List of currently registered input devices changed listeners by process id.
private Object mInputDevicesLock = new Object();
+ @GuardedBy("mInputDevicesLock")
private boolean mInputDevicesChangedPending; // guarded by mInputDevicesLock
+ @GuardedBy("mInputDevicesLock")
private InputDevice[] mInputDevices = new InputDevice[0];
private final SparseArray<InputDevicesChangedListenerRecord> mInputDevicesChangedListeners =
new SparseArray<InputDevicesChangedListenerRecord>(); // guarded by mInputDevicesLock
@@ -244,7 +259,7 @@
int deviceId, int sourceMask, int[] keyCodes, boolean[] keyExists);
private static native InputChannel nativeCreateInputChannel(long ptr, String name);
private static native InputChannel nativeCreateInputMonitor(long ptr, int displayId,
- boolean isGestureMonitor, String name);
+ boolean isGestureMonitor, String name, int pid);
private static native void nativeRemoveInputChannel(long ptr, IBinder connectionToken);
private static native void nativePilferPointers(long ptr, IBinder token);
private static native void nativeSetInputFilterEnabled(long ptr, boolean enable);
@@ -285,10 +300,16 @@
private static native void nativeSetPointerIconType(long ptr, int iconId);
private static native void nativeReloadPointerIcons(long ptr);
private static native void nativeSetCustomPointerIcon(long ptr, PointerIcon icon);
- private static native void nativeSetPointerCapture(long ptr, boolean detached);
+ private static native void nativeRequestPointerCapture(long ptr, IBinder windowToken,
+ boolean enabled);
private static native boolean nativeCanDispatchToDisplay(long ptr, int deviceId, int displayId);
private static native void nativeNotifyPortAssociationsChanged(long ptr);
private static native void nativeSetMotionClassifierEnabled(long ptr, boolean enabled);
+ private static native InputSensorInfo[] nativeGetSensorList(long ptr, int deviceId);
+ private static native boolean nativeFlushSensor(long ptr, int deviceId, int sensorType);
+ private static native boolean nativeEnableSensor(long ptr, int deviceId, int sensorType,
+ int samplingPeriodUs, int maxBatchReportLatencyUs);
+ private static native void nativeDisableSensor(long ptr, int deviceId, int sensorType);
// Maximum number of milliseconds to wait for input event injection.
private static final int INJECTION_TIMEOUT_MILLIS = 30 * 1000;
@@ -586,7 +607,7 @@
}
return nativeCreateInputMonitor(mPtr, displayId, false /* isGestureMonitor */,
- inputChannelName);
+ inputChannelName, Binder.getCallingPid());
}
/**
@@ -614,7 +635,7 @@
final long ident = Binder.clearCallingIdentity();
try {
InputChannel inputChannel = nativeCreateInputMonitor(
- mPtr, displayId, true /*isGestureMonitor*/, inputChannelName);
+ mPtr, displayId, true /*isGestureMonitor*/, inputChannelName, pid);
InputMonitorHost host = new InputMonitorHost(inputChannel.getToken());
synchronized (mGestureMonitorPidsLock) {
mGestureMonitorPidsByToken.put(inputChannel.getToken(), pid);
@@ -1611,12 +1632,12 @@
}
@Override
- public void requestPointerCapture(IBinder windowToken, boolean enabled) {
- boolean requestConfigurationRefresh =
- mWindowManagerCallbacks.requestPointerCapture(windowToken, enabled);
- if (requestConfigurationRefresh) {
- nativeSetPointerCapture(mPtr, enabled);
+ public void requestPointerCapture(IBinder inputChannelToken, boolean enabled) {
+ if (inputChannelToken == null) {
+ return;
}
+
+ nativeRequestPointerCapture(mPtr, inputChannelToken, enabled);
}
public void setInputDispatchMode(boolean enabled, boolean frozen) {
@@ -2043,6 +2064,97 @@
nativeNotifyPortAssociationsChanged(mPtr);
}
+ @Override // Binder call
+ public InputSensorInfo[] getSensorList(int deviceId) {
+ InputSensorInfo[] sensors = nativeGetSensorList(mPtr, deviceId);
+ return sensors;
+ }
+
+ @Override // Binder call
+ public boolean registerSensorListener(IInputSensorEventListener listener) {
+ if (DEBUG) {
+ Slog.d(TAG, "registerSensorListener: listener=" + listener + " callingPid="
+ + Binder.getCallingPid());
+ }
+ if (listener == null) {
+ Slog.e(TAG, "listener must not be null");
+ return false;
+ }
+
+ synchronized (mInputDevicesLock) {
+ int callingPid = Binder.getCallingPid();
+ if (mSensorEventListeners.get(callingPid) != null) {
+ Slog.e(TAG, "The calling process " + callingPid + " has already "
+ + "registered an InputSensorEventListener.");
+ return false;
+ }
+
+ SensorEventListenerRecord record =
+ new SensorEventListenerRecord(callingPid, listener);
+ try {
+ IBinder binder = listener.asBinder();
+ binder.linkToDeath(record, 0);
+ } catch (RemoteException ex) {
+ // give up
+ throw new RuntimeException(ex);
+ }
+
+ mSensorEventListeners.put(callingPid, record);
+ }
+ return true;
+ }
+
+ @Override // Binder call
+ public void unregisterSensorListener(IInputSensorEventListener listener) {
+ if (DEBUG) {
+ Slog.d(TAG, "unregisterSensorListener: listener=" + listener + " callingPid="
+ + Binder.getCallingPid());
+ }
+
+ if (listener == null) {
+ throw new IllegalArgumentException("listener must not be null");
+ }
+
+ synchronized (mInputDevicesLock) {
+ int callingPid = Binder.getCallingPid();
+ if (mSensorEventListeners.get(callingPid) != null) {
+ SensorEventListenerRecord record = mSensorEventListeners.get(callingPid);
+ if (record.getListener().asBinder() != listener.asBinder()) {
+ throw new IllegalArgumentException("listener is not registered");
+ }
+ mSensorEventListeners.remove(callingPid);
+ }
+ }
+ }
+
+ @Override // Binder call
+ public boolean flushSensor(int deviceId, int sensorType) {
+ synchronized (mInputDevicesLock) {
+ int callingPid = Binder.getCallingPid();
+ SensorEventListenerRecord listener = mSensorEventListeners.get(callingPid);
+ if (listener != null) {
+ return nativeFlushSensor(mPtr, deviceId, sensorType);
+ }
+ return false;
+ }
+ }
+
+ @Override // Binder call
+ public boolean enableSensor(int deviceId, int sensorType, int samplingPeriodUs,
+ int maxBatchReportLatencyUs) {
+ synchronized (mInputDevicesLock) {
+ return nativeEnableSensor(mPtr, deviceId, sensorType, samplingPeriodUs,
+ maxBatchReportLatencyUs);
+ }
+ }
+
+ @Override // Binder call
+ public void disableSensor(int deviceId, int sensorType) {
+ synchronized (mInputDevicesLock) {
+ nativeDisableSensor(mPtr, deviceId, sensorType);
+ }
+ }
+
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
@@ -2189,11 +2301,7 @@
// Native callback
private void notifyFocusChanged(IBinder oldToken, IBinder newToken) {
- final boolean requestConfigurationRefresh =
- mWindowManagerCallbacks.notifyFocusChanged(oldToken, newToken);
- if (requestConfigurationRefresh) {
- nativeSetPointerCapture(mPtr, false);
- }
+ mWindowManagerCallbacks.notifyFocusChanged(oldToken, newToken);
}
// Native callback
@@ -2244,6 +2352,46 @@
}
// Native callback.
+ private void notifySensorEvent(int deviceId, int sensorType, int accuracy, long timestamp,
+ float[] values) {
+ if (DEBUG) {
+ Slog.d(TAG, "notifySensorEvent: deviceId=" + deviceId + " sensorType="
+ + sensorType + " values=" + Arrays.toString(values));
+ }
+ mSensorEventListenersToNotify.clear();
+ final int numListeners;
+ synchronized (mSensorEventLock) {
+ numListeners = mSensorEventListeners.size();
+ for (int i = 0; i < numListeners; i++) {
+ mSensorEventListenersToNotify.add(
+ mSensorEventListeners.valueAt(i));
+ }
+ }
+ for (int i = 0; i < numListeners; i++) {
+ mSensorEventListenersToNotify.get(i).notifySensorEvent(deviceId, sensorType,
+ accuracy, timestamp, values);
+ }
+ mSensorEventListenersToNotify.clear();
+ }
+
+ // Native callback.
+ private void notifySensorAccuracy(int deviceId, int sensorType, int accuracy) {
+ mSensorAccuracyListenersToNotify.clear();
+ final int numListeners;
+ synchronized (mSensorEventLock) {
+ numListeners = mSensorEventListeners.size();
+ for (int i = 0; i < numListeners; i++) {
+ mSensorAccuracyListenersToNotify.add(mSensorEventListeners.valueAt(i));
+ }
+ }
+ for (int i = 0; i < numListeners; i++) {
+ mSensorAccuracyListenersToNotify.get(i).notifySensorAccuracy(
+ deviceId, sensorType, accuracy);
+ }
+ mSensorAccuracyListenersToNotify.clear();
+ }
+
+ // Native callback.
final boolean filterInputEvent(InputEvent event, int policyFlags) {
synchronized (mInputFilterLock) {
if (mInputFilter != null) {
@@ -2591,17 +2739,8 @@
/**
* Called when the focused window has changed.
- *
- * @return true if we want to request a configuration refresh.
*/
- boolean notifyFocusChanged(IBinder oldToken, IBinder newToken);
-
- /**
- * Called by the client to request pointer capture.
- *
- * @return true if we want to request a configuration refresh.
- */
- boolean requestPointerCapture(IBinder windowToken, boolean enabled);
+ void notifyFocusChanged(IBinder oldToken, IBinder newToken);
}
/**
@@ -2784,6 +2923,56 @@
}
}
+ private void onSensorEventListenerDied(int pid) {
+ synchronized (mSensorEventLock) {
+ mSensorEventListeners.remove(pid);
+ }
+ }
+
+ private final class SensorEventListenerRecord implements DeathRecipient {
+ private final int mPid;
+ private final IInputSensorEventListener mListener;
+
+ SensorEventListenerRecord(int pid, IInputSensorEventListener listener) {
+ mPid = pid;
+ mListener = listener;
+ }
+
+ @Override
+ public void binderDied() {
+ if (DEBUG) {
+ Slog.d(TAG, "Sensor event listener for pid " + mPid + " died.");
+ }
+ onSensorEventListenerDied(mPid);
+ }
+
+ public IInputSensorEventListener getListener() {
+ return mListener;
+ }
+
+ public void notifySensorEvent(int deviceId, int sensorType, int accuracy, long timestamp,
+ float[] values) {
+ try {
+ mListener.onInputSensorChanged(deviceId, sensorType, accuracy, timestamp,
+ values);
+ } catch (RemoteException ex) {
+ Slog.w(TAG, "Failed to notify process " + mPid
+ + " that sensor event notified, assuming it died.", ex);
+ binderDied();
+ }
+ }
+
+ public void notifySensorAccuracy(int deviceId, int sensorType, int accuracy) {
+ try {
+ mListener.onInputSensorAccuracyChanged(deviceId, sensorType, accuracy);
+ } catch (RemoteException ex) {
+ Slog.w(TAG, "Failed to notify process " + mPid
+ + " that sensor accuracy notified, assuming it died.", ex);
+ binderDied();
+ }
+ }
+ }
+
private final class VibratorToken implements DeathRecipient {
public final int mDeviceId;
public final IBinder mToken;
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 6395094..a0fa72a 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -159,9 +159,12 @@
import com.android.internal.compat.IPlatformCompat;
import com.android.internal.content.PackageMonitor;
import com.android.internal.inputmethod.CallbackUtils;
+import com.android.internal.inputmethod.IBooleanResultCallback;
import com.android.internal.inputmethod.IInputBindResultResultCallback;
import com.android.internal.inputmethod.IInputContentUriToken;
import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
+import com.android.internal.inputmethod.IInputMethodSubtypeListResultCallback;
+import com.android.internal.inputmethod.IInputMethodSubtypeResultCallback;
import com.android.internal.inputmethod.InputMethodDebug;
import com.android.internal.inputmethod.SoftInputShowHideReason;
import com.android.internal.inputmethod.StartInputFlags;
@@ -2158,27 +2161,34 @@
}
/**
- * @param imiId if null, returns enabled subtypes for the current imi
- * @return enabled subtypes of the specified imi
+ * Gets enabled subtypes of the specified {@link InputMethodInfo}.
+ *
+ * @param imiId if null, returns enabled subtypes for the current {@link InputMethodInfo}.
+ * @param allowsImplicitlySelectedSubtypes {@code true} to return the implicitly selected
+ * subtypes.
+ * @param resultCallback to callback the result.
*/
@Override
- public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(String imiId,
- boolean allowsImplicitlySelectedSubtypes) {
- final int callingUserId = UserHandle.getCallingUserId();
- synchronized (mMethodMap) {
- final int[] resolvedUserIds = InputMethodUtils.resolveUserId(callingUserId,
- mSettings.getCurrentUserId(), null);
- if (resolvedUserIds.length != 1) {
- return Collections.emptyList();
+ public void getEnabledInputMethodSubtypeList(String imiId,
+ boolean allowsImplicitlySelectedSubtypes,
+ IInputMethodSubtypeListResultCallback resultCallback) {
+ CallbackUtils.onResult(resultCallback, () -> {
+ final int callingUserId = UserHandle.getCallingUserId();
+ synchronized (mMethodMap) {
+ final int[] resolvedUserIds = InputMethodUtils.resolveUserId(callingUserId,
+ mSettings.getCurrentUserId(), null);
+ if (resolvedUserIds.length != 1) {
+ return Collections.emptyList();
+ }
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ return getEnabledInputMethodSubtypeListLocked(imiId,
+ allowsImplicitlySelectedSubtypes, resolvedUserIds[0]);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
}
- final long ident = Binder.clearCallingIdentity();
- try {
- return getEnabledInputMethodSubtypeListLocked(imiId,
- allowsImplicitlySelectedSubtypes, resolvedUserIds[0]);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
+ });
}
@GuardedBy("mMethodMap")
@@ -3150,41 +3160,44 @@
}
@Override
- public boolean showSoftInput(IInputMethodClient client, IBinder windowToken, int flags,
- ResultReceiver resultReceiver) {
- Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.showSoftInput");
- int uid = Binder.getCallingUid();
- ImeTracing.getInstance().triggerManagerServiceDump(
- "InputMethodManagerService#showSoftInput");
- synchronized (mMethodMap) {
- if (!calledFromValidUserLocked()) {
- return false;
- }
- final long ident = Binder.clearCallingIdentity();
- try {
- if (mCurClient == null || client == null
- || mCurClient.client.asBinder() != client.asBinder()) {
- // We need to check if this is the current client with
- // focus in the window manager, to allow this call to
- // be made before input is started in it.
- final ClientState cs = mClients.get(client.asBinder());
- if (cs == null) {
- throw new IllegalArgumentException("unknown client " + client.asBinder());
- }
- if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid,
- cs.selfReportedDisplayId)) {
- Slog.w(TAG, "Ignoring showSoftInput of uid " + uid + ": " + client);
- return false;
- }
+ public void showSoftInput(IInputMethodClient client, IBinder windowToken, int flags,
+ ResultReceiver resultReceiver, IBooleanResultCallback resultCallback) {
+ CallbackUtils.onResult(resultCallback, () -> {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.showSoftInput");
+ int uid = Binder.getCallingUid();
+ ImeTracing.getInstance().triggerManagerServiceDump(
+ "InputMethodManagerService#showSoftInput");
+ synchronized (mMethodMap) {
+ if (!calledFromValidUserLocked()) {
+ return false;
}
- if (DEBUG) Slog.v(TAG, "Client requesting input be shown");
- return showCurrentInputLocked(windowToken, flags, resultReceiver,
- SoftInputShowHideReason.SHOW_SOFT_INPUT);
- } finally {
- Binder.restoreCallingIdentity(ident);
- Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ if (mCurClient == null || client == null
+ || mCurClient.client.asBinder() != client.asBinder()) {
+ // We need to check if this is the current client with
+ // focus in the window manager, to allow this call to
+ // be made before input is started in it.
+ final ClientState cs = mClients.get(client.asBinder());
+ if (cs == null) {
+ throw new IllegalArgumentException(
+ "unknown client " + client.asBinder());
+ }
+ if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid,
+ cs.selfReportedDisplayId)) {
+ Slog.w(TAG, "Ignoring showSoftInput of uid " + uid + ": " + client);
+ return false;
+ }
+ }
+ if (DEBUG) Slog.v(TAG, "Client requesting input be shown");
+ return showCurrentInputLocked(windowToken, flags, resultReceiver,
+ SoftInputShowHideReason.SHOW_SOFT_INPUT);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+ }
}
- }
+ });
}
@BinderThread
@@ -3266,44 +3279,49 @@
}
@Override
- public boolean hideSoftInput(IInputMethodClient client, IBinder windowToken, int flags,
- ResultReceiver resultReceiver) {
- int uid = Binder.getCallingUid();
- ImeTracing.getInstance().triggerManagerServiceDump(
- "InputMethodManagerService#hideSoftInput");
- synchronized (mMethodMap) {
- if (!calledFromValidUserLocked()) {
- return false;
- }
- final long ident = Binder.clearCallingIdentity();
- try {
- Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.hideSoftInput");
- if (mCurClient == null || client == null
- || mCurClient.client.asBinder() != client.asBinder()) {
- // We need to check if this is the current client with
- // focus in the window manager, to allow this call to
- // be made before input is started in it.
- final ClientState cs = mClients.get(client.asBinder());
- if (cs == null) {
- throw new IllegalArgumentException("unknown client " + client.asBinder());
- }
- if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid,
- cs.selfReportedDisplayId)) {
- if (DEBUG) {
- Slog.w(TAG, "Ignoring hideSoftInput of uid " + uid + ": " + client);
- }
- return false;
- }
+ public void hideSoftInput(IInputMethodClient client, IBinder windowToken, int flags,
+ ResultReceiver resultReceiver, IBooleanResultCallback resultCallback) {
+ CallbackUtils.onResult(resultCallback, () -> {
+ int uid = Binder.getCallingUid();
+ ImeTracing.getInstance().triggerManagerServiceDump(
+ "InputMethodManagerService#hideSoftInput");
+ synchronized (mMethodMap) {
+ if (!InputMethodManagerService.this.calledFromValidUserLocked()) {
+ return false;
}
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.hideSoftInput");
+ if (mCurClient == null || client == null
+ || mCurClient.client.asBinder() != client.asBinder()) {
+ // We need to check if this is the current client with
+ // focus in the window manager, to allow this call to
+ // be made before input is started in it.
+ final ClientState cs = mClients.get(client.asBinder());
+ if (cs == null) {
+ throw new IllegalArgumentException(
+ "unknown client " + client.asBinder());
+ }
+ if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid,
+ cs.selfReportedDisplayId)) {
+ if (DEBUG) {
+ Slog.w(TAG,
+ "Ignoring hideSoftInput of uid " + uid + ": " + client);
+ }
+ return false;
+ }
+ }
- if (DEBUG) Slog.v(TAG, "Client requesting input be hidden");
- return hideCurrentInputLocked(windowToken, flags, resultReceiver,
- SoftInputShowHideReason.HIDE_SOFT_INPUT);
- } finally {
- Binder.restoreCallingIdentity(ident);
- Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+ if (DEBUG) Slog.v(TAG, "Client requesting input be hidden");
+ return InputMethodManagerService.this.hideCurrentInputLocked(windowToken,
+ flags, resultReceiver,
+ SoftInputShowHideReason.HIDE_SOFT_INPUT);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+ }
}
- }
+ });
}
boolean hideCurrentInputLocked(IBinder windowToken, int flags, ResultReceiver resultReceiver,
@@ -3726,9 +3744,15 @@
MSG_SHOW_IM_SUBTYPE_PICKER, auxiliarySubtypeMode, displayId));
}
- public boolean isInputMethodPickerShownForTest() {
+ /**
+ * A test API for CTS to make sure that the input method menu is showing.
+ *
+ * @param resultCallback {@code true} while the input method menu is showing UI.
+ */
+ public void isInputMethodPickerShownForTest(IBooleanResultCallback resultCallback) {
synchronized(mMethodMap) {
- return mMenuController.isisInputMethodPickerShownForTestLocked();
+ CallbackUtils.onResult(
+ resultCallback, mMenuController::isisInputMethodPickerShownForTestLocked);
}
}
@@ -3877,29 +3901,31 @@
}
@Override
- public InputMethodSubtype getLastInputMethodSubtype() {
- synchronized (mMethodMap) {
- if (!calledFromValidUserLocked()) {
- return null;
- }
- final Pair<String, String> lastIme = mSettings.getLastInputMethodAndSubtypeLocked();
- // TODO: Handle the case of the last IME with no subtypes
- if (lastIme == null || TextUtils.isEmpty(lastIme.first)
- || TextUtils.isEmpty(lastIme.second)) return null;
- final InputMethodInfo lastImi = mMethodMap.get(lastIme.first);
- if (lastImi == null) return null;
- try {
- final int lastSubtypeHash = Integer.parseInt(lastIme.second);
- final int lastSubtypeId =
- InputMethodUtils.getSubtypeIdFromHashCode(lastImi, lastSubtypeHash);
- if (lastSubtypeId < 0 || lastSubtypeId >= lastImi.getSubtypeCount()) {
+ public void getLastInputMethodSubtype(IInputMethodSubtypeResultCallback resultCallback) {
+ CallbackUtils.onResult(resultCallback, () -> {
+ synchronized (mMethodMap) {
+ if (!calledFromValidUserLocked()) {
return null;
}
- return lastImi.getSubtypeAt(lastSubtypeId);
- } catch (NumberFormatException e) {
- return null;
+ final Pair<String, String> lastIme = mSettings.getLastInputMethodAndSubtypeLocked();
+ // TODO: Handle the case of the last IME with no subtypes
+ if (lastIme == null || TextUtils.isEmpty(lastIme.first)
+ || TextUtils.isEmpty(lastIme.second)) return null;
+ final InputMethodInfo lastImi = mMethodMap.get(lastIme.first);
+ if (lastImi == null) return null;
+ try {
+ final int lastSubtypeHash = Integer.parseInt(lastIme.second);
+ final int lastSubtypeId =
+ InputMethodUtils.getSubtypeIdFromHashCode(lastImi, lastSubtypeHash);
+ if (lastSubtypeId < 0 || lastSubtypeId >= lastImi.getSubtypeCount()) {
+ return null;
+ }
+ return lastImi.getSubtypeAt(lastSubtypeId);
+ } catch (NumberFormatException e) {
+ return null;
+ }
}
- }
+ });
}
@Override
@@ -4120,8 +4146,8 @@
@BinderThread
@Override
- public boolean isImeTraceEnabled() {
- return ImeTracing.getInstance().isEnabled();
+ public void isImeTraceEnabled(IBooleanResultCallback resultCallback) {
+ CallbackUtils.onResult(resultCallback, () -> ImeTracing.getInstance().isEnabled());
}
@BinderThread
@@ -4935,17 +4961,21 @@
}
/**
- * @return Return the current subtype of this input method.
+ * Gets the current subtype of this input method.
+ *
+ * @param resultCallback to callback the result.
*/
@Override
- public InputMethodSubtype getCurrentInputMethodSubtype() {
- synchronized (mMethodMap) {
- // TODO: Make this work even for non-current users?
- if (!calledFromValidUserLocked()) {
- return null;
+ public void getCurrentInputMethodSubtype(IInputMethodSubtypeResultCallback resultCallback) {
+ CallbackUtils.onResult(resultCallback, () -> {
+ synchronized (mMethodMap) {
+ // TODO: Make this work even for non-current users?
+ if (!calledFromValidUserLocked()) {
+ return null;
+ }
+ return getCurrentInputMethodSubtypeLocked();
}
- return getCurrentInputMethodSubtypeLocked();
- }
+ });
}
InputMethodSubtype getCurrentInputMethodSubtypeLocked() {
diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
index 6bdae63..40ef55e 100644
--- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
@@ -73,7 +73,10 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.inputmethod.CallbackUtils;
+import com.android.internal.inputmethod.IBooleanResultCallback;
import com.android.internal.inputmethod.IInputBindResultResultCallback;
+import com.android.internal.inputmethod.IInputMethodSubtypeListResultCallback;
+import com.android.internal.inputmethod.IInputMethodSubtypeResultCallback;
import com.android.internal.inputmethod.IMultiClientInputMethod;
import com.android.internal.inputmethod.IMultiClientInputMethodPrivilegedOperations;
import com.android.internal.inputmethod.IMultiClientInputMethodSession;
@@ -1474,17 +1477,18 @@
@BinderThread
@Override
- public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(String imiId,
- boolean allowsImplicitlySelectedSubtypes) {
+ public void getEnabledInputMethodSubtypeList(String imiId,
+ boolean allowsImplicitlySelectedSubtypes,
+ IInputMethodSubtypeListResultCallback resultCallback) {
reportNotSupported();
- return Collections.emptyList();
+ CallbackUtils.onResult(resultCallback, Collections::emptyList);
}
@BinderThread
@Override
- public InputMethodSubtype getLastInputMethodSubtype() {
+ public void getLastInputMethodSubtype(IInputMethodSubtypeResultCallback resultCallback) {
reportNotSupported();
- return null;
+ CallbackUtils.onResult(resultCallback, () -> null);
}
@BinderThread
@@ -1501,7 +1505,15 @@
@BinderThread
@Override
- public boolean showSoftInput(
+ public void showSoftInput(
+ IInputMethodClient client, IBinder token, int flags,
+ ResultReceiver resultReceiver, IBooleanResultCallback resultCallback) {
+ CallbackUtils.onResult(resultCallback,
+ () -> showSoftInputInternal(client, token, flags, resultReceiver));
+ }
+
+ @BinderThread
+ private boolean showSoftInputInternal(
IInputMethodClient client, IBinder token, int flags,
ResultReceiver resultReceiver) {
final int callingUid = Binder.getCallingUid();
@@ -1548,7 +1560,16 @@
@BinderThread
@Override
- public boolean hideSoftInput(
+ public void hideSoftInput(
+ IInputMethodClient client, IBinder windowToken, int flags,
+ ResultReceiver resultReceiver, IBooleanResultCallback resultCallback) {
+ CallbackUtils.onResult(resultCallback,
+ () -> hideSoftInputInternal(client, windowToken, flags, resultReceiver));
+
+ }
+
+ @BinderThread
+ private boolean hideSoftInputInternal(
IInputMethodClient client, IBinder windowToken, int flags,
ResultReceiver resultReceiver) {
final int callingUid = Binder.getCallingUid();
@@ -1768,16 +1789,16 @@
@BinderThread
@Override
- public boolean isInputMethodPickerShownForTest() {
+ public void isInputMethodPickerShownForTest(IBooleanResultCallback resultCallback) {
reportNotSupported();
- return false;
+ CallbackUtils.onResult(resultCallback, () -> false);
}
@BinderThread
@Override
- public InputMethodSubtype getCurrentInputMethodSubtype() {
+ public void getCurrentInputMethodSubtype(IInputMethodSubtypeResultCallback resultCallback) {
reportNotSupported();
- return null;
+ CallbackUtils.onResult(resultCallback, () -> null);
}
@BinderThread
@@ -1834,8 +1855,8 @@
@BinderThread
@Override
- public boolean isImeTraceEnabled() {
- return false;
+ public void isImeTraceEnabled(IBooleanResultCallback resultCallback) {
+ CallbackUtils.onResult(resultCallback, () -> false);
}
@BinderThread
diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java
index 324332f..9068287 100644
--- a/services/core/java/com/android/server/location/LocationManagerService.java
+++ b/services/core/java/com/android/server/location/LocationManagerService.java
@@ -47,7 +47,7 @@
import android.location.Geofence;
import android.location.GnssCapabilities;
import android.location.GnssMeasurementCorrections;
-import android.location.GnssRequest;
+import android.location.GnssMeasurementRequest;
import android.location.IGeocodeListener;
import android.location.IGnssAntennaInfoListener;
import android.location.IGnssMeasurementsListener;
@@ -859,7 +859,7 @@
}
@Override
- public void addGnssMeasurementsListener(@Nullable GnssRequest request,
+ public void addGnssMeasurementsListener(@Nullable GnssMeasurementRequest request,
IGnssMeasurementsListener listener, String packageName, String attributionTag) {
if (mGnssManagerService != null) {
mGnssManagerService.addGnssMeasurementsListener(request, listener, packageName,
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubClientBroker.java b/services/core/java/com/android/server/location/contexthub/ContextHubClientBroker.java
index 20458b4..cc510fb 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubClientBroker.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubClientBroker.java
@@ -39,6 +39,10 @@
import com.android.server.location.ClientBrokerProto;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Supplier;
@@ -119,6 +123,13 @@
private final boolean mHasAccessContextHubPermission;
/*
+ * The set of nanoapp IDs that represent the group of nanoapps this client has a messaging
+ * channel with, i.e. has sent or received messages from this particular nanoapp.
+ */
+ private final Set<Long> mMessageChannelNanoappIdSet =
+ Collections.newSetFromMap(new ConcurrentHashMap<Long, Boolean>());
+
+ /*
* Helper class to manage registered PendingIntent requests from the client.
*/
private class PendingIntentRequest {
@@ -134,7 +145,8 @@
private boolean mValid = false;
- PendingIntentRequest() {}
+ PendingIntentRequest() {
+ }
PendingIntentRequest(PendingIntent pendingIntent, long nanoAppId) {
mPendingIntent = pendingIntent;
@@ -177,7 +189,7 @@
mPackage = mContext.getPackageManager().getNameForUid(Binder.getCallingUid());
mHasAccessContextHubPermission = context.checkCallingPermission(
- Manifest.permission.ACCESS_CONTEXT_HUB) == PERMISSION_GRANTED;
+ Manifest.permission.ACCESS_CONTEXT_HUB) == PERMISSION_GRANTED;
}
/* package */ ContextHubClientBroker(
@@ -193,7 +205,7 @@
mPackage = pendingIntent.getCreatorPackage();
mHasAccessContextHubPermission = context.checkCallingPermission(
- Manifest.permission.ACCESS_CONTEXT_HUB) == PERMISSION_GRANTED;
+ Manifest.permission.ACCESS_CONTEXT_HUB) == PERMISSION_GRANTED;
}
/**
@@ -209,6 +221,7 @@
int result;
if (isRegistered()) {
+ mMessageChannelNanoappIdSet.add(message.getNanoAppId());
ContextHubMsg messageToNanoApp =
ContextHubServiceUtil.createHidlContextHubMessage(mHostEndPointId, message);
@@ -269,6 +282,7 @@
* @param message the message that came from a nanoapp
*/
/* package */ void sendMessageToClient(NanoAppMessage message) {
+ mMessageChannelNanoappIdSet.add(message.getNanoAppId());
invokeCallback(callback -> callback.onMessageFromNanoApp(message));
Supplier<Intent> supplier =
@@ -413,7 +427,7 @@
/**
* Sends an intent to any existing PendingIntent
*
- * @param supplier method to create the extra Intent
+ * @param supplier method to create the extra Intent
* @param nanoAppId the ID of the nanoapp which this event is for
*/
private synchronized void sendPendingIntent(Supplier<Intent> supplier, long nanoAppId) {
@@ -427,7 +441,7 @@
* Sends a PendingIntent with extra Intent data
*
* @param pendingIntent the PendingIntent
- * @param intent the extra Intent data
+ * @param intent the extra Intent data
*/
private void doSendPendingIntent(PendingIntent pendingIntent, Intent intent) {
try {
@@ -500,6 +514,17 @@
} else {
out += "package: " + mPackage;
}
+ if (mMessageChannelNanoappIdSet.size() > 0) {
+ out += " messageChannelNanoappSet: (";
+ Iterator<Long> it = mMessageChannelNanoappIdSet.iterator();
+ while (it.hasNext()) {
+ out += "0x" + Long.toHexString(it.next());
+ if (it.hasNext()) {
+ out += ",";
+ }
+ }
+ out += ")";
+ }
out += "]";
return out;
diff --git a/services/core/java/com/android/server/location/gnss/GnssManagerService.java b/services/core/java/com/android/server/location/gnss/GnssManagerService.java
index 326265f..fa137aa 100644
--- a/services/core/java/com/android/server/location/gnss/GnssManagerService.java
+++ b/services/core/java/com/android/server/location/gnss/GnssManagerService.java
@@ -21,9 +21,9 @@
import android.content.Context;
import android.location.GnssAntennaInfo;
import android.location.GnssMeasurementCorrections;
+import android.location.GnssMeasurementRequest;
import android.location.GnssMeasurementsEvent;
import android.location.GnssNavigationMessage;
-import android.location.GnssRequest;
import android.location.IGnssAntennaInfoListener;
import android.location.IGnssMeasurementsListener;
import android.location.IGnssNavigationMessageListener;
@@ -176,12 +176,10 @@
/**
* Adds a GNSS measurements listener.
*/
- public void addGnssMeasurementsListener(GnssRequest request, IGnssMeasurementsListener listener,
- String packageName, @Nullable String attributionTag) {
+ public void addGnssMeasurementsListener(GnssMeasurementRequest request,
+ IGnssMeasurementsListener listener, String packageName,
+ @Nullable String attributionTag) {
mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
- if (request.isFullTracking()) {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.LOCATION_HARDWARE, null);
- }
CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag);
mGnssMeasurementsProvider.addListener(request, identity, listener);
diff --git a/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java b/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
index 59a533c..fa8e2a6 100644
--- a/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
@@ -21,8 +21,8 @@
import android.annotation.Nullable;
import android.app.AppOpsManager;
+import android.location.GnssMeasurementRequest;
import android.location.GnssMeasurementsEvent;
-import android.location.GnssRequest;
import android.location.IGnssMeasurementsListener;
import android.location.util.identity.CallerIdentity;
import android.os.IBinder;
@@ -47,18 +47,18 @@
* @hide
*/
public final class GnssMeasurementsProvider extends
- GnssListenerMultiplexer<GnssRequest, IGnssMeasurementsListener, Boolean> implements
- SettingsHelper.GlobalSettingChangedListener {
+ GnssListenerMultiplexer<GnssMeasurementRequest, IGnssMeasurementsListener, Boolean>
+ implements SettingsHelper.GlobalSettingChangedListener {
private class GnssMeasurementListenerRegistration extends GnssListenerRegistration {
private static final String GNSS_MEASUREMENTS_BUCKET = "gnss_measurement";
protected GnssMeasurementListenerRegistration(
- @Nullable GnssRequest gnssRequest,
+ @Nullable GnssMeasurementRequest request,
CallerIdentity callerIdentity,
IGnssMeasurementsListener iGnssMeasurementsListener) {
- super(gnssRequest, callerIdentity, iGnssMeasurementsListener);
+ super(request, callerIdentity, iGnssMeasurementsListener);
}
@Nullable
@@ -100,13 +100,13 @@
}
@Override
- public void addListener(GnssRequest request, CallerIdentity identity,
+ public void addListener(GnssMeasurementRequest request, CallerIdentity identity,
IGnssMeasurementsListener listener) {
super.addListener(request, identity, listener);
}
@Override
- protected GnssListenerRegistration createRegistration(GnssRequest request,
+ protected GnssListenerRegistration createRegistration(GnssMeasurementRequest request,
CallerIdentity callerIdentity, IGnssMeasurementsListener listener) {
return new GnssMeasurementListenerRegistration(request, callerIdentity, listener);
}
diff --git a/services/core/java/com/android/server/location/timezone/BinderLocationTimeZoneProvider.java b/services/core/java/com/android/server/location/timezone/BinderLocationTimeZoneProvider.java
index fd8cf70..b9c23b7 100644
--- a/services/core/java/com/android/server/location/timezone/BinderLocationTimeZoneProvider.java
+++ b/services/core/java/com/android/server/location/timezone/BinderLocationTimeZoneProvider.java
@@ -17,20 +17,17 @@
package com.android.server.location.timezone;
import static com.android.server.location.timezone.LocationTimeZoneManagerService.debugLog;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_DISABLED;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_ENABLED_CERTAIN;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_ENABLED_INITIALIZING;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_ENABLED_UNCERTAIN;
import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_PERM_FAILED;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_CERTAIN;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_INITIALIZING;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_UNCERTAIN;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STOPPED;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.util.IndentingPrintWriter;
import android.util.Slog;
-import com.android.internal.location.timezone.LocationTimeZoneEvent;
-import com.android.internal.location.timezone.LocationTimeZoneProviderRequest;
-
import java.time.Duration;
import java.util.Objects;
@@ -57,9 +54,9 @@
void onInitialize() {
mProxy.initialize(new LocationTimeZoneProviderProxy.Listener() {
@Override
- public void onReportLocationTimeZoneEvent(
- @NonNull LocationTimeZoneEvent locationTimeZoneEvent) {
- handleLocationTimeZoneEvent(locationTimeZoneEvent);
+ public void onReportTimeZoneProviderEvent(
+ @NonNull TimeZoneProviderEvent timeZoneProviderEvent) {
+ handleTimeZoneProviderEvent(timeZoneProviderEvent);
}
@Override
@@ -80,27 +77,27 @@
synchronized (mSharedLock) {
ProviderState currentState = mCurrentState.get();
switch (currentState.stateEnum) {
- case PROVIDER_STATE_ENABLED_INITIALIZING:
- case PROVIDER_STATE_ENABLED_UNCERTAIN:
- case PROVIDER_STATE_ENABLED_CERTAIN: {
+ case PROVIDER_STATE_STARTED_INITIALIZING:
+ case PROVIDER_STATE_STARTED_UNCERTAIN:
+ case PROVIDER_STATE_STARTED_CERTAIN: {
// Losing a remote provider is treated as becoming uncertain.
String msg = "handleProviderLost reason=" + reason
+ ", mProviderName=" + mProviderName
+ ", currentState=" + currentState;
debugLog(msg);
- // This is an unusual PROVIDER_STATE_ENABLED_UNCERTAIN state because
+ // This is an unusual PROVIDER_STATE_STARTED_UNCERTAIN state because
// event == null
ProviderState newState = currentState.newState(
- PROVIDER_STATE_ENABLED_UNCERTAIN, null,
+ PROVIDER_STATE_STARTED_UNCERTAIN, null,
currentState.currentUserConfiguration, msg);
setCurrentState(newState, true);
break;
}
- case PROVIDER_STATE_DISABLED: {
+ case PROVIDER_STATE_STOPPED: {
debugLog("handleProviderLost reason=" + reason
+ ", mProviderName=" + mProviderName
+ ", currentState=" + currentState
- + ": No state change required, provider is disabled.");
+ + ": No state change required, provider is stopped.");
break;
}
case PROVIDER_STATE_PERM_FAILED: {
@@ -123,16 +120,16 @@
synchronized (mSharedLock) {
ProviderState currentState = mCurrentState.get();
switch (currentState.stateEnum) {
- case PROVIDER_STATE_ENABLED_INITIALIZING:
- case PROVIDER_STATE_ENABLED_CERTAIN:
- case PROVIDER_STATE_ENABLED_UNCERTAIN: {
+ case PROVIDER_STATE_STARTED_INITIALIZING:
+ case PROVIDER_STATE_STARTED_CERTAIN:
+ case PROVIDER_STATE_STARTED_UNCERTAIN: {
debugLog("handleOnProviderBound mProviderName=" + mProviderName
- + ", currentState=" + currentState + ": Provider is enabled.");
+ + ", currentState=" + currentState + ": Provider is started.");
break;
}
- case PROVIDER_STATE_DISABLED: {
+ case PROVIDER_STATE_STOPPED: {
debugLog("handleOnProviderBound mProviderName=" + mProviderName
- + ", currentState=" + currentState + ": Provider is disabled.");
+ + ", currentState=" + currentState + ": Provider is stopped.");
break;
}
case PROVIDER_STATE_PERM_FAILED: {
@@ -150,23 +147,17 @@
}
@Override
- void onEnable(@NonNull Duration initializationTimeout) {
+ void onStartUpdates(@NonNull Duration initializationTimeout) {
// Set a request on the proxy - it will be sent immediately if the service is bound,
// or will be sent as soon as the service becomes bound.
- LocationTimeZoneProviderRequest request =
- new LocationTimeZoneProviderRequest.Builder()
- .setReportLocationTimeZone(true)
- .setInitializationTimeoutMillis(initializationTimeout.toMillis())
- .build();
+ TimeZoneProviderRequest request =
+ TimeZoneProviderRequest.createStartUpdatesRequest(initializationTimeout);
mProxy.setRequest(request);
}
@Override
- void onDisable() {
- LocationTimeZoneProviderRequest request =
- new LocationTimeZoneProviderRequest.Builder()
- .setReportLocationTimeZone(false)
- .build();
+ void onStopUpdates() {
+ TimeZoneProviderRequest request = TimeZoneProviderRequest.createStopUpdatesRequest();
mProxy.setRequest(request);
}
diff --git a/services/core/java/com/android/server/location/timezone/ControllerImpl.java b/services/core/java/com/android/server/location/timezone/ControllerImpl.java
index 07615ff..7496168 100644
--- a/services/core/java/com/android/server/location/timezone/ControllerImpl.java
+++ b/services/core/java/com/android/server/location/timezone/ControllerImpl.java
@@ -16,24 +16,24 @@
package com.android.server.location.timezone;
-import static com.android.internal.location.timezone.LocationTimeZoneEvent.EVENT_TYPE_PERMANENT_FAILURE;
-import static com.android.internal.location.timezone.LocationTimeZoneEvent.EVENT_TYPE_SUCCESS;
-import static com.android.internal.location.timezone.LocationTimeZoneEvent.EVENT_TYPE_UNCERTAIN;
import static com.android.server.location.timezone.LocationTimeZoneManagerService.debugLog;
import static com.android.server.location.timezone.LocationTimeZoneManagerService.warnLog;
import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_DISABLED;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_ENABLED_CERTAIN;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_ENABLED_INITIALIZING;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_ENABLED_UNCERTAIN;
import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_PERM_FAILED;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_CERTAIN;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_INITIALIZING;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_UNCERTAIN;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STOPPED;
+import static com.android.server.location.timezone.TimeZoneProviderEvent.EVENT_TYPE_PERMANENT_FAILURE;
+import static com.android.server.location.timezone.TimeZoneProviderEvent.EVENT_TYPE_SUGGESTION;
+import static com.android.server.location.timezone.TimeZoneProviderEvent.EVENT_TYPE_UNCERTAIN;
+import android.annotation.DurationMillisLong;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.util.IndentingPrintWriter;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.location.timezone.LocationTimeZoneEvent;
import com.android.server.location.timezone.ThreadingDomain.SingleRunnableQueue;
import com.android.server.timezonedetector.ConfigurationInternal;
import com.android.server.timezonedetector.GeolocationTimeZoneSuggestion;
@@ -46,9 +46,9 @@
* A real implementation of {@link LocationTimeZoneProviderController} that supports a primary and a
* secondary {@link LocationTimeZoneProvider}.
*
- * <p>The primary is used until it fails or becomes uncertain. The secondary will then be enabled.
+ * <p>The primary is used until it fails or becomes uncertain. The secondary will then be started.
* The controller will immediately make suggestions based on "certain" {@link
- * LocationTimeZoneEvent}s, i.e. events that demonstrate the provider is certain what the time zone
+ * TimeZoneProviderEvent}s, i.e. events that demonstrate the provider is certain what the time zone
* is. The controller will not make immediate suggestions based on "uncertain" events, giving
* providers time to change their mind. This also gives the secondary provider time to initialize
* when the primary becomes uncertain.
@@ -107,7 +107,7 @@
mPrimaryProvider.initialize(providerListener);
mSecondaryProvider.initialize(providerListener);
- alterProvidersEnabledStateIfRequired(
+ alterProvidersStartedStateIfRequired(
null /* oldConfiguration */, mCurrentUserConfiguration);
}
}
@@ -125,15 +125,15 @@
if (!newConfig.equals(oldConfig)) {
if (newConfig.getUserId() != oldConfig.getUserId()) {
- // If the user changed, disable the providers if needed. They may be re-enabled
+ // If the user changed, stop the providers if needed. They may be re-started
// for the new user immediately afterwards if their settings allow.
debugLog("User changed. old=" + oldConfig.getUserId()
- + ", new=" + newConfig.getUserId() + ": Disabling providers");
- disableProviders();
+ + ", new=" + newConfig.getUserId() + ": Stopping providers");
+ stopProviders();
- alterProvidersEnabledStateIfRequired(null /* oldConfiguration */, newConfig);
+ alterProvidersStartedStateIfRequired(null /* oldConfiguration */, newConfig);
} else {
- alterProvidersEnabledStateIfRequired(oldConfig, newConfig);
+ alterProvidersStartedStateIfRequired(oldConfig, newConfig);
}
}
}
@@ -145,43 +145,44 @@
}
@Override
+ @DurationMillisLong
long getUncertaintyTimeoutDelayMillis() {
return mUncertaintyTimeoutQueue.getQueuedDelayMillis();
}
@GuardedBy("mSharedLock")
- private void disableProviders() {
- disableProviderIfEnabled(mPrimaryProvider);
- disableProviderIfEnabled(mSecondaryProvider);
+ private void stopProviders() {
+ stopProviderIfStarted(mPrimaryProvider);
+ stopProviderIfStarted(mSecondaryProvider);
- // By definition, if both providers are disabled, the controller is uncertain.
+ // By definition, if both providers are stopped, the controller is uncertain.
cancelUncertaintyTimeout();
}
@GuardedBy("mSharedLock")
- private void disableProviderIfEnabled(@NonNull LocationTimeZoneProvider provider) {
- if (provider.getCurrentState().isEnabled()) {
- disableProvider(provider);
+ private void stopProviderIfStarted(@NonNull LocationTimeZoneProvider provider) {
+ if (provider.getCurrentState().isStarted()) {
+ stopProvider(provider);
}
}
@GuardedBy("mSharedLock")
- private void disableProvider(@NonNull LocationTimeZoneProvider provider) {
+ private void stopProvider(@NonNull LocationTimeZoneProvider provider) {
ProviderState providerState = provider.getCurrentState();
switch (providerState.stateEnum) {
- case PROVIDER_STATE_DISABLED: {
- debugLog("No need to disable " + provider + ": already disabled");
+ case PROVIDER_STATE_STOPPED: {
+ debugLog("No need to stop " + provider + ": already stopped");
break;
}
- case PROVIDER_STATE_ENABLED_INITIALIZING:
- case PROVIDER_STATE_ENABLED_CERTAIN:
- case PROVIDER_STATE_ENABLED_UNCERTAIN: {
- debugLog("Disabling " + provider);
- provider.disable();
+ case PROVIDER_STATE_STARTED_INITIALIZING:
+ case PROVIDER_STATE_STARTED_CERTAIN:
+ case PROVIDER_STATE_STARTED_UNCERTAIN: {
+ debugLog("Stopping " + provider);
+ provider.stopUpdates();
break;
}
case PROVIDER_STATE_PERM_FAILED: {
- debugLog("Unable to disable " + provider + ": it is perm failed");
+ debugLog("Unable to stop " + provider + ": it is perm failed");
break;
}
default: {
@@ -192,20 +193,20 @@
}
/**
- * Sets the providers into the correct enabled/disabled state for the {@code newConfiguration}
+ * Sets the providers into the correct started/stopped state for the {@code newConfiguration}
* and, if there is a provider state change, makes any suggestions required to inform the
* downstream time zone detection code.
*
* <p>This is a utility method that exists to avoid duplicated logic for the various cases when
- * provider enabled / disabled state may need to be set or changed, e.g. during initialization
+ * provider started / stopped state may need to be set or changed, e.g. during initialization
* or when a new configuration has been received.
*/
@GuardedBy("mSharedLock")
- private void alterProvidersEnabledStateIfRequired(
+ private void alterProvidersStartedStateIfRequired(
@Nullable ConfigurationInternal oldConfiguration,
@NonNull ConfigurationInternal newConfiguration) {
- // Provider enabled / disabled states only need to be changed if geoDetectionEnabled has
+ // Provider started / stopped states only need to be changed if geoDetectionEnabled has
// changed.
boolean oldGeoDetectionEnabled = oldConfiguration != null
&& oldConfiguration.getGeoDetectionEnabledBehavior();
@@ -215,28 +216,28 @@
}
// The check above ensures that the logic below only executes if providers are going from
- // {enabled *} -> {disabled}, or {disabled} -> {enabled initializing}. If this changes in
- // future and there could be {enabled *} -> {enabled *} cases, or cases where the provider
- // can't be assumed to go straight to the {enabled initializing} state, then the logic below
+ // {started *} -> {stopped}, or {stopped} -> {started initializing}. If this changes in
+ // future and there could be {started *} -> {started *} cases, or cases where the provider
+ // can't be assumed to go straight to the {started initializing} state, then the logic below
// would need to cover extra conditions, for example:
- // 1) If the primary is in {enabled uncertain}, the secondary should be enabled.
+ // 1) If the primary is in {started uncertain}, the secondary should be started.
// 2) If (1), and the secondary instantly enters the {perm failed} state, the uncertainty
- // timeout started when the primary entered {enabled uncertain} should be cancelled.
+ // timeout started when the primary entered {started uncertain} should be cancelled.
if (newGeoDetectionEnabled) {
- // Try to enable the primary provider.
- tryEnableProvider(mPrimaryProvider, newConfiguration);
+ // Try to start the primary provider.
+ tryStartProvider(mPrimaryProvider, newConfiguration);
- // The secondary should only ever be enabled if the primary now isn't enabled (i.e. it
- // couldn't become {enabled initializing} because it is {perm failed}).
+ // The secondary should only ever be started if the primary now isn't started (i.e. it
+ // couldn't become {started initializing} because it is {perm failed}).
ProviderState newPrimaryState = mPrimaryProvider.getCurrentState();
- if (!newPrimaryState.isEnabled()) {
- // If the primary provider is {perm failed} then the controller must try to enable
+ if (!newPrimaryState.isStarted()) {
+ // If the primary provider is {perm failed} then the controller must try to start
// the secondary.
- tryEnableProvider(mSecondaryProvider, newConfiguration);
+ tryStartProvider(mSecondaryProvider, newConfiguration);
ProviderState newSecondaryState = mSecondaryProvider.getCurrentState();
- if (!newSecondaryState.isEnabled()) {
+ if (!newSecondaryState.isStarted()) {
// If both providers are {perm failed} then the controller immediately
// becomes uncertain.
GeolocationTimeZoneSuggestion suggestion = createUncertainSuggestion(
@@ -247,7 +248,7 @@
}
}
} else {
- disableProviders();
+ stopProviders();
// There can be an uncertainty timeout set if the controller most recently received
// an uncertain event. This is a no-op if there isn't a timeout set.
@@ -256,34 +257,35 @@
// If a previous "certain" suggestion has been made, then a new "uncertain"
// suggestion must now be made to indicate the controller {does not / no longer has}
// an opinion and will not be sending further updates (until at least the config
- // changes again and providers are re-enabled).
+ // changes again and providers are re-started).
if (mLastSuggestion != null && mLastSuggestion.getZoneIds() != null) {
GeolocationTimeZoneSuggestion suggestion = createUncertainSuggestion(
- "Provider is disabled:"
+ "Provider is stopped:"
+ " primary=" + mPrimaryProvider.getCurrentState());
makeSuggestion(suggestion);
}
}
}
- private void tryEnableProvider(@NonNull LocationTimeZoneProvider provider,
+ private void tryStartProvider(@NonNull LocationTimeZoneProvider provider,
@NonNull ConfigurationInternal configuration) {
ProviderState providerState = provider.getCurrentState();
switch (providerState.stateEnum) {
- case PROVIDER_STATE_DISABLED: {
+ case PROVIDER_STATE_STOPPED: {
debugLog("Enabling " + provider);
- provider.enable(configuration, mEnvironment.getProviderInitializationTimeout(),
+ provider.startUpdates(configuration,
+ mEnvironment.getProviderInitializationTimeout(),
mEnvironment.getProviderInitializationTimeoutFuzz());
break;
}
- case PROVIDER_STATE_ENABLED_INITIALIZING:
- case PROVIDER_STATE_ENABLED_CERTAIN:
- case PROVIDER_STATE_ENABLED_UNCERTAIN: {
- debugLog("No need to enable " + provider + ": already enabled");
+ case PROVIDER_STATE_STARTED_INITIALIZING:
+ case PROVIDER_STATE_STARTED_CERTAIN:
+ case PROVIDER_STATE_STARTED_UNCERTAIN: {
+ debugLog("No need to start " + provider + ": already started");
break;
}
case PROVIDER_STATE_PERM_FAILED: {
- debugLog("Unable to enable " + provider + ": it is perm failed");
+ debugLog("Unable to start " + provider + ": it is perm failed");
break;
}
default: {
@@ -300,20 +302,20 @@
synchronized (mSharedLock) {
switch (providerState.stateEnum) {
- case PROVIDER_STATE_DISABLED: {
- // This should never happen: entering disabled does not trigger a state change.
- warnLog("onProviderStateChange: Unexpected state change for disabled provider,"
+ case PROVIDER_STATE_STOPPED: {
+ // This should never happen: entering stopped does not trigger a state change.
+ warnLog("onProviderStateChange: Unexpected state change for stopped provider,"
+ " provider=" + provider);
break;
}
- case PROVIDER_STATE_ENABLED_INITIALIZING:
- case PROVIDER_STATE_ENABLED_CERTAIN:
- case PROVIDER_STATE_ENABLED_UNCERTAIN: {
- // Entering enabled does not trigger a state change, so this only happens if an
- // event is received while the provider is enabled.
+ case PROVIDER_STATE_STARTED_INITIALIZING:
+ case PROVIDER_STATE_STARTED_CERTAIN:
+ case PROVIDER_STATE_STARTED_UNCERTAIN: {
+ // Entering started does not trigger a state change, so this only happens if an
+ // event is received while the provider is started.
debugLog("onProviderStateChange: Received notification of a state change while"
- + " enabled, provider=" + provider);
- handleProviderEnabledStateChange(providerState);
+ + " started, provider=" + provider);
+ handleProviderStartedStateChange(providerState);
break;
}
case PROVIDER_STATE_PERM_FAILED: {
@@ -344,18 +346,18 @@
ProviderState primaryCurrentState = mPrimaryProvider.getCurrentState();
ProviderState secondaryCurrentState = mSecondaryProvider.getCurrentState();
- // If a provider has failed, the other may need to be enabled.
+ // If a provider has failed, the other may need to be started.
if (failedProvider == mPrimaryProvider) {
if (secondaryCurrentState.stateEnum != PROVIDER_STATE_PERM_FAILED) {
- // The primary must have failed. Try to enable the secondary. This does nothing if
- // the provider is already enabled, and will leave the provider in
- // {enabled initializing} if the provider is disabled.
- tryEnableProvider(mSecondaryProvider, mCurrentUserConfiguration);
+ // The primary must have failed. Try to start the secondary. This does nothing if
+ // the provider is already started, and will leave the provider in
+ // {started initializing} if the provider is stopped.
+ tryStartProvider(mSecondaryProvider, mCurrentUserConfiguration);
}
} else if (failedProvider == mSecondaryProvider) {
// No-op: The secondary will only be active if the primary is uncertain or is failed.
- // So, there the primary should not need to be enabled when the secondary fails.
- if (primaryCurrentState.stateEnum != PROVIDER_STATE_ENABLED_UNCERTAIN
+ // So, there the primary should not need to be started when the secondary fails.
+ if (primaryCurrentState.stateEnum != PROVIDER_STATE_STARTED_UNCERTAIN
&& primaryCurrentState.stateEnum != PROVIDER_STATE_PERM_FAILED) {
warnLog("Secondary provider unexpected reported a failure:"
+ " failed provider=" + failedProvider.getName()
@@ -384,16 +386,16 @@
}
/**
- * Called when a provider has changed state but just moved from one enabled state to another
- * enabled state, usually as a result of a new {@link LocationTimeZoneEvent} being received.
+ * Called when a provider has changed state but just moved from one started state to another
+ * started state, usually as a result of a new {@link TimeZoneProviderEvent} being received.
* However, there are rare cases where the event can also be null.
*/
@GuardedBy("mSharedLock")
- private void handleProviderEnabledStateChange(@NonNull ProviderState providerState) {
+ private void handleProviderStartedStateChange(@NonNull ProviderState providerState) {
LocationTimeZoneProvider provider = providerState.provider;
- LocationTimeZoneEvent event = providerState.event;
+ TimeZoneProviderEvent event = providerState.event;
if (event == null) {
- // Implicit uncertainty, i.e. where the provider is enabled, but a problem has been
+ // Implicit uncertainty, i.e. where the provider is started, but a problem has been
// detected without having received an event. For example, if the process has detected
// the loss of a binder-based provider, or initialization took too long. This is treated
// the same as explicit uncertainty, i.e. where the provider has explicitly told this
@@ -404,18 +406,18 @@
}
if (!mCurrentUserConfiguration.getGeoDetectionEnabledBehavior()) {
- // This should not happen: the provider should not be in an enabled state if the user
+ // This should not happen: the provider should not be in an started state if the user
// does not have geodetection enabled.
- warnLog("Provider=" + provider + " is enabled, but"
+ warnLog("Provider=" + provider + " is started, but"
+ " currentUserConfiguration=" + mCurrentUserConfiguration
+ " suggests it shouldn't be.");
}
- switch (event.getEventType()) {
+ switch (event.getType()) {
case EVENT_TYPE_PERMANENT_FAILURE: {
- // This shouldn't happen. A provider cannot be enabled and have this event type.
+ // This shouldn't happen. A provider cannot be started and have this event type.
warnLog("Provider=" + provider
- + " is enabled, but event suggests it shouldn't be");
+ + " is started, but event suggests it shouldn't be");
break;
}
case EVENT_TYPE_UNCERTAIN: {
@@ -423,13 +425,13 @@
+ ", explicit uncertainty. event=" + event);
break;
}
- case EVENT_TYPE_SUCCESS: {
- handleProviderCertainty(provider, event.getTimeZoneIds(),
+ case EVENT_TYPE_SUGGESTION: {
+ handleProviderSuggestion(provider, event.getSuggestion().getTimeZoneIds(),
"Event received provider=" + provider + ", event=" + event);
break;
}
default: {
- warnLog("Unknown eventType=" + event.getEventType());
+ warnLog("Unknown eventType=" + event.getType());
break;
}
}
@@ -439,7 +441,7 @@
* Called when a provider has become "certain" about the time zone(s).
*/
@GuardedBy("mSharedLock")
- private void handleProviderCertainty(
+ private void handleProviderSuggestion(
@NonNull LocationTimeZoneProvider provider,
@Nullable List<String> timeZoneIds,
@NonNull String reason) {
@@ -447,11 +449,10 @@
cancelUncertaintyTimeout();
if (provider == mPrimaryProvider) {
- disableProviderIfEnabled(mSecondaryProvider);
+ stopProviderIfStarted(mSecondaryProvider);
}
- GeolocationTimeZoneSuggestion suggestion =
- new GeolocationTimeZoneSuggestion(timeZoneIds);
+ GeolocationTimeZoneSuggestion suggestion = new GeolocationTimeZoneSuggestion(timeZoneIds);
suggestion.addDebugInfo(reason);
// Rely on the receiver to dedupe suggestions. It is better to over-communicate.
makeSuggestion(suggestion);
@@ -503,7 +504,7 @@
* Called when a provider has become "uncertain" about the time zone.
*
* <p>A provider is expected to report its uncertainty as soon as it becomes uncertain, as
- * this enables the most flexibility for the controller to enable other providers when there are
+ * this enables the most flexibility for the controller to start other providers when there are
* multiple ones available. The controller is therefore responsible for deciding when to make a
* "uncertain" suggestion to the downstream time zone detector.
*
@@ -532,11 +533,11 @@
}
if (provider == mPrimaryProvider) {
- // (Try to) enable the secondary. It could already be enabled, or enabling might not
+ // (Try to) start the secondary. It could already be started, or enabling might not
// succeed if the provider has previously reported it is perm failed. The uncertainty
// timeout (set above) is used to ensure that an uncertain suggestion will be made if
// the secondary cannot generate a success event in time.
- tryEnableProvider(mSecondaryProvider, mCurrentUserConfiguration);
+ tryStartProvider(mSecondaryProvider, mCurrentUserConfiguration);
}
}
diff --git a/services/core/java/com/android/server/location/timezone/HandlerThreadingDomain.java b/services/core/java/com/android/server/location/timezone/HandlerThreadingDomain.java
index 17e719e..b59898a 100644
--- a/services/core/java/com/android/server/location/timezone/HandlerThreadingDomain.java
+++ b/services/core/java/com/android/server/location/timezone/HandlerThreadingDomain.java
@@ -16,6 +16,7 @@
package com.android.server.location.timezone;
+import android.annotation.DurationMillisLong;
import android.annotation.NonNull;
import android.os.Handler;
@@ -57,12 +58,12 @@
}
@Override
- void postDelayed(@NonNull Runnable r, long delayMillis) {
+ void postDelayed(@NonNull Runnable r, @DurationMillisLong long delayMillis) {
getHandler().postDelayed(r, delayMillis);
}
@Override
- void postDelayed(Runnable r, Object token, long delayMillis) {
+ void postDelayed(Runnable r, Object token, @DurationMillisLong long delayMillis) {
getHandler().postDelayed(r, token, delayMillis);
}
diff --git a/services/core/java/com/android/server/location/timezone/LocationTimeZoneManagerService.java b/services/core/java/com/android/server/location/timezone/LocationTimeZoneManagerService.java
index c8a1db6..98ebec2 100644
--- a/services/core/java/com/android/server/location/timezone/LocationTimeZoneManagerService.java
+++ b/services/core/java/com/android/server/location/timezone/LocationTimeZoneManagerService.java
@@ -24,6 +24,7 @@
import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.os.SystemProperties;
+import android.service.timezone.TimeZoneProviderService;
import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.Slog;
@@ -44,7 +45,7 @@
* A service class that acts as a container for the {@link LocationTimeZoneProviderController},
* which determines what {@link com.android.server.timezonedetector.GeolocationTimeZoneSuggestion}
* are made to the {@link TimeZoneDetectorInternal}, and the {@link LocationTimeZoneProvider}s that
- * (indirectly) generate {@link com.android.internal.location.timezone.LocationTimeZoneEvent}s.
+ * (indirectly) generate {@link TimeZoneProviderEvent}s.
*
* <p>For details of the time zone suggestion behavior, see {@link
* LocationTimeZoneProviderController}.
@@ -120,9 +121,9 @@
private static final String ATTRIBUTION_TAG = "LocationTimeZoneService";
private static final String PRIMARY_LOCATION_TIME_ZONE_SERVICE_ACTION =
- "com.android.location.timezone.service.v1.PrimaryLocationTimeZoneProvider";
+ TimeZoneProviderService.PRIMARY_LOCATION_TIME_ZONE_PROVIDER_SERVICE_INTERFACE;
private static final String SECONDARY_LOCATION_TIME_ZONE_SERVICE_ACTION =
- "com.android.location.timezone.service.v1.SecondaryLocationTimeZoneProvider";
+ TimeZoneProviderService.SECONDARY_LOCATION_TIME_ZONE_PROVIDER_SERVICE_INTERFACE;
@NonNull private final Context mContext;
diff --git a/services/core/java/com/android/server/location/timezone/LocationTimeZoneProvider.java b/services/core/java/com/android/server/location/timezone/LocationTimeZoneProvider.java
index dc56238..8b51ab4 100644
--- a/services/core/java/com/android/server/location/timezone/LocationTimeZoneProvider.java
+++ b/services/core/java/com/android/server/location/timezone/LocationTimeZoneProvider.java
@@ -16,16 +16,17 @@
package com.android.server.location.timezone;
-import static com.android.internal.location.timezone.LocationTimeZoneEvent.EVENT_TYPE_PERMANENT_FAILURE;
-import static com.android.internal.location.timezone.LocationTimeZoneEvent.EVENT_TYPE_SUCCESS;
-import static com.android.internal.location.timezone.LocationTimeZoneEvent.EVENT_TYPE_UNCERTAIN;
import static com.android.server.location.timezone.LocationTimeZoneManagerService.debugLog;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_DISABLED;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_ENABLED_CERTAIN;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_ENABLED_INITIALIZING;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_ENABLED_UNCERTAIN;
import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_PERM_FAILED;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_CERTAIN;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_INITIALIZING;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_UNCERTAIN;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STOPPED;
+import static com.android.server.location.timezone.TimeZoneProviderEvent.EVENT_TYPE_PERMANENT_FAILURE;
+import static com.android.server.location.timezone.TimeZoneProviderEvent.EVENT_TYPE_SUGGESTION;
+import static com.android.server.location.timezone.TimeZoneProviderEvent.EVENT_TYPE_UNCERTAIN;
+import android.annotation.ElapsedRealtimeLong;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -34,7 +35,6 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.location.timezone.LocationTimeZoneEvent;
import com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.ProviderStateEnum;
import com.android.server.location.timezone.ThreadingDomain.SingleRunnableQueue;
import com.android.server.timezonedetector.ConfigurationInternal;
@@ -50,7 +50,7 @@
* process, or could be a stubbed instance when no real provider is registered.
*
* <p>The provider is supplied with a {@link ProviderListener} via {@link
- * #initialize(ProviderListener)}. This enables it to communicates asynchronous detection / error
+ * #initialize(ProviderListener)}. This starts communication of asynchronous detection / error
* events back to the {@link LocationTimeZoneProviderController} via the {@link
* ProviderListener#onProviderStateChange} method. This call must be made on the
* {@link Handler} thread from the {@link ThreadingDomain} passed to the constructor.
@@ -77,9 +77,10 @@
*/
static class ProviderState {
- @IntDef({ PROVIDER_STATE_UNKNOWN, PROVIDER_STATE_ENABLED_INITIALIZING,
- PROVIDER_STATE_ENABLED_CERTAIN, PROVIDER_STATE_ENABLED_UNCERTAIN,
- PROVIDER_STATE_DISABLED, PROVIDER_STATE_PERM_FAILED })
+ @IntDef(prefix = "PROVIDER_STATE_",
+ value = { PROVIDER_STATE_UNKNOWN, PROVIDER_STATE_STARTED_INITIALIZING,
+ PROVIDER_STATE_STARTED_CERTAIN, PROVIDER_STATE_STARTED_UNCERTAIN,
+ PROVIDER_STATE_STOPPED, PROVIDER_STATE_PERM_FAILED })
@interface ProviderStateEnum {}
/**
@@ -88,31 +89,31 @@
static final int PROVIDER_STATE_UNKNOWN = 0;
/**
- * The provider is enabled and has not reported its first event.
+ * The provider is started and has not reported its first event.
*/
- static final int PROVIDER_STATE_ENABLED_INITIALIZING = 1;
+ static final int PROVIDER_STATE_STARTED_INITIALIZING = 1;
/**
- * The provider is enabled and most recently reported a "success" event.
+ * The provider is started and most recently reported a "suggestion" event.
*/
- static final int PROVIDER_STATE_ENABLED_CERTAIN = 2;
+ static final int PROVIDER_STATE_STARTED_CERTAIN = 2;
/**
- * The provider is enabled and most recently reported an "uncertain" event.
+ * The provider is started and most recently reported an "uncertain" event.
*/
- static final int PROVIDER_STATE_ENABLED_UNCERTAIN = 3;
+ static final int PROVIDER_STATE_STARTED_UNCERTAIN = 3;
/**
- * The provider is disabled.
+ * The provider is stopped.
*
* This is the state after {@link #initialize} is called.
*/
- static final int PROVIDER_STATE_DISABLED = 4;
+ static final int PROVIDER_STATE_STOPPED = 4;
/**
- * The provider has failed and cannot be re-enabled.
+ * The provider has failed and cannot be re-started.
*
- * Providers may enter this state after a provider is enabled.
+ * Providers may enter this state after a provider is started.
*/
static final int PROVIDER_STATE_PERM_FAILED = 5;
@@ -123,16 +124,16 @@
public final @ProviderStateEnum int stateEnum;
/**
- * The last {@link LocationTimeZoneEvent} received. Only populated when {@link #stateEnum}
- * is either {@link #PROVIDER_STATE_ENABLED_CERTAIN} or {@link
- * #PROVIDER_STATE_ENABLED_UNCERTAIN}, but it can be {@code null} then too if no event has
+ * The last {@link TimeZoneProviderEvent} received. Only populated when {@link #stateEnum}
+ * is either {@link #PROVIDER_STATE_STARTED_CERTAIN} or {@link
+ * #PROVIDER_STATE_STARTED_UNCERTAIN}, but it can be {@code null} then too if no event has
* yet been received.
*/
- @Nullable public final LocationTimeZoneEvent event;
+ @Nullable public final TimeZoneProviderEvent event;
/**
* The user configuration associated with the current state. Only and always present when
- * {@link #stateEnum} is one of the enabled states.
+ * {@link #stateEnum} is one of the started states.
*/
@Nullable public final ConfigurationInternal currentUserConfiguration;
@@ -140,6 +141,7 @@
* The time according to the elapsed realtime clock when the provider entered the current
* state. Included for debugging, not used for equality.
*/
+ @ElapsedRealtimeLong
private final long mStateEntryTimeMillis;
/**
@@ -151,7 +153,7 @@
private ProviderState(@NonNull LocationTimeZoneProvider provider,
@ProviderStateEnum int stateEnum,
- @Nullable LocationTimeZoneEvent event,
+ @Nullable TimeZoneProviderEvent event,
@Nullable ConfigurationInternal currentUserConfiguration,
@Nullable String debugInfo) {
this.provider = Objects.requireNonNull(provider);
@@ -174,25 +176,25 @@
* and that the required parameters for the new state are present / absent.
*/
ProviderState newState(@ProviderStateEnum int newStateEnum,
- @Nullable LocationTimeZoneEvent event,
+ @Nullable TimeZoneProviderEvent event,
@Nullable ConfigurationInternal currentUserConfig,
@Nullable String debugInfo) {
// Check valid "from" transitions.
switch (this.stateEnum) {
case PROVIDER_STATE_UNKNOWN: {
- if (newStateEnum != PROVIDER_STATE_DISABLED) {
+ if (newStateEnum != PROVIDER_STATE_STOPPED) {
throw new IllegalArgumentException(
"Must transition from " + prettyPrintStateEnum(
PROVIDER_STATE_UNKNOWN)
- + " to " + prettyPrintStateEnum(PROVIDER_STATE_DISABLED));
+ + " to " + prettyPrintStateEnum(PROVIDER_STATE_STOPPED));
}
break;
}
- case PROVIDER_STATE_DISABLED:
- case PROVIDER_STATE_ENABLED_INITIALIZING:
- case PROVIDER_STATE_ENABLED_CERTAIN:
- case PROVIDER_STATE_ENABLED_UNCERTAIN: {
+ case PROVIDER_STATE_STOPPED:
+ case PROVIDER_STATE_STARTED_INITIALIZING:
+ case PROVIDER_STATE_STARTED_CERTAIN:
+ case PROVIDER_STATE_STARTED_UNCERTAIN: {
// These can go to each other or PROVIDER_STATE_PERM_FAILED.
break;
}
@@ -211,21 +213,21 @@
throw new IllegalArgumentException("Cannot transition to "
+ prettyPrintStateEnum(PROVIDER_STATE_UNKNOWN));
}
- case PROVIDER_STATE_DISABLED: {
+ case PROVIDER_STATE_STOPPED: {
if (event != null || currentUserConfig != null) {
throw new IllegalArgumentException(
- "Disabled state: event and currentUserConfig must be null"
+ "Stopped state: event and currentUserConfig must be null"
+ ", event=" + event
+ ", currentUserConfig=" + currentUserConfig);
}
break;
}
- case PROVIDER_STATE_ENABLED_INITIALIZING:
- case PROVIDER_STATE_ENABLED_CERTAIN:
- case PROVIDER_STATE_ENABLED_UNCERTAIN: {
+ case PROVIDER_STATE_STARTED_INITIALIZING:
+ case PROVIDER_STATE_STARTED_CERTAIN:
+ case PROVIDER_STATE_STARTED_UNCERTAIN: {
if (currentUserConfig == null) {
throw new IllegalArgumentException(
- "Enabled state: currentUserConfig must not be null");
+ "Started state: currentUserConfig must not be null");
}
break;
}
@@ -245,11 +247,11 @@
return new ProviderState(provider, newStateEnum, event, currentUserConfig, debugInfo);
}
- /** Returns {@code true} if {@link #stateEnum} is one of the enabled states. */
- boolean isEnabled() {
- return stateEnum == PROVIDER_STATE_ENABLED_INITIALIZING
- || stateEnum == PROVIDER_STATE_ENABLED_CERTAIN
- || stateEnum == PROVIDER_STATE_ENABLED_UNCERTAIN;
+ /** Returns {@code true} if {@link #stateEnum} is one of the started states. */
+ boolean isStarted() {
+ return stateEnum == PROVIDER_STATE_STARTED_INITIALIZING
+ || stateEnum == PROVIDER_STATE_STARTED_CERTAIN
+ || stateEnum == PROVIDER_STATE_STARTED_UNCERTAIN;
}
@Override
@@ -286,14 +288,14 @@
private static String prettyPrintStateEnum(@ProviderStateEnum int state) {
switch (state) {
- case PROVIDER_STATE_DISABLED:
- return "Disabled (" + PROVIDER_STATE_DISABLED + ")";
- case PROVIDER_STATE_ENABLED_INITIALIZING:
- return "Enabled initializing (" + PROVIDER_STATE_ENABLED_INITIALIZING + ")";
- case PROVIDER_STATE_ENABLED_CERTAIN:
- return "Enabled certain (" + PROVIDER_STATE_ENABLED_CERTAIN + ")";
- case PROVIDER_STATE_ENABLED_UNCERTAIN:
- return "Enabled uncertain (" + PROVIDER_STATE_ENABLED_UNCERTAIN + ")";
+ case PROVIDER_STATE_STOPPED:
+ return "Stopped (" + PROVIDER_STATE_STOPPED + ")";
+ case PROVIDER_STATE_STARTED_INITIALIZING:
+ return "Started initializing (" + PROVIDER_STATE_STARTED_INITIALIZING + ")";
+ case PROVIDER_STATE_STARTED_CERTAIN:
+ return "Started certain (" + PROVIDER_STATE_STARTED_CERTAIN + ")";
+ case PROVIDER_STATE_STARTED_UNCERTAIN:
+ return "Started uncertain (" + PROVIDER_STATE_STARTED_UNCERTAIN + ")";
case PROVIDER_STATE_PERM_FAILED:
return "Perm failure (" + PROVIDER_STATE_PERM_FAILED + ")";
case PROVIDER_STATE_UNKNOWN:
@@ -315,7 +317,7 @@
new ReferenceWithHistory<>(10);
/**
- * Used for scheduling initialization timeouts, i.e. for providers that have just been enabled.
+ * Used for scheduling initialization timeouts, i.e. for providers that have just been started.
*/
@NonNull private final SingleRunnableQueue mInitializationTimeoutQueue;
@@ -344,7 +346,7 @@
mProviderListener = Objects.requireNonNull(providerListener);
ProviderState currentState = ProviderState.createStartingState(this);
ProviderState newState = currentState.newState(
- PROVIDER_STATE_DISABLED, null, null,
+ PROVIDER_STATE_STOPPED, null, null,
"initialize() called");
setCurrentState(newState, false);
@@ -407,28 +409,28 @@
}
/**
- * Enables the provider. It is an error to call this method except when the {@link
- * #getCurrentState()} is at {@link ProviderState#PROVIDER_STATE_DISABLED}. This method must be
+ * Starts the provider. It is an error to call this method except when the {@link
+ * #getCurrentState()} is at {@link ProviderState#PROVIDER_STATE_STOPPED}. This method must be
* called using the handler thread from the {@link ThreadingDomain}.
*/
- final void enable(@NonNull ConfigurationInternal currentUserConfiguration,
+ final void startUpdates(@NonNull ConfigurationInternal currentUserConfiguration,
@NonNull Duration initializationTimeout, @NonNull Duration initializationTimeoutFuzz) {
mThreadingDomain.assertCurrentThread();
synchronized (mSharedLock) {
- assertCurrentState(PROVIDER_STATE_DISABLED);
+ assertCurrentState(PROVIDER_STATE_STOPPED);
ProviderState currentState = mCurrentState.get();
ProviderState newState = currentState.newState(
- PROVIDER_STATE_ENABLED_INITIALIZING, null /* event */,
- currentUserConfiguration, "enable() called");
+ PROVIDER_STATE_STARTED_INITIALIZING, null /* event */,
+ currentUserConfiguration, "startUpdates() called");
setCurrentState(newState, false);
Duration delay = initializationTimeout.plus(initializationTimeoutFuzz);
mInitializationTimeoutQueue.runDelayed(
this::handleInitializationTimeout, delay.toMillis());
- onEnable(initializationTimeout);
+ onStartUpdates(initializationTimeout);
}
}
@@ -437,10 +439,10 @@
synchronized (mSharedLock) {
ProviderState currentState = mCurrentState.get();
- if (currentState.stateEnum == PROVIDER_STATE_ENABLED_INITIALIZING) {
+ if (currentState.stateEnum == PROVIDER_STATE_STARTED_INITIALIZING) {
// On initialization timeout the provider becomes uncertain.
ProviderState newState = currentState.newState(
- PROVIDER_STATE_ENABLED_UNCERTAIN, null /* event */,
+ PROVIDER_STATE_STARTED_UNCERTAIN, null /* event */,
currentState.currentUserConfiguration, "initialization timeout");
setCurrentState(newState, true);
}
@@ -448,65 +450,64 @@
}
/**
- * Implemented by subclasses to do work during {@link #enable}.
+ * Implemented by subclasses to do work during {@link #startUpdates}.
*/
- abstract void onEnable(@NonNull Duration initializationTimeout);
+ abstract void onStartUpdates(@NonNull Duration initializationTimeout);
/**
- * Disables the provider. It is an error* to call this method except when the {@link
- * #getCurrentState()} is one of the enabled states. This method must be
+ * Stops the provider. It is an error* to call this method except when the {@link
+ * #getCurrentState()} is one of the started states. This method must be
* called using the handler thread from the {@link ThreadingDomain}.
*/
- final void disable() {
+ final void stopUpdates() {
mThreadingDomain.assertCurrentThread();
synchronized (mSharedLock) {
- assertIsEnabled();
+ assertIsStarted();
ProviderState currentState = mCurrentState.get();
ProviderState newState = currentState.newState(
- PROVIDER_STATE_DISABLED, null, null, "disable() called");
+ PROVIDER_STATE_STOPPED, null, null, "stopUpdates() called");
setCurrentState(newState, false);
if (mInitializationTimeoutQueue.hasQueued()) {
mInitializationTimeoutQueue.cancel();
}
- onDisable();
+ onStopUpdates();
}
}
/**
- * Implemented by subclasses to do work during {@link #disable}.
+ * Implemented by subclasses to do work during {@link #stopUpdates}.
*/
- abstract void onDisable();
+ abstract void onStopUpdates();
- /** For subclasses to invoke when a {@link LocationTimeZoneEvent} has been received. */
- final void handleLocationTimeZoneEvent(
- @NonNull LocationTimeZoneEvent locationTimeZoneEvent) {
+ /** For subclasses to invoke when a {@link TimeZoneProviderEvent} has been received. */
+ final void handleTimeZoneProviderEvent(@NonNull TimeZoneProviderEvent timeZoneProviderEvent) {
mThreadingDomain.assertCurrentThread();
- Objects.requireNonNull(locationTimeZoneEvent);
+ Objects.requireNonNull(timeZoneProviderEvent);
synchronized (mSharedLock) {
- debugLog("handleLocationTimeZoneEvent: mProviderName=" + mProviderName
- + ", locationTimeZoneEvent=" + locationTimeZoneEvent);
+ debugLog("handleTimeZoneProviderEvent: mProviderName=" + mProviderName
+ + ", timeZoneProviderEvent=" + timeZoneProviderEvent);
ProviderState currentState = mCurrentState.get();
- int eventType = locationTimeZoneEvent.getEventType();
+ int eventType = timeZoneProviderEvent.getType();
switch (currentState.stateEnum) {
case PROVIDER_STATE_PERM_FAILED: {
// After entering perm failed, there is nothing to do. The remote peer is
// supposed to stop sending events after it has reported perm failure.
- logWarn("handleLocationTimeZoneEvent: Event=" + locationTimeZoneEvent
+ logWarn("handleTimeZoneProviderEvent: Event=" + timeZoneProviderEvent
+ " received for provider=" + this + " when in failed state");
return;
}
- case PROVIDER_STATE_DISABLED: {
+ case PROVIDER_STATE_STOPPED: {
switch (eventType) {
case EVENT_TYPE_PERMANENT_FAILURE: {
- String msg = "handleLocationTimeZoneEvent:"
- + " Failure event=" + locationTimeZoneEvent
- + " received for disabled provider=" + this
+ String msg = "handleTimeZoneProviderEvent:"
+ + " Failure event=" + timeZoneProviderEvent
+ + " received for stopped provider=" + this
+ ", entering permanently failed state";
logWarn(msg);
ProviderState newState = currentState.newState(
@@ -517,30 +518,30 @@
}
return;
}
- case EVENT_TYPE_SUCCESS:
+ case EVENT_TYPE_SUGGESTION:
case EVENT_TYPE_UNCERTAIN: {
- // Any geolocation-related events received for a disabled provider are
+ // Any geolocation-related events received for a stopped provider are
// ignored: they should not happen.
- logWarn("handleLocationTimeZoneEvent:"
- + " event=" + locationTimeZoneEvent
- + " received for disabled provider=" + this
+ logWarn("handleTimeZoneProviderEvent:"
+ + " event=" + timeZoneProviderEvent
+ + " received for stopped provider=" + this
+ ", ignoring");
return;
}
default: {
throw new IllegalStateException(
- "Unknown eventType=" + locationTimeZoneEvent);
+ "Unknown eventType=" + timeZoneProviderEvent);
}
}
}
- case PROVIDER_STATE_ENABLED_INITIALIZING:
- case PROVIDER_STATE_ENABLED_CERTAIN:
- case PROVIDER_STATE_ENABLED_UNCERTAIN: {
+ case PROVIDER_STATE_STARTED_INITIALIZING:
+ case PROVIDER_STATE_STARTED_CERTAIN:
+ case PROVIDER_STATE_STARTED_UNCERTAIN: {
switch (eventType) {
case EVENT_TYPE_PERMANENT_FAILURE: {
- String msg = "handleLocationTimeZoneEvent:"
- + " Failure event=" + locationTimeZoneEvent
+ String msg = "handleTimeZoneProviderEvent:"
+ + " Failure event=" + timeZoneProviderEvent
+ " received for provider=" + this
+ ", entering permanently failed state";
logWarn(msg);
@@ -554,16 +555,16 @@
return;
}
case EVENT_TYPE_UNCERTAIN:
- case EVENT_TYPE_SUCCESS: {
+ case EVENT_TYPE_SUGGESTION: {
@ProviderStateEnum int providerStateEnum;
if (eventType == EVENT_TYPE_UNCERTAIN) {
- providerStateEnum = PROVIDER_STATE_ENABLED_UNCERTAIN;
+ providerStateEnum = PROVIDER_STATE_STARTED_UNCERTAIN;
} else {
- providerStateEnum = PROVIDER_STATE_ENABLED_CERTAIN;
+ providerStateEnum = PROVIDER_STATE_STARTED_CERTAIN;
}
ProviderState newState = currentState.newState(providerStateEnum,
- locationTimeZoneEvent, currentState.currentUserConfiguration,
- "handleLocationTimeZoneEvent() when enabled");
+ timeZoneProviderEvent, currentState.currentUserConfiguration,
+ "handleTimeZoneProviderEvent() when started");
setCurrentState(newState, true);
if (mInitializationTimeoutQueue.hasQueued()) {
mInitializationTimeoutQueue.cancel();
@@ -572,7 +573,7 @@
}
default: {
throw new IllegalStateException(
- "Unknown eventType=" + locationTimeZoneEvent);
+ "Unknown eventType=" + timeZoneProviderEvent);
}
}
}
@@ -589,10 +590,10 @@
abstract void logWarn(String msg);
@GuardedBy("mSharedLock")
- private void assertIsEnabled() {
+ private void assertIsStarted() {
ProviderState currentState = mCurrentState.get();
- if (!currentState.isEnabled()) {
- throw new IllegalStateException("Required an enabled state, but was " + currentState);
+ if (!currentState.isStarted()) {
+ throw new IllegalStateException("Required a started state, but was " + currentState);
}
}
diff --git a/services/core/java/com/android/server/location/timezone/LocationTimeZoneProviderController.java b/services/core/java/com/android/server/location/timezone/LocationTimeZoneProviderController.java
index ace066e..45ec400 100644
--- a/services/core/java/com/android/server/location/timezone/LocationTimeZoneProviderController.java
+++ b/services/core/java/com/android/server/location/timezone/LocationTimeZoneProviderController.java
@@ -16,6 +16,7 @@
package com.android.server.location.timezone;
+import android.annotation.DurationMillisLong;
import android.annotation.NonNull;
import android.os.Handler;
@@ -59,7 +60,7 @@
* disputed areas and oceans. Distinguishing uncertainty allows the controller to try other
* providers (or give up), where as certainty means it should not.
*
- * <p>A provider can fail permanently. A permanent failure will disable the provider until next
+ * <p>A provider can fail permanently. A permanent failure will stop the provider until next
* boot.
*/
abstract class LocationTimeZoneProviderController implements Dumpable {
@@ -90,6 +91,7 @@
abstract boolean isUncertaintyTimeoutSet();
@VisibleForTesting
+ @DurationMillisLong
abstract long getUncertaintyTimeoutDelayMillis();
/**
diff --git a/services/core/java/com/android/server/location/timezone/LocationTimeZoneProviderProxy.java b/services/core/java/com/android/server/location/timezone/LocationTimeZoneProviderProxy.java
index 8a0259d..91b52f1 100644
--- a/services/core/java/com/android/server/location/timezone/LocationTimeZoneProviderProxy.java
+++ b/services/core/java/com/android/server/location/timezone/LocationTimeZoneProviderProxy.java
@@ -23,17 +23,15 @@
import android.util.IndentingPrintWriter;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.location.timezone.LocationTimeZoneEvent;
-import com.android.internal.location.timezone.LocationTimeZoneProviderRequest;
import com.android.server.timezonedetector.Dumpable;
import java.util.Objects;
/**
- * System server-side proxy for ILocationTimeZoneProvider implementations, i.e. this provides the
- * system server object used to communicate with a remote LocationTimeZoneProvider over Binder,
- * which could be running in a different process. As LocationTimeZoneProviders are bound / unbound
- * this proxy will rebind to the "best" available remote process.
+ * System server-side proxy for ITimeZoneProvider implementations, i.e. this provides the system
+ * server object used to communicate with a remote TimeZoneProvider over Binder, which could be
+ * running in a different process. As TimeZoneProviders are bound / unbound this proxy will rebind
+ * to the "best" available remote process.
*
* <p>Threading guarantees provided / required by this interface:
* <ul>
@@ -41,8 +39,8 @@
* from the {@link ThreadingDomain} passed to the constructor, excluding
* {@link #dump(IndentingPrintWriter, String[])}</li>
* <li>Non-static public methods that make binder calls to remote processes (e.g.
- * {@link #setRequest(LocationTimeZoneProviderRequest)}) are executed asynchronously and will
- * return immediately.</li>
+ * {@link #setRequest(TimeZoneProviderRequest)}) are executed asynchronously and will return
+ * immediately.</li>
* <li>Callbacks received via binder are delivered via {@link Listener} are delivered on the
* {@link Handler} thread from the {@link ThreadingDomain} passed to the constructor.
* </ul>
@@ -93,16 +91,15 @@
/**
* Sets a new request for the provider.
*/
- abstract void setRequest(@NonNull LocationTimeZoneProviderRequest request);
+ abstract void setRequest(@NonNull TimeZoneProviderRequest request);
/**
- * Handles a {@link LocationTimeZoneEvent} from a remote process.
+ * Handles a {@link TimeZoneProviderEvent} from a remote process.
*/
- final void handleLocationTimeZoneEvent(
- @NonNull LocationTimeZoneEvent locationTimeZoneEvent) {
+ final void handleTimeZoneProviderEvent(@NonNull TimeZoneProviderEvent timeZoneProviderEvent) {
// These calls are invoked on a binder thread. Move to the mThreadingDomain thread as
// required by the guarantees for this class.
- mThreadingDomain.post(() -> mListener.onReportLocationTimeZoneEvent(locationTimeZoneEvent));
+ mThreadingDomain.post(() -> mListener.onReportTimeZoneProviderEvent(timeZoneProviderEvent));
}
/**
@@ -112,9 +109,9 @@
interface Listener {
/**
- * Called when a provider receives a {@link LocationTimeZoneEvent}.
+ * Called when a provider receives a {@link TimeZoneProviderEvent}.
*/
- void onReportLocationTimeZoneEvent(@NonNull LocationTimeZoneEvent locationTimeZoneEvent);
+ void onReportTimeZoneProviderEvent(@NonNull TimeZoneProviderEvent timeZoneProviderEvent);
/**
* Called when a provider is (re)bound.
diff --git a/services/core/java/com/android/server/location/timezone/NullLocationTimeZoneProvider.java b/services/core/java/com/android/server/location/timezone/NullLocationTimeZoneProvider.java
index fbcc71f..e11a7ce 100644
--- a/services/core/java/com/android/server/location/timezone/NullLocationTimeZoneProvider.java
+++ b/services/core/java/com/android/server/location/timezone/NullLocationTimeZoneProvider.java
@@ -35,11 +35,11 @@
* and a secondary {@link LocationTimeZoneProvider}, but only a primary is configured, the secondary
* config will be left null and the {@link LocationTimeZoneProvider} implementation will be
* defaulted to a {@link NullLocationTimeZoneProvider}. The {@link NullLocationTimeZoneProvider}
- * enters a {@link ProviderState#PROVIDER_STATE_PERM_FAILED} state immediately after being enabled
+ * enters a {@link ProviderState#PROVIDER_STATE_PERM_FAILED} state immediately after being started
* for the first time and sends the appropriate event, which ensures the {@link
* LocationTimeZoneProviderController} won't expect any further {@link
- * com.android.internal.location.timezone.LocationTimeZoneEvent}s to come from it, and won't attempt
- * to use it again.
+ * TimeZoneProviderEvent}s to come from it, and won't attempt to use it
+ * again.
*/
class NullLocationTimeZoneProvider extends LocationTimeZoneProvider {
@@ -57,7 +57,7 @@
}
@Override
- void onEnable(@NonNull Duration initializationTimeout) {
+ void onStartUpdates(@NonNull Duration initializationTimeout) {
// Report a failure (asynchronously using the mThreadingDomain thread to avoid recursion).
mThreadingDomain.post(()-> {
// Enter the perm-failed state.
@@ -69,8 +69,8 @@
}
@Override
- void onDisable() {
- // Ignored - NullLocationTimeZoneProvider is always permanently failed.
+ void onStopUpdates() {
+ // Ignored - this implementation is always permanently failed.
}
@Override
diff --git a/services/core/java/com/android/server/location/timezone/RealLocationTimeZoneProviderProxy.java b/services/core/java/com/android/server/location/timezone/RealLocationTimeZoneProviderProxy.java
index 1a01288..1bb5cec 100644
--- a/services/core/java/com/android/server/location/timezone/RealLocationTimeZoneProviderProxy.java
+++ b/services/core/java/com/android/server/location/timezone/RealLocationTimeZoneProviderProxy.java
@@ -22,22 +22,22 @@
import android.content.Context;
import android.os.IBinder;
import android.os.RemoteException;
+import android.service.timezone.ITimeZoneProvider;
+import android.service.timezone.ITimeZoneProviderManager;
+import android.service.timezone.TimeZoneProviderSuggestion;
import android.util.IndentingPrintWriter;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.location.timezone.ILocationTimeZoneProvider;
-import com.android.internal.location.timezone.ILocationTimeZoneProviderManager;
-import com.android.internal.location.timezone.LocationTimeZoneEvent;
-import com.android.internal.location.timezone.LocationTimeZoneProviderRequest;
import com.android.server.ServiceWatcher;
import java.util.Objects;
/**
- * System server-side proxy for ILocationTimeZoneProvider implementations, i.e. this provides the
- * system server object used to communicate with a remote LocationTimeZoneProvider over Binder,
- * which could be running in a different process. As "remote" LocationTimeZoneProviders are bound /
- * unbound this proxy will rebind to the "best" available remote process.
+ * System server-side proxy for ITimeZoneProvider implementations, i.e. this provides the
+ * system server object used to communicate with a remote {@link
+ * android.service.timezone.TimeZoneProviderService} over Binder, which could be running in a
+ * different process. As "remote" providers are bound / unbound this proxy will rebind to the "best"
+ * available remote process.
*/
class RealLocationTimeZoneProviderProxy extends LocationTimeZoneProviderProxy {
@@ -47,7 +47,7 @@
@Nullable private ManagerProxy mManagerProxy;
@GuardedBy("mProxyLock")
- @NonNull private LocationTimeZoneProviderRequest mRequest;
+ @NonNull private TimeZoneProviderRequest mRequest;
RealLocationTimeZoneProviderProxy(
@NonNull Context context, @NonNull ThreadingDomain threadingDomain,
@@ -55,7 +55,7 @@
int nonOverlayPackageResId) {
super(context, threadingDomain);
mManagerProxy = null;
- mRequest = LocationTimeZoneProviderRequest.EMPTY_REQUEST;
+ mRequest = TimeZoneProviderRequest.createStopUpdatesRequest();
mServiceWatcher = new ServiceWatcher(context, action, this::onBind, this::onUnbind,
enableOverlayResId, nonOverlayPackageResId);
}
@@ -93,12 +93,12 @@
private void onBindOnHandlerThread(@NonNull IBinder binder) {
mThreadingDomain.assertCurrentThread();
- ILocationTimeZoneProvider provider = ILocationTimeZoneProvider.Stub.asInterface(binder);
+ ITimeZoneProvider provider = ITimeZoneProvider.Stub.asInterface(binder);
synchronized (mSharedLock) {
try {
mManagerProxy = new ManagerProxy();
- provider.setLocationTimeZoneProviderManager(mManagerProxy);
+ provider.setTimeZoneProviderManager(mManagerProxy);
trySendCurrentRequest();
mListener.onProviderBound();
} catch (RemoteException e) {
@@ -118,7 +118,7 @@
}
@Override
- final void setRequest(@NonNull LocationTimeZoneProviderRequest request) {
+ final void setRequest(@NonNull TimeZoneProviderRequest request) {
mThreadingDomain.assertCurrentThread();
Objects.requireNonNull(request);
@@ -131,11 +131,14 @@
@GuardedBy("mProxyLock")
private void trySendCurrentRequest() {
- LocationTimeZoneProviderRequest request = mRequest;
+ TimeZoneProviderRequest request = mRequest;
mServiceWatcher.runOnBinder(binder -> {
- ILocationTimeZoneProvider service =
- ILocationTimeZoneProvider.Stub.asInterface(binder);
- service.setRequest(request);
+ ITimeZoneProvider service = ITimeZoneProvider.Stub.asInterface(binder);
+ if (request.sendUpdates()) {
+ service.startUpdates(request.getInitializationTimeout().toMillis());
+ } else {
+ service.stopUpdates();
+ }
});
}
@@ -148,21 +151,39 @@
}
/**
- * A system Server-side proxy for the ILocationTimeZoneProviderManager, i.e. this is a local
- * binder stub. Each "remote" LocationTimeZoneProvider is passed a binder instance that it
- * then uses to communicate back with the system server, invoking the logic here.
+ * A system Server-side proxy for the ITimeZoneProviderManager, i.e. this is a local binder stub
+ * Each "remote" TimeZoneProvider is passed a binder instance that it then uses to communicate
+ * back with the system server, invoking the logic here.
*/
- private class ManagerProxy extends ILocationTimeZoneProviderManager.Stub {
+ private class ManagerProxy extends ITimeZoneProviderManager.Stub {
// executed on binder thread
@Override
- public void onLocationTimeZoneEvent(LocationTimeZoneEvent locationTimeZoneEvent) {
+ public void onTimeZoneProviderSuggestion(TimeZoneProviderSuggestion suggestion) {
+ onTimeZoneProviderEvent(TimeZoneProviderEvent.createSuggestionEvent(suggestion));
+ }
+
+ // executed on binder thread
+ @Override
+ public void onTimeZoneProviderUncertain() {
+ onTimeZoneProviderEvent(TimeZoneProviderEvent.createUncertainEvent());
+
+ }
+
+ // executed on binder thread
+ @Override
+ public void onTimeZoneProviderPermanentFailure(String failureReason) {
+ onTimeZoneProviderEvent(
+ TimeZoneProviderEvent.createPermanentFailureEvent(failureReason));
+ }
+
+ private void onTimeZoneProviderEvent(TimeZoneProviderEvent event) {
synchronized (mSharedLock) {
if (mManagerProxy != this) {
return;
}
}
- handleLocationTimeZoneEvent(locationTimeZoneEvent);
+ handleTimeZoneProviderEvent(event);
}
}
}
diff --git a/services/core/java/com/android/server/location/timezone/SimulatedBinderProviderEvent.java b/services/core/java/com/android/server/location/timezone/SimulatedBinderProviderEvent.java
index 7725309..0987ee5 100644
--- a/services/core/java/com/android/server/location/timezone/SimulatedBinderProviderEvent.java
+++ b/services/core/java/com/android/server/location/timezone/SimulatedBinderProviderEvent.java
@@ -16,9 +16,6 @@
package com.android.server.location.timezone;
-import static com.android.internal.location.timezone.LocationTimeZoneEvent.EVENT_TYPE_PERMANENT_FAILURE;
-import static com.android.internal.location.timezone.LocationTimeZoneEvent.EVENT_TYPE_SUCCESS;
-import static com.android.internal.location.timezone.LocationTimeZoneEvent.EVENT_TYPE_UNCERTAIN;
import static com.android.server.location.timezone.LocationTimeZoneManagerService.PRIMARY_PROVIDER_NAME;
import static com.android.server.location.timezone.LocationTimeZoneManagerService.SECONDARY_PROVIDER_NAME;
@@ -26,8 +23,7 @@
import android.annotation.Nullable;
import android.os.ShellCommand;
import android.os.SystemClock;
-
-import com.android.internal.location.timezone.LocationTimeZoneEvent;
+import android.service.timezone.TimeZoneProviderSuggestion;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -50,14 +46,14 @@
@NonNull private final String mProviderName;
- private final int mEventType;
- @Nullable private final LocationTimeZoneEvent mLocationTimeZoneEvent;
+ private final int mType;
+ @Nullable private final TimeZoneProviderEvent mTimeZoneProviderEvent;
private SimulatedBinderProviderEvent(@NonNull String providerName, int eventType,
- @Nullable LocationTimeZoneEvent locationTimeZoneEvent) {
+ @Nullable TimeZoneProviderEvent timeZoneProviderEvent) {
this.mProviderName = Objects.requireNonNull(providerName);
- this.mEventType = eventType;
- this.mLocationTimeZoneEvent = locationTimeZoneEvent;
+ this.mType = eventType;
+ this.mTimeZoneProviderEvent = timeZoneProviderEvent;
}
@NonNull
@@ -66,24 +62,24 @@
}
@Nullable
- LocationTimeZoneEvent getLocationTimeZoneEvent() {
- return mLocationTimeZoneEvent;
+ TimeZoneProviderEvent getTimeZoneProviderEvent() {
+ return mTimeZoneProviderEvent;
}
- int getEventType() {
- return mEventType;
+ int getType() {
+ return mType;
}
/** Prints the command line options that {@link #createFromArgs(ShellCommand)} understands. */
static void printCommandLineOpts(PrintWriter pw) {
pw.println("Simulated provider binder event:");
pw.println();
- pw.println("<provider name> [onBind|onUnbind|locationTimeZoneEvent"
+ pw.println("<provider name> [onBind|onUnbind|timeZoneProviderEvent"
+ " <location time zone event args>]");
pw.println();
pw.println("<provider name> = " + VALID_PROVIDER_NAMES);
- pw.println("<location time zone event args> ="
- + " [PERMANENT_FAILURE|UNCERTAIN|SUCCESS <time zone ids>*]");
+ pw.println("<time zone provider event args> ="
+ + " [PERMANENT_FAILURE|UNCERTAIN|SUGGESTION <time zone ids>*]");
}
/**
@@ -104,8 +100,8 @@
return new SimulatedBinderProviderEvent(
providerName, INJECTED_EVENT_TYPE_ON_UNBIND, null);
}
- case "locationTimeZoneEvent": {
- LocationTimeZoneEvent event = parseLocationTimeZoneEventArgs(shellCommand);
+ case "timeZoneProviderEvent": {
+ TimeZoneProviderEvent event = parseTimeZoneProviderEventArgs(shellCommand);
return new SimulatedBinderProviderEvent(providerName,
INJECTED_EVENT_TYPE_LOCATION_TIME_ZONE_EVENT, event);
}
@@ -115,30 +111,31 @@
}
}
- private static LocationTimeZoneEvent parseLocationTimeZoneEventArgs(ShellCommand shellCommand) {
- LocationTimeZoneEvent.Builder eventBuilder = new LocationTimeZoneEvent.Builder()
- .setElapsedRealtimeMillis(SystemClock.elapsedRealtime());
-
+ private static TimeZoneProviderEvent parseTimeZoneProviderEventArgs(ShellCommand shellCommand) {
+ TimeZoneProviderEvent event;
String eventTypeString = shellCommand.getNextArgRequired();
switch (eventTypeString.toUpperCase()) {
case "PERMANENT_FAILURE": {
- eventBuilder.setEventType(EVENT_TYPE_PERMANENT_FAILURE);
+ event = TimeZoneProviderEvent.createPermanentFailureEvent("Simulated");
break;
}
case "UNCERTAIN": {
- eventBuilder.setEventType(EVENT_TYPE_UNCERTAIN);
+ event = TimeZoneProviderEvent.createUncertainEvent();
break;
}
- case "SUCCESS": {
- eventBuilder.setEventType(EVENT_TYPE_SUCCESS)
- .setTimeZoneIds(parseTimeZoneArgs(shellCommand));
+ case "SUGGESTION": {
+ TimeZoneProviderSuggestion suggestion = new TimeZoneProviderSuggestion.Builder()
+ .setElapsedRealtimeMillis(SystemClock.elapsedRealtime())
+ .setTimeZoneIds(parseTimeZoneArgs(shellCommand))
+ .build();
+ event = TimeZoneProviderEvent.createSuggestionEvent(suggestion);
break;
}
default: {
throw new IllegalArgumentException("Error: Unknown eventType: " + eventTypeString);
}
}
- return eventBuilder.build();
+ return event;
}
private static List<String> parseTimeZoneArgs(ShellCommand shellCommand) {
@@ -154,8 +151,8 @@
public String toString() {
return "SimulatedBinderProviderEvent{"
+ "mProviderName=" + mProviderName
- + ", mEventType=" + mEventType
- + ", mLocationTimeZoneEvent=" + mLocationTimeZoneEvent
+ + ", mType=" + mType
+ + ", mTimeZoneProviderEvent=" + mTimeZoneProviderEvent
+ '}';
}
}
diff --git a/services/core/java/com/android/server/location/timezone/SimulatedLocationTimeZoneProviderProxy.java b/services/core/java/com/android/server/location/timezone/SimulatedLocationTimeZoneProviderProxy.java
index 5e66a99..cac5621 100644
--- a/services/core/java/com/android/server/location/timezone/SimulatedLocationTimeZoneProviderProxy.java
+++ b/services/core/java/com/android/server/location/timezone/SimulatedLocationTimeZoneProviderProxy.java
@@ -26,7 +26,6 @@
import android.util.IndentingPrintWriter;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.location.timezone.LocationTimeZoneProviderRequest;
import com.android.server.timezonedetector.ReferenceWithHistory;
import java.util.Objects;
@@ -38,7 +37,7 @@
class SimulatedLocationTimeZoneProviderProxy extends LocationTimeZoneProviderProxy {
@GuardedBy("mSharedLock")
- @NonNull private LocationTimeZoneProviderRequest mRequest;
+ @NonNull private TimeZoneProviderRequest mRequest;
@GuardedBy("mSharedLock")
@NonNull private final ReferenceWithHistory<String> mLastEvent = new ReferenceWithHistory<>(50);
@@ -46,7 +45,7 @@
SimulatedLocationTimeZoneProviderProxy(
@NonNull Context context, @NonNull ThreadingDomain threadingDomain) {
super(context, threadingDomain);
- mRequest = LocationTimeZoneProviderRequest.EMPTY_REQUEST;
+ mRequest = TimeZoneProviderRequest.createStopUpdatesRequest();
}
@Override
@@ -60,7 +59,7 @@
Objects.requireNonNull(event);
synchronized (mSharedLock) {
- switch (event.getEventType()) {
+ switch (event.getType()) {
case INJECTED_EVENT_TYPE_ON_BIND: {
mLastEvent.set("Simulating onProviderBound(), event=" + event);
mThreadingDomain.post(this::onBindOnHandlerThread);
@@ -72,12 +71,12 @@
break;
}
case INJECTED_EVENT_TYPE_LOCATION_TIME_ZONE_EVENT: {
- if (!mRequest.getReportLocationTimeZone()) {
+ if (!mRequest.sendUpdates()) {
mLastEvent.set("Test event=" + event + " is testing an invalid case:"
+ " reporting is off. mRequest=" + mRequest);
}
- mLastEvent.set("Simulating LocationTimeZoneEvent, event=" + event);
- handleLocationTimeZoneEvent(event.getLocationTimeZoneEvent());
+ mLastEvent.set("Simulating TimeZoneProviderResult, event=" + event);
+ handleTimeZoneProviderEvent(event.getTimeZoneProviderEvent());
break;
}
default: {
@@ -106,7 +105,7 @@
}
@Override
- final void setRequest(@NonNull LocationTimeZoneProviderRequest request) {
+ final void setRequest(@NonNull TimeZoneProviderRequest request) {
mThreadingDomain.assertCurrentThread();
Objects.requireNonNull(request);
diff --git a/services/core/java/com/android/server/location/timezone/ThreadingDomain.java b/services/core/java/com/android/server/location/timezone/ThreadingDomain.java
index d55d3ed..a50f8ad 100644
--- a/services/core/java/com/android/server/location/timezone/ThreadingDomain.java
+++ b/services/core/java/com/android/server/location/timezone/ThreadingDomain.java
@@ -16,6 +16,7 @@
package com.android.server.location.timezone;
+import android.annotation.DurationMillisLong;
import android.annotation.NonNull;
import com.android.internal.util.Preconditions;
@@ -68,9 +69,9 @@
/**
* Execute the supplied runnable on the threading domain's thread with a delay.
*/
- abstract void postDelayed(@NonNull Runnable runnable, long delayMillis);
+ abstract void postDelayed(@NonNull Runnable runnable, @DurationMillisLong long delayMillis);
- abstract void postDelayed(Runnable r, Object token, long delayMillis);
+ abstract void postDelayed(Runnable r, Object token, @DurationMillisLong long delayMillis);
abstract void removeQueuedRunnables(Object token);
@@ -90,6 +91,7 @@
final class SingleRunnableQueue {
private boolean mIsQueued;
+ @DurationMillisLong
private long mDelayMillis;
/**
@@ -97,7 +99,7 @@
* handler thread, cancelling any queued but not-yet-executed {@link Runnable} previously
* added by this. This method must be called from the threading domain's thread.
*/
- void runDelayed(Runnable r, long delayMillis) {
+ void runDelayed(Runnable r, @DurationMillisLong long delayMillis) {
cancel();
mIsQueued = true;
mDelayMillis = delayMillis;
@@ -122,6 +124,7 @@
* IllegalStateException} if nothing is currently queued, see {@link #hasQueued()}.
* This method must be called from the threading domain's thread.
*/
+ @DurationMillisLong
long getQueuedDelayMillis() {
assertCurrentThread();
if (!mIsQueued) {
diff --git a/services/core/java/com/android/server/location/timezone/TimeZoneProviderEvent.java b/services/core/java/com/android/server/location/timezone/TimeZoneProviderEvent.java
new file mode 100644
index 0000000..2d6f8ad
--- /dev/null
+++ b/services/core/java/com/android/server/location/timezone/TimeZoneProviderEvent.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.location.timezone;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.service.timezone.TimeZoneProviderService;
+import android.service.timezone.TimeZoneProviderSuggestion;
+
+import java.util.Objects;
+
+/**
+ * An event from a {@link TimeZoneProviderService}.
+ */
+final class TimeZoneProviderEvent {
+
+ @IntDef(prefix = "EVENT_TYPE_",
+ value = { EVENT_TYPE_PERMANENT_FAILURE, EVENT_TYPE_SUGGESTION, EVENT_TYPE_UNCERTAIN })
+ public @interface EventType {}
+
+ /**
+ * The provider failed permanently. See {@link
+ * TimeZoneProviderService#reportPermanentFailure(Throwable)}
+ */
+ public static final int EVENT_TYPE_PERMANENT_FAILURE = 1;
+
+ /**
+ * The provider made a suggestion. See {@link
+ * TimeZoneProviderService#reportSuggestion(TimeZoneProviderSuggestion)}
+ */
+ public static final int EVENT_TYPE_SUGGESTION = 2;
+
+ /**
+ * The provider was uncertain about the time zone. See {@link
+ * TimeZoneProviderService#reportUncertain()}
+ */
+ public static final int EVENT_TYPE_UNCERTAIN = 3;
+
+ private static final TimeZoneProviderEvent UNCERTAIN_EVENT =
+ new TimeZoneProviderEvent(EVENT_TYPE_UNCERTAIN, null, null);
+
+ @EventType
+ private final int mType;
+
+ @Nullable
+ private final TimeZoneProviderSuggestion mSuggestion;
+
+ @Nullable
+ private final String mFailureCause;
+
+ private TimeZoneProviderEvent(@EventType int type,
+ @Nullable TimeZoneProviderSuggestion suggestion,
+ @Nullable String failureCause) {
+ mType = type;
+ mSuggestion = suggestion;
+ mFailureCause = failureCause;
+ }
+
+ /** Returns a event of type {@link #EVENT_TYPE_SUGGESTION}. */
+ public static TimeZoneProviderEvent createSuggestionEvent(
+ @NonNull TimeZoneProviderSuggestion suggestion) {
+ return new TimeZoneProviderEvent(EVENT_TYPE_SUGGESTION,
+ Objects.requireNonNull(suggestion), null);
+ }
+
+ /** Returns a event of type {@link #EVENT_TYPE_UNCERTAIN}. */
+ public static TimeZoneProviderEvent createUncertainEvent() {
+ return UNCERTAIN_EVENT;
+ }
+
+ /** Returns a event of type {@link #EVENT_TYPE_PERMANENT_FAILURE}. */
+ public static TimeZoneProviderEvent createPermanentFailureEvent(@NonNull String cause) {
+ return new TimeZoneProviderEvent(EVENT_TYPE_PERMANENT_FAILURE, null,
+ Objects.requireNonNull(cause));
+ }
+
+ /**
+ * Returns the event type.
+ */
+ public @EventType int getType() {
+ return mType;
+ }
+
+ /**
+ * Returns the suggestion. Populated when {@link #getType()} is {@link #EVENT_TYPE_SUGGESTION}.
+ */
+ @Nullable
+ public TimeZoneProviderSuggestion getSuggestion() {
+ return mSuggestion;
+ }
+
+ /**
+ * Returns the failure cauese. Populated when {@link #getType()} is {@link
+ * #EVENT_TYPE_PERMANENT_FAILURE}.
+ */
+ @Nullable
+ public String getFailureCause() {
+ return mFailureCause;
+ }
+
+ @Override
+ public String toString() {
+ return "TimeZoneProviderEvent{"
+ + "mType=" + mType
+ + ", mSuggestion=" + mSuggestion
+ + ", mFailureCause=" + mFailureCause
+ + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ TimeZoneProviderEvent that = (TimeZoneProviderEvent) o;
+ return mType == that.mType
+ && Objects.equals(mSuggestion, that.mSuggestion)
+ && Objects.equals(mFailureCause, that.mFailureCause);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mType, mSuggestion, mFailureCause);
+ }
+}
diff --git a/services/core/java/com/android/server/location/timezone/TimeZoneProviderRequest.java b/services/core/java/com/android/server/location/timezone/TimeZoneProviderRequest.java
new file mode 100644
index 0000000..649a74b
--- /dev/null
+++ b/services/core/java/com/android/server/location/timezone/TimeZoneProviderRequest.java
@@ -0,0 +1,105 @@
+/*
+ * 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.location.timezone;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import java.time.Duration;
+import java.util.Objects;
+
+/**
+ * This class encapsulates a request to a provider.
+ */
+final class TimeZoneProviderRequest {
+
+ @NonNull
+ private static final TimeZoneProviderRequest STOP_UPDATES =
+ new TimeZoneProviderRequest(
+ false /* sendUpdates */,
+ null /* initializationTimeout */);
+
+ private final boolean mSendUpdates;
+
+ @Nullable
+ private final Duration mInitializationTimeout;
+
+ private TimeZoneProviderRequest(
+ boolean sendUpdates, @Nullable Duration initializationTimeout) {
+ mSendUpdates = sendUpdates;
+ mInitializationTimeout = initializationTimeout;
+ }
+
+ /** Creates a request to start updates with the specified timeout. */
+ public static TimeZoneProviderRequest createStartUpdatesRequest(
+ @NonNull Duration initializationTimeout) {
+ return new TimeZoneProviderRequest(true, Objects.requireNonNull(initializationTimeout));
+ }
+
+ /** Creates a request to stop updates. */
+ public static TimeZoneProviderRequest createStopUpdatesRequest() {
+ return STOP_UPDATES;
+ }
+
+ /**
+ * Returns {@code true} if the provider should send updates related to the device's current
+ * time zone, {@code false} otherwise.
+ */
+ public boolean sendUpdates() {
+ return mSendUpdates;
+ }
+
+ // TODO(b/152744911) - once there are a couple of implementations, decide whether this needs to
+ // be passed to the TimeZoneProviderService and remove if it is not useful.
+ /**
+ * Returns the maximum time that the provider is allowed to initialize before it is expected to
+ * send an event of any sort. Only valid when {@link #sendUpdates()} is {@code true}. Failure to
+ * send an event in this time (with some fuzz) may be interpreted as if the provider is
+ * uncertain of the time zone, and/or it could lead to the provider being stopped.
+ */
+ @Nullable
+ public Duration getInitializationTimeout() {
+ return mInitializationTimeout;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ TimeZoneProviderRequest
+ that = (TimeZoneProviderRequest) o;
+ return mSendUpdates == that.mSendUpdates
+ && mInitializationTimeout == that.mInitializationTimeout;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mSendUpdates, mInitializationTimeout);
+ }
+
+ @Override
+ public String toString() {
+ return "TimeZoneProviderRequest{"
+ + "mSendUpdates=" + mSendUpdates
+ + ", mInitializationTimeout=" + mInitializationTimeout
+ + "}";
+ }
+}
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 11dbef2..17ceb15 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -16,6 +16,7 @@
package com.android.server.media;
+import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.os.UserHandle.ALL;
import static android.os.UserHandle.CURRENT;
@@ -40,7 +41,6 @@
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
-import android.content.pm.UserInfo;
import android.media.AudioManager;
import android.media.AudioPlaybackConfiguration;
import android.media.IRemoteVolumeControllerCallback;
@@ -393,15 +393,17 @@
synchronized (mLock) {
UserManager manager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
mFullUserIds.clear();
- List<UserInfo> allUsers = manager.getUsers();
+ List<UserHandle> allUsers = manager.getUserHandles(/*excludeDying=*/false);
if (allUsers != null) {
- for (UserInfo userInfo : allUsers) {
- if (userInfo.isManagedProfile()) {
- mFullUserIds.put(userInfo.id, userInfo.profileGroupId);
+ for (UserHandle user : allUsers) {
+ UserHandle parent = manager.getProfileParent(user);
+ if (parent != null) {
+ mFullUserIds.put(user.getIdentifier(), parent.getIdentifier());
} else {
- mFullUserIds.put(userInfo.id, userInfo.id);
- if (mUserRecords.get(userInfo.id) == null) {
- mUserRecords.put(userInfo.id, new FullUserRecord(userInfo.id));
+ mFullUserIds.put(user.getIdentifier(), user.getIdentifier());
+ if (mUserRecords.get(user.getIdentifier()) == null) {
+ mUserRecords.put(user.getIdentifier(),
+ new FullUserRecord(user.getIdentifier()));
}
}
}
@@ -1114,8 +1116,7 @@
final long token = Binder.clearCallingIdentity();
try {
enforcePackageName(packageName, uid);
- int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
- false /* allowAll */, true /* requireFull */, "createSession", packageName);
+ int resolvedUserId = handleIncomingUser(pid, uid, userId, packageName);
if (cb == null) {
throw new IllegalArgumentException("Controller callback cannot be null");
}
@@ -1190,11 +1191,8 @@
final long token = Binder.clearCallingIdentity();
try {
- // Check that they can make calls on behalf of the user and
- // get the final user id
- int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
- true /* allowAll */, true /* requireFull */, "getSession2Tokens",
- null /* optional packageName */);
+ // Check that they can make calls on behalf of the user and get the final user id
+ int resolvedUserId = handleIncomingUser(pid, uid, userId, null);
List<Session2Token> result;
synchronized (mLock) {
FullUserRecord user = getFullUserRecordLocked(userId);
@@ -1261,9 +1259,7 @@
try {
// Check that they can make calls on behalf of the user and get the final user id.
- int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
- true /* allowAll */, true /* requireFull */, "addSession2TokensListener",
- null /* optional packageName */);
+ int resolvedUserId = handleIncomingUser(pid, uid, userId, null);
synchronized (mLock) {
int index = findIndexOfSession2TokensListenerLocked(listener);
if (index >= 0) {
@@ -1980,16 +1976,40 @@
packageName = componentName.getPackageName();
enforcePackageName(packageName, uid);
}
- // Check that they can make calls on behalf of the user and
- // get the final user id
- int resolvedUserId = ActivityManager.handleIncomingUser(pid, uid, userId,
- true /* allowAll */, true /* requireFull */, "getSessions", packageName);
- // Check if they have the permissions or their component is
- // enabled for the user they're calling from.
+ // Check that they can make calls on behalf of the user and get the final user id
+ int resolvedUserId = handleIncomingUser(pid, uid, userId, packageName);
+ // Check if they have the permissions or their component is enabled for the user
+ // they're calling from.
enforceMediaPermissions(componentName, pid, uid, resolvedUserId);
return resolvedUserId;
}
+ // Handles incoming user by checking whether the caller has permission to access the
+ // given user id's information or not. Permission is not necessary if the given user id is
+ // equal to the caller's user id, but if not, the caller needs to have the
+ // INTERACT_ACROSS_USERS_FULL permission. Otherwise, a security exception will be thrown.
+ // The return value will be the given user id, unless the given user id is
+ // UserHandle.CURRENT, which will return the ActivityManager.getCurrentUser() value instead.
+ private int handleIncomingUser(int pid, int uid, int userId, String packageName) {
+ int callingUserId = UserHandle.getUserHandleForUid(uid).getIdentifier();
+ if (userId == callingUserId) {
+ return userId;
+ }
+
+ boolean canInteractAcrossUsersFull = mContext.checkPermission(
+ INTERACT_ACROSS_USERS_FULL, pid, uid) == PackageManager.PERMISSION_GRANTED;
+ if (canInteractAcrossUsersFull) {
+ if (userId == CURRENT.getIdentifier()) {
+ return ActivityManager.getCurrentUser();
+ }
+ return userId;
+ }
+
+ throw new SecurityException("Permission denied while calling from " + packageName
+ + " with user id: " + userId + "; Need to run as either the calling user id ("
+ + callingUserId + "), or with " + INTERACT_ACROSS_USERS_FULL + " permission");
+ }
+
private boolean hasEnabledNotificationListener(int callingUserId,
String controllerPackageName, int controllerUid) {
int controllerUserId = UserHandle.getUserHandleForUid(controllerUid).getIdentifier();
diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java
index 342a11b..c4beddd4 100644
--- a/services/core/java/com/android/server/net/NetworkStatsCollection.java
+++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java
@@ -28,9 +28,9 @@
import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
import static android.net.TrafficStats.UID_REMOVED;
-import static android.net.NetworkUtils.multiplySafeByRational;
import static android.text.format.DateUtils.WEEK_IN_MILLIS;
+import static com.android.internal.net.NetworkUtilsInternal.multiplySafeByRational;
import static com.android.server.net.NetworkStatsService.TAG;
import android.net.NetworkIdentity;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index d3d998a..c9ed518 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -6363,6 +6363,7 @@
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,
@@ -6382,6 +6383,7 @@
this.mRank = rank;
this.mCount = count;
this.mListener = listener;
+ this.mWhen = System.currentTimeMillis();
}
@Override
@@ -6393,8 +6395,33 @@
}
synchronized (mNotificationLock) {
- // Look for the notification, searching both the posted and enqueued lists.
- NotificationRecord r = findNotificationLocked(mPkg, mTag, mId, mUserId);
+ // 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);
if (r != null) {
// The notification was found, check if it should be removed.
@@ -6417,6 +6444,10 @@
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 b131aff..094be06 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -55,6 +55,12 @@
import com.android.server.compat.CompatChange;
import com.android.server.om.OverlayReferenceMapper;
import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.utils.Snappable;
+import com.android.server.utils.Snapshots;
+import com.android.server.utils.Watchable;
+import com.android.server.utils.WatchableImpl;
+import com.android.server.utils.WatchedArrayMap;
+import com.android.server.utils.Watcher;
import java.io.PrintWriter;
import java.util.Arrays;
@@ -69,7 +75,7 @@
* manifests.
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
-public class AppsFilter {
+public class AppsFilter implements Watchable, Snappable {
private static final String TAG = "AppsFilter";
@@ -145,6 +151,55 @@
@GuardedBy("mCacheLock")
private volatile SparseArray<SparseBooleanArray> mShouldFilterCache;
+ /**
+ * A cached snapshot.
+ */
+ private volatile AppsFilter mSnapshot = null;
+
+ /**
+ * Watchable machinery
+ */
+ private final WatchableImpl mWatchable = new WatchableImpl();
+
+ /**
+ * Ensures an observer is in the list, exactly once. The observer cannot be null. The
+ * function quietly returns if the observer is already in the list.
+ *
+ * @param observer The {@link Watcher} to be notified when the {@link Watchable} changes.
+ */
+ public void registerObserver(@NonNull Watcher observer) {
+ mWatchable.registerObserver(observer);
+ }
+
+ /**
+ * Ensures an observer is not in the list. The observer must not be null. The function
+ * quietly returns if the objserver is not in the list.
+ *
+ * @param observer The {@link Watcher} that should not be in the notification list.
+ */
+ public void unregisterObserver(@NonNull Watcher observer) {
+ mWatchable.unregisterObserver(observer);
+ }
+
+ /**
+ * Invokes {@link Watcher#onChange} on each registered observer. The method can be called
+ * with the {@link Watchable} that generated the event. In a tree of {@link Watchable}s, this
+ * is generally the first (deepest) {@link Watchable} to detect a change.
+ *
+ * @param what The {@link Watchable} that generated the event.
+ */
+ public void dispatchChange(@Nullable Watchable what) {
+ mSnapshot = null;
+ mWatchable.dispatchChange(what);
+ }
+
+ /**
+ * Report a change to observers.
+ */
+ private void onChanged() {
+ dispatchChange(this);
+ }
+
@VisibleForTesting(visibility = PRIVATE)
AppsFilter(StateProvider stateProvider,
FeatureConfig featureConfig,
@@ -162,6 +217,44 @@
}
/**
+ * The copy constructor is used by PackageManagerService to construct a snapshot.
+ * Attributes are not deep-copied since these are supposed to be immutable.
+ * TODO: deep-copy the attributes, if necessary.
+ */
+ private AppsFilter(AppsFilter orig) {
+ Snapshots.copy(mImplicitlyQueryable, orig.mImplicitlyQueryable);
+ Snapshots.copy(mQueriesViaPackage, orig.mQueriesViaPackage);
+ Snapshots.copy(mQueriesViaComponent, orig.mQueriesViaComponent);
+ mQueriesViaComponentRequireRecompute = orig.mQueriesViaComponentRequireRecompute;
+ mForceQueryable.addAll(orig.mForceQueryable);
+ mForceQueryableByDevicePackageNames = orig.mForceQueryableByDevicePackageNames;
+ mSystemAppsQueryable = orig.mSystemAppsQueryable;
+ mFeatureConfig = orig.mFeatureConfig;
+ mOverlayReferenceMapper = orig.mOverlayReferenceMapper;
+ mStateProvider = orig.mStateProvider;
+ mSystemSigningDetails = orig.mSystemSigningDetails;
+ mProtectedBroadcasts = orig.mProtectedBroadcasts;
+ mShouldFilterCache = orig.mShouldFilterCache;
+
+ mBackgroundExecutor = null;
+ }
+
+ /**
+ * Return a snapshot. If the cached snapshot is null, build a new one. The logic in
+ * the function ensures that this function returns a valid snapshot even if a race
+ * condition causes the cached snapshot to be cleared asynchronously to this method.
+ */
+ public AppsFilter snapshot() {
+ AppsFilter s = mSnapshot;
+ if (s == null) {
+ s = new AppsFilter(this);
+ s.mWatchable.seal();
+ mSnapshot = s;
+ }
+ return s;
+ }
+
+ /**
* Provides system state to AppsFilter via {@link CurrentStateCallback} after properly guarding
* the data with the package lock.
*/
@@ -311,6 +404,9 @@
} else {
mDisabledPackages.add(pkg.getPackageName());
}
+ if (mAppsFilter != null) {
+ mAppsFilter.onChanged();
+ }
}
@Override
@@ -347,7 +443,7 @@
}
final StateProvider stateProvider = command -> {
synchronized (injector.getLock()) {
- command.currentState(injector.getSettings().getPackagesLocked(),
+ command.currentState(injector.getSettings().getPackagesLocked().untrackedMap(),
injector.getUserManagerInternal().getUserInfos());
}
};
@@ -482,7 +578,8 @@
*/
public void grantImplicitAccess(int recipientUid, int visibleUid) {
if (recipientUid != visibleUid) {
- if (mImplicitlyQueryable.add(recipientUid, visibleUid) && DEBUG_LOGGING) {
+ final boolean changed = mImplicitlyQueryable.add(recipientUid, visibleUid);
+ if (changed && DEBUG_LOGGING) {
Slog.i(TAG, "implicit access granted: " + recipientUid + " -> " + visibleUid);
}
synchronized (mCacheLock) {
@@ -497,6 +594,9 @@
visibleUids.put(visibleUid, false);
}
}
+ if (changed) {
+ onChanged();
+ }
}
}
@@ -505,6 +605,7 @@
mFeatureConfig.onSystemReady();
updateEntireShouldFilterCacheAsync();
+ onChanged();
}
/**
@@ -530,6 +631,7 @@
}
});
} finally {
+ onChanged();
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
@@ -712,6 +814,7 @@
synchronized (mCacheLock) {
if (mShouldFilterCache != null) {
updateEntireShouldFilterCache();
+ onChanged();
}
}
}
@@ -870,6 +973,16 @@
}
/**
+ * This api does type conversion on the <existingSettings> parameter.
+ */
+ @VisibleForTesting(visibility = PRIVATE)
+ @Nullable
+ SparseArray<int[]> getVisibilityAllowList(PackageSetting setting, int[] users,
+ WatchedArrayMap<String, PackageSetting> existingSettings) {
+ return getVisibilityAllowList(setting, users, existingSettings.untrackedMap());
+ }
+
+ /**
* Equivalent to calling {@link #addPackage(PackageSetting, boolean)} with {@code isReplace}
* equal to {@code false}.
* @see AppsFilter#addPackage(PackageSetting, boolean)
@@ -946,6 +1059,7 @@
siblingSetting, settings, users, settings.size());
}
}
+ onChanged();
}
});
}
diff --git a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
index a234f5a..1d73abc 100644
--- a/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
+++ b/services/core/java/com/android/server/pm/CrossProfileAppsServiceImpl.java
@@ -14,14 +14,17 @@
* limitations under the License.
*/
package com.android.server.pm;
-
+import static android.Manifest.permission.CONFIGURE_INTERACT_ACROSS_PROFILES;
+import static android.Manifest.permission.INTERACT_ACROSS_PROFILES;
+import static android.Manifest.permission.INTERACT_ACROSS_USERS;
+import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+import static android.Manifest.permission.MANAGE_APP_OPS_MODES;
import static android.app.AppOpsManager.OP_INTERACT_ACROSS_PROFILES;
import static android.content.Intent.FLAG_RECEIVER_REGISTERED_ONLY;
import static android.content.pm.CrossProfileApps.ACTION_CAN_INTERACT_ACROSS_PROFILES_CHANGED;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
-import android.Manifest;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
@@ -31,7 +34,6 @@
import android.app.AppOpsManager.Mode;
import android.app.IApplicationThread;
import android.app.admin.DevicePolicyEventLogger;
-import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyManagerInternal;
import android.content.ComponentName;
import android.content.Context;
@@ -154,15 +156,15 @@
if (callerUserId != userId) {
final int permissionFlag = PermissionChecker.checkPermissionForPreflight(
mContext,
- android.Manifest.permission.INTERACT_ACROSS_PROFILES,
+ INTERACT_ACROSS_PROFILES,
callingPid,
callingUid,
callingPackage);
if (permissionFlag != PermissionChecker.PERMISSION_GRANTED
|| !isSameProfileGroup(callerUserId, userId)) {
throw new SecurityException("Attempt to launch activity without required "
- + android.Manifest.permission.INTERACT_ACROSS_PROFILES + " permission"
- + " or target user is not in the same profile group.");
+ + INTERACT_ACROSS_PROFILES
+ + " permission or target user is not in the same profile group.");
}
}
launchIntent.setComponent(component);
@@ -217,8 +219,8 @@
if (callerUserId != userId) {
if (!hasCallerGotInteractAcrossProfilesPermission(callingPackage)) {
throw new SecurityException("Attempt to launch activity without required "
- + android.Manifest.permission.INTERACT_ACROSS_PROFILES + " permission"
- + " or target user is not in the same profile group.");
+ + INTERACT_ACROSS_PROFILES
+ + " permission or target user is not in the same profile group.");
}
}
@@ -294,13 +296,13 @@
callingPackage, mInjector.getCallingUid(), mInjector.getCallingPid());
}
- private boolean isCrossProfilePackageWhitelisted(String packageName) {
+ private boolean isCrossProfilePackageAllowlisted(String packageName) {
return mInjector.withCleanCallingIdentity(() ->
mInjector.getDevicePolicyManagerInternal()
.getAllCrossProfilePackages().contains(packageName));
}
- private boolean isCrossProfilePackageWhitelistedByDefault(String packageName) {
+ private boolean isCrossProfilePackageAllowlistedByDefault(String packageName) {
return mInjector.withCleanCallingIdentity(() ->
mInjector.getDevicePolicyManagerInternal()
.getDefaultCrossProfilePackages().contains(packageName));
@@ -388,32 +390,36 @@
/**
* See {@link android.content.pm.CrossProfileApps#setInteractAcrossProfilesAppOp(String, int)}.
*
- * <p>Logs metrics. Use {@link #setInteractAcrossProfilesAppOpUnchecked(String, int, boolean)}
- * to avoid permission checks or to specify not to log metrics.
+ * <p>Use {@link #setInteractAcrossProfilesAppOpUnchecked(String, int, int)} to avoid permission
+ * checks.
*/
@Override
public void setInteractAcrossProfilesAppOp(String packageName, @Mode int newMode) {
+ setInteractAcrossProfilesAppOp(packageName, newMode, mInjector.getCallingUserId());
+ }
+
+ private void setInteractAcrossProfilesAppOp(
+ String packageName, @Mode int newMode, @UserIdInt int userId) {
final int callingUid = mInjector.getCallingUid();
- if (!isPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS_FULL, callingUid)
- && !isPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS, callingUid)) {
+ if (!isPermissionGranted(INTERACT_ACROSS_USERS_FULL, callingUid)
+ && !isPermissionGranted(INTERACT_ACROSS_USERS, callingUid)) {
throw new SecurityException(
"INTERACT_ACROSS_USERS or INTERACT_ACROSS_USERS_FULL is required to set the"
+ " app-op for interacting across profiles.");
}
- if (!isPermissionGranted(Manifest.permission.MANAGE_APP_OPS_MODES, callingUid)
- && !isPermissionGranted(
- Manifest.permission.CONFIGURE_INTERACT_ACROSS_PROFILES, callingUid)) {
+ if (!isPermissionGranted(MANAGE_APP_OPS_MODES, callingUid)
+ && !isPermissionGranted(CONFIGURE_INTERACT_ACROSS_PROFILES, callingUid)) {
throw new SecurityException(
"MANAGE_APP_OPS_MODES or CONFIGURE_INTERACT_ACROSS_PROFILES is required to set"
+ " the app-op for interacting across profiles.");
}
- setInteractAcrossProfilesAppOpUnchecked(packageName, newMode, /* logMetrics= */ true);
+ setInteractAcrossProfilesAppOpUnchecked(packageName, newMode, userId);
}
private void setInteractAcrossProfilesAppOpUnchecked(
- String packageName, @Mode int newMode, boolean logMetrics) {
+ String packageName, @Mode int newMode, @UserIdInt int userId) {
if (newMode == AppOpsManager.MODE_ALLOWED
- && !canConfigureInteractAcrossProfiles(packageName)) {
+ && !canConfigureInteractAcrossProfiles(packageName, userId)) {
// The user should not be prompted for apps that cannot request to interact across
// profiles. However, we return early here if required to avoid race conditions.
Slog.e(TAG, "Tried to turn on the appop for interacting across profiles for invalid"
@@ -421,56 +427,57 @@
return;
}
final int[] profileIds =
- mInjector.getUserManager()
- .getProfileIds(mInjector.getCallingUserId(), /* enabledOnly= */ false);
+ mInjector.getUserManager().getProfileIds(userId, /* enabledOnly= */ false);
for (int profileId : profileIds) {
if (!isPackageInstalled(packageName, profileId)) {
continue;
}
- setInteractAcrossProfilesAppOpForUser(packageName, newMode, profileId, logMetrics);
+ // Only log once per profile group by checking against the user ID.
+ setInteractAcrossProfilesAppOpForProfile(
+ packageName, newMode, profileId, /* logMetrics= */ profileId == userId);
}
}
+ /**
+ * Returns whether the given package name is installed in the given user ID. The calling UID is
+ * used as the filter calling UID, as described at {@link PackageManagerInternal#getPackageInfo(
+ * String, int, int, int)}.
+ */
private boolean isPackageInstalled(String packageName, @UserIdInt int userId) {
- final int callingUid = mInjector.getCallingUid();
return mInjector.withCleanCallingIdentity(() -> {
+ final int flags = MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE;
final PackageInfo info =
mInjector.getPackageManagerInternal()
- .getPackageInfo(
- packageName,
- MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
- callingUid,
- userId);
+ .getPackageInfo(packageName, flags, mInjector.getCallingUid(), userId);
return info != null;
});
}
- private void setInteractAcrossProfilesAppOpForUser(
- String packageName, @Mode int newMode, @UserIdInt int userId, boolean logMetrics) {
+ private void setInteractAcrossProfilesAppOpForProfile(
+ String packageName, @Mode int newMode, @UserIdInt int profileId, boolean logMetrics) {
try {
- setInteractAcrossProfilesAppOpForUserOrThrow(packageName, newMode, userId, logMetrics);
+ setInteractAcrossProfilesAppOpForProfileOrThrow(
+ packageName, newMode, profileId, logMetrics);
} catch (PackageManager.NameNotFoundException e) {
- Slog.e(TAG, "Missing package " + packageName + " on user ID " + userId, e);
+ Slog.e(TAG, "Missing package " + packageName + " on profile user ID " + profileId, e);
}
}
- private void setInteractAcrossProfilesAppOpForUserOrThrow(
- String packageName, @Mode int newMode, @UserIdInt int userId, boolean logMetrics)
+ private void setInteractAcrossProfilesAppOpForProfileOrThrow(
+ String packageName, @Mode int newMode, @UserIdInt int profileId, boolean logMetrics)
throws PackageManager.NameNotFoundException {
final int uid = mInjector.getPackageManager()
- .getPackageUidAsUser(packageName, /* flags= */ 0, userId);
+ .getPackageUidAsUser(packageName, /* flags= */ 0, profileId);
if (currentModeEquals(newMode, packageName, uid)) {
Slog.i(TAG, "Attempt to set mode to existing value of " + newMode + " for "
- + packageName + " on user ID " + userId);
+ + packageName + " on profile user ID " + profileId);
return;
}
final boolean hadPermission = hasInteractAcrossProfilesPermission(
packageName, uid, PermissionChecker.PID_UNKNOWN);
- final int callingUid = mInjector.getCallingUid();
- if (isPermissionGranted(
- Manifest.permission.CONFIGURE_INTERACT_ACROSS_PROFILES, callingUid)) {
+ if (isPermissionGranted(CONFIGURE_INTERACT_ACROSS_PROFILES, mInjector.getCallingUid())) {
// Clear calling identity since the CONFIGURE_INTERACT_ACROSS_PROFILES permission allows
// this particular app-op to be modified without the broader app-op permissions.
mInjector.withCleanCallingIdentity(() ->
@@ -483,16 +490,15 @@
// Kill the UID before sending the broadcast to ensure that apps can be informed when
// their app-op has been revoked.
maybeKillUid(packageName, uid, hadPermission);
- sendCanInteractAcrossProfilesChangedBroadcast(packageName, uid, UserHandle.of(userId));
- maybeLogSetInteractAcrossProfilesAppOp(packageName, newMode, userId, logMetrics, uid);
+ sendCanInteractAcrossProfilesChangedBroadcast(packageName, uid, UserHandle.of(profileId));
+ maybeLogSetInteractAcrossProfilesAppOp(packageName, newMode, logMetrics, uid);
}
/**
* Kills the process represented by the given UID if it has lost the permission to
* interact across profiles.
*/
- private void maybeKillUid(
- String packageName, int uid, boolean hadPermission) {
+ private void maybeKillUid(String packageName, int uid, boolean hadPermission) {
if (!hadPermission) {
return;
}
@@ -503,18 +509,10 @@
}
private void maybeLogSetInteractAcrossProfilesAppOp(
- String packageName,
- @Mode int newMode,
- @UserIdInt int userId,
- boolean logMetrics,
- int uid) {
+ String packageName, @Mode int newMode, boolean logMetrics, int uid) {
if (!logMetrics) {
return;
}
- if (userId != mInjector.getCallingUserId()) {
- // Only log once per profile group by checking for the calling user ID.
- return;
- }
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_INTERACT_ACROSS_PROFILES_APP_OP)
.setStrings(packageName)
@@ -529,8 +527,7 @@
* any necessary permission checks.
*/
private boolean currentModeEquals(@Mode int otherMode, String packageName, int uid) {
- final String op =
- AppOpsManager.permissionToOp(Manifest.permission.INTERACT_ACROSS_PROFILES);
+ final String op = AppOpsManager.permissionToOp(INTERACT_ACROSS_PROFILES);
return mInjector.withCleanCallingIdentity(() -> otherMode
== mInjector.getAppOpsManager().unsafeCheckOpNoThrow(op, uid, packageName));
}
@@ -562,37 +559,49 @@
@Override
public boolean canConfigureInteractAcrossProfiles(String packageName) {
- if (!canUserAttemptToConfigureInteractAcrossProfiles(packageName)) {
+ return canConfigureInteractAcrossProfiles(packageName, mInjector.getCallingUserId());
+ }
+
+ private boolean canConfigureInteractAcrossProfiles(String packageName, @UserIdInt int userId) {
+ if (!canUserAttemptToConfigureInteractAcrossProfiles(packageName, userId)) {
return false;
}
- if (!hasOtherProfileWithPackageInstalled(packageName, mInjector.getCallingUserId())) {
+ if (!hasOtherProfileWithPackageInstalled(packageName, userId)) {
return false;
}
if (!hasRequestedAppOpPermission(
AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName)) {
return false;
}
- return isCrossProfilePackageWhitelisted(packageName);
+ return isCrossProfilePackageAllowlisted(packageName);
}
@Override
public boolean canUserAttemptToConfigureInteractAcrossProfiles(String packageName) {
- final int[] profileIds = mInjector.getUserManager().getProfileIds(
- mInjector.getCallingUserId(), /* enabledOnly= */ false);
+ return canUserAttemptToConfigureInteractAcrossProfiles(
+ packageName, mInjector.getCallingUserId());
+ }
+
+ private boolean canUserAttemptToConfigureInteractAcrossProfiles(
+ String packageName, @UserIdInt int userId) {
+ final int[] profileIds =
+ mInjector.getUserManager().getProfileIds(userId, /* enabledOnly= */ false);
if (profileIds.length < 2) {
return false;
}
if (isProfileOwner(packageName, profileIds)) {
return false;
}
- return hasRequestedAppOpPermission(
- AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName)
- && !isPlatformSignedAppWithNonUserConfigurablePermission(packageName, profileIds);
+ if (!hasRequestedAppOpPermission(
+ AppOpsManager.opToPermission(OP_INTERACT_ACROSS_PROFILES), packageName)) {
+ return false;
+ }
+ return !isPlatformSignedAppWithNonUserConfigurablePermission(packageName, profileIds);
}
private boolean isPlatformSignedAppWithNonUserConfigurablePermission(
String packageName, int[] profileIds) {
- return !isCrossProfilePackageWhitelistedByDefault(packageName)
+ return !isCrossProfilePackageAllowlistedByDefault(packageName)
&& isPlatformSignedAppWithAutomaticProfilesPermission(packageName, profileIds);
}
@@ -610,7 +619,7 @@
if (uid == -1) {
continue;
}
- if (isPermissionGranted(Manifest.permission.INTERACT_ACROSS_PROFILES, uid)) {
+ if (isPermissionGranted(INTERACT_ACROSS_PROFILES, uid)) {
return true;
}
}
@@ -642,7 +651,7 @@
return;
}
final String op =
- AppOpsManager.permissionToOp(Manifest.permission.INTERACT_ACROSS_PROFILES);
+ AppOpsManager.permissionToOp(INTERACT_ACROSS_PROFILES);
setInteractAcrossProfilesAppOp(packageName, AppOpsManager.opToDefaultMode(op));
}
@@ -650,7 +659,7 @@
public void clearInteractAcrossProfilesAppOps() {
final int defaultMode =
AppOpsManager.opToDefaultMode(
- AppOpsManager.permissionToOp(Manifest.permission.INTERACT_ACROSS_PROFILES));
+ AppOpsManager.permissionToOp(INTERACT_ACROSS_PROFILES));
findAllPackageNames()
.forEach(packageName -> setInteractAcrossProfilesAppOp(packageName, defaultMode));
}
@@ -695,17 +704,13 @@
}
private boolean hasInteractAcrossProfilesPermission(String packageName, int uid, int pid) {
- if (isPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS_FULL, uid)
- || isPermissionGranted(Manifest.permission.INTERACT_ACROSS_USERS, uid)) {
+ if (isPermissionGranted(INTERACT_ACROSS_USERS_FULL, uid)
+ || isPermissionGranted(INTERACT_ACROSS_USERS, uid)) {
return true;
}
return PermissionChecker.PERMISSION_GRANTED
== PermissionChecker.checkPermissionForPreflight(
- mContext,
- Manifest.permission.INTERACT_ACROSS_PROFILES,
- pid,
- uid,
- packageName);
+ mContext, INTERACT_ACROSS_PROFILES, pid, uid, packageName);
}
private boolean isProfileOwner(String packageName, int[] userIds) {
@@ -898,5 +903,12 @@
public List<UserHandle> getTargetUserProfiles(String packageName, int userId) {
return getTargetUserProfilesUnchecked(packageName, userId);
}
+
+ @Override
+ public void setInteractAcrossProfilesAppOp(
+ String packageName, int newMode, @UserIdInt int userId) {
+ CrossProfileAppsServiceImpl.this.setInteractAcrossProfilesAppOpUnchecked(
+ packageName, newMode, userId);
+ }
}
}
diff --git a/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java b/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java
index 8e6b89a..bf7f466 100644
--- a/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java
+++ b/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java
@@ -14,21 +14,22 @@
* limitations under the License.
*/
-
package com.android.server.pm;
-
import android.annotation.NonNull;
import android.content.IntentFilter;
-import com.android.server.IntentResolver;
+import com.android.server.utils.Snappable;
+import com.android.server.utils.WatchableIntentResolver;
+
import java.util.List;
/**
* Used to find a list of {@link CrossProfileIntentFilter}s that match an intent.
*/
class CrossProfileIntentResolver
- extends IntentResolver<CrossProfileIntentFilter, CrossProfileIntentFilter> {
+ extends WatchableIntentResolver<CrossProfileIntentFilter, CrossProfileIntentFilter>
+ implements Snappable {
@Override
protected CrossProfileIntentFilter[] newArray(int size) {
return new CrossProfileIntentFilter[size];
@@ -48,4 +49,15 @@
protected IntentFilter getIntentFilter(@NonNull CrossProfileIntentFilter input) {
return input;
}
+
+ /**
+ * Return a snapshot of the current object. The snapshot is a read-only copy suitable
+ * for read-only methods.
+ * @return A snapshot of the current object.
+ */
+ public CrossProfileIntentResolver snapshot() {
+ CrossProfileIntentResolver result = new CrossProfileIntentResolver();
+ result.doCopy(this);
+ return result;
+ }
}
diff --git a/services/core/java/com/android/server/pm/InstantAppRegistry.java b/services/core/java/com/android/server/pm/InstantAppRegistry.java
index a09640d..69d3e5c 100644
--- a/services/core/java/com/android/server/pm/InstantAppRegistry.java
+++ b/services/core/java/com/android/server/pm/InstantAppRegistry.java
@@ -24,6 +24,7 @@
import android.content.pm.InstantAppInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
+import android.content.pm.PermissionInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
@@ -36,13 +37,13 @@
import android.os.Message;
import android.os.UserHandle;
import android.os.storage.StorageManager;
+import android.permission.PermissionManager;
import android.provider.Settings;
import android.util.ArrayMap;
import android.util.AtomicFile;
import android.util.PackageUtils;
import android.util.Slog;
import android.util.SparseArray;
-import android.util.SparseBooleanArray;
import android.util.TypedXmlPullParser;
import android.util.TypedXmlSerializer;
import android.util.Xml;
@@ -55,20 +56,23 @@
import com.android.server.pm.parsing.PackageInfoUtils;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
+import com.android.server.utils.Snappable;
+import com.android.server.utils.Watchable;
+import com.android.server.utils.WatchableImpl;
+import com.android.server.utils.WatchedSparseArray;
+import com.android.server.utils.WatchedSparseBooleanArray;
+import com.android.server.utils.Watcher;
import libcore.io.IoUtils;
import libcore.util.HexEncoding;
-import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
@@ -82,7 +86,7 @@
* pruning installed instant apps and meta-data for uninstalled instant apps
* when free space is needed.
*/
-class InstantAppRegistry {
+class InstantAppRegistry implements Watchable, Snappable {
private static final boolean DEBUG = false;
private static final String LOG_TAG = "InstantAppRegistry";
@@ -120,7 +124,7 @@
/** State for uninstalled instant apps */
@GuardedBy("mService.mLock")
- private SparseArray<List<UninstalledInstantAppState>> mUninstalledInstantApps;
+ private final WatchedSparseArray<List<UninstalledInstantAppState>> mUninstalledInstantApps;
/**
* Automatic grants for access to instant app metadata.
@@ -129,17 +133,90 @@
* UserID -> TargetAppId -> InstantAppId
*/
@GuardedBy("mService.mLock")
- private SparseArray<SparseArray<SparseBooleanArray>> mInstantGrants;
+ private final WatchedSparseArray<WatchedSparseArray<WatchedSparseBooleanArray>> mInstantGrants;
/** The set of all installed instant apps. UserID -> AppID */
@GuardedBy("mService.mLock")
- private SparseArray<SparseBooleanArray> mInstalledInstantAppUids;
+ private final WatchedSparseArray<WatchedSparseBooleanArray> mInstalledInstantAppUids;
+
+ /**
+ * The cached snapshot
+ */
+ private volatile InstantAppRegistry mSnapshot = null;
+
+ /**
+ * Watchable machinery
+ */
+ private final WatchableImpl mWatchable = new WatchableImpl();
+ public void registerObserver(@NonNull Watcher observer) {
+ mWatchable.registerObserver(observer);
+ }
+ public void unregisterObserver(@NonNull Watcher observer) {
+ mWatchable.unregisterObserver(observer);
+ }
+ public void dispatchChange(@Nullable Watchable what) {
+ mSnapshot = null;
+ mWatchable.dispatchChange(what);
+ }
+ /**
+ * Notify listeners that this object has changed.
+ */
+ private void onChanged() {
+ dispatchChange(this);
+ }
+
+ /** The list of observers */
+ private final Watcher mObserver = new Watcher() {
+ @Override
+ public void onChange(@Nullable Watchable what) {
+ InstantAppRegistry.this.onChanged();
+ }
+ };
public InstantAppRegistry(PackageManagerService service,
PermissionManagerServiceInternal permissionManager) {
mService = service;
mPermissionManager = permissionManager;
mCookiePersistence = new CookiePersistence(BackgroundThread.getHandler().getLooper());
+
+ mUninstalledInstantApps = new WatchedSparseArray<List<UninstalledInstantAppState>>();
+ mInstantGrants = new WatchedSparseArray<WatchedSparseArray<WatchedSparseBooleanArray>>();
+ mInstalledInstantAppUids = new WatchedSparseArray<WatchedSparseBooleanArray>();
+
+ mUninstalledInstantApps.registerObserver(mObserver);
+ mInstantGrants.registerObserver(mObserver);
+ mInstalledInstantAppUids.registerObserver(mObserver);
+ }
+
+ /**
+ * The copy constructor is used by PackageManagerService to construct a snapshot.
+ */
+ private InstantAppRegistry(InstantAppRegistry r) {
+ mService = r.mService;
+ mPermissionManager = r.mPermissionManager;
+ mCookiePersistence = null;
+
+ mUninstalledInstantApps = new WatchedSparseArray<List<UninstalledInstantAppState>>(
+ r.mUninstalledInstantApps);
+ mInstantGrants = new WatchedSparseArray<WatchedSparseArray<WatchedSparseBooleanArray>>(
+ r.mInstantGrants);
+ mInstalledInstantAppUids = new WatchedSparseArray<WatchedSparseBooleanArray>(
+ r.mInstalledInstantAppUids);
+
+ // Do not register any observers. This is a clone
+ }
+
+ /**
+ * Return a snapshot: the value is the cached snapshot if available.
+ */
+ public InstantAppRegistry snapshot() {
+ InstantAppRegistry s = mSnapshot;
+ if (s == null) {
+ s = new InstantAppRegistry(this);
+ s.mWatchable.seal();
+ mSnapshot = s;
+ }
+ return s;
}
@GuardedBy("mService.mLock")
@@ -370,37 +447,20 @@
@GuardedBy("mService.mLock")
public void onUserRemovedLPw(int userId) {
- if (mUninstalledInstantApps != null) {
- mUninstalledInstantApps.remove(userId);
- if (mUninstalledInstantApps.size() <= 0) {
- mUninstalledInstantApps = null;
- }
- }
- if (mInstalledInstantAppUids != null) {
- mInstalledInstantAppUids.remove(userId);
- if (mInstalledInstantAppUids.size() <= 0) {
- mInstalledInstantAppUids = null;
- }
- }
- if (mInstantGrants != null) {
- mInstantGrants.remove(userId);
- if (mInstantGrants.size() <= 0) {
- mInstantGrants = null;
- }
- }
+ mUninstalledInstantApps.remove(userId);
+ mInstalledInstantAppUids.remove(userId);
+ mInstantGrants.remove(userId);
deleteDir(getInstantApplicationsDir(userId));
}
public boolean isInstantAccessGranted(@UserIdInt int userId, int targetAppId,
int instantAppId) {
- if (mInstantGrants == null) {
- return false;
- }
- final SparseArray<SparseBooleanArray> targetAppList = mInstantGrants.get(userId);
+ final WatchedSparseArray<WatchedSparseBooleanArray> targetAppList =
+ mInstantGrants.get(userId);
if (targetAppList == null) {
return false;
}
- final SparseBooleanArray instantGrantList = targetAppList.get(targetAppId);
+ final WatchedSparseBooleanArray instantGrantList = targetAppList.get(targetAppId);
if (instantGrantList == null) {
return false;
}
@@ -413,7 +473,7 @@
if (mInstalledInstantAppUids == null) {
return; // no instant apps installed; no need to grant
}
- SparseBooleanArray instantAppList = mInstalledInstantAppUids.get(userId);
+ WatchedSparseBooleanArray instantAppList = mInstalledInstantAppUids.get(userId);
if (instantAppList == null || !instantAppList.get(instantAppId)) {
return; // instant app id isn't installed; no need to grant
}
@@ -426,17 +486,14 @@
return; // launched via VIEW/BROWSABLE intent; no need to grant
}
}
- if (mInstantGrants == null) {
- mInstantGrants = new SparseArray<>();
- }
- SparseArray<SparseBooleanArray> targetAppList = mInstantGrants.get(userId);
+ WatchedSparseArray<WatchedSparseBooleanArray> targetAppList = mInstantGrants.get(userId);
if (targetAppList == null) {
- targetAppList = new SparseArray<>();
+ targetAppList = new WatchedSparseArray<>();
mInstantGrants.put(userId, targetAppList);
}
- SparseBooleanArray instantGrantList = targetAppList.get(recipientUid);
+ WatchedSparseBooleanArray instantGrantList = targetAppList.get(recipientUid);
if (instantGrantList == null) {
- instantGrantList = new SparseBooleanArray();
+ instantGrantList = new WatchedSparseBooleanArray();
targetAppList.put(recipientUid, instantGrantList);
}
instantGrantList.put(instantAppId, true /*granted*/);
@@ -444,15 +501,13 @@
@GuardedBy("mService.mLock")
public void addInstantAppLPw(@UserIdInt int userId, int instantAppId) {
- if (mInstalledInstantAppUids == null) {
- mInstalledInstantAppUids = new SparseArray<>();
- }
- SparseBooleanArray instantAppList = mInstalledInstantAppUids.get(userId);
+ WatchedSparseBooleanArray instantAppList = mInstalledInstantAppUids.get(userId);
if (instantAppList == null) {
- instantAppList = new SparseBooleanArray();
+ instantAppList = new WatchedSparseBooleanArray();
mInstalledInstantAppUids.put(userId, instantAppList);
}
instantAppList.put(instantAppId, true /*installed*/);
+ onChanged();
}
@GuardedBy("mService.mLock")
@@ -461,23 +516,28 @@
if (mInstalledInstantAppUids == null) {
return; // no instant apps on the system
}
- final SparseBooleanArray instantAppList = mInstalledInstantAppUids.get(userId);
+ final WatchedSparseBooleanArray instantAppList = mInstalledInstantAppUids.get(userId);
if (instantAppList == null) {
return;
}
- instantAppList.delete(instantAppId);
+ try {
+ instantAppList.delete(instantAppId);
- // remove any grants
- if (mInstantGrants == null) {
- return; // no grants on the system
- }
- final SparseArray<SparseBooleanArray> targetAppList = mInstantGrants.get(userId);
- if (targetAppList == null) {
- return; // no grants for this user
- }
- for (int i = targetAppList.size() - 1; i >= 0; --i) {
- targetAppList.valueAt(i).delete(instantAppId);
+ // remove any grants
+ if (mInstantGrants == null) {
+ return; // no grants on the system
+ }
+ final WatchedSparseArray<WatchedSparseBooleanArray> targetAppList =
+ mInstantGrants.get(userId);
+ if (targetAppList == null) {
+ return; // no grants for this user
+ }
+ for (int i = targetAppList.size() - 1; i >= 0; --i) {
+ targetAppList.valueAt(i).delete(instantAppId);
+ }
+ } finally {
+ onChanged();
}
}
@@ -487,11 +547,13 @@
if (mInstantGrants == null) {
return; // no grants on the system
}
- final SparseArray<SparseBooleanArray> targetAppList = mInstantGrants.get(userId);
+ final WatchedSparseArray<WatchedSparseBooleanArray> targetAppList =
+ mInstantGrants.get(userId);
if (targetAppList == null) {
return; // no grants for this user
}
targetAppList.delete(targetAppId);
+ onChanged();
}
@GuardedBy("mService.mLock")
@@ -502,9 +564,6 @@
if (uninstalledApp == null) {
return;
}
- if (mUninstalledInstantApps == null) {
- mUninstalledInstantApps = new SparseArray<>();
- }
List<UninstalledInstantAppState> uninstalledAppStates =
mUninstalledInstantApps.get(userId);
if (uninstalledAppStates == null) {
@@ -593,9 +652,7 @@
uninstalledAppStates.remove(i);
if (uninstalledAppStates.isEmpty()) {
mUninstalledInstantApps.remove(userId);
- if (mUninstalledInstantApps.size() <= 0) {
- mUninstalledInstantApps = null;
- }
+ onChanged();
return;
}
}
@@ -919,8 +976,7 @@
final long identity = Binder.clearCallingIdentity();
try {
for (String grantedPermission : appInfo.getGrantedPermissions()) {
- final boolean propagatePermission =
- mPermissionManager.canPropagatePermissionToInstantApp(grantedPermission);
+ final boolean propagatePermission = canPropagatePermission(grantedPermission);
if (propagatePermission && pkg.getRequestedPermissions().contains(
grantedPermission)) {
mService.grantRuntimePermission(pkg.getPackageName(), grantedPermission,
@@ -932,6 +988,19 @@
}
}
+ private boolean canPropagatePermission(@NonNull String permissionName) {
+ final PermissionManager permissionManager = mService.mContext.getSystemService(
+ PermissionManager.class);
+ final PermissionInfo permissionInfo = permissionManager.getPermissionInfo(permissionName,
+ 0);
+ return permissionInfo != null
+ && (permissionInfo.getProtection() == PermissionInfo.PROTECTION_DANGEROUS
+ || (permissionInfo.getProtectionFlags()
+ & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0)
+ && (permissionInfo.getProtectionFlags() & PermissionInfo.PROTECTION_FLAG_INSTANT)
+ != 0;
+ }
+
private @NonNull
InstantAppInfo peekOrParseUninstalledInstantAppInfo(
@NonNull String packageName, @UserIdInt int userId) {
@@ -994,12 +1063,7 @@
}
}
- if (uninstalledAppStates != null) {
- if (mUninstalledInstantApps == null) {
- mUninstalledInstantApps = new SparseArray<>();
- }
- mUninstalledInstantApps.put(userId, uninstalledAppStates);
- }
+ mUninstalledInstantApps.put(userId, uninstalledAppStates);
return uninstalledAppStates;
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 9e48ddd..2d393c0 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -291,23 +291,23 @@
}
void restoreAndApplyStagedSessionIfNeeded() {
- List<PackageInstallerSession> stagedSessionsToRestore = new ArrayList<>();
+ List<StagingManager.StagedSession> stagedSessionsToRestore = new ArrayList<>();
synchronized (mSessions) {
for (int i = 0; i < mSessions.size(); i++) {
final PackageInstallerSession session = mSessions.valueAt(i);
if (session.isStaged()) {
- stagedSessionsToRestore.add(session);
+ stagedSessionsToRestore.add(session.mStagedSession);
}
}
}
// Don't hold mSessions lock when calling restoreSession, since it might trigger an APK
// atomic install which needs to query sessions, which requires lock on mSessions.
boolean isDeviceUpgrading = mPm.isDeviceUpgrading();
- for (PackageInstallerSession session : stagedSessionsToRestore) {
- if (!session.isStagedAndInTerminalState() && session.hasParentSessionId()
+ for (StagingManager.StagedSession session : stagedSessionsToRestore) {
+ if (!session.isInTerminalState() && session.hasParentSessionId()
&& getSession(session.getParentSessionId()) == null) {
- session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
- "An orphan staged session " + session.sessionId + " is found, "
+ session.setSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
+ "An orphan staged session " + session.sessionId() + " is found, "
+ "parent " + session.getParentSessionId() + " is missing");
}
mStagingManager.restoreSession(session, isDeviceUpgrading);
@@ -1399,7 +1399,7 @@
@Override
public void run() {
if (session.isStaged() && !success) {
- mStagingManager.abortSession(session);
+ mStagingManager.abortSession(session.mStagedSession);
}
synchronized (mSessions) {
if (!session.isStaged() || !success) {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 2537e1b..f97a5ee 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -429,30 +429,341 @@
@GuardedBy("mLock")
private ArrayMap<String, List<CertifiedChecksum>> mChecksums = new ArrayMap<>();
- @GuardedBy("mLock")
- private boolean mStagedSessionApplied;
- @GuardedBy("mLock")
- private boolean mStagedSessionReady;
- @GuardedBy("mLock")
- private boolean mStagedSessionFailed;
- @GuardedBy("mLock")
- private int mStagedSessionErrorCode = SessionInfo.STAGED_SESSION_NO_ERROR;
- @GuardedBy("mLock")
- private String mStagedSessionErrorMessage;
-
- /**
- * The callback to run when pre-reboot verification has ended. Used by {@link #abandonStaged()}
- * to delay session clean-up until it is safe to do so.
- */
- @GuardedBy("mLock")
@Nullable
- private Runnable mPendingAbandonCallback;
- /**
- * {@code true} if pre-reboot verification is ongoing which means it is not safe for
- * {@link #abandon()} to clean up staging directories.
- */
- @GuardedBy("mLock")
- private boolean mInPreRebootVerification;
+ final StagedSession mStagedSession;
+
+ @VisibleForTesting
+ public class StagedSession implements StagingManager.StagedSession {
+ @GuardedBy("mLock")
+ private boolean mSessionApplied;
+ @GuardedBy("mLock")
+ private boolean mSessionReady;
+ @GuardedBy("mLock")
+ private boolean mSessionFailed;
+ @GuardedBy("mLock")
+ private int mSessionErrorCode = SessionInfo.STAGED_SESSION_NO_ERROR;
+ @GuardedBy("mLock")
+ private String mSessionErrorMessage;
+
+ /**
+ * The callback to run when pre-reboot verification has ended. Used by {@link #abandon()}
+ * to delay session clean-up until it is safe to do so.
+ */
+ @GuardedBy("mLock")
+ @Nullable
+ private Runnable mPendingAbandonCallback;
+ /**
+ * {@code true} if pre-reboot verification is ongoing which means it is not safe for
+ * {@link #abandon()} to clean up staging directories.
+ */
+ @GuardedBy("mLock")
+ private boolean mInPreRebootVerification;
+
+ StagedSession(boolean isReady, boolean isApplied, boolean isFailed, int errorCode,
+ String errorMessage) {
+ mSessionReady = isReady;
+ mSessionApplied = isApplied;
+ mSessionFailed = isFailed;
+ mSessionErrorCode = errorCode;
+ mSessionErrorMessage = errorMessage != null ? errorMessage : "";
+ }
+
+ @Override
+ public List<StagingManager.StagedSession> getChildSessions() {
+ if (!params.isMultiPackage) {
+ return Collections.EMPTY_LIST;
+ }
+ synchronized (mLock) {
+ int size = mChildSessions.size();
+ List<StagingManager.StagedSession> childSessions = new ArrayList<>(size);
+ for (int i = 0; i < size; ++i) {
+ childSessions.add(mChildSessions.valueAt(i).mStagedSession);
+ }
+ return childSessions;
+ }
+ }
+
+ @Override
+ public SessionParams sessionParams() {
+ return params;
+ }
+
+ @Override
+ public boolean isMultiPackage() {
+ return params.isMultiPackage;
+ }
+
+ @Override
+ public boolean isApexSession() {
+ return (params.installFlags & PackageManager.INSTALL_APEX) != 0;
+ }
+
+ @Override
+ public int sessionId() {
+ return sessionId;
+ }
+
+ @Override
+ public boolean containsApexSession() {
+ return sessionContains((s) -> s.isApexSession());
+ }
+
+ @Override
+ public String getPackageName() {
+ return PackageInstallerSession.this.getPackageName();
+ }
+
+ @Override
+ public void setSessionReady() {
+ synchronized (mLock) {
+ // Do not allow destroyed/failed staged session to change state
+ if (mDestroyed || mSessionFailed) return;
+ mSessionReady = true;
+ mSessionApplied = false;
+ mSessionFailed = false;
+ mSessionErrorCode = SessionInfo.STAGED_SESSION_NO_ERROR;
+ mSessionErrorMessage = "";
+ }
+ mCallback.onStagedSessionChanged(PackageInstallerSession.this);
+ }
+
+ @Override
+ public void setSessionFailed(int errorCode, String errorMessage) {
+ List<PackageInstallerSession> childSessions;
+ synchronized (mLock) {
+ // Do not allow destroyed/failed staged session to change state
+ if (mDestroyed || mSessionFailed) return;
+ mSessionReady = false;
+ mSessionApplied = false;
+ mSessionFailed = true;
+ mSessionErrorCode = errorCode;
+ mSessionErrorMessage = errorMessage;
+ Slog.d(TAG, "Marking session " + sessionId + " as failed: " + errorMessage);
+ childSessions = getChildSessionsLocked();
+ }
+ cleanStageDir(childSessions);
+ mCallback.onStagedSessionChanged(PackageInstallerSession.this);
+ }
+
+ @Override
+ public void setSessionApplied() {
+ List<PackageInstallerSession> childSessions;
+ synchronized (mLock) {
+ // Do not allow destroyed/failed staged session to change state
+ if (mDestroyed || mSessionFailed) return;
+ mSessionReady = false;
+ mSessionApplied = true;
+ mSessionFailed = false;
+ mSessionErrorCode = SessionInfo.STAGED_SESSION_NO_ERROR;
+ mSessionErrorMessage = "";
+ Slog.d(TAG, "Marking session " + sessionId + " as applied");
+ childSessions = getChildSessionsLocked();
+ }
+ cleanStageDir(childSessions);
+ mCallback.onStagedSessionChanged(PackageInstallerSession.this);
+ }
+
+ @Override
+ public boolean containsApkSession() {
+ return PackageInstallerSession.this.containsApkSession();
+ }
+
+ /**
+ * Installs apks of staged session while skipping the verification process for a committed
+ * and ready session.
+ */
+ @Override
+ public void installSession(IntentSender statusReceiver) {
+ assertCallerIsOwnerOrRootOrSystemLocked();
+ assertNotChildLocked("StagedSession#installSession");
+ Preconditions.checkArgument(isCommitted() && isSessionReady());
+
+ // Since staged sessions are installed during boot, the original reference to status
+ // receiver from the owner has already been lost. We can safely replace it with a
+ // status receiver from the system without effecting the flow.
+ updateRemoteStatusReceiver(statusReceiver);
+ install();
+ }
+
+ private void updateRemoteStatusReceiver(IntentSender remoteStatusReceiver) {
+ synchronized (mLock) {
+ mRemoteStatusReceiver = remoteStatusReceiver;
+ if (isMultiPackage()) {
+ final IntentSender childIntentSender = new ChildStatusIntentReceiver(
+ mChildSessions.clone(), remoteStatusReceiver).getIntentSender();
+ for (int i = mChildSessions.size() - 1; i >= 0; --i) {
+ mChildSessions.valueAt(i).mRemoteStatusReceiver = childIntentSender;
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean hasParentSessionId() {
+ return PackageInstallerSession.this.hasParentSessionId();
+ }
+
+ @Override
+ public int getParentSessionId() {
+ return PackageInstallerSession.this.getParentSessionId();
+ }
+
+ @Override
+ public boolean isCommitted() {
+ return PackageInstallerSession.this.isCommitted();
+ }
+
+ @Override
+ public boolean isInTerminalState() {
+ synchronized (mLock) {
+ return mSessionApplied || mSessionFailed;
+ }
+ }
+
+ @Override
+ public boolean isDestroyed() {
+ return PackageInstallerSession.this.isDestroyed();
+ }
+
+ @Override
+ public long getCommittedMillis() {
+ return PackageInstallerSession.this.getCommittedMillis();
+ }
+
+ @Override
+ public boolean sessionContains(Predicate<StagingManager.StagedSession> filter) {
+ return PackageInstallerSession.this.sessionContains(s -> filter.test(s.mStagedSession));
+ }
+
+ @Override
+ public boolean isSessionReady() {
+ synchronized (mLock) {
+ return mSessionReady;
+ }
+ }
+
+ @Override
+ public boolean isSessionApplied() {
+ synchronized (mLock) {
+ return mSessionApplied;
+ }
+ }
+
+ @Override
+ public boolean isSessionFailed() {
+ synchronized (mLock) {
+ return mSessionFailed;
+ }
+ }
+
+ @StagedSessionErrorCode int getSessionErrorCode() {
+ synchronized (mLock) {
+ return mSessionErrorCode;
+ }
+ }
+
+ String getSessionErrorMessage() {
+ synchronized (mLock) {
+ return mSessionErrorMessage;
+ }
+ }
+
+ @Override
+ public void abandon() {
+ final Runnable r;
+ synchronized (mLock) {
+ assertNotChildLocked("StagedSession#abandon");
+ assertCallerIsOwnerOrRootLocked();
+ if (isInTerminalState()) {
+ // We keep the session in the database if it's in a finalized state. It will be
+ // removed by PackageInstallerService when the last update time is old enough.
+ // Also, in such cases cleanStageDir() has already been executed so no need to
+ // do it now.
+ return;
+ }
+ mDestroyed = true;
+ boolean isCommitted = mCommitted;
+ List<PackageInstallerSession> childSessions = getChildSessionsLocked();
+ r = () -> {
+ assertNotLocked("abandonStaged");
+ if (isCommitted) {
+ mStagingManager.abortCommittedSession(this);
+ }
+ cleanStageDir(childSessions);
+ destroyInternal();
+ dispatchSessionFinished(INSTALL_FAILED_ABORTED, "Session was abandoned", null);
+ maybeCleanUpChildSessions();
+ };
+ if (mInPreRebootVerification) {
+ // Pre-reboot verification is ongoing, not safe to clean up the session yet.
+ mPendingAbandonCallback = r;
+ mCallback.onStagedSessionChanged(PackageInstallerSession.this);
+ return;
+ }
+ }
+ r.run();
+ }
+
+ /**
+ * Notified by the staging manager that pre-reboot verification is about to start. The
+ * return value should be checked to decide whether it is OK to start pre-reboot
+ * verification. In the case of a destroyed session, {@code false} is returned and there is
+ * no need to start pre-reboot verification.
+ */
+ @Override
+ public boolean notifyStartPreRebootVerification() {
+ synchronized (mLock) {
+ if (mInPreRebootVerification) {
+ throw new IllegalStateException("Pre-reboot verification has started");
+ }
+ if (mDestroyed) {
+ return false;
+ }
+ mInPreRebootVerification = true;
+ return true;
+ }
+ }
+
+ /**
+ * Notified by the staging manager that pre-reboot verification has ended. Now it is safe to
+ * clean up the session if {@link #abandon()} has been called previously.
+ */
+ @Override
+ public void notifyEndPreRebootVerification() {
+ synchronized (mLock) {
+ if (!mInPreRebootVerification) {
+ throw new IllegalStateException("Pre-reboot verification not started");
+ }
+ mInPreRebootVerification = false;
+ }
+ dispatchPendingAbandonCallback();
+ }
+
+ /**
+ * Resumes verification process for non-final committed staged session.
+ *
+ * Useful if a device gets rebooted before verification is complete and we need to restart
+ * the verification.
+ */
+ @Override
+ public void verifySession() {
+ assertCallerIsOwnerOrRootOrSystemLocked();
+ Preconditions.checkArgument(isCommitted());
+ Preconditions.checkArgument(!mSessionApplied && !mSessionFailed);
+ verify();
+ }
+
+ private void dispatchPendingAbandonCallback() {
+ final Runnable callback;
+ synchronized (mLock) {
+ callback = mPendingAbandonCallback;
+ mPendingAbandonCallback = null;
+ }
+ if (callback != null) {
+ callback.run();
+ }
+ }
+ }
/**
* Path to the validated base APK for this session, which may point at an
@@ -691,12 +1002,8 @@
mPrepared = prepared;
mCommitted = committed;
mDestroyed = destroyed;
- mStagedSessionReady = isReady;
- mStagedSessionFailed = isFailed;
- mStagedSessionApplied = isApplied;
- mStagedSessionErrorCode = stagedSessionErrorCode;
- mStagedSessionErrorMessage =
- stagedSessionErrorMessage != null ? stagedSessionErrorMessage : "";
+ mStagedSession = params.isStaged ? new StagedSession(isReady, isApplied, isFailed,
+ stagedSessionErrorCode, stagedSessionErrorMessage) : null;
if (isDataLoaderInstallation()) {
if (isApexSession()) {
@@ -789,10 +1096,11 @@
info.rollbackDataPolicy = params.rollbackDataPolicy;
info.parentSessionId = mParentSessionId;
info.childSessionIds = getChildSessionIdsLocked();
- info.isStagedSessionApplied = mStagedSessionApplied;
- info.isStagedSessionReady = mStagedSessionReady;
- info.isStagedSessionFailed = mStagedSessionFailed;
- info.setStagedSessionErrorCode(mStagedSessionErrorCode, mStagedSessionErrorMessage);
+ info.isStagedSessionApplied = isStagedSessionApplied();
+ info.isStagedSessionReady = isStagedSessionReady();
+ info.isStagedSessionFailed = isStagedSessionFailed();
+ info.setStagedSessionErrorCode(getStagedSessionErrorCode(),
+ getStagedSessionErrorMessage());
info.createdMillis = createdMillis;
info.updatedMillis = updatedMillis;
}
@@ -827,9 +1135,7 @@
/** Returns true if a staged session has reached a final state and can be forgotten about */
public boolean isStagedAndInTerminalState() {
- synchronized (mLock) {
- return params.isStaged && (mStagedSessionApplied || mStagedSessionFailed);
- }
+ return params.isStaged && mStagedSession.isInTerminalState();
}
private void assertNotLocked(String cookie) {
@@ -1724,11 +2030,11 @@
// Session is sealed and committed but could not be verified, we need to destroy it.
destroyInternal();
if (isStaged()) {
- setStagedSessionFailed(
+ mStagedSession.setSessionFailed(
SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, msgWithErrorCode);
// TODO(b/136257624): Remove this once all verification logic has been transferred out
// of StagingManager.
- mStagingManager.notifyVerificationComplete(this);
+ mStagingManager.notifyVerificationComplete(mStagedSession);
} else {
// Dispatch message to remove session from PackageInstallerService.
dispatchSessionFinished(error, msg, null);
@@ -1847,7 +2153,7 @@
.write();
}
if (params.isStaged) {
- mStagingManager.commitSession(this);
+ mStagingManager.commitSession(mStagedSession);
// TODO(b/136257624): CTS test fails if we don't send session finished broadcast, even
// though ideally, we just need to send session committed broadcast.
dispatchSessionFinished(INSTALL_SUCCEEDED, "Session staged", null);
@@ -1863,21 +2169,6 @@
verify();
}
- /**
- * Resumes verification process for non-final committed staged session.
- *
- * Useful if a device gets rebooted before verification is complete and we need to restart the
- * verification.
- */
- void verifyStagedSession() {
- assertCallerIsOwnerOrRootOrSystemLocked();
- Preconditions.checkArgument(isCommitted());
- Preconditions.checkArgument(isStaged());
- Preconditions.checkArgument(!mStagedSessionApplied && !mStagedSessionFailed);
-
- verify();
- }
-
private void verify() {
try {
verifyNonStaged();
@@ -1932,36 +2223,6 @@
}
}
- /**
- * Installs apks of staged session while skipping the verification process for a committed and
- * ready session.
- */
- void installStagedSession(IntentSender statusReceiver) {
- assertCallerIsOwnerOrRootOrSystemLocked();
- Preconditions.checkArgument(!hasParentSessionId()); // Don't allow installing child sessions
- Preconditions.checkArgument(isCommitted() && isStagedSessionReady());
-
- // Since staged sessions are installed during boot, the original reference to status
- // receiver from the owner has already been lost. We can safely replace it with a
- // status receiver from the system without effecting the flow.
- updateRemoteStatusReceiver(statusReceiver);
- install();
- }
-
- private void updateRemoteStatusReceiver(IntentSender remoteStatusReceiver) {
- synchronized (mLock) {
- mRemoteStatusReceiver = remoteStatusReceiver;
- if (isMultiPackage()) {
- final IntentSender childIntentSender =
- new ChildStatusIntentReceiver(mChildSessions.clone(), remoteStatusReceiver)
- .getIntentSender();
- for (int i = mChildSessions.size() - 1; i >= 0; --i) {
- mChildSessions.valueAt(i).mRemoteStatusReceiver = childIntentSender;
- }
- }
- }
- }
-
private void install() {
try {
installNonStaged();
@@ -2188,7 +2449,7 @@
if (isStaged()) {
// TODO(b/136257624): Remove this once all verification logic has been transferred out
// of StagingManager.
- mStagingManager.notifyPreRebootVerification_Apk_Complete(this);
+ mStagingManager.notifyPreRebootVerification_Apk_Complete(mStagedSession);
// TODO(b/136257624): We also need to destroy internals for verified staged session,
// otherwise file descriptors are never closed for verified staged session until reboot
return;
@@ -2370,10 +2631,6 @@
return false;
}
- boolean containsApexSession() {
- return sessionContains((s) -> s.isApexSession());
- }
-
boolean containsApkSession() {
return sessionContains((s) -> !s.isApexSession());
}
@@ -3195,6 +3452,7 @@
private void abandonNonStaged() {
synchronized (mLock) {
+ assertNotChildLocked("abandonNonStaged");
assertCallerIsOwnerOrRootLocked();
if (mRelinquished) {
if (LOGD) Slog.d(TAG, "Ignoring abandon after commit relinquished control");
@@ -3206,98 +3464,23 @@
maybeCleanUpChildSessions();
}
- private void abandonStaged() {
- final Runnable r;
- synchronized (mLock) {
- assertCallerIsOwnerOrRootLocked();
- if (isStagedAndInTerminalState()) {
- // We keep the session in the database if it's in a finalized state. It will be
- // removed by PackageInstallerService when the last update time is old enough.
- // Also, in such cases cleanStageDir() has already been executed so no need to
- // do it now.
- return;
- }
- mDestroyed = true;
- boolean isCommitted = mCommitted;
- List<PackageInstallerSession> childSessions = getChildSessionsLocked();
- r = () -> {
- assertNotLocked("abandonStaged");
- if (isCommitted) {
- mStagingManager.abortCommittedSession(this);
- }
- cleanStageDir(childSessions);
- destroyInternal();
- dispatchSessionFinished(INSTALL_FAILED_ABORTED, "Session was abandoned", null);
- maybeCleanUpChildSessions();
- };
- if (mInPreRebootVerification) {
- // Pre-reboot verification is ongoing. It is not safe to clean up the session yet.
- mPendingAbandonCallback = r;
- mCallback.onStagedSessionChanged(this);
- return;
- }
+ @GuardedBy("mLock")
+ private void assertNotChildLocked(String cookie) {
+ if (hasParentSessionId()) {
+ throw new IllegalStateException(cookie + " can't be called on a child session, id="
+ + sessionId + " parentId=" + getParentSessionId());
}
- r.run();
}
@Override
public void abandon() {
- if (hasParentSessionId()) {
- throw new IllegalStateException(
- "Session " + sessionId + " is a child of multi-package session "
- + getParentSessionId() + " and may not be abandoned directly.");
- }
if (params.isStaged) {
- abandonStaged();
+ mStagedSession.abandon();
} else {
abandonNonStaged();
}
}
- /**
- * Notified by the staging manager that pre-reboot verification is about to start. The return
- * value should be checked to decide whether it is OK to start pre-reboot verification. In
- * the case of a destroyed session, {@code false} is returned and there is no need to start
- * pre-reboot verification.
- */
- boolean notifyStagedStartPreRebootVerification() {
- synchronized (mLock) {
- if (mInPreRebootVerification) {
- throw new IllegalStateException("Pre-reboot verification has started");
- }
- if (mDestroyed) {
- return false;
- }
- mInPreRebootVerification = true;
- return true;
- }
- }
-
- private void dispatchPendingAbandonCallback() {
- final Runnable callback;
- synchronized (mLock) {
- callback = mPendingAbandonCallback;
- mPendingAbandonCallback = null;
- }
- if (callback != null) {
- callback.run();
- }
- }
-
- /**
- * Notified by the staging manager that pre-reboot verification has ended. Now it is safe to
- * clean up the session if {@link #abandon()} has been called previously.
- */
- void notifyStagedEndPreRebootVerification() {
- synchronized (mLock) {
- if (!mInPreRebootVerification) {
- throw new IllegalStateException("Pre-reboot verification not started");
- }
- mInPreRebootVerification = false;
- }
- dispatchPendingAbandonCallback();
- }
-
@Override
public boolean isMultiPackage() {
return params.isMultiPackage;
@@ -3783,88 +3966,29 @@
}
/** {@hide} */
- void setStagedSessionReady() {
- synchronized (mLock) {
- // Do not allow destroyed/failed staged session to change state
- if (mDestroyed || mStagedSessionFailed) return;
- mStagedSessionReady = true;
- mStagedSessionApplied = false;
- mStagedSessionFailed = false;
- mStagedSessionErrorCode = SessionInfo.STAGED_SESSION_NO_ERROR;
- mStagedSessionErrorMessage = "";
- }
- mCallback.onStagedSessionChanged(this);
- }
-
- /** {@hide} */
- void setStagedSessionFailed(@StagedSessionErrorCode int errorCode, String errorMessage) {
- List<PackageInstallerSession> childSessions;
- synchronized (mLock) {
- // Do not allow destroyed/failed staged session to change state
- if (mDestroyed || mStagedSessionFailed) return;
- mStagedSessionReady = false;
- mStagedSessionApplied = false;
- mStagedSessionFailed = true;
- mStagedSessionErrorCode = errorCode;
- mStagedSessionErrorMessage = errorMessage;
- Slog.d(TAG, "Marking session " + sessionId + " as failed: " + errorMessage);
- childSessions = getChildSessionsLocked();
- }
- cleanStageDir(childSessions);
- mCallback.onStagedSessionChanged(this);
- }
-
- /** {@hide} */
- void setStagedSessionApplied() {
- List<PackageInstallerSession> childSessions;
- synchronized (mLock) {
- // Do not allow destroyed/failed staged session to change state
- if (mDestroyed || mStagedSessionFailed) return;
- mStagedSessionReady = false;
- mStagedSessionApplied = true;
- mStagedSessionFailed = false;
- mStagedSessionErrorCode = SessionInfo.STAGED_SESSION_NO_ERROR;
- mStagedSessionErrorMessage = "";
- Slog.d(TAG, "Marking session " + sessionId + " as applied");
- childSessions = getChildSessionsLocked();
- }
- cleanStageDir(childSessions);
- mCallback.onStagedSessionChanged(this);
- }
-
- /** {@hide} */
boolean isStagedSessionReady() {
- synchronized (mLock) {
- return mStagedSessionReady;
- }
+ return params.isStaged && mStagedSession.isSessionReady();
}
/** {@hide} */
boolean isStagedSessionApplied() {
- synchronized (mLock) {
- return mStagedSessionApplied;
- }
+ return params.isStaged && mStagedSession.isSessionApplied();
}
/** {@hide} */
boolean isStagedSessionFailed() {
- synchronized (mLock) {
- return mStagedSessionFailed;
- }
+ return params.isStaged && mStagedSession.isSessionFailed();
}
/** {@hide} */
@StagedSessionErrorCode int getStagedSessionErrorCode() {
- synchronized (mLock) {
- return mStagedSessionErrorCode;
- }
+ return params.isStaged ? mStagedSession.getSessionErrorCode()
+ : SessionInfo.STAGED_SESSION_NO_ERROR;
}
/** {@hide} */
String getStagedSessionErrorMessage() {
- synchronized (mLock) {
- return mStagedSessionErrorMessage;
- }
+ return params.isStaged ? mStagedSession.getSessionErrorMessage() : "";
}
private void destroyInternal() {
@@ -3961,11 +4085,11 @@
pw.printPair("params.isStaged", params.isStaged);
pw.printPair("mParentSessionId", mParentSessionId);
pw.printPair("mChildSessionIds", getChildSessionIdsLocked());
- pw.printPair("mStagedSessionApplied", mStagedSessionApplied);
- pw.printPair("mStagedSessionFailed", mStagedSessionFailed);
- pw.printPair("mStagedSessionReady", mStagedSessionReady);
- pw.printPair("mStagedSessionErrorCode", mStagedSessionErrorCode);
- pw.printPair("mStagedSessionErrorMessage", mStagedSessionErrorMessage);
+ pw.printPair("mStagedSessionApplied", isStagedSessionApplied());
+ pw.printPair("mStagedSessionFailed", isStagedSessionFailed());
+ pw.printPair("mStagedSessionReady", isStagedSessionReady());
+ pw.printPair("mStagedSessionErrorCode", getStagedSessionErrorCode());
+ pw.printPair("mStagedSessionErrorMessage", getStagedSessionErrorMessage());
pw.println();
pw.decreaseIndent();
@@ -4131,12 +4255,12 @@
writeBooleanAttribute(out, ATTR_MULTI_PACKAGE, params.isMultiPackage);
writeBooleanAttribute(out, ATTR_STAGED_SESSION, params.isStaged);
- writeBooleanAttribute(out, ATTR_IS_READY, mStagedSessionReady);
- writeBooleanAttribute(out, ATTR_IS_FAILED, mStagedSessionFailed);
- writeBooleanAttribute(out, ATTR_IS_APPLIED, mStagedSessionApplied);
- out.attributeInt(null, ATTR_STAGED_SESSION_ERROR_CODE, mStagedSessionErrorCode);
+ writeBooleanAttribute(out, ATTR_IS_READY, isStagedSessionReady());
+ writeBooleanAttribute(out, ATTR_IS_FAILED, isStagedSessionFailed());
+ writeBooleanAttribute(out, ATTR_IS_APPLIED, isStagedSessionApplied());
+ out.attributeInt(null, ATTR_STAGED_SESSION_ERROR_CODE, getStagedSessionErrorCode());
writeStringAttribute(out, ATTR_STAGED_SESSION_ERROR_MESSAGE,
- mStagedSessionErrorMessage);
+ getStagedSessionErrorMessage());
// TODO(patb,109941548): avoid writing to xml and instead infer / validate this after
// we've read all sessions.
out.attributeInt(null, ATTR_PARENT_SESSION_ID, mParentSessionId);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 282fb58..22f4a92 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -394,6 +394,7 @@
import com.android.server.storage.DeviceStorageMonitorInternal;
import com.android.server.uri.UriGrantsManagerInternal;
import com.android.server.utils.TimingsTraceAndSlog;
+import com.android.server.utils.WatchedArrayMap;
import com.android.server.wm.ActivityTaskManagerInternal;
import dalvik.system.CloseGuard;
@@ -1002,7 +1003,7 @@
Producer<PackageParser2> scanningPackageParserProducer,
Producer<PackageParser2> preparingPackageParserProducer,
Producer<PackageInstallerService> packageInstallerServiceProducer,
- ProducerWithArgument<InstantAppResolverConnection, ComponentName>
+ ProducerWithArgument<InstantAppResolverConnection, ComponentName>
instantAppResolverConnectionProducer,
Producer<ModuleInfoProvider> moduleInfoProviderProducer,
Producer<LegacyPermissionManagerInternal> legacyPermissionManagerInternalProducer,
@@ -3302,7 +3303,8 @@
// Clean up orphaned packages for which the code path doesn't exist
// and they are an update to a system app - caused by bug/32321269
- final ArrayMap<String, PackageSetting> packageSettings = mSettings.getPackagesLocked();
+ final WatchedArrayMap<String, PackageSetting> packageSettings =
+ mSettings.getPackagesLocked();
final int packageSettingCount = packageSettings.size();
for (int i = packageSettingCount - 1; i >= 0; i--) {
PackageSetting ps = packageSettings.valueAt(i);
@@ -4806,6 +4808,12 @@
enforceCrossUserPermission(Binder.getCallingUid(), userId,
false /* requireFullPermission */, false /* checkShell */, "get package info");
+ return getPackageInfoInternalBody(packageName, versionCode, flags, filterCallingUid,
+ userId);
+ }
+
+ private PackageInfo getPackageInfoInternalBody(String packageName, long versionCode,
+ int flags, int filterCallingUid, int userId) {
// reader
synchronized (mLock) {
// Normalize package name to handle renamed packages and static libs
@@ -5227,6 +5235,11 @@
"get application info");
}
+ return getApplicationInfoInternalBody(packageName, flags, filterCallingUid, userId);
+ }
+
+ private ApplicationInfo getApplicationInfoInternalBody(String packageName, int flags,
+ int filterCallingUid, int userId) {
// writer
synchronized (mLock) {
// Normalize package name to handle renamed packages and static libs
@@ -5417,6 +5430,14 @@
InstantAppRegistry.DEFAULT_UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD))) {
return;
}
+
+ // 11. Free storage service cache
+ StorageManagerInternal smInternal =
+ mInjector.getLocalService(StorageManagerInternal.class);
+ // TODO(b/170481432): Decide what value of bytes needs to be sent instead of
+ // sending the bytes parameter of freeStorage
+ smInternal.freeCache(volumeUuid, bytes);
+ if (file.getUsableSpace() >= bytes) return;
} else {
try {
mInstaller.freeCache(volumeUuid, bytes, 0, 0);
@@ -5651,6 +5672,11 @@
false /* requireFullPermission */, false /* checkShell */, "get activity info");
}
+ return getActivityInfoInternalBody(component, flags, filterCallingUid, userId);
+ }
+
+ private ActivityInfo getActivityInfoInternalBody(ComponentName component, int flags,
+ int filterCallingUid, int userId) {
synchronized (mLock) {
ParsedActivity a = mComponentResolver.getActivity(component);
@@ -5957,6 +5983,11 @@
flags = updateFlagsForComponent(flags, userId);
enforceCrossUserOrProfilePermission(callingUid, userId, false /* requireFullPermission */,
false /* checkShell */, "get service info");
+ return getServiceInfoBody(component, flags, userId, callingUid);
+ }
+
+ private ServiceInfo getServiceInfoBody(ComponentName component, int flags, int userId,
+ int callingUid) {
synchronized (mLock) {
ParsedService s = mComponentResolver.getService(component);
if (DEBUG_PACKAGE_INFO) Log.v(
@@ -6529,6 +6560,11 @@
final boolean isCallerInstantApp = getInstantAppPackageName(callingUid) != null;
final int userId = UserHandle.getUserId(uid);
final int appId = UserHandle.getAppId(uid);
+ return getPackagesForUidInternalBody(callingUid, userId, appId, isCallerInstantApp);
+ }
+
+ private String[] getPackagesForUidInternalBody(int callingUid, int userId, int appId,
+ boolean isCallerInstantApp) {
// reader
synchronized (mLock) {
final Object obj = mSettings.getSettingLPr(appId);
@@ -6880,6 +6916,15 @@
}
// Deny ephemeral apps if the user chose _ALWAYS or _ALWAYS_ASK for intent resolution.
// Or if there's already an ephemeral app installed that handles the action
+ return isInstantAppResolutionAllowedBody(intent, resolvedActivities, userId,
+ skipPackageCheck);
+ }
+
+ // Deny ephemeral apps if the user chose _ALWAYS or _ALWAYS_ASK for intent resolution.
+ // Or if there's already an ephemeral app installed that handles the action
+ private boolean isInstantAppResolutionAllowedBody(
+ Intent intent, List<ResolveInfo> resolvedActivities, int userId,
+ boolean skipPackageCheck) {
synchronized (mLock) {
final int count = (resolvedActivities == null ? 0 : resolvedActivities.size());
for (int n = 0; n < count; n++) {
@@ -7449,6 +7494,23 @@
userId, false /*resolveForStart*/, true /*allowDynamicSplits*/);
}
+ // Collect the results of queryIntentActivitiesInternalBody into a single class
+ private static class QueryIntentActivitiesResult {
+ public boolean sortResult = false;
+ public boolean addInstant = false;
+ public List<ResolveInfo> result = null;
+ public List<ResolveInfo> answer = null;
+
+ QueryIntentActivitiesResult(List<ResolveInfo> l) {
+ answer = l;
+ }
+ QueryIntentActivitiesResult(boolean s, boolean a, List<ResolveInfo> l) {
+ sortResult = s;
+ addInstant = a;
+ result = l;
+ }
+ }
+
private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
String resolvedType, int flags, @PrivateResolveFlags int privateResolveFlags,
int filterCallingUid, int userId, boolean resolveForStart, boolean allowDynamicSplits) {
@@ -7522,11 +7584,37 @@
return result;
}
+ QueryIntentActivitiesResult lockedResult =
+ queryIntentActivitiesInternalBody(
+ intent, resolvedType, flags, filterCallingUid, userId, resolveForStart,
+ allowDynamicSplits, pkgName, instantAppPkgName);
+ if (lockedResult.answer != null) {
+ return lockedResult.answer;
+ }
+
+ if (lockedResult.addInstant) {
+ String callingPkgName = getInstantAppPackageName(filterCallingUid);
+ boolean isRequesterInstantApp = isInstantApp(callingPkgName, userId);
+ lockedResult.result = maybeAddInstantAppInstaller(lockedResult.result, intent,
+ resolvedType, flags, userId, resolveForStart, isRequesterInstantApp);
+ }
+ if (lockedResult.sortResult) {
+ Collections.sort(lockedResult.result, RESOLVE_PRIORITY_SORTER);
+ }
+ return applyPostResolutionFilter(
+ lockedResult.result, instantAppPkgName, allowDynamicSplits, filterCallingUid,
+ resolveForStart, userId, intent);
+ }
+
+ private @NonNull QueryIntentActivitiesResult queryIntentActivitiesInternalBody(
+ Intent intent, String resolvedType, int flags, int filterCallingUid, int userId,
+ boolean resolveForStart, boolean allowDynamicSplits, String pkgName,
+ String instantAppPkgName) {
// reader
- boolean sortResult = false;
- boolean addInstant = false;
- List<ResolveInfo> result;
synchronized (mLock) {
+ boolean sortResult = false;
+ boolean addInstant = false;
+ List<ResolveInfo> result = null;
if (pkgName == null) {
List<CrossProfileIntentFilter> matchingFilters =
getMatchingCrossProfileIntentFilters(intent, resolvedType, userId);
@@ -7536,9 +7624,11 @@
if (xpResolveInfo != null) {
List<ResolveInfo> xpResult = new ArrayList<>(1);
xpResult.add(xpResolveInfo);
- return applyPostResolutionFilter(
- filterIfNotSystemUser(xpResult, userId), instantAppPkgName,
- allowDynamicSplits, filterCallingUid, resolveForStart, userId, intent);
+ return new QueryIntentActivitiesResult(
+ applyPostResolutionFilter(
+ filterIfNotSystemUser(xpResult, userId), instantAppPkgName,
+ allowDynamicSplits, filterCallingUid, resolveForStart, userId,
+ intent));
}
// Check for results in the current profile.
@@ -7577,17 +7667,19 @@
// And we are not going to add emphemeral app, so we can return the
// result straight away.
result.add(xpDomainInfo.resolveInfo);
- return applyPostResolutionFilter(result, instantAppPkgName,
- allowDynamicSplits, filterCallingUid, resolveForStart, userId,
- intent);
+ return new QueryIntentActivitiesResult(
+ applyPostResolutionFilter(result, instantAppPkgName,
+ allowDynamicSplits, filterCallingUid, resolveForStart,
+ userId, intent));
}
} else if (result.size() <= 1 && !addInstant) {
// No result in parent user and <= 1 result in current profile, and we
// are not going to add emphemeral app, so we can return the result without
// further processing.
- return applyPostResolutionFilter(result, instantAppPkgName,
+ return new QueryIntentActivitiesResult(
+ applyPostResolutionFilter(result, instantAppPkgName,
allowDynamicSplits, filterCallingUid, resolveForStart, userId,
- intent);
+ intent));
}
// We have more than one candidate (combining results from current and parent
// profile), so we need filtering and sorting.
@@ -7615,19 +7707,8 @@
}
}
}
+ return new QueryIntentActivitiesResult(sortResult, addInstant, result);
}
- if (addInstant) {
- String callingPkgName = getInstantAppPackageName(filterCallingUid);
- boolean isRequesterInstantApp = isInstantApp(callingPkgName, userId);
- result = maybeAddInstantAppInstaller(result, intent, resolvedType, flags, userId,
- resolveForStart, isRequesterInstantApp);
- }
- if (sortResult) {
- Collections.sort(result, RESOLVE_PRIORITY_SORTER);
- }
- return applyPostResolutionFilter(
- result, instantAppPkgName, allowDynamicSplits, filterCallingUid, resolveForStart,
- userId, intent);
}
private List<ResolveInfo> maybeAddInstantAppInstaller(List<ResolveInfo> result, Intent intent,
@@ -7974,14 +8055,30 @@
candidates.size());
}
- final ArrayList<ResolveInfo> result = new ArrayList<>();
- final ArrayList<ResolveInfo> alwaysList = new ArrayList<>();
- final ArrayList<ResolveInfo> undefinedList = new ArrayList<>();
- final ArrayList<ResolveInfo> alwaysAskList = new ArrayList<>();
- final ArrayList<ResolveInfo> neverList = new ArrayList<>();
- final ArrayList<ResolveInfo> matchAllList = new ArrayList<>();
+ final ArrayList<ResolveInfo> result =
+ filterCandidatesWithDomainPreferredActivitiesLPrBody(
+ intent, matchFlags, candidates, xpDomainInfo, userId, debug);
+ if (DEBUG_PREFERRED || DEBUG_DOMAIN_VERIFICATION) {
+ Slog.v(TAG, "Filtered results with preferred activities. New candidates count: "
+ + result.size());
+ for (ResolveInfo info : result) {
+ Slog.v(TAG, " + " + info.activityInfo);
+ }
+ }
+ return result;
+ }
+
+ private ArrayList<ResolveInfo> filterCandidatesWithDomainPreferredActivitiesLPrBody(
+ Intent intent, int matchFlags, List<ResolveInfo> candidates,
+ CrossProfileDomainInfo xpDomainInfo, int userId, boolean debug) {
synchronized (mLock) {
+ final ArrayList<ResolveInfo> result = new ArrayList<>();
+ final ArrayList<ResolveInfo> alwaysList = new ArrayList<>();
+ final ArrayList<ResolveInfo> undefinedList = new ArrayList<>();
+ final ArrayList<ResolveInfo> alwaysAskList = new ArrayList<>();
+ final ArrayList<ResolveInfo> neverList = new ArrayList<>();
+ final ArrayList<ResolveInfo> matchAllList = new ArrayList<>();
final int count = candidates.size();
// First, try to use linked apps. Partition the candidates into four lists:
// one for the final results, one for the "do not use ever", one for "undefined status"
@@ -8117,15 +8214,8 @@
result.removeAll(neverList);
}
}
+ return result;
}
- if (DEBUG_PREFERRED || DEBUG_DOMAIN_VERIFICATION) {
- Slog.v(TAG, "Filtered results with preferred activities. New candidates count: " +
- result.size());
- for (ResolveInfo info : result) {
- Slog.v(TAG, " + " + info.activityInfo);
- }
- }
- return result;
}
// Returns a packed value as a long:
@@ -8624,6 +8714,13 @@
return list;
}
+ return queryIntentServicesInternalBody(intent, resolvedType, flags,
+ userId, callingUid, instantAppPkgName);
+ }
+
+ private @NonNull List<ResolveInfo> queryIntentServicesInternalBody(Intent intent,
+ String resolvedType, int flags, int userId, int callingUid,
+ String instantAppPkgName) {
// reader
synchronized (mLock) {
String pkgName = intent.getPackage();
@@ -8849,15 +8946,21 @@
}
if (!mUserManager.exists(userId)) return ParceledListSlice.emptyList();
flags = updateFlagsForPackage(flags, userId);
- final boolean listUninstalled = (flags & MATCH_KNOWN_PACKAGES) != 0;
- final boolean listApex = (flags & MATCH_APEX) != 0;
- final boolean listFactory = (flags & MATCH_FACTORY_ONLY) != 0;
enforceCrossUserPermission(callingUid, userId, false /* requireFullPermission */,
false /* checkShell */, "get installed packages");
+ return getInstalledPackagesBody(flags, userId, callingUid);
+ }
+
+ private ParceledListSlice<PackageInfo> getInstalledPackagesBody(int flags, int userId,
+ int callingUid) {
// writer
synchronized (mLock) {
+ final boolean listUninstalled = (flags & MATCH_KNOWN_PACKAGES) != 0;
+ final boolean listApex = (flags & MATCH_APEX) != 0;
+ final boolean listFactory = (flags & MATCH_FACTORY_ONLY) != 0;
+
ArrayList<PackageInfo> list;
if (listUninstalled) {
list = new ArrayList<>(mSettings.getPackagesLocked().size());
@@ -9107,6 +9210,11 @@
if (HIDE_EPHEMERAL_APIS) {
return false;
}
+ return isInstantAppInternalBody(packageName, userId, callingUid);
+ }
+
+ private boolean isInstantAppInternalBody(String packageName, @UserIdInt int userId,
+ int callingUid) {
synchronized (mLock) {
if (Process.isIsolated(callingUid)) {
callingUid = mIsolatedOwners.get(callingUid);
@@ -20805,8 +20913,12 @@
mSettings.applyDefaultPreferredAppsLPw(userId);
clearIntentFilterVerificationsLPw(userId);
primeDomainVerificationsLPw(userId);
+ final int numPackages = mPackages.size();
+ for (int i = 0; i < numPackages; i++) {
+ final AndroidPackage pkg = mPackages.valueAt(i);
+ mPermissionManager.resetRuntimePermissions(pkg, userId);
+ }
}
- mPermissionManager.resetAllRuntimePermissions(userId);
updateDefaultHomeNotLocked(userId);
// TODO: We have to reset the default SMS and Phone. This requires
// significant refactoring to keep all default apps in the package
@@ -22304,7 +22416,7 @@
mUserManager.reconcileUsers(StorageManager.UUID_PRIVATE_INTERNAL);
reconcileApps(StorageManager.UUID_PRIVATE_INTERNAL);
- mPermissionManager.systemReady();
+ mPermissionManager.onSystemReady();
int[] grantPermissionsUserIds = EMPTY_INT_ARRAY;
for (int userId : UserManagerService.getInstance().getUserIds()) {
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index ac76cf7..67bd82b4 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -175,22 +175,27 @@
public void setInstallerPackageName(String packageName) {
installSource = installSource.setInstallerPackage(packageName);
+ onChanged();
}
public void setInstallSource(InstallSource installSource) {
this.installSource = Objects.requireNonNull(installSource);
+ onChanged();
}
void removeInstallerPackage(String packageName) {
installSource = installSource.removeInstallerPackage(packageName);
+ onChanged();
}
public void setIsOrphaned(boolean isOrphaned) {
installSource = installSource.setIsOrphaned(isOrphaned);
+ onChanged();
}
public void setVolumeUuid(String volumeUuid) {
this.volumeUuid = volumeUuid;
+ onChanged();
}
public String getVolumeUuid() {
@@ -199,10 +204,12 @@
public void setTimeStamp(long newStamp) {
timeStamp = newStamp;
+ onChanged();
}
public void setUpdateAvailable(boolean updateAvailable) {
this.updateAvailable = updateAvailable;
+ onChanged();
}
public boolean isUpdateAvailable() {
@@ -272,6 +279,7 @@
if (state == null) {
state = new PackageUserState();
mUserState.put(userId, state);
+ onChanged();
}
return state;
}
@@ -289,6 +297,7 @@
PackageUserState st = modifyUserState(userId);
st.enabled = state;
st.lastDisableAppCaller = callingPackage;
+ onChanged();
}
int getEnabled(int userId) {
@@ -434,6 +443,7 @@
}
existingUserState.suspendParams.put(suspendingPackage, newSuspendParams);
existingUserState.suspended = true;
+ onChanged();
}
void removeSuspension(String suspendingPackage, int userId) {
@@ -445,6 +455,7 @@
}
}
existingUserState.suspended = (existingUserState.suspendParams != null);
+ onChanged();
}
void removeSuspension(Predicate<String> suspendingPackagePredicate, int userId) {
@@ -461,6 +472,7 @@
}
}
existingUserState.suspended = (existingUserState.suspendParams != null);
+ onChanged();
}
public boolean getInstantApp(int userId) {
@@ -506,6 +518,7 @@
state.instantApp = instantApp;
state.virtualPreload = virtualPreload;
state.harmfulAppWarning = harmfulAppWarning;
+ onChanged();
}
void setUserState(int userId, PackageUserState otherState) {
@@ -547,11 +560,17 @@
PackageUserState modifyUserStateComponents(int userId, boolean disabled, boolean enabled) {
PackageUserState state = modifyUserState(userId);
+ boolean changed = false;
if (disabled && state.disabledComponents == null) {
state.disabledComponents = new ArraySet<String>(1);
+ changed = true;
}
if (enabled && state.enabledComponents == null) {
state.enabledComponents = new ArraySet<String>(1);
+ changed = true;
+ }
+ if (changed) {
+ onChanged();
}
return state;
}
@@ -603,6 +622,7 @@
void removeUser(int userId) {
mUserState.delete(userId);
+ onChanged();
}
public int[] getNotInstalledUserIds() {
@@ -630,6 +650,7 @@
void setIntentFilterVerificationInfo(IntentFilterVerificationInfo info) {
verificationInfo = info;
+ onChanged();
}
// Returns a packed value as a long:
@@ -648,6 +669,7 @@
state.domainVerificationStatus = status;
if (status == PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS) {
state.appLinkGeneration = generation;
+ onChanged();
}
}
@@ -694,6 +716,7 @@
void setHarmfulAppWarning(int userId, String harmfulAppWarning) {
PackageUserState userState = modifyUserState(userId);
userState.harmfulAppWarning = harmfulAppWarning;
+ onChanged();
}
String getHarmfulAppWarning(int userId) {
@@ -838,6 +861,7 @@
for (int i = 0; i < other.mUserState.size(); i++) {
mUserState.put(other.mUserState.keyAt(i), other.mUserState.valueAt(i));
}
+ onChanged();
return this;
}
}
diff --git a/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java b/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java
index 08a87d8..d0f9787 100644
--- a/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java
+++ b/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java
@@ -19,10 +19,12 @@
import android.annotation.NonNull;
import android.content.IntentFilter;
-import com.android.server.IntentResolver;
+import com.android.server.utils.Snappable;
+import com.android.server.utils.WatchableIntentResolver;
public class PersistentPreferredIntentResolver
- extends IntentResolver<PersistentPreferredActivity, PersistentPreferredActivity> {
+ extends WatchableIntentResolver<PersistentPreferredActivity, PersistentPreferredActivity>
+ implements Snappable {
@Override
protected PersistentPreferredActivity[] newArray(int size) {
return new PersistentPreferredActivity[size];
@@ -37,4 +39,15 @@
protected boolean isPackageForFilter(String packageName, PersistentPreferredActivity filter) {
return packageName.equals(filter.mComponent.getPackageName());
}
+
+ /**
+ * Return a snapshot of the current object. The snapshot is a read-only copy suitable
+ * for read-only methods.
+ * @return A snapshot of the current object.
+ */
+ public PersistentPreferredIntentResolver snapshot() {
+ PersistentPreferredIntentResolver result = new PersistentPreferredIntentResolver();
+ result.doCopy(this);
+ return result;
+ }
}
diff --git a/services/core/java/com/android/server/pm/PreferredIntentResolver.java b/services/core/java/com/android/server/pm/PreferredIntentResolver.java
index ff3df13..b62421e 100644
--- a/services/core/java/com/android/server/pm/PreferredIntentResolver.java
+++ b/services/core/java/com/android/server/pm/PreferredIntentResolver.java
@@ -19,13 +19,15 @@
import android.annotation.NonNull;
import android.content.IntentFilter;
-import java.io.PrintWriter;
+import com.android.server.utils.Snappable;
+import com.android.server.utils.WatchableIntentResolver;
-import com.android.server.IntentResolver;
+import java.io.PrintWriter;
import java.util.ArrayList;
public class PreferredIntentResolver
- extends IntentResolver<PreferredActivity, PreferredActivity> {
+ extends WatchableIntentResolver<PreferredActivity, PreferredActivity>
+ implements Snappable {
@Override
protected PreferredActivity[] newArray(int size) {
return new PreferredActivity[size];
@@ -66,4 +68,15 @@
}
return true;
}
+
+ /**
+ * Return a snapshot of the current object. The snapshot is a read-only copy suitable
+ * for read-only methods.
+ * @return A snapshot of the current object.
+ */
+ public PreferredIntentResolver snapshot() {
+ PreferredIntentResolver result = new PreferredIntentResolver();
+ result.doCopy(this);
+ return result;
+ }
}
diff --git a/services/core/java/com/android/server/pm/SettingBase.java b/services/core/java/com/android/server/pm/SettingBase.java
index 968c4b5..7924d5d 100644
--- a/services/core/java/com/android/server/pm/SettingBase.java
+++ b/services/core/java/com/android/server/pm/SettingBase.java
@@ -16,17 +16,71 @@
package com.android.server.pm;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.pm.ApplicationInfo;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.pm.permission.LegacyPermissionState;
+import com.android.server.utils.Watchable;
+import com.android.server.utils.WatchableImpl;
+import com.android.server.utils.Watcher;
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
-public abstract class SettingBase {
+public abstract class SettingBase implements Watchable {
+ // TODO: make this variable protected, or even private with a getter and setter.
+ // Simply making it protected or private requires that the name be changed to conformm
+ // to the Android naming convention, and that touches quite a few files.
int pkgFlags;
+
+ // TODO: make this variable protected, or even private with a getter and setter.
+ // Simply making it protected or private requires that the name be changed to conformm
+ // to the Android naming convention, and that touches quite a few files.
int pkgPrivateFlags;
/**
+ * Watchable machinery
+ */
+ private final Watchable mWatchable = new WatchableImpl();
+
+ /**
+ * Ensures an observer is in the list, exactly once. The observer cannot be null. The
+ * function quietly returns if the observer is already in the list.
+ *
+ * @param observer The {@link Watcher} to be notified when the {@link Watchable} changes.
+ */
+ public void registerObserver(@NonNull Watcher observer) {
+ mWatchable.registerObserver(observer);
+ }
+
+ /**
+ * Ensures an observer is not in the list. The observer must not be null. The function
+ * quietly returns if the objserver is not in the list.
+ *
+ * @param observer The {@link Watcher} that should not be in the notification list.
+ */
+ public void unregisterObserver(@NonNull Watcher observer) {
+ mWatchable.unregisterObserver(observer);
+ }
+
+ /**
+ * Invokes {@link Watcher#onChange} on each registered observer. The method can be called
+ * with the {@link Watchable} that generated the event. In a tree of {@link Watchable}s, this
+ * is generally the first (deepest) {@link Watchable} to detect a change.
+ *
+ * @param what The {@link Watchable} that generated the event.
+ */
+ public void dispatchChange(@Nullable Watchable what) {
+ mWatchable.dispatchChange(what);
+ }
+ /**
+ * Notify listeners that this object has changed.
+ */
+ protected void onChanged() {
+ dispatchChange(this);
+ }
+
+ /**
* The legacy permission state that is read from package settings persistence for migration.
* This state here can not reflect the current permission state and should not be used for
* purposes other than migration.
@@ -53,6 +107,7 @@
pkgFlags = orig.pkgFlags;
pkgPrivateFlags = orig.pkgPrivateFlags;
mLegacyPermissionsState.copyFrom(orig.mLegacyPermissionsState);
+ onChanged();
}
@Deprecated
@@ -64,6 +119,7 @@
this.pkgFlags = pkgFlags
& (ApplicationInfo.FLAG_SYSTEM
| ApplicationInfo.FLAG_EXTERNAL_STORAGE);
+ onChanged();
}
void setPrivateFlags(int pkgPrivateFlags) {
@@ -75,5 +131,6 @@
| ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT
| ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER
| ApplicationInfo.PRIVATE_FLAG_ODM);
+ onChanged();
}
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 7482ef45..7c4dade 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -114,7 +114,14 @@
import com.android.server.pm.permission.LegacyPermissionSettings;
import com.android.server.pm.permission.LegacyPermissionState;
import com.android.server.pm.permission.LegacyPermissionState.PermissionState;
+import com.android.server.utils.Snappable;
+import com.android.server.utils.Snapshots;
import com.android.server.utils.TimingsTraceAndSlog;
+import com.android.server.utils.Watchable;
+import com.android.server.utils.WatchableImpl;
+import com.android.server.utils.WatchedArrayMap;
+import com.android.server.utils.WatchedSparseArray;
+import com.android.server.utils.Watcher;
import libcore.io.IoUtils;
@@ -148,10 +155,58 @@
/**
* Holds information about dynamic settings.
*/
-public final class Settings {
+public final class Settings implements Watchable, Snappable {
private static final String TAG = "PackageSettings";
/**
+ * Cached snapshot
+ */
+ private volatile Settings mSnapshot = null;
+
+ /**
+ * Watchable machinery
+ */
+ private final WatchableImpl mWatchable = new WatchableImpl();
+
+ /**
+ * Ensures an observer is in the list, exactly once. The observer cannot be null. The
+ * function quietly returns if the observer is already in the list.
+ *
+ * @param observer The {@link Watcher} to be notified when the {@link Watchable} changes.
+ */
+ public void registerObserver(@NonNull Watcher observer) {
+ mWatchable.registerObserver(observer);
+ }
+
+ /**
+ * Ensures an observer is not in the list. The observer must not be null. The function
+ * quietly returns if the objserver is not in the list.
+ *
+ * @param observer The {@link Watcher} that should not be in the notification list.
+ */
+ public void unregisterObserver(@NonNull Watcher observer) {
+ mWatchable.unregisterObserver(observer);
+ }
+
+ /**
+ * Invokes {@link Watcher#onChange} on each registered observer. The method can be called
+ * with the {@link Watchable} that generated the event. In a tree of {@link Watchable}s, this
+ * is generally the first (deepest) {@link Watchable} to detect a change.
+ *
+ * @param what The {@link Watchable} that generated the event.
+ */
+ public void dispatchChange(@Nullable Watchable what) {
+ mSnapshot = null;
+ mWatchable.dispatchChange(what);
+ }
+ /**
+ * Notify listeners that this object has changed.
+ */
+ protected void onChanged() {
+ dispatchChange(this);
+ }
+
+ /**
* Current version of the package database. Set it to the latest version in
* the {@link DatabaseVersion} class below to ensure the database upgrade
* doesn't happen repeatedly.
@@ -296,7 +351,7 @@
/** Map from package name to settings */
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
- final ArrayMap<String, PackageSetting> mPackages = new ArrayMap<>();
+ final WatchedArrayMap<String, PackageSetting> mPackages = new WatchedArrayMap<>();
/**
* List of packages that were involved in installing other packages, i.e. are listed
@@ -368,21 +423,21 @@
// The user's preferred activities associated with particular intent
// filters.
- private final SparseArray<PreferredIntentResolver> mPreferredActivities =
- new SparseArray<PreferredIntentResolver>();
+ private final WatchedSparseArray<PreferredIntentResolver>
+ mPreferredActivities = new WatchedSparseArray<>();
// The persistent preferred activities of the user's profile/device owner
// associated with particular intent filters.
- private final SparseArray<PersistentPreferredIntentResolver> mPersistentPreferredActivities =
- new SparseArray<PersistentPreferredIntentResolver>();
+ private final WatchedSparseArray<PersistentPreferredIntentResolver>
+ mPersistentPreferredActivities = new WatchedSparseArray<>();
// For every user, it is used to find to which other users the intent can be forwarded.
- private final SparseArray<CrossProfileIntentResolver> mCrossProfileIntentResolvers =
- new SparseArray<CrossProfileIntentResolver>();
+ private final WatchedSparseArray<CrossProfileIntentResolver>
+ mCrossProfileIntentResolvers = new WatchedSparseArray<>();
final ArrayMap<String, SharedUserSetting> mSharedUsers = new ArrayMap<>();
- private final ArrayList<SettingBase> mAppIds = new ArrayList<>();
- private final SparseArray<SettingBase> mOtherAppIds = new SparseArray<>();
+ private final ArrayList<SettingBase> mAppIds;
+ private final SparseArray<SettingBase> mOtherAppIds;
// For reading/writing settings file.
private final ArrayList<Signature> mPastSignatures =
@@ -415,17 +470,30 @@
private final File mSystemDir;
- public final KeySetManagerService mKeySetManagerService = new KeySetManagerService(mPackages);
+ public final KeySetManagerService mKeySetManagerService =
+ new KeySetManagerService(mPackages.untrackedMap());
/** Settings and other information about permissions */
final LegacyPermissionSettings mPermissions;
private final LegacyPermissionDataProvider mPermissionDataProvider;
+ /**
+ * The observer that watches for changes from array members
+ */
+ private final Watcher mObserver = new Watcher() {
+ @Override
+ public void onChange(@Nullable Watchable what) {
+ Settings.this.dispatchChange(what);
+ }
+ };
+
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
public Settings(Map<String, PackageSetting> pkgSettings) {
mLock = new Object();
mPackages.putAll(pkgSettings);
+ mAppIds = new ArrayList<>();
+ mOtherAppIds = new SparseArray<>();
mSystemDir = null;
mPermissions = null;
mRuntimePermissionsPersistence = null;
@@ -436,11 +504,17 @@
mStoppedPackagesFilename = null;
mBackupStoppedPackagesFilename = null;
mKernelMappingFilename = null;
+ mPackages.registerObserver(mObserver);
+ mPreferredActivities.registerObserver(mObserver);
+ mPersistentPreferredActivities.registerObserver(mObserver);
+ mCrossProfileIntentResolvers.registerObserver(mObserver);
}
Settings(File dataDir, RuntimePermissionsPersistence runtimePermissionsPersistence,
LegacyPermissionDataProvider permissionDataProvider, Object lock) {
mLock = lock;
+ mAppIds = new ArrayList<>();
+ mOtherAppIds = new SparseArray<>();
mPermissions = new LegacyPermissionSettings(lock);
mRuntimePermissionsPersistence = new RuntimePermissionPersistence(
runtimePermissionsPersistence);
@@ -463,18 +537,91 @@
// Deprecated: Needed for migration
mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
+ mPackages.registerObserver(mObserver);
+ mPreferredActivities.registerObserver(mObserver);
+ mPersistentPreferredActivities.registerObserver(mObserver);
+ mCrossProfileIntentResolvers.registerObserver(mObserver);
}
- private static void invalidatePackageCache() {
+ /**
+ * A copy constructor used in snapshot(). Attributes that are supposed to be
+ * immutable in the PackageManagerService application are referenced. Attributes that
+ * are changed by PackageManagerService APIs are deep-copied
+ */
+ private Settings(Settings r) {
+ final int mPackagesSize = r.mPackages.size();
+ mPackages.putAll(r.mPackages);
+
+ // The following assignments satisfy Java requirements but are not
+ // needed by the read-only methods. Note especially that the lock
+ // is not required because this clone is meant to support lock-free
+ // read-only methods.
+ mLock = null;
+ mRuntimePermissionsPersistence = r.mRuntimePermissionsPersistence;
+ mSettingsFilename = null;
+ mBackupSettingsFilename = null;
+ mPackageListFilename = null;
+ mStoppedPackagesFilename = null;
+ mBackupStoppedPackagesFilename = null;
+ mKernelMappingFilename = null;
+
+ mInstallerPackages.addAll(r.mInstallerPackages);
+ mKernelMapping.putAll(r.mKernelMapping);
+ mDisabledSysPackages.putAll(r.mDisabledSysPackages);
+ Snapshots.copy(mBlockUninstallPackages, r.mBlockUninstallPackages);
+ mRestoredIntentFilterVerifications.putAll(r.mRestoredIntentFilterVerifications);
+ mVersion.putAll(r.mVersion);
+ mVerifierDeviceIdentity = r.mVerifierDeviceIdentity;
+ WatchedSparseArray.snapshot(
+ mPreferredActivities, r.mPreferredActivities);
+ WatchedSparseArray.snapshot(
+ mPersistentPreferredActivities, r.mPersistentPreferredActivities);
+ WatchedSparseArray.snapshot(
+ mCrossProfileIntentResolvers, r.mCrossProfileIntentResolvers);
+ mSharedUsers.putAll(r.mSharedUsers);
+ mAppIds = new ArrayList<>(r.mAppIds);
+ mOtherAppIds = r.mOtherAppIds.clone();
+ mPastSignatures.addAll(r.mPastSignatures);
+ mKeySetRefs.putAll(r.mKeySetRefs);
+ mRenamedPackages.putAll(r.mRenamedPackages);
+ Snapshots.copy(mDefaultBrowserApp, r.mDefaultBrowserApp);
+ Snapshots.snapshot(mNextAppLinkGeneration, r.mNextAppLinkGeneration);
+ // mReadMessages
+ mPendingPackages.addAll(r.mPendingPackages);
+ mSystemDir = null;
+ // mKeySetManagerService;
+ mPermissions = r.mPermissions;
+ mPermissionDataProvider = r.mPermissionDataProvider;
+
+ // Do not register any Watchables
+ }
+
+ /**
+ * Return a snapshot. If the cached snapshot is null, build a new one. The logic in
+ * the function ensures that this function returns a valid snapshot even if a race
+ * condition causes the cached snapshot to be cleared asynchronously to this method.
+ */
+ public Settings snapshot() {
+ Settings s = mSnapshot;
+ if (s == null) {
+ s = new Settings(this);
+ s.mWatchable.seal();
+ mSnapshot = s;
+ }
+ return s;
+ }
+
+ private void invalidatePackageCache() {
PackageManagerService.invalidatePackageInfoCache();
ChangeIdStateCache.invalidate();
+ onChanged();
}
PackageSetting getPackageLPr(String pkgName) {
return mPackages.get(pkgName);
}
- ArrayMap<String, PackageSetting> getPackagesLocked() {
+ WatchedArrayMap<String, PackageSetting> getPackagesLocked() {
return mPackages;
}
@@ -5558,6 +5705,7 @@
/** This method takes a specific user id as well as UserHandle.USER_ALL. */
void clearPackagePreferredActivities(String packageName,
@NonNull SparseBooleanArray outUserChanged, int userId) {
+ boolean changed = false;
ArrayList<PreferredActivity> removed = null;
for (int i = 0; i < mPreferredActivities.size(); i++) {
final int thisUserId = mPreferredActivities.keyAt(i);
@@ -5585,8 +5733,12 @@
pir.removeFilter(pa);
}
outUserChanged.put(thisUserId, true);
+ changed = true;
}
}
+ if (changed) {
+ onChanged();
+ }
}
boolean clearPackagePersistentPreferredActivities(String packageName, int userId) {
@@ -5617,6 +5769,9 @@
changed = true;
}
}
+ if (changed) {
+ onChanged();
+ }
return changed;
}
@@ -5649,6 +5804,7 @@
changed.add(mPreferredActivities.keyAt(i));
}
}
+ onChanged();
return changed;
}
diff --git a/services/core/java/com/android/server/pm/SharedUserSetting.java b/services/core/java/com/android/server/pm/SharedUserSetting.java
index 6103f558..9b1c08d 100644
--- a/services/core/java/com/android/server/pm/SharedUserSetting.java
+++ b/services/core/java/com/android/server/pm/SharedUserSetting.java
@@ -93,6 +93,7 @@
proc.addStateFrom(newProc);
}
}
+ onChanged();
}
}
@@ -117,6 +118,7 @@
}
// recalculate processes.
updateProcesses();
+ onChanged();
return true;
}
@@ -129,6 +131,7 @@
if (packages.add(packageSetting)) {
setFlags(this.pkgFlags | packageSetting.pkgFlags);
setPrivateFlags(this.pkgPrivateFlags | packageSetting.pkgPrivateFlags);
+ onChanged();
}
if (packageSetting.pkg != null) {
addProcesses(packageSetting.pkg.getProcesses());
@@ -169,6 +172,7 @@
}
if (ps.pkg.getTargetSdkVersion() < seInfoTargetSdkVersion) {
seInfoTargetSdkVersion = ps.pkg.getTargetSdkVersion();
+ onChanged();
}
}
@@ -179,6 +183,7 @@
final boolean isPrivileged = isPrivileged() | ps.pkg.isPrivileged();
ps.getPkgState().setOverrideSeInfo(SELinuxMMAC.getSeInfo(ps.pkg, isPrivileged,
seInfoTargetSdkVersion));
+ onChanged();
}
}
@@ -234,6 +239,7 @@
} else {
this.processes = null;
}
+ onChanged();
return this;
}
}
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 56fb5e8..95ce140 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -2739,7 +2739,8 @@
// Default launcher from role manager.
final long startGetHomeRoleHoldersAsUser = getStatStartTime();
- final String defaultLauncher = injectGetHomeRoleHolderAsUser(userId);
+ final String defaultLauncher = injectGetHomeRoleHolderAsUser(
+ getParentOrSelfUserId(userId));
logDurationStat(Stats.GET_DEFAULT_HOME, startGetHomeRoleHoldersAsUser);
if (defaultLauncher != null) {
@@ -4694,7 +4695,7 @@
final List<ResolveInfo> allHomeCandidates = new ArrayList<>();
// Default launcher from package manager.
final ComponentName defaultLauncher = mPackageManagerInternal
- .getHomeActivitiesAsUser(allHomeCandidates, mUserId);
+ .getHomeActivitiesAsUser(allHomeCandidates, getParentOrSelfUserId(mUserId));
getOutPrintWriter().println("Launcher: " + defaultLauncher);
}
}
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 222874d..545567c 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -32,6 +32,7 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageInstaller.SessionInfo;
+import android.content.pm.PackageInstaller.SessionInfo.StagedSessionErrorCode;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageParser.PackageParserException;
@@ -82,6 +83,7 @@
import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
+import java.util.function.Predicate;
import java.util.function.Supplier;
/**
@@ -102,7 +104,7 @@
private String mFailureReason;
@GuardedBy("mStagedSessions")
- private final SparseArray<PackageInstallerSession> mStagedSessions = new SparseArray<>();
+ private final SparseArray<StagedSession> mStagedSessions = new SparseArray<>();
@GuardedBy("mFailedPackageNames")
private final List<String> mFailedPackageNames = new ArrayList<>();
@@ -111,6 +113,35 @@
@GuardedBy("mSuccessfulStagedSessionIds")
private final List<Integer> mSuccessfulStagedSessionIds = new ArrayList<>();
+ interface StagedSession {
+ boolean isMultiPackage();
+ boolean isApexSession();
+ boolean isCommitted();
+ boolean isInTerminalState();
+ boolean isDestroyed();
+ boolean isSessionReady();
+ boolean isSessionApplied();
+ boolean isSessionFailed();
+ List<StagedSession> getChildSessions();
+ String getPackageName();
+ int getParentSessionId();
+ int sessionId();
+ PackageInstaller.SessionParams sessionParams();
+ boolean sessionContains(Predicate<StagedSession> filter);
+ boolean containsApkSession();
+ boolean containsApexSession();
+ void setSessionReady();
+ void setSessionFailed(@StagedSessionErrorCode int errorCode, String errorMessage);
+ void setSessionApplied();
+ void installSession(IntentSender statusReceiver);
+ boolean hasParentSessionId();
+ long getCommittedMillis();
+ void abandon();
+ boolean notifyStartPreRebootVerification();
+ void notifyEndPreRebootVerification();
+ void verifySession();
+ }
+
StagingManager(Context context, Supplier<PackageParser2> packageParserSupplier) {
mContext = context;
mPackageParserSupplier = packageParserSupplier;
@@ -213,20 +244,20 @@
+ " compatible with the one currently installed on device");
}
- private List<PackageInfo> submitSessionToApexService(@NonNull PackageInstallerSession session,
+ private List<PackageInfo> submitSessionToApexService(@NonNull StagedSession session,
int rollbackId) throws PackageManagerException {
final IntArray childSessionIds = new IntArray();
if (session.isMultiPackage()) {
- for (PackageInstallerSession s : session.getChildSessions()) {
+ for (StagedSession s : session.getChildSessions()) {
if (s.isApexSession()) {
- childSessionIds.add(s.sessionId);
+ childSessionIds.add(s.sessionId());
}
}
}
ApexSessionParams apexSessionParams = new ApexSessionParams();
- apexSessionParams.sessionId = session.sessionId;
+ apexSessionParams.sessionId = session.sessionId();
apexSessionParams.childSessionIds = childSessionIds.toArray();
- if (session.params.installReason == PackageManager.INSTALL_REASON_ROLLBACK) {
+ if (session.sessionParams().installReason == PackageManager.INSTALL_REASON_ROLLBACK) {
apexSessionParams.isRollback = true;
apexSessionParams.rollbackId = rollbackId;
} else {
@@ -269,7 +300,7 @@
result.add(packageInfo);
apexPackageNames.add(packageInfo.packageName);
}
- Slog.d(TAG, "Session " + session.sessionId + " has following APEX packages: "
+ Slog.d(TAG, "Session " + session.sessionId() + " has following APEX packages: "
+ apexPackageNames);
return result;
}
@@ -288,22 +319,23 @@
"Could not find rollback id for commit session: " + sessionId);
}
- private void checkRequiredVersionCode(final PackageInstallerSession session,
+ private void checkRequiredVersionCode(final StagedSession session,
final PackageInfo activePackage) throws PackageManagerException {
- if (session.params.requiredInstalledVersionCode == PackageManager.VERSION_CODE_HIGHEST) {
+ if (session.sessionParams().requiredInstalledVersionCode
+ == PackageManager.VERSION_CODE_HIGHEST) {
return;
}
final long activeVersion = activePackage.applicationInfo.longVersionCode;
- if (activeVersion != session.params.requiredInstalledVersionCode) {
+ if (activeVersion != session.sessionParams().requiredInstalledVersionCode) {
throw new PackageManagerException(
SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
"Installed version of APEX package " + activePackage.packageName
+ " does not match required. Active version: " + activeVersion
- + " required: " + session.params.requiredInstalledVersionCode);
+ + " required: " + session.sessionParams().requiredInstalledVersionCode);
}
}
- private void checkDowngrade(final PackageInstallerSession session,
+ private void checkDowngrade(final StagedSession session,
final PackageInfo activePackage, final PackageInfo newPackage)
throws PackageManagerException {
final long activeVersion = activePackage.applicationInfo.longVersionCode;
@@ -311,7 +343,7 @@
final boolean isAppDebuggable = (activePackage.applicationInfo.flags
& ApplicationInfo.FLAG_DEBUGGABLE) != 0;
final boolean allowsDowngrade = PackageManagerServiceUtils.isDowngradePermitted(
- session.params.installFlags, isAppDebuggable);
+ session.sessionParams().installFlags, isAppDebuggable);
if (activeVersion > newVersionCode && !allowsDowngrade) {
throw new PackageManagerException(
SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
@@ -363,10 +395,10 @@
/**
* Utility function for extracting apex sessions out of multi-package/single session.
*/
- private List<PackageInstallerSession> extractApexSessions(PackageInstallerSession session) {
- List<PackageInstallerSession> apexSessions = new ArrayList<>();
+ private List<StagedSession> extractApexSessions(StagedSession session) {
+ List<StagedSession> apexSessions = new ArrayList<>();
if (session.isMultiPackage()) {
- for (PackageInstallerSession s : session.getChildSessions()) {
+ for (StagedSession s : session.getChildSessions()) {
if (s.containsApexSession()) {
apexSessions.add(s);
}
@@ -383,14 +415,14 @@
*
* @throws PackageManagerException if any apk-in-apex failed to install
*/
- private void checkInstallationOfApkInApexSuccessful(PackageInstallerSession session)
+ private void checkInstallationOfApkInApexSuccessful(StagedSession session)
throws PackageManagerException {
- final List<PackageInstallerSession> apexSessions = extractApexSessions(session);
+ final List<StagedSession> apexSessions = extractApexSessions(session);
if (apexSessions.isEmpty()) {
return;
}
- for (PackageInstallerSession apexSession : apexSessions) {
+ for (StagedSession apexSession : apexSessions) {
String packageName = apexSession.getPackageName();
if (!mApexManager.isApkInApexInstallSuccess(packageName)) {
throw new PackageManagerException(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
@@ -405,16 +437,16 @@
* directory directly by PackageManager, as such, RollbackManager need to handle their data
* separately here.
*/
- private void snapshotAndRestoreForApexSession(PackageInstallerSession session) {
+ private void snapshotAndRestoreForApexSession(StagedSession session) {
boolean doSnapshotOrRestore =
- (session.params.installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0
- || session.params.installReason == PackageManager.INSTALL_REASON_ROLLBACK;
+ (session.sessionParams().installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0
+ || session.sessionParams().installReason == PackageManager.INSTALL_REASON_ROLLBACK;
if (!doSnapshotOrRestore) {
return;
}
// Find all the apex sessions that needs processing
- final List<PackageInstallerSession> apexSessions = extractApexSessions(session);
+ final List<StagedSession> apexSessions = extractApexSessions(session);
if (apexSessions.isEmpty()) {
return;
}
@@ -475,7 +507,7 @@
* session package names.
* Logging needs to wait until the ACTION_BOOT_COMPLETED broadcast is sent.
*/
- private void prepareForLoggingApexdRevert(@NonNull PackageInstallerSession session,
+ private void prepareForLoggingApexdRevert(@NonNull StagedSession session,
@NonNull String nativeFailureReason) {
synchronized (mFailedPackageNames) {
mNativeFailureReason = nativeFailureReason;
@@ -485,15 +517,15 @@
}
}
- private void resumeSession(@NonNull PackageInstallerSession session)
+ private void resumeSession(@NonNull StagedSession session)
throws PackageManagerException {
- Slog.d(TAG, "Resuming session " + session.sessionId);
+ Slog.d(TAG, "Resuming session " + session.sessionId());
final boolean hasApex = session.containsApexSession();
ApexSessionInfo apexSessionInfo = null;
if (hasApex) {
// Check with apexservice whether the apex packages have been activated.
- apexSessionInfo = mApexManager.getStagedSessionInfo(session.sessionId);
+ apexSessionInfo = mApexManager.getStagedSessionInfo(session.sessionId());
// Prepare for logging a native crash during boot, if one occurred.
if (apexSessionInfo != null && !TextUtils.isEmpty(
@@ -506,7 +538,7 @@
// pre-reboot verification, perhaps because the device rebooted in the meantime.
// Greedily re-trigger the pre-reboot verification. We want to avoid marking it as
// failed when not in checkpoint mode, hence it is being processed separately.
- Slog.d(TAG, "Found pending staged session " + session.sessionId + " still to "
+ Slog.d(TAG, "Found pending staged session " + session.sessionId() + " still to "
+ "be verified, resuming pre-reboot verification");
mPreRebootVerificationHandler.startPreRebootVerification(session);
return;
@@ -523,21 +555,21 @@
// mode. If not, we fail all sessions.
if (supportsCheckpoint() && !needsCheckpoint()) {
String revertMsg = "Reverting back to safe state. Marking "
- + session.sessionId + " as failed.";
+ + session.sessionId() + " as failed.";
final String reasonForRevert = getReasonForRevert();
if (!TextUtils.isEmpty(reasonForRevert)) {
revertMsg += " Reason for revert: " + reasonForRevert;
}
Slog.d(TAG, revertMsg);
- session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_UNKNOWN, revertMsg);
+ session.setSessionFailed(SessionInfo.STAGED_SESSION_UNKNOWN, revertMsg);
return;
}
} catch (RemoteException e) {
// Cannot continue staged install without knowing if fs-checkpoint is supported
Slog.e(TAG, "Checkpoint support unknown. Aborting staged install for session "
- + session.sessionId, e);
+ + session.sessionId(), e);
// TODO: Mark all staged sessions together and reboot only once
- session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_UNKNOWN,
+ session.setSessionFailed(SessionInfo.STAGED_SESSION_UNKNOWN,
"Checkpoint support unknown. Aborting staged install.");
if (hasApex) {
mApexManager.revertActiveSessions();
@@ -568,7 +600,7 @@
// Apexd did not apply the session for some unknown reason. There is no
// guarantee that apexd will install it next time. Safer to proactively mark
// it as failed.
- final String errorMsg = "Staged session " + session.sessionId + "at boot "
+ final String errorMsg = "Staged session " + session.sessionId() + "at boot "
+ "didn't activate nor fail. Marking it as failed anyway.";
throw new PackageManagerException(
SessionInfo.STAGED_SESSION_ACTIVATION_FAILED, errorMsg);
@@ -580,38 +612,38 @@
checkInstallationOfApkInApexSuccessful(session);
checkDuplicateApkInApex(session);
snapshotAndRestoreForApexSession(session);
- Slog.i(TAG, "APEX packages in session " + session.sessionId
+ Slog.i(TAG, "APEX packages in session " + session.sessionId()
+ " were successfully activated. Proceeding with APK packages, if any");
}
// The APEX part of the session is activated, proceed with the installation of APKs.
- Slog.d(TAG, "Installing APK packages in session " + session.sessionId);
+ Slog.d(TAG, "Installing APK packages in session " + session.sessionId());
installApksInSession(session);
- Slog.d(TAG, "Marking session " + session.sessionId + " as applied");
- session.setStagedSessionApplied();
+ Slog.d(TAG, "Marking session " + session.sessionId() + " as applied");
+ session.setSessionApplied();
if (hasApex) {
try {
if (supportsCheckpoint()) {
// Store the session ID, which will be marked as successful by ApexManager
// upon boot completion.
synchronized (mSuccessfulStagedSessionIds) {
- mSuccessfulStagedSessionIds.add(session.sessionId);
+ mSuccessfulStagedSessionIds.add(session.sessionId());
}
} else {
// Mark sessions as successful immediately on non-checkpointing devices.
- mApexManager.markStagedSessionSuccessful(session.sessionId);
+ mApexManager.markStagedSessionSuccessful(session.sessionId());
}
} catch (RemoteException e) {
Slog.w(TAG, "Checkpoint support unknown, marking session as successful "
+ "immediately.");
- mApexManager.markStagedSessionSuccessful(session.sessionId);
+ mApexManager.markStagedSessionSuccessful(session.sessionId());
}
}
}
- void onInstallationFailure(PackageInstallerSession session, PackageManagerException e) {
- session.setStagedSessionFailed(e.error, e.getMessage());
- abortCheckpoint(session.sessionId, e.getMessage());
+ void onInstallationFailure(StagedSession session, PackageManagerException e) {
+ session.setSessionFailed(e.error, e.getMessage());
+ abortCheckpoint(session.sessionId(), e.getMessage());
// If checkpoint is not supported, we have to handle failure for one staged session.
if (!session.containsApexSession()) {
@@ -641,26 +673,26 @@
/**
* Throws a PackageManagerException if there are duplicate packages in apk and apk-in-apex.
*/
- private void checkDuplicateApkInApex(@NonNull PackageInstallerSession session)
+ private void checkDuplicateApkInApex(@NonNull StagedSession session)
throws PackageManagerException {
if (!session.isMultiPackage()) {
return;
}
final Set<String> apkNames = new ArraySet<>();
- for (PackageInstallerSession s : session.getChildSessions()) {
+ for (StagedSession s : session.getChildSessions()) {
if (!s.isApexSession()) {
apkNames.add(s.getPackageName());
}
}
- final List<PackageInstallerSession> apexSessions = extractApexSessions(session);
- for (PackageInstallerSession apexSession : apexSessions) {
+ final List<StagedSession> apexSessions = extractApexSessions(session);
+ for (StagedSession apexSession : apexSessions) {
String packageName = apexSession.getPackageName();
for (String apkInApex : mApexManager.getApksInApex(packageName)) {
if (!apkNames.add(apkInApex)) {
throw new PackageManagerException(
SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
"Package: " + packageName + " in session: "
- + apexSession.sessionId + " has duplicate apk-in-apex: "
+ + apexSession.sessionId() + " has duplicate apk-in-apex: "
+ apkInApex, null);
}
@@ -668,14 +700,14 @@
}
}
- private void installApksInSession(PackageInstallerSession session)
+ private void installApksInSession(StagedSession session)
throws PackageManagerException {
if (!session.containsApkSession()) {
return;
}
final LocalIntentReceiverSync receiver = new LocalIntentReceiverSync();
- session.installStagedSession(receiver.getIntentSender());
+ session.installSession(receiver.getIntentSender());
final Intent result = receiver.getResult();
final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
PackageInstaller.STATUS_FAILURE);
@@ -683,31 +715,31 @@
final String errorMessage = result.getStringExtra(
PackageInstaller.EXTRA_STATUS_MESSAGE);
Slog.e(TAG, "Failure to install APK staged session "
- + session.sessionId + " [" + errorMessage + "]");
+ + session.sessionId() + " [" + errorMessage + "]");
throw new PackageManagerException(
SessionInfo.STAGED_SESSION_ACTIVATION_FAILED, errorMessage);
}
}
- void commitSession(@NonNull PackageInstallerSession session) {
+ void commitSession(@NonNull StagedSession session) {
// Store this parent session which will be used to check overlapping later
createSession(session);
mPreRebootVerificationHandler.startPreRebootVerification(session);
}
- private int getSessionIdForParentOrSelf(PackageInstallerSession session) {
- return session.hasParentSessionId() ? session.getParentSessionId() : session.sessionId;
+ private int getSessionIdForParentOrSelf(StagedSession session) {
+ return session.hasParentSessionId() ? session.getParentSessionId() : session.sessionId();
}
- private PackageInstallerSession getParentSessionOrSelf(PackageInstallerSession session) {
+ private StagedSession getParentSessionOrSelf(StagedSession session) {
return session.hasParentSessionId()
? getStagedSession(session.getParentSessionId())
: session;
}
- private boolean isRollback(PackageInstallerSession session) {
- final PackageInstallerSession root = getParentSessionOrSelf(session);
- return root.params.installReason == PackageManager.INSTALL_REASON_ROLLBACK;
+ private boolean isRollback(StagedSession session) {
+ final StagedSession root = getParentSessionOrSelf(session);
+ return root.sessionParams().installReason == PackageManager.INSTALL_REASON_ROLLBACK;
}
/**
@@ -722,7 +754,7 @@
* @throws PackageManagerException if session fails the check
*/
@VisibleForTesting
- void checkNonOverlappingWithStagedSessions(@NonNull PackageInstallerSession session)
+ void checkNonOverlappingWithStagedSessions(@NonNull StagedSession session)
throws PackageManagerException {
if (session.isMultiPackage()) {
// We cannot say a parent session overlaps until we process its children
@@ -732,7 +764,7 @@
String packageName = session.getPackageName();
if (packageName == null) {
throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
- "Cannot stage session " + session.sessionId + " with package name null");
+ "Cannot stage session " + session.sessionId() + " with package name null");
}
boolean supportsCheckpoint = ((StorageManager) mContext.getSystemService(
@@ -742,9 +774,9 @@
synchronized (mStagedSessions) {
for (int i = 0; i < mStagedSessions.size(); i++) {
- final PackageInstallerSession stagedSession = mStagedSessions.valueAt(i);
+ final StagedSession stagedSession = mStagedSessions.valueAt(i);
if (stagedSession.hasParentSessionId() || !stagedSession.isCommitted()
- || stagedSession.isStagedAndInTerminalState()
+ || stagedSession.isInTerminalState()
|| stagedSession.isDestroyed()) {
continue;
}
@@ -759,8 +791,8 @@
// From here on, stagedSession is a parent active staged session
// Check if session is one of the active sessions
- if (getSessionIdForParentOrSelf(session) == stagedSession.sessionId) {
- Slog.w(TAG, "Session " + session.sessionId + " is already staged");
+ if (getSessionIdForParentOrSelf(session) == stagedSession.sessionId()) {
+ Slog.w(TAG, "Session " + session.sessionId() + " is already staged");
continue;
}
@@ -769,24 +801,25 @@
if (isRollback) {
// If the new session is a rollback, then it gets priority. The existing
// session is failed to unblock rollback.
- final PackageInstallerSession root = stagedSession;
+ final StagedSession root = stagedSession;
if (!ensureActiveApexSessionIsAborted(root)) {
- Slog.e(TAG, "Failed to abort apex session " + root.sessionId);
+ Slog.e(TAG, "Failed to abort apex session " + root.sessionId());
// Safe to ignore active apex session abort failure since session
// will be marked failed on next step and staging directory for session
// will be deleted.
}
- root.setStagedSessionFailed(
+ root.setSessionFailed(
SessionInfo.STAGED_SESSION_CONFLICT,
- "Session was blocking rollback session: " + session.sessionId);
- Slog.i(TAG, "Session " + root.sessionId + " is marked failed due to "
- + "blocking rollback session: " + session.sessionId);
+ "Session was blocking rollback session: " + session.sessionId());
+ Slog.i(TAG, "Session " + root.sessionId() + " is marked failed due to "
+ + "blocking rollback session: " + session.sessionId());
} else {
throw new PackageManagerException(
SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
"Package: " + session.getPackageName() + " in session: "
- + session.sessionId + " has been staged already by session:"
- + " " + stagedSession.sessionId, null);
+ + session.sessionId()
+ + " has been staged already by session: "
+ + stagedSession.sessionId(), null);
}
}
@@ -803,24 +836,24 @@
}
@VisibleForTesting
- void createSession(@NonNull PackageInstallerSession sessionInfo) {
+ void createSession(@NonNull StagedSession sessionInfo) {
synchronized (mStagedSessions) {
- mStagedSessions.append(sessionInfo.sessionId, sessionInfo);
+ mStagedSessions.append(sessionInfo.sessionId(), sessionInfo);
}
}
- void abortSession(@NonNull PackageInstallerSession session) {
+ void abortSession(@NonNull StagedSession session) {
synchronized (mStagedSessions) {
- mStagedSessions.remove(session.sessionId);
+ mStagedSessions.remove(session.sessionId());
}
}
/**
* <p>Abort committed staged session
*/
- void abortCommittedSession(@NonNull PackageInstallerSession session) {
- int sessionId = session.sessionId;
- if (session.isStagedAndInTerminalState()) {
+ void abortCommittedSession(@NonNull StagedSession session) {
+ int sessionId = session.sessionId();
+ if (session.isInTerminalState()) {
Slog.w(TAG, "Cannot abort session in final state: " + sessionId);
return;
}
@@ -834,12 +867,12 @@
}
// A session could be marked ready once its pre-reboot verification ends
- if (session.isStagedSessionReady()) {
+ if (session.isSessionReady()) {
if (!ensureActiveApexSessionIsAborted(session)) {
// Failed to ensure apex session is aborted, so it can still be staged. We can still
// safely cleanup the staged session since pre-reboot verification is complete.
// Also, cleaning up the stageDir prevents the apex from being activated.
- Slog.e(TAG, "Failed to abort apex session " + session.sessionId);
+ Slog.e(TAG, "Failed to abort apex session " + session.sessionId());
}
}
@@ -853,15 +886,15 @@
*
* @return returns true if it is ensured that there is no active apex session, otherwise false
*/
- private boolean ensureActiveApexSessionIsAborted(PackageInstallerSession session) {
+ private boolean ensureActiveApexSessionIsAborted(StagedSession session) {
if (!session.containsApexSession()) {
return true;
}
- final ApexSessionInfo apexSession = mApexManager.getStagedSessionInfo(session.sessionId);
+ final ApexSessionInfo apexSession = mApexManager.getStagedSessionInfo(session.sessionId());
if (apexSession == null || isApexSessionFinalized(apexSession)) {
return true;
}
- return mApexManager.abortStagedSession(session.sessionId);
+ return mApexManager.abortStagedSession(session.sessionId());
}
private boolean isApexSessionFinalized(ApexSessionInfo session) {
@@ -878,7 +911,7 @@
|| apexSessionInfo.isRevertFailed;
}
- void restoreSession(@NonNull PackageInstallerSession session, boolean isDeviceUpgrading) {
+ void restoreSession(@NonNull StagedSession session, boolean isDeviceUpgrading) {
if (session.hasParentSessionId()) {
// Only parent sessions can be restored
return;
@@ -887,16 +920,16 @@
createSession(session);
// The preconditions used during pre-reboot verification might have changed when device
// is upgrading. Updated staged sessions to activation failed before we resume the session.
- PackageInstallerSession sessionToResume = session;
- if (isDeviceUpgrading && !sessionToResume.isStagedAndInTerminalState()) {
- sessionToResume.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
+ StagedSession sessionToResume = session;
+ if (isDeviceUpgrading && !sessionToResume.isInTerminalState()) {
+ sessionToResume.setSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
"Build fingerprint has changed");
return;
}
checkStateAndResume(sessionToResume);
}
- private void checkStateAndResume(@NonNull PackageInstallerSession session) {
+ private void checkStateAndResume(@NonNull StagedSession session) {
// Do not resume session if boot completed already
if (SystemProperties.getBoolean("sys.boot_completed", false)) {
return;
@@ -907,7 +940,7 @@
return;
}
// Check the state of the session and decide what to do next.
- if (session.isStagedSessionFailed() || session.isStagedSessionApplied()) {
+ if (session.isSessionFailed() || session.isSessionApplied()) {
// Final states, nothing to do.
return;
}
@@ -916,7 +949,7 @@
session.abandon();
return;
}
- if (!session.isStagedSessionReady()) {
+ if (!session.isSessionReady()) {
// The framework got restarted before the pre-reboot verification could complete,
// restart the verification.
mPreRebootVerificationHandler.startPreRebootVerification(session);
@@ -998,8 +1031,8 @@
}
}
- private PackageInstallerSession getStagedSession(int sessionId) {
- PackageInstallerSession session;
+ private StagedSession getStagedSession(int sessionId) {
+ StagedSession session;
synchronized (mStagedSessions) {
session = mStagedSessions.get(sessionId);
}
@@ -1009,20 +1042,20 @@
// TODO(b/136257624): Temporary API to let PMS communicate with StagingManager. When all
// verification logic is extracted out of StagingManager into PMS, we can remove
// this.
- void notifyVerificationComplete(PackageInstallerSession session) {
+ void notifyVerificationComplete(StagedSession session) {
mPreRebootVerificationHandler.onPreRebootVerificationComplete(session);
}
// TODO(b/136257624): Temporary API to let PMS communicate with StagingManager. When all
// verification logic is extracted out of StagingManager into PMS, we can remove
// this.
- void notifyPreRebootVerification_Apk_Complete(@NonNull PackageInstallerSession session) {
+ void notifyPreRebootVerification_Apk_Complete(@NonNull StagedSession session) {
mPreRebootVerificationHandler.notifyPreRebootVerification_Apk_Complete(session);
}
private final class PreRebootVerificationHandler extends Handler {
// Hold sessions before handler gets ready to do the verification.
- private List<PackageInstallerSession> mPendingSessions;
+ private List<StagedSession> mPendingSessions;
private boolean mIsReady;
PreRebootVerificationHandler(Looper looper) {
@@ -1052,8 +1085,8 @@
public void handleMessage(Message msg) {
final int sessionId = msg.arg1;
final int rollbackId = msg.arg2;
- final PackageInstallerSession session = (PackageInstallerSession) msg.obj;
- if (session.isDestroyed() || session.isStagedSessionFailed()) {
+ final StagedSession session = (StagedSession) msg.obj;
+ if (session.isDestroyed() || session.isSessionFailed()) {
// No point in running verification on a destroyed/failed session
onPreRebootVerificationComplete(session);
return;
@@ -1086,7 +1119,7 @@
mIsReady = true;
if (mPendingSessions != null) {
for (int i = 0; i < mPendingSessions.size(); i++) {
- PackageInstallerSession session = mPendingSessions.get(i);
+ StagedSession session = mPendingSessions.get(i);
startPreRebootVerification(session);
}
mPendingSessions = null;
@@ -1095,7 +1128,7 @@
// Method for starting the pre-reboot verification
private synchronized void startPreRebootVerification(
- @NonNull PackageInstallerSession session) {
+ @NonNull StagedSession session) {
if (!mIsReady) {
if (mPendingSessions == null) {
mPendingSessions = new ArrayList<>();
@@ -1104,47 +1137,47 @@
return;
}
- if (session.notifyStagedStartPreRebootVerification()) {
- int sessionId = session.sessionId;
+ if (session.notifyStartPreRebootVerification()) {
+ int sessionId = session.sessionId();
Slog.d(TAG, "Starting preRebootVerification for session " + sessionId);
obtainMessage(MSG_PRE_REBOOT_VERIFICATION_START, sessionId, -1, session)
.sendToTarget();
}
}
- private void onPreRebootVerificationFailure(PackageInstallerSession session,
+ private void onPreRebootVerificationFailure(StagedSession session,
@SessionInfo.StagedSessionErrorCode int errorCode, String errorMessage) {
if (!ensureActiveApexSessionIsAborted(session)) {
- Slog.e(TAG, "Failed to abort apex session " + session.sessionId);
+ Slog.e(TAG, "Failed to abort apex session " + session.sessionId());
// Safe to ignore active apex session abortion failure since session will be marked
// failed on next step and staging directory for session will be deleted.
}
- session.setStagedSessionFailed(errorCode, errorMessage);
+ session.setSessionFailed(errorCode, errorMessage);
onPreRebootVerificationComplete(session);
}
// Things to do when pre-reboot verification completes for a particular sessionId
- private void onPreRebootVerificationComplete(PackageInstallerSession session) {
- int sessionId = session.sessionId;
+ private void onPreRebootVerificationComplete(StagedSession session) {
+ int sessionId = session.sessionId();
Slog.d(TAG, "Stopping preRebootVerification for session " + sessionId);
- session.notifyStagedEndPreRebootVerification();
+ session.notifyEndPreRebootVerification();
}
private void notifyPreRebootVerification_Start_Complete(
- @NonNull PackageInstallerSession session, int rollbackId) {
- obtainMessage(MSG_PRE_REBOOT_VERIFICATION_APEX, session.sessionId, rollbackId, session)
- .sendToTarget();
+ @NonNull StagedSession session, int rollbackId) {
+ obtainMessage(MSG_PRE_REBOOT_VERIFICATION_APEX, session.sessionId(), rollbackId,
+ session).sendToTarget();
}
private void notifyPreRebootVerification_Apex_Complete(
- @NonNull PackageInstallerSession session) {
- obtainMessage(MSG_PRE_REBOOT_VERIFICATION_APK, session.sessionId, -1, session)
+ @NonNull StagedSession session) {
+ obtainMessage(MSG_PRE_REBOOT_VERIFICATION_APK, session.sessionId(), -1, session)
.sendToTarget();
}
private void notifyPreRebootVerification_Apk_Complete(
- @NonNull PackageInstallerSession session) {
- obtainMessage(MSG_PRE_REBOOT_VERIFICATION_END, session.sessionId, -1, session)
+ @NonNull StagedSession session) {
+ obtainMessage(MSG_PRE_REBOOT_VERIFICATION_END, session.sessionId(), -1, session)
.sendToTarget();
}
@@ -1153,10 +1186,10 @@
*
* See {@link PreRebootVerificationHandler} to see all nodes of pre reboot verification
*/
- private void handlePreRebootVerification_Start(@NonNull PackageInstallerSession session) {
+ private void handlePreRebootVerification_Start(@NonNull StagedSession session) {
try {
if (session.isMultiPackage()) {
- for (PackageInstallerSession s : session.getChildSessions()) {
+ for (StagedSession s : session.getChildSessions()) {
checkNonOverlappingWithStagedSessions(s);
}
} else {
@@ -1168,7 +1201,8 @@
}
int rollbackId = -1;
- if ((session.params.installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0) {
+ if ((session.sessionParams().installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK)
+ != 0) {
// If rollback is enabled for this session, we call through to the RollbackManager
// with the list of sessions it must enable rollback for. Note that
// notifyStagedSession is a synchronous operation.
@@ -1177,14 +1211,15 @@
try {
// NOTE: To stay consistent with the non-staged install flow, we don't fail the
// entire install if rollbacks can't be enabled.
- rollbackId = rm.notifyStagedSession(session.sessionId);
+ rollbackId = rm.notifyStagedSession(session.sessionId());
} catch (RuntimeException re) {
Slog.e(TAG, "Failed to notifyStagedSession for session: "
- + session.sessionId, re);
+ + session.sessionId(), re);
}
- } else if (session.params.installReason == PackageManager.INSTALL_REASON_ROLLBACK) {
+ } else if (session.sessionParams().installReason
+ == PackageManager.INSTALL_REASON_ROLLBACK) {
try {
- rollbackId = retrieveRollbackIdForCommitSession(session.sessionId);
+ rollbackId = retrieveRollbackIdForCommitSession(session.sessionId());
} catch (PackageManagerException e) {
onPreRebootVerificationFailure(session, e.error, e.getMessage());
return;
@@ -1203,7 +1238,7 @@
* </ul></p>
*/
private void handlePreRebootVerification_Apex(
- @NonNull PackageInstallerSession session, int rollbackId) {
+ @NonNull StagedSession session, int rollbackId) {
final boolean hasApex = session.containsApexSession();
// APEX checks. For single-package sessions, check if they contain an APEX. For
@@ -1233,12 +1268,12 @@
* {@link PackageManagerService} for verification and it notifies back the result via
* {@link #notifyPreRebootVerification_Apk_Complete}
*/
- private void handlePreRebootVerification_Apk(@NonNull PackageInstallerSession session) {
+ private void handlePreRebootVerification_Apk(@NonNull StagedSession session) {
if (!session.containsApkSession()) {
notifyPreRebootVerification_Apk_Complete(session);
return;
}
- session.verifyStagedSession();
+ session.verifySession();
}
/**
@@ -1248,7 +1283,7 @@
* <li>marks session as ready</li>
* </ul></p>
*/
- private void handlePreRebootVerification_End(@NonNull PackageInstallerSession session) {
+ private void handlePreRebootVerification_End(@NonNull StagedSession session) {
// Before marking the session as ready, start checkpoint service if available
try {
IStorageManager storageManager = PackageHelper.getStorageManager();
@@ -1280,15 +1315,15 @@
// On the other hand, if the order of the calls was inverted (first call apexd, then
// mark session as ready), then if a device gets rebooted right after the call to apexd,
// only apex part of the train will be applied, leaving device in an inconsistent state.
- Slog.d(TAG, "Marking session " + session.sessionId + " as ready");
- session.setStagedSessionReady();
- if (session.isStagedSessionReady()) {
+ Slog.d(TAG, "Marking session " + session.sessionId() + " as ready");
+ session.setSessionReady();
+ if (session.isSessionReady()) {
final boolean hasApex = session.containsApexSession();
if (hasApex) {
try {
- mApexManager.markStagedSessionReady(session.sessionId);
+ mApexManager.markStagedSessionReady(session.sessionId());
} catch (PackageManagerException e) {
- session.setStagedSessionFailed(e.error, e.getMessage());
+ session.setSessionFailed(e.error, e.getMessage());
return;
}
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 225c998..ccbf73c 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -4760,31 +4760,13 @@
final boolean hasParent = user.profileGroupId != user.id
&& user.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID;
if (verbose) {
- final DevicePolicyManagerInternal dpm = getDevicePolicyManagerInternal();
- String deviceOwner = "";
- String profileOwner = "";
- if (dpm != null) {
- final long ident = Binder.clearCallingIdentity();
- try {
- if (dpm.getDeviceOwnerUserId() == user.id) {
- deviceOwner = " (device-owner)";
- }
- if (dpm.getProfileOwnerAsUser(user.id) != null) {
- profileOwner = " (profile-owner)";
- }
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
- pw.printf("%d: id=%d, name=%s, flags=%s%s%s%s%s%s%s%s%s\n", i, user.id,
- user.name,
+ pw.printf("%d: id=%d, name=%s, flags=%s%s%s%s%s%s%s\n", i, user.id, user.name,
UserInfo.flagsToString(user.flags),
hasParent ? " (parentId=" + user.profileGroupId + ")" : "",
running ? " (running)" : "",
user.partial ? " (partial)" : "",
user.preCreated ? " (pre-created)" : "",
user.convertedFromPreCreated ? " (converted)" : "",
- deviceOwner, profileOwner,
current ? " (current)" : "");
} else {
// NOTE: the standard "list users" command is used by integration tests and
@@ -4878,21 +4860,6 @@
if (userInfo.convertedFromPreCreated) {
pw.print(" <converted>");
}
- final DevicePolicyManagerInternal dpm = getDevicePolicyManagerInternal();
- if (dpm != null) {
- final long ident = Binder.clearCallingIdentity();
- try {
- if (dpm.getDeviceOwnerUserId() == userId) {
- pw.print(" <device-owner>");
- }
- if (dpm.getProfileOwnerAsUser(userId) != null) {
- pw.print(" <profile-owner>");
- }
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
-
pw.println();
pw.print(" Type: "); pw.println(userInfo.userType);
pw.print(" Flags: "); pw.print(userInfo.flags); pw.print(" (");
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 1dbf839..2107536f 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -1117,8 +1117,9 @@
mOnPermissionChangeListeners.removeListener(listener);
}
+ @Nullable
@Override
- @Nullable public List<String> getWhitelistedRestrictedPermissions(@NonNull String packageName,
+ public List<String> getAllowlistedRestrictedPermissions(@NonNull String packageName,
@PermissionWhitelistFlags int flags, @UserIdInt int userId) {
Objects.requireNonNull(packageName);
Preconditions.checkFlagsArgument(flags,
@@ -1131,7 +1132,7 @@
if (UserHandle.getCallingUserId() != userId) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.INTERACT_ACROSS_USERS,
- "getWhitelistedRestrictedPermissions for user " + userId);
+ "getAllowlistedRestrictedPermissions for user " + userId);
}
final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
@@ -1217,7 +1218,7 @@
}
@Override
- public boolean addWhitelistedRestrictedPermission(@NonNull String packageName,
+ public boolean addAllowlistedRestrictedPermission(@NonNull String packageName,
@NonNull String permName, @PermissionWhitelistFlags int flags,
@UserIdInt int userId) {
// Other argument checks are done in get/setAllowlistedRestrictedPermissions
@@ -1228,7 +1229,7 @@
}
List<String> permissions =
- getWhitelistedRestrictedPermissions(packageName, flags, userId);
+ getAllowlistedRestrictedPermissions(packageName, flags, userId);
if (permissions == null) {
permissions = new ArrayList<>(1);
}
@@ -1255,14 +1256,14 @@
if (isImmutablyRestrictedPermission && mContext.checkCallingOrSelfPermission(
Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS)
!= PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Cannot modify whitelisting of an immutably "
+ throw new SecurityException("Cannot modify allowlisting of an immutably "
+ "restricted permission: " + permName);
}
return true;
}
@Override
- public boolean removeWhitelistedRestrictedPermission(@NonNull String packageName,
+ public boolean removeAllowlistedRestrictedPermission(@NonNull String packageName,
@NonNull String permName, @PermissionWhitelistFlags int flags,
@UserIdInt int userId) {
// Other argument checks are done in get/setAllowlistedRestrictedPermissions
@@ -1273,7 +1274,7 @@
}
final List<String> permissions =
- getWhitelistedRestrictedPermissions(packageName, flags, userId);
+ getAllowlistedRestrictedPermissions(packageName, flags, userId);
if (permissions != null && permissions.remove(permName)) {
return setAllowlistedRestrictedPermissions(packageName, permissions,
flags, userId);
@@ -1328,20 +1329,20 @@
+ " being installer on record or "
+ Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
}
- final List<String> whitelistedPermissions =
- getWhitelistedRestrictedPermissions(pkg.getPackageName(), flags, userId);
+ final List<String> allowlistedPermissions =
+ getAllowlistedRestrictedPermissions(pkg.getPackageName(), flags, userId);
if (permissions == null || permissions.isEmpty()) {
- if (whitelistedPermissions == null || whitelistedPermissions.isEmpty()) {
+ if (allowlistedPermissions == null || allowlistedPermissions.isEmpty()) {
return true;
}
} else {
// Only the system can add and remove while the installer can only remove.
final int permissionCount = permissions.size();
for (int i = 0; i < permissionCount; i++) {
- if ((whitelistedPermissions == null
- || !whitelistedPermissions.contains(permissions.get(i)))
+ if ((allowlistedPermissions == null
+ || !allowlistedPermissions.contains(permissions.get(i)))
&& !isCallerPrivileged) {
- throw new SecurityException("Adding to upgrade whitelist requires"
+ throw new SecurityException("Adding to upgrade allowlist requires"
+ Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
}
}
@@ -1349,7 +1350,7 @@
if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER) != 0) {
if (!isCallerPrivileged && !isCallerInstallerOnRecord) {
- throw new SecurityException("Modifying installer whitelist requires"
+ throw new SecurityException("Modifying installer allowlist requires"
+ " being installer on record or "
+ Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
}
@@ -1367,8 +1368,8 @@
}
@Override
- public boolean setAutoRevokeWhitelisted(
- @NonNull String packageName, boolean whitelisted, int userId) {
+ public boolean setAutoRevokeExempted(
+ @NonNull String packageName, boolean exempted, int userId) {
Objects.requireNonNull(packageName);
final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
@@ -1378,7 +1379,7 @@
return false;
}
- return setAutoRevokeExemptedInternal(pkg, whitelisted, userId);
+ return setAutoRevokeExemptedInternal(pkg, exempted, userId);
}
private boolean setAutoRevokeExemptedInternal(@NonNull AndroidPackage pkg, boolean exempted,
@@ -1386,7 +1387,7 @@
final int packageUid = UserHandle.getUid(userId, pkg.getUid());
if (mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_AUTO_REVOKE_MANAGED_BY_INSTALLER,
packageUid, pkg.getPackageName()) != MODE_ALLOWED) {
- // Whitelist user set - don't override
+ // Allowlist user set - don't override
return false;
}
@@ -1420,7 +1421,7 @@
}
@Override
- public boolean isAutoRevokeWhitelisted(@NonNull String packageName, int userId) {
+ public boolean isAutoRevokeExempted(@NonNull String packageName, int userId) {
Objects.requireNonNull(packageName);
final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
@@ -2872,7 +2873,7 @@
boolean softRestricted = bp.isSoftRestricted();
// If permission policy is not ready we don't deal with restricted
- // permissions as the policy may whitelist some permissions. Once
+ // permissions as the policy may allowlist some permissions. Once
// the policy is initialized we would re-evaluate permissions.
final boolean permissionPolicyInitialized =
isPermissionPolicyInitialized.get(userId);
@@ -3576,9 +3577,9 @@
if (isInSystemConfigPrivAppPermissions(pkg, permissionName)) {
return true;
}
- // Only enforce whitelist this on boot
+ // Only enforce the allowlist on boot
if (!mSystemReady
- // Updated system apps do not need to be whitelisted
+ // Updated system apps do not need to be allowlisted
&& !isUpdatedSystemApp) {
final ApexManager apexManager = ApexManager.getInstance();
final String packageName = pkg.getPackageName();
@@ -3587,7 +3588,7 @@
final boolean isInUpdatedApex = containingApexPackageName != null
&& !apexManager.isFactory(apexManager.getPackageInfo(containingApexPackageName,
MATCH_ACTIVE_PACKAGE));
- // Apps that are in updated apexs' do not need to be whitelisted
+ // Apps that are in updated apexs' do not need to be allowlisted
if (!isInUpdatedApex) {
// it's only a reportable violation if the permission isn't explicitly
// denied
@@ -3596,7 +3597,7 @@
}
Slog.w(TAG, "Privileged permission " + permissionName + " for package "
+ packageName + " (" + pkg.getPath()
- + ") not in privapp-permissions whitelist");
+ + ") not in privapp-permissions allowlist");
if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {
synchronized (mLock) {
if (mPrivappPermissionsViolations == null) {
@@ -3775,10 +3776,10 @@
int newFlags = oldFlags;
int mask = 0;
- int whitelistFlagsCopy = allowlistFlags;
- while (whitelistFlagsCopy != 0) {
- final int flag = 1 << Integer.numberOfTrailingZeros(whitelistFlagsCopy);
- whitelistFlagsCopy &= ~flag;
+ int allowlistFlagsCopy = allowlistFlags;
+ while (allowlistFlagsCopy != 0) {
+ final int flag = 1 << Integer.numberOfTrailingZeros(allowlistFlagsCopy);
+ allowlistFlagsCopy &= ~flag;
switch (flag) {
case FLAG_PERMISSION_WHITELIST_SYSTEM: {
mask |= FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
@@ -3825,26 +3826,26 @@
updatePermissions = true;
- final boolean wasWhitelisted = (oldFlags
+ final boolean wasAllowlisted = (oldFlags
& (PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT)) != 0;
- final boolean isWhitelisted = (newFlags
+ final boolean isAllowlisted = (newFlags
& (PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT)) != 0;
// If the permission is policy fixed as granted but it is no longer
- // on any of the whitelists we need to clear the policy fixed flag
- // as whitelisting trumps policy i.e. policy cannot grant a non
+ // on any of the allowlists we need to clear the policy fixed flag
+ // as allowlisting trumps policy i.e. policy cannot grant a non
// grantable permission.
if ((oldFlags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
- if (!isWhitelisted && isGranted) {
+ if (!isAllowlisted && isGranted) {
mask |= PackageManager.FLAG_PERMISSION_POLICY_FIXED;
newFlags &= ~PackageManager.FLAG_PERMISSION_POLICY_FIXED;
}
}
- // If we are whitelisting an app that does not support runtime permissions
+ // If we are allowlisting an app that does not support runtime permissions
// we need to make sure it goes through the permission review UI at launch.
if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.M
- && !wasWhitelisted && isWhitelisted) {
+ && !wasAllowlisted && isAllowlisted) {
mask |= PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
newFlags |= PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
}
@@ -3854,7 +3855,7 @@
}
if (updatePermissions) {
- // Update permission of this app to take into account the new whitelist state.
+ // Update permission of this app to take into account the new allowlist state.
restorePermissionState(pkg, false, pkg.getPackageName(), mDefaultPermissionCallback);
// If this resulted in losing a permission we need to kill the app.
@@ -4487,7 +4488,7 @@
synchronized (mLock) {
if (mPrivappPermissionsViolations != null) {
throw new IllegalStateException("Signature|privileged permissions not in "
- + "privapp-permissions whitelist: " + mPrivappPermissionsViolations);
+ + "privapp-permissions allowlist: " + mPrivappPermissionsViolations);
}
}
@@ -4868,13 +4869,6 @@
}
}
- private boolean canPropagatePermissionToInstantApp(@NonNull String permissionName) {
- synchronized (mLock) {
- final Permission bp = mRegistry.getPermission(permissionName);
- return bp != null && (bp.isRuntime() || bp.isDevelopment()) && bp.isInstant();
- }
- }
-
@NonNull
private List<LegacyPermission> getLegacyPermissions() {
synchronized (mLock) {
@@ -4954,7 +4948,7 @@
private class PermissionManagerServiceInternalImpl implements PermissionManagerServiceInternal {
@Override
- public void systemReady() {
+ public void onSystemReady() {
PermissionManagerService.this.systemReady();
}
@@ -5012,11 +5006,6 @@
Preconditions.checkArgumentNonNegative(userId, "userId");
resetRuntimePermissionsInternal(pkg, userId);
}
- @Override
- public void resetAllRuntimePermissions(@UserIdInt int userId) {
- Preconditions.checkArgumentNonNegative(userId, "userId");
- mPackageManagerInt.forEachPackage(pkg -> resetRuntimePermissionsInternal(pkg, userId));
- }
@Override
public Permission getPermissionTEMP(String permName) {
@@ -5157,11 +5146,6 @@
onPackageUninstalledInternal(packageName, appId, pkg, sharedUserPkgs, userId);
}
- @Override
- public boolean canPropagatePermissionToInstantApp(@NonNull String permissionName) {
- return PermissionManagerService.this.canPropagatePermissionToInstantApp(permissionName);
- }
-
@NonNull
@Override
public List<LegacyPermission> getLegacyPermissions() {
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
index 0817d4f..1cfae00 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
@@ -54,8 +54,6 @@
void removeOnRuntimePermissionStateChangedListener(
@NonNull OnRuntimePermissionStateChangedListener listener);
- void systemReady();
-
/**
* Get whether permission review is required for a package.
*
@@ -94,14 +92,6 @@
@UserIdInt int userId);
/**
- * Reset the runtime permission state changes for all packages.
- *
- * @param userId the user ID
- */
- //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
- void resetAllRuntimePermissions(@UserIdInt int userId);
-
- /**
* Read legacy permission state from package settings.
*
* TODO(zhanghai): This is a temporary method because we should not expose
@@ -201,6 +191,12 @@
void writeLegacyPermissionsTEMP(@NonNull LegacyPermissionSettings legacyPermissionSettings);
/**
+ * Callback when the system is ready.
+ */
+ //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+ void onSystemReady();
+
+ /**
* Callback when a user has been created.
*
* @param userId the created user ID
@@ -265,14 +261,6 @@
@NonNull List<AndroidPackage> sharedUserPkgs, @UserIdInt int userId);
/**
- * Check whether a permission can be propagated to instant app.
- *
- * @param permissionName the name of the permission
- * @return whether the permission can be propagated
- */
- boolean canPropagatePermissionToInstantApp(@NonNull String permissionName);
-
- /**
* Listener for package permission state (permissions or flags) changes.
*/
interface OnRuntimePermissionStateChangedListener {
diff --git a/services/core/java/com/android/server/policy/OWNERS b/services/core/java/com/android/server/policy/OWNERS
index d25ec4a..8887e40 100644
--- a/services/core/java/com/android/server/policy/OWNERS
+++ b/services/core/java/com/android/server/policy/OWNERS
@@ -1,2 +1,3 @@
include /services/core/java/com/android/server/wm/OWNERS
include /services/core/java/com/android/server/input/OWNERS
+include /services/core/java/com/android/server/pm/permission/OWNERS
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 977b31e..1553966 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -496,6 +496,32 @@
* @return int An arbitrary integer used to order windows, with lower numbers below higher ones.
*/
default int getWindowLayerFromTypeLw(int type, boolean canAddInternalSystemWindow) {
+ return getWindowLayerFromTypeLw(type, canAddInternalSystemWindow,
+ false /* roundedCornerOverlay */);
+ }
+
+ /**
+ * Returns the layer assignment for the window type. Allows you to control how different
+ * kinds of windows are ordered on-screen.
+ *
+ * @param type The type of window being assigned.
+ * @param canAddInternalSystemWindow If the owner window associated with the type we are
+ * evaluating can add internal system windows. I.e they have
+ * {@link Manifest.permission#INTERNAL_SYSTEM_WINDOW}. If true, alert window
+ * types {@link android.view.WindowManager.LayoutParams#isSystemAlertWindowType(int)}
+ * can be assigned layers greater than the layer for
+ * {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY} Else, their
+ * layers would be lesser.
+ * @param roundedCornerOverlay {#code true} to indicate that the owner window is rounded corner
+ * overlay.
+ * @return int An arbitrary integer used to order windows, with lower numbers below higher ones.
+ */
+ default int getWindowLayerFromTypeLw(int type, boolean canAddInternalSystemWindow,
+ boolean roundedCornerOverlay) {
+ // Always put the rounded corner layer to the top most.
+ if (roundedCornerOverlay && canAddInternalSystemWindow) {
+ return getMaxWindowLayer();
+ }
if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
return APPLICATION_LAYER;
}
@@ -598,8 +624,17 @@
}
}
+ // TODO(b/155340867): consider to remove the logic after using pure Surface for rounded corner
+ // overlay.
+ /**
+ * Returns the max window layer.
+ * <p>Note that the max window layer should be higher that the maximum value which reported
+ * by {@link #getWindowLayerFromTypeLw(int, boolean)} to contain rounded corner overlay.</p>
+ *
+ * @see WindowManager.LayoutParams#PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY
+ */
default int getMaxWindowLayer() {
- return 35;
+ return 36;
}
/**
diff --git a/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java b/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java
index 017c684..b95c5ef 100644
--- a/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java
+++ b/services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.java
@@ -33,6 +33,7 @@
import com.android.internal.telephony.SmsApplication;
import com.android.internal.util.CollectionUtils;
import com.android.server.LocalServices;
+import com.android.server.role.LegacyRoleHolderProvider;
import com.android.server.role.RoleManagerService;
import java.util.Collections;
@@ -48,7 +49,7 @@
*
* @see RoleManagerService#migrateRoleIfNecessary
*/
-public class LegacyRoleResolutionPolicy implements RoleManagerService.RoleHoldersResolver {
+public class LegacyRoleResolutionPolicy implements LegacyRoleHolderProvider {
private static final boolean DEBUG = false;
private static final String LOG_TAG = "LegacyRoleResolutionPol";
@@ -62,7 +63,7 @@
@NonNull
@Override
- public List<String> getRoleHolders(@NonNull String roleName, @UserIdInt int userId) {
+ public List<String> getLegacyRoleHolders(@NonNull String roleName, @UserIdInt int userId) {
switch (roleName) {
case RoleManager.ROLE_ASSISTANT: {
String packageName;
diff --git a/services/core/java/com/android/server/powerstats/PowerStatsHALWrapper.java b/services/core/java/com/android/server/powerstats/PowerStatsHALWrapper.java
index 88e5f69..79c0392 100644
--- a/services/core/java/com/android/server/powerstats/PowerStatsHALWrapper.java
+++ b/services/core/java/com/android/server/powerstats/PowerStatsHALWrapper.java
@@ -16,7 +16,11 @@
package com.android.server.powerstats;
+import android.hardware.power.stats.ChannelInfo;
+import android.hardware.power.stats.EnergyMeasurement;
import android.hardware.power.stats.IPowerStats;
+import android.hardware.power.stats.PowerEntityInfo;
+import android.hardware.power.stats.StateResidencyResult;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
@@ -32,6 +36,7 @@
*/
public final class PowerStatsHALWrapper {
private static final String TAG = PowerStatsHALWrapper.class.getSimpleName();
+ private static final boolean DEBUG = false;
/**
* IPowerStatsHALWrapper defines the interface to the PowerStatsHAL.
@@ -122,17 +127,30 @@
*
* @return true if connection to power stats HAL was correctly established.
*/
- boolean initialize();
+ boolean isInitialized();
}
/**
- * PowerStatsHALWrapperImpl is the implementation of the IPowerStatsHALWrapper
- * used by the PowerStatsService. Other implementations will be used by the testing
- * framework and will be passed into the PowerStatsService through an injector.
+ * PowerStatsHALWrapper20Impl is the implementation of the IPowerStatsHALWrapper
+ * used by the PowerStatsService on devices that support only PowerStats HAL 2.0.
+ * Other implementations will be used by the testing framework and will be passed
+ * into the PowerStatsService through an injector.
*/
- public static final class PowerStatsHALWrapperImpl implements IPowerStatsHALWrapper {
+ public static final class PowerStatsHAL20WrapperImpl implements IPowerStatsHALWrapper {
private static Supplier<IPowerStats> sVintfPowerStats;
+ public PowerStatsHAL20WrapperImpl() {
+ Supplier<IPowerStats> service = new VintfHalCache();
+ sVintfPowerStats = null;
+
+ if (service.get() == null) {
+ if (DEBUG) Slog.d(TAG, "PowerStats HAL 2.0 not available on this device.");
+ sVintfPowerStats = null;
+ } else {
+ sVintfPowerStats = service;
+ }
+ }
+
@Override
public android.hardware.power.stats.PowerEntityInfo[] getPowerEntityInfo() {
android.hardware.power.stats.PowerEntityInfo[] powerEntityInfoHAL = null;
@@ -141,7 +159,7 @@
try {
powerEntityInfoHAL = sVintfPowerStats.get().getPowerEntityInfo();
} catch (RemoteException e) {
- Slog.e(TAG, "Failed to get power entity info from PowerStats HAL");
+ if (DEBUG) Slog.d(TAG, "Failed to get power entity info from PowerStats HAL");
}
}
@@ -158,7 +176,7 @@
stateResidencyResultHAL =
sVintfPowerStats.get().getStateResidency(powerEntityIds);
} catch (RemoteException e) {
- Slog.e(TAG, "Failed to get state residency from PowerStats HAL");
+ if (DEBUG) Slog.d(TAG, "Failed to get state residency from PowerStats HAL");
}
}
@@ -173,7 +191,9 @@
try {
energyConsumerInfoHAL = sVintfPowerStats.get().getEnergyConsumerInfo();
} catch (RemoteException e) {
- Slog.e(TAG, "Failed to get energy consumer info from PowerStats HAL");
+ if (DEBUG) {
+ Slog.d(TAG, "Failed to get energy consumer info from PowerStats HAL");
+ }
}
}
@@ -190,7 +210,9 @@
energyConsumedHAL =
sVintfPowerStats.get().getEnergyConsumed(energyConsumerIds);
} catch (RemoteException e) {
- Slog.e(TAG, "Failed to get energy consumer results from PowerStats HAL");
+ if (DEBUG) {
+ Slog.d(TAG, "Failed to get energy consumer results from PowerStats HAL");
+ }
}
}
@@ -205,7 +227,7 @@
try {
energyMeterInfoHAL = sVintfPowerStats.get().getEnergyMeterInfo();
} catch (RemoteException e) {
- Slog.e(TAG, "Failed to get energy meter info from PowerStats HAL");
+ if (DEBUG) Slog.d(TAG, "Failed to get energy meter info from PowerStats HAL");
}
}
@@ -221,7 +243,7 @@
energyMeasurementHAL =
sVintfPowerStats.get().readEnergyMeters(channelIds);
} catch (RemoteException e) {
- Slog.e(TAG, "Failed to get energy measurements from PowerStats HAL");
+ if (DEBUG) Slog.d(TAG, "Failed to get energy measurements from PowerStats HAL");
}
}
@@ -229,17 +251,90 @@
}
@Override
- public boolean initialize() {
- Supplier<IPowerStats> service = new VintfHalCache();
+ public boolean isInitialized() {
+ return (sVintfPowerStats != null);
+ }
+ }
- if (service.get() == null) {
- sVintfPowerStats = null;
- return false;
+ /**
+ * PowerStatsHALWrapper10Impl is the implementation of the IPowerStatsHALWrapper
+ * used by the PowerStatsService on devices that support only PowerStats HAL 1.0.
+ * Other implementations will be used by the testing framework and will be passed
+ * into the PowerStatsService through an injector.
+ */
+ public static final class PowerStatsHAL10WrapperImpl implements IPowerStatsHALWrapper {
+ private boolean mIsInitialized;
+
+ // PowerStatsHAL 1.0 native functions exposed by JNI layer.
+ private static native boolean nativeInit();
+ private static native PowerEntityInfo[] nativeGetPowerEntityInfo();
+ private static native StateResidencyResult[] nativeGetStateResidency(int[] powerEntityIds);
+ private static native ChannelInfo[] nativeGetEnergyMeterInfo();
+ private static native EnergyMeasurement[] nativeReadEnergyMeters(int[] channelIds);
+
+ public PowerStatsHAL10WrapperImpl() {
+ if (nativeInit()) {
+ mIsInitialized = true;
} else {
- sVintfPowerStats = service;
- return true;
+ if (DEBUG) Slog.d(TAG, "PowerStats HAL 1.0 not available on this device.");
+ mIsInitialized = false;
}
}
+
+ @Override
+ public android.hardware.power.stats.PowerEntityInfo[] getPowerEntityInfo() {
+ return nativeGetPowerEntityInfo();
+ }
+
+ @Override
+ public android.hardware.power.stats.StateResidencyResult[] getStateResidency(
+ int[] powerEntityIds) {
+ return nativeGetStateResidency(powerEntityIds);
+ }
+
+ @Override
+ public int[] getEnergyConsumerInfo() {
+ if (DEBUG) Slog.d(TAG, "Energy consumer info is not supported");
+ return null;
+ }
+
+ @Override
+ public android.hardware.power.stats.EnergyConsumerResult[] getEnergyConsumed(
+ int[] energyConsumerIds) {
+ if (DEBUG) Slog.d(TAG, "Energy consumer results are not supported");
+ return null;
+ }
+
+ @Override
+ public android.hardware.power.stats.ChannelInfo[] getEnergyMeterInfo() {
+ return nativeGetEnergyMeterInfo();
+ }
+
+ @Override
+ public android.hardware.power.stats.EnergyMeasurement[] readEnergyMeters(int[] channelIds) {
+ return nativeReadEnergyMeters(channelIds);
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return mIsInitialized;
+ }
+ }
+
+ /**
+ * Returns an instance of an IPowerStatsHALWrapper. If PowerStats HAL 2.0 is supported on the
+ * device, return a PowerStatsHAL20WrapperImpl, else return a PowerStatsHAL10WrapperImpl.
+ *
+ * @return an instance of an IPowerStatsHALWrapper where preference is given to PowerStats HAL
+ * 2.0.
+ */
+ public static IPowerStatsHALWrapper getPowerStatsHalImpl() {
+ PowerStatsHAL20WrapperImpl powerStatsHAL20WrapperImpl = new PowerStatsHAL20WrapperImpl();
+ if (powerStatsHAL20WrapperImpl.isInitialized()) {
+ return powerStatsHAL20WrapperImpl;
+ } else {
+ return new PowerStatsHAL10WrapperImpl();
+ }
}
private static class VintfHalCache implements Supplier<IPowerStats>, IBinder.DeathRecipient {
diff --git a/services/core/java/com/android/server/powerstats/PowerStatsService.java b/services/core/java/com/android/server/powerstats/PowerStatsService.java
index 1150d4b..ce50e58 100644
--- a/services/core/java/com/android/server/powerstats/PowerStatsService.java
+++ b/services/core/java/com/android/server/powerstats/PowerStatsService.java
@@ -29,7 +29,6 @@
import com.android.internal.util.DumpUtils;
import com.android.server.SystemService;
import com.android.server.powerstats.PowerStatsHALWrapper.IPowerStatsHALWrapper;
-import com.android.server.powerstats.PowerStatsHALWrapper.PowerStatsHALWrapperImpl;
import com.android.server.powerstats.ProtoStreamUtils.ChannelInfoUtils;
import com.android.server.powerstats.ProtoStreamUtils.EnergyConsumerIdUtils;
import com.android.server.powerstats.ProtoStreamUtils.PowerEntityInfoUtils;
@@ -78,7 +77,7 @@
}
IPowerStatsHALWrapper createPowerStatsHALWrapperImpl() {
- return new PowerStatsHALWrapperImpl();
+ return PowerStatsHALWrapper.getPowerStatsHalImpl();
}
PowerStatsLogger createPowerStatsLogger(Context context, File dataStoragePath,
@@ -143,7 +142,7 @@
private void onSystemServiceReady() {
mPowerStatsHALWrapper = mInjector.createPowerStatsHALWrapperImpl();
- if (mPowerStatsHALWrapper.initialize()) {
+ if (mPowerStatsHALWrapper.isInitialized()) {
if (DEBUG) Slog.d(TAG, "Starting PowerStatsService");
// Only start logger and triggers if initialization is successful.
diff --git a/services/core/java/com/android/server/powerstats/ProtoStreamUtils.java b/services/core/java/com/android/server/powerstats/ProtoStreamUtils.java
index 5a4256a..5e23b86 100644
--- a/services/core/java/com/android/server/powerstats/ProtoStreamUtils.java
+++ b/services/core/java/com/android/server/powerstats/ProtoStreamUtils.java
@@ -46,23 +46,31 @@
static class PowerEntityInfoUtils {
public static void print(PowerEntityInfo[] powerEntityInfo) {
+ if (powerEntityInfo == null) return;
+
for (int i = 0; i < powerEntityInfo.length; i++) {
Slog.d(TAG, "PowerEntityId: " + powerEntityInfo[i].powerEntityId
+ ", PowerEntityName: " + powerEntityInfo[i].powerEntityName);
- for (int j = 0; j < powerEntityInfo[i].states.length; j++) {
- Slog.d(TAG, " StateId: " + powerEntityInfo[i].states[j].stateId
- + ", StateName: " + powerEntityInfo[i].states[j].stateName);
+ if (powerEntityInfo[i].states != null) {
+ for (int j = 0; j < powerEntityInfo[i].states.length; j++) {
+ Slog.d(TAG, " StateId: " + powerEntityInfo[i].states[j].stateId
+ + ", StateName: " + powerEntityInfo[i].states[j].stateName);
+ }
}
}
}
public static void dumpsys(PowerEntityInfo[] powerEntityInfo, PrintWriter pw) {
+ if (powerEntityInfo == null) return;
+
for (int i = 0; i < powerEntityInfo.length; i++) {
pw.println("PowerEntityId: " + powerEntityInfo[i].powerEntityId
+ ", PowerEntityName: " + powerEntityInfo[i].powerEntityName);
- for (int j = 0; j < powerEntityInfo[i].states.length; j++) {
- pw.println(" StateId: " + powerEntityInfo[i].states[j].stateId
- + ", StateName: " + powerEntityInfo[i].states[j].stateName);
+ if (powerEntityInfo[i].states != null) {
+ for (int j = 0; j < powerEntityInfo[i].states.length; j++) {
+ pw.println(" StateId: " + powerEntityInfo[i].states[j].stateId
+ + ", StateName: " + powerEntityInfo[i].states[j].stateName);
+ }
}
}
}
@@ -70,6 +78,8 @@
static class StateResidencyResultUtils {
public static void print(StateResidencyResult[] stateResidencyResult) {
+ if (stateResidencyResult == null) return;
+
for (int i = 0; i < stateResidencyResult.length; i++) {
Slog.d(TAG, "PowerEntityId: " + stateResidencyResult[i].powerEntityId);
for (int j = 0; j < stateResidencyResult[i].stateResidencyData.length; j++) {
@@ -90,6 +100,8 @@
public static void packProtoMessage(ChannelInfo[] channelInfo, ProtoOutputStream pos) {
long token;
+ if (channelInfo == null) return;
+
for (int i = 0; i < channelInfo.length; i++) {
token = pos.start(PowerStatsServiceMeterProto.CHANNEL_INFO);
pos.write(ChannelInfoProto.CHANNEL_ID, channelInfo[i].channelId);
@@ -100,6 +112,8 @@
}
public static void print(ChannelInfo[] channelInfo) {
+ if (channelInfo == null) return;
+
for (int i = 0; i < channelInfo.length; i++) {
Slog.d(TAG, "ChannelId: " + channelInfo[i].channelId
+ ", ChannelName: " + channelInfo[i].channelName);
@@ -107,6 +121,8 @@
}
public static void dumpsys(ChannelInfo[] channelInfo, PrintWriter pw) {
+ if (channelInfo == null) return;
+
for (int i = 0; i < channelInfo.length; i++) {
pw.println("ChannelId: " + channelInfo[i].channelId
+ ", ChannelName: " + channelInfo[i].channelName);
@@ -125,6 +141,8 @@
ProtoOutputStream pos) {
long token;
+ if (energyMeasurement == null) return;
+
for (int i = 0; i < energyMeasurement.length; i++) {
token = pos.start(PowerStatsServiceMeterProto.ENERGY_MEASUREMENT);
pos.write(EnergyMeasurementProto.CHANNEL_ID, energyMeasurement[i].channelId);
@@ -200,6 +218,8 @@
}
public static void print(EnergyMeasurement[] energyMeasurement) {
+ if (energyMeasurement == null) return;
+
for (int i = 0; i < energyMeasurement.length; i++) {
Slog.d(TAG, "ChannelId: " + energyMeasurement[i].channelId
+ ", Timestamp (ms): " + energyMeasurement[i].timestampMs
@@ -212,6 +232,8 @@
public static void packProtoMessage(int[] energyConsumerId, ProtoOutputStream pos) {
long token;
+ if (energyConsumerId == null) return;
+
for (int i = 0; i < energyConsumerId.length; i++) {
token = pos.start(PowerStatsServiceModelProto.ENERGY_CONSUMER_ID);
pos.write(EnergyConsumerIdProto.ENERGY_CONSUMER_ID, energyConsumerId[i]);
@@ -220,12 +242,16 @@
}
public static void print(int[] energyConsumerId) {
+ if (energyConsumerId == null) return;
+
for (int i = 0; i < energyConsumerId.length; i++) {
Slog.d(TAG, "EnergyConsumerId: " + energyConsumerId[i]);
}
}
public static void dumpsys(int[] energyConsumerId, PrintWriter pw) {
+ if (energyConsumerId == null) return;
+
for (int i = 0; i < energyConsumerId.length; i++) {
pw.println("EnergyConsumerId: " + energyConsumerId[i]);
}
@@ -243,6 +269,8 @@
ProtoOutputStream pos) {
long token;
+ if (energyConsumerResult == null) return;
+
for (int i = 0; i < energyConsumerResult.length; i++) {
token = pos.start(PowerStatsServiceModelProto.ENERGY_CONSUMER_RESULT);
pos.write(EnergyConsumerResultProto.ENERGY_CONSUMER_ID,
@@ -321,6 +349,8 @@
}
public static void print(EnergyConsumerResult[] energyConsumerResult) {
+ if (energyConsumerResult == null) return;
+
for (int i = 0; i < energyConsumerResult.length; i++) {
Slog.d(TAG, "EnergyConsumerId: " + energyConsumerResult[i].energyConsumerId
+ ", Timestamp (ms): " + energyConsumerResult[i].timestampMs
diff --git a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
index e0701e8..5c01e43 100644
--- a/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
+++ b/services/core/java/com/android/server/recoverysystem/RecoverySystemService.java
@@ -16,8 +16,10 @@
package com.android.server.recoverysystem;
+import android.annotation.IntDef;
import android.content.Context;
import android.content.IntentSender;
+import android.content.pm.PackageManager;
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
import android.os.Binder;
@@ -30,8 +32,11 @@
import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.os.SystemProperties;
+import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.Slog;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.widget.LockSettingsInternal;
import com.android.internal.widget.RebootEscrowListener;
@@ -76,9 +81,53 @@
private final Injector mInjector;
private final Context mContext;
- private boolean mPreparedForReboot;
- private String mUnattendedRebootToken;
- private IntentSender mPreparedForRebootIntentSender;
+ @GuardedBy("this")
+ private final ArrayMap<String, IntentSender> mCallerPendingRequest = new ArrayMap<>();
+ @GuardedBy("this")
+ private final ArraySet<String> mCallerPreparedForReboot = new ArraySet<>();
+
+ /**
+ * Need to prepare for resume on reboot.
+ */
+ private static final int ROR_NEED_PREPARATION = 0;
+ /**
+ * Resume on reboot has been prepared, notify the caller.
+ */
+ private static final int ROR_SKIP_PREPARATION_AND_NOTIFY = 1;
+ /**
+ * Resume on reboot has been requested. Caller won't be notified until the preparation is done.
+ */
+ private static final int ROR_SKIP_PREPARATION_NOT_NOTIFY = 2;
+
+ /**
+ * The caller never requests for resume on reboot, no need for clear.
+ */
+ private static final int ROR_NOT_REQUESTED = 0;
+ /**
+ * Clear the resume on reboot preparation state.
+ */
+ private static final int ROR_REQUESTED_NEED_CLEAR = 1;
+ /**
+ * The caller has requested for resume on reboot. No need for clear since other callers may
+ * exist.
+ */
+ private static final int ROR_REQUESTED_SKIP_CLEAR = 2;
+
+ /**
+ * The action to perform upon new resume on reboot prepare request for a given client.
+ */
+ @IntDef({ ROR_NEED_PREPARATION,
+ ROR_SKIP_PREPARATION_AND_NOTIFY,
+ ROR_SKIP_PREPARATION_NOT_NOTIFY })
+ private @interface ResumeOnRebootActionsOnRequest {}
+
+ /**
+ * The action to perform upon resume on reboot clear request for a given client.
+ */
+ @IntDef({ROR_NOT_REQUESTED,
+ ROR_REQUESTED_NEED_CLEAR,
+ ROR_REQUESTED_SKIP_CLEAR})
+ private @interface ResumeOnRebootActionsOnClear{}
static class Injector {
protected final Context mContext;
@@ -286,47 +335,95 @@
}
}
- @Override // Binder call
- public boolean requestLskf(String updateToken, IntentSender intentSender) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
+ private void enforcePermissionForResumeOnReboot() {
+ if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.RECOVERY)
+ != PackageManager.PERMISSION_GRANTED
+ && mContext.checkCallingOrSelfPermission(android.Manifest.permission.REBOOT)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Caller must have " + android.Manifest.permission.RECOVERY
+ + " or " + android.Manifest.permission.REBOOT + " for resume on reboot.");
+ }
+ }
- if (updateToken == null) {
+ @Override // Binder call
+ public boolean requestLskf(String packageName, IntentSender intentSender) {
+ enforcePermissionForResumeOnReboot();
+
+ if (packageName == null) {
+ Slog.w(TAG, "Missing packageName when requesting lskf.");
return false;
}
- // No need to prepare again for the same token.
- if (mPreparedForReboot && updateToken.equals(mUnattendedRebootToken)) {
- return true;
+ @ResumeOnRebootActionsOnRequest int action = updateRoRPreparationStateOnNewRequest(
+ packageName, intentSender);
+ switch (action) {
+ case ROR_SKIP_PREPARATION_AND_NOTIFY:
+ // We consider the preparation done if someone else has prepared.
+ sendPreparedForRebootIntentIfNeeded(intentSender);
+ return true;
+ case ROR_SKIP_PREPARATION_NOT_NOTIFY:
+ return true;
+ case ROR_NEED_PREPARATION:
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ mInjector.getLockSettingsService().prepareRebootEscrow();
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ return true;
+ default:
+ throw new IllegalStateException("Unsupported action type on new request " + action);
+ }
+ }
+
+ // Checks and updates the resume on reboot preparation state.
+ private synchronized @ResumeOnRebootActionsOnRequest int updateRoRPreparationStateOnNewRequest(
+ String packageName, IntentSender intentSender) {
+ if (!mCallerPreparedForReboot.isEmpty()) {
+ if (mCallerPreparedForReboot.contains(packageName)) {
+ Slog.i(TAG, "RoR already has prepared for " + packageName);
+ }
+
+ // Someone else has prepared. Consider the preparation done, and send back the intent.
+ mCallerPreparedForReboot.add(packageName);
+ return ROR_SKIP_PREPARATION_AND_NOTIFY;
}
- mPreparedForReboot = false;
- mUnattendedRebootToken = updateToken;
- mPreparedForRebootIntentSender = intentSender;
-
- final long origId = Binder.clearCallingIdentity();
- try {
- mInjector.getLockSettingsService().prepareRebootEscrow();
- } finally {
- Binder.restoreCallingIdentity(origId);
+ boolean needPreparation = mCallerPendingRequest.isEmpty();
+ if (mCallerPendingRequest.containsKey(packageName)) {
+ Slog.i(TAG, "Duplicate RoR preparation request for " + packageName);
}
-
- return true;
+ // Update the request with the new intentSender.
+ mCallerPendingRequest.put(packageName, intentSender);
+ return needPreparation ? ROR_NEED_PREPARATION : ROR_SKIP_PREPARATION_NOT_NOTIFY;
}
@Override
public void onPreparedForReboot(boolean ready) {
- if (mUnattendedRebootToken == null) {
- Slog.w(TAG, "onPreparedForReboot called when mUnattendedRebootToken is null");
+ if (!ready) {
+ return;
}
-
- mPreparedForReboot = ready;
- if (ready) {
- sendPreparedForRebootIntentIfNeeded();
- }
+ updateRoRPreparationStateOnPreparedForReboot();
}
- private void sendPreparedForRebootIntentIfNeeded() {
- final IntentSender intentSender = mPreparedForRebootIntentSender;
+ private synchronized void updateRoRPreparationStateOnPreparedForReboot() {
+ if (!mCallerPreparedForReboot.isEmpty()) {
+ Slog.w(TAG, "onPreparedForReboot called when some clients have prepared.");
+ }
+
+ if (mCallerPendingRequest.isEmpty()) {
+ Slog.w(TAG, "onPreparedForReboot called but no client has requested.");
+ }
+
+ // Send intents to notify callers
+ for (int i = 0; i < mCallerPendingRequest.size(); i++) {
+ sendPreparedForRebootIntentIfNeeded(mCallerPendingRequest.valueAt(i));
+ mCallerPreparedForReboot.add(mCallerPendingRequest.keyAt(i));
+ }
+ mCallerPendingRequest.clear();
+ }
+
+ private void sendPreparedForRebootIntentIfNeeded(IntentSender intentSender) {
if (intentSender != null) {
try {
intentSender.sendIntent(null, 0, null, null, null);
@@ -337,37 +434,59 @@
}
@Override // Binder call
- public boolean clearLskf() {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
-
- mPreparedForReboot = false;
- mUnattendedRebootToken = null;
- mPreparedForRebootIntentSender = null;
-
- final long origId = Binder.clearCallingIdentity();
- try {
- mInjector.getLockSettingsService().clearRebootEscrow();
- } finally {
- Binder.restoreCallingIdentity(origId);
+ public boolean clearLskf(String packageName) {
+ enforcePermissionForResumeOnReboot();
+ if (packageName == null) {
+ Slog.w(TAG, "Missing packageName when clearing lskf.");
+ return false;
}
- return true;
+ @ResumeOnRebootActionsOnClear int action = updateRoRPreparationStateOnClear(packageName);
+ switch (action) {
+ case ROR_NOT_REQUESTED:
+ Slog.w(TAG, "RoR clear called before preparation for caller " + packageName);
+ return true;
+ case ROR_REQUESTED_SKIP_CLEAR:
+ return true;
+ case ROR_REQUESTED_NEED_CLEAR:
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ mInjector.getLockSettingsService().clearRebootEscrow();
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ return true;
+ default:
+ throw new IllegalStateException("Unsupported action type on clear " + action);
+ }
}
- @Override // Binder call
- public boolean rebootWithLskf(String updateToken, String reason) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
+ private synchronized @ResumeOnRebootActionsOnClear int updateRoRPreparationStateOnClear(
+ String packageName) {
+ if (!mCallerPreparedForReboot.contains(packageName) && !mCallerPendingRequest.containsKey(
+ packageName)) {
+ Slog.w(TAG, packageName + " hasn't prepared for resume on reboot");
+ return ROR_NOT_REQUESTED;
+ }
+ mCallerPendingRequest.remove(packageName);
+ mCallerPreparedForReboot.remove(packageName);
- if (!mPreparedForReboot) {
- Slog.i(TAG, "Reboot requested before prepare completed");
+ // Check if others have prepared ROR.
+ boolean needClear = mCallerPendingRequest.isEmpty() && mCallerPreparedForReboot.isEmpty();
+ return needClear ? ROR_REQUESTED_NEED_CLEAR : ROR_REQUESTED_SKIP_CLEAR;
+ }
+
+ private boolean rebootWithLskfImpl(String packageName, String reason, boolean slotSwitch) {
+ if (packageName == null) {
+ Slog.w(TAG, "Missing packageName when rebooting with lskf.");
+ return false;
+ }
+ if (!isLskfCaptured(packageName)) {
return false;
}
- if (updateToken != null && !updateToken.equals(mUnattendedRebootToken)) {
- Slog.i(TAG, "Reboot requested after preparation, but with mismatching token");
- return false;
- }
-
+ // TODO(xunchang) check the slot to boot into, and fail the reboot upon slot mismatch.
+ // TODO(xunchang) write the vbmeta digest along with the escrowKey before reboot.
if (!mInjector.getLockSettingsService().armRebootEscrow()) {
Slog.w(TAG, "Failure to escrow key for reboot");
return false;
@@ -378,6 +497,34 @@
return true;
}
+ @Override // Binder call for the legacy rebootWithLskf
+ public boolean rebootWithLskfAssumeSlotSwitch(String packageName, String reason) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
+ return rebootWithLskfImpl(packageName, reason, true);
+ }
+
+ @Override // Binder call
+ public boolean rebootWithLskf(String packageName, String reason, boolean slotSwitch) {
+ enforcePermissionForResumeOnReboot();
+ return rebootWithLskfImpl(packageName, reason, slotSwitch);
+ }
+
+ @Override // Binder call
+ public boolean isLskfCaptured(String packageName) {
+ enforcePermissionForResumeOnReboot();
+ boolean captured;
+ synchronized (this) {
+ captured = mCallerPreparedForReboot.contains(packageName);
+ }
+
+ if (!captured) {
+ Slog.i(TAG, "Reboot requested before prepare completed for caller "
+ + packageName);
+ return false;
+ }
+ return true;
+ }
+
/**
* Check if any of the init services is still running. If so, we cannot
* start a new uncrypt/setup-bcb/clear-bcb service right away; otherwise
diff --git a/services/core/java/com/android/server/recoverysystem/RecoverySystemShellCommand.java b/services/core/java/com/android/server/recoverysystem/RecoverySystemShellCommand.java
index c6905b5..f20d80d 100644
--- a/services/core/java/com/android/server/recoverysystem/RecoverySystemShellCommand.java
+++ b/services/core/java/com/android/server/recoverysystem/RecoverySystemShellCommand.java
@@ -56,26 +56,31 @@
}
private int requestLskf() throws RemoteException {
- String updateToken = getNextArgRequired();
- boolean success = mService.requestLskf(updateToken, null);
+ String packageName = getNextArgRequired();
+ boolean success = mService.requestLskf(packageName, null);
PrintWriter pw = getOutPrintWriter();
- pw.println("Request LSKF status: " + (success ? "success" : "failure"));
+ pw.printf("Request LSKF for packageName: %s, status: %s\n", packageName,
+ success ? "success" : "failure");
return 0;
}
private int clearLskf() throws RemoteException {
- boolean success = mService.clearLskf();
+ String packageName = getNextArgRequired();
+ boolean success = mService.clearLskf(packageName);
PrintWriter pw = getOutPrintWriter();
- pw.println("Clear LSKF: " + (success ? "success" : "failure"));
+ pw.printf("Clear LSKF for packageName: %s, status: %s\n", packageName,
+ success ? "success" : "failure");
return 0;
}
private int rebootAndApply() throws RemoteException {
- String updateToken = getNextArgRequired();
+ String packageName = getNextArgRequired();
String rebootReason = getNextArgRequired();
- boolean success = mService.rebootWithLskf(updateToken, rebootReason);
+ boolean success = mService.rebootWithLskf(packageName, rebootReason, true);
PrintWriter pw = getOutPrintWriter();
- pw.println("Reboot and apply status: " + (success ? "success" : "failure"));
+ // Keep the old message for cts test.
+ pw.printf("%s Reboot and apply status: %s\n", packageName,
+ success ? "success" : "failure");
return 0;
}
diff --git a/services/core/java/com/android/server/role/LegacyRoleHolderProvider.java b/services/core/java/com/android/server/role/LegacyRoleHolderProvider.java
new file mode 100644
index 0000000..ed0d675
--- /dev/null
+++ b/services/core/java/com/android/server/role/LegacyRoleHolderProvider.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.role;
+
+import android.annotation.NonNull;
+import android.annotation.UserIdInt;
+
+import java.util.List;
+
+/**
+ * A provider for migrating legacy "role"s to their actual role implementation.
+ */
+//@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+public interface LegacyRoleHolderProvider {
+ /**
+ * Get the list of holders of a legacy "role" before its actual role is introduced.
+ * <p>
+ * This method will only be called for the first time a role is made available in the platform.
+ *
+ * @param roleName the name of the role
+ * @param userId the user ID
+ * @return a list of holders for the given role
+ */
+ @NonNull
+ List<String> getLegacyRoleHolders(@NonNull String roleName, @UserIdInt int userId);
+}
diff --git a/services/core/java/com/android/server/role/RoleManagerService.java b/services/core/java/com/android/server/role/RoleManagerService.java
index 106dc21..d6add78 100644
--- a/services/core/java/com/android/server/role/RoleManagerService.java
+++ b/services/core/java/com/android/server/role/RoleManagerService.java
@@ -103,14 +103,7 @@
private final Object mLock = new Object();
@NonNull
- private final RoleHoldersResolver mLegacyRoleResolver;
-
- /** @see #getRoleHolders(String, int) */
- public interface RoleHoldersResolver {
- /** @return a list of packages that hold a given role for a given user */
- @NonNull
- List<String> getRoleHolders(@NonNull String roleName, @UserIdInt int userId);
- }
+ private final LegacyRoleHolderProvider mLegacyRoleHolderProvider;
/**
* Maps user id to its state.
@@ -146,10 +139,10 @@
new SparseArray<>();
public RoleManagerService(@NonNull Context context,
- @NonNull RoleHoldersResolver legacyRoleResolver) {
+ @NonNull LegacyRoleHolderProvider legacyRoleHolderProvider) {
super(context);
- mLegacyRoleResolver = legacyRoleResolver;
+ mLegacyRoleHolderProvider = legacyRoleHolderProvider;
RoleControllerManager.initializeRemoteServiceComponentName(context);
@@ -275,7 +268,7 @@
// Any role for which we have a record are already migrated
RoleUserState userState = getOrCreateUserState(userId);
if (!userState.isRoleAvailable(role)) {
- List<String> roleHolders = mLegacyRoleResolver.getRoleHolders(role, userId);
+ List<String> roleHolders = mLegacyRoleHolderProvider.getLegacyRoleHolders(role, userId);
if (roleHolders.isEmpty()) {
return;
}
diff --git a/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
index de06c92..da56824 100644
--- a/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
+++ b/services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
@@ -472,8 +472,8 @@
final CharSequence details = context.getText(
com.android.internal.R.string.low_internal_storage_view_text);
- PendingIntent intent = PendingIntent.getActivityAsUser(context, 0, lowMemIntent, 0,
- null, UserHandle.CURRENT);
+ PendingIntent intent = PendingIntent.getActivityAsUser(context, 0, lowMemIntent,
+ PendingIntent.FLAG_IMMUTABLE, null, UserHandle.CURRENT);
Notification notification =
new Notification.Builder(context, SystemNotificationChannels.ALERTS)
.setSmallIcon(com.android.internal.R.drawable.stat_notify_disk_full)
diff --git a/services/core/java/com/android/server/storage/StorageSessionController.java b/services/core/java/com/android/server/storage/StorageSessionController.java
index 0abeac8..808d130 100644
--- a/services/core/java/com/android/server/storage/StorageSessionController.java
+++ b/services/core/java/com/android/server/storage/StorageSessionController.java
@@ -32,6 +32,7 @@
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.os.UserHandle;
+import android.os.storage.StorageVolume;
import android.os.storage.VolumeInfo;
import android.provider.MediaStore;
import android.service.storage.ExternalStorageService;
@@ -133,6 +134,28 @@
}
}
+ /**
+ * Frees any cache held by ExternalStorageService.
+ *
+ * <p> Blocks until the service frees the cache or fails in doing so.
+ *
+ * @param volumeUuid uuid of the {@link StorageVolume} from which cache needs to be freed
+ * @param bytes number of bytes which need to be freed
+ * @throws ExternalStorageServiceException if it fails to connect to ExternalStorageService
+ */
+ public void freeCache(String volumeUuid, long bytes)
+ throws ExternalStorageServiceException {
+ synchronized (mLock) {
+ int size = mConnections.size();
+ for (int i = 0; i < size; i++) {
+ int key = mConnections.keyAt(i);
+ StorageUserConnection connection = mConnections.get(key);
+ if (connection != null) {
+ connection.freeCache(volumeUuid, bytes);
+ }
+ }
+ }
+ }
/**
* Removes and returns the {@link StorageUserConnection} for {@code vol}.
diff --git a/services/core/java/com/android/server/storage/StorageUserConnection.java b/services/core/java/com/android/server/storage/StorageUserConnection.java
index af26289..13cceee 100644
--- a/services/core/java/com/android/server/storage/StorageUserConnection.java
+++ b/services/core/java/com/android/server/storage/StorageUserConnection.java
@@ -125,6 +125,24 @@
}
/**
+ * Frees any cache held by ExternalStorageService.
+ *
+ * <p> Blocks until the service frees the cache or fails in doing so.
+ *
+ * @param volumeUuid uuid of the {@link StorageVolume} from which cache needs to be freed
+ * @param bytes number of bytes which need to be freed
+ * @throws ExternalStorageServiceException if it fails to connect to ExternalStorageService
+ */
+ public void freeCache(String volumeUuid, long bytes)
+ throws ExternalStorageServiceException {
+ synchronized (mSessionsLock) {
+ for (String sessionId : mSessions.keySet()) {
+ mActiveConnection.freeCache(sessionId, volumeUuid, bytes);
+ }
+ }
+ }
+
+ /**
* Removes a session without ending it or waiting for exit.
*
* This should only be used if the session has certainly been ended because the volume was
@@ -214,7 +232,7 @@
// A list of outstanding futures for async calls, for which we are still waiting
// for a callback. Used to unblock waiters if the service dies.
@GuardedBy("mLock")
- private ArrayList<CompletableFuture<Void>> mOutstandingOps = new ArrayList<>();
+ private final ArrayList<CompletableFuture<Void>> mOutstandingOps = new ArrayList<>();
@Override
public void close() {
@@ -309,6 +327,17 @@
}
}
+ public void freeCache(String sessionId, String volumeUuid, long bytes)
+ throws ExternalStorageServiceException {
+ try {
+ waitForAsync((service, callback) ->
+ service.freeCache(sessionId, volumeUuid, bytes, callback));
+ } catch (Exception e) {
+ throw new ExternalStorageServiceException("Failed to free " + bytes
+ + " bytes for volumeUuid : " + volumeUuid, e);
+ }
+ }
+
private void setResult(Bundle result, CompletableFuture<Void> future) {
ParcelableException ex = result.getParcelable(EXTRA_ERROR);
if (ex != null) {
diff --git a/services/core/java/com/android/server/utils/Snapshots.java b/services/core/java/com/android/server/utils/Snapshots.java
index 33b2bd4..f2406ab 100644
--- a/services/core/java/com/android/server/utils/Snapshots.java
+++ b/services/core/java/com/android/server/utils/Snapshots.java
@@ -48,7 +48,7 @@
* @param dst The destination array. It must be empty.
* @param src The source array
*/
- public <E> void copy(@NonNull SparseArray<E> dst, @NonNull SparseArray<E> src) {
+ public static <E> void copy(@NonNull SparseArray<E> dst, @NonNull SparseArray<E> src) {
if (dst.size() != 0) {
throw new IllegalArgumentException("copy destination is not empty");
}
@@ -83,7 +83,7 @@
* @param dst The destination array. It must be empty.
* @param src The source array
*/
- public void snapshot(@NonNull SparseIntArray dst, @NonNull SparseIntArray src) {
+ public static void snapshot(@NonNull SparseIntArray dst, @NonNull SparseIntArray src) {
if (dst.size() != 0) {
throw new IllegalArgumentException("snapshot destination is not empty");
}
diff --git a/services/core/java/com/android/server/utils/WatchableIntentResolver.java b/services/core/java/com/android/server/utils/WatchableIntentResolver.java
new file mode 100644
index 0000000..767fc07
--- /dev/null
+++ b/services/core/java/com/android/server/utils/WatchableIntentResolver.java
@@ -0,0 +1,93 @@
+/*
+ * 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.utils;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import com.android.server.IntentResolver;
+
+import java.util.List;
+
+/**
+ * A watched {@link IntentResolver}. The parameters are inherited from the superclass.
+ * @param <F> The filter type
+ * @param <R> The resolver type.
+ * {@hide}
+ */
+public abstract class WatchableIntentResolver<F, R extends Object>
+ extends IntentResolver<F, R>
+ implements Watchable {
+
+ /**
+ * Watchable machinery
+ */
+ private final Watchable mWatchable = new WatchableImpl();
+ /**
+ * Register an observer to receive change notifications.
+ * @param observer The observer to register.
+ */
+ public void registerObserver(@NonNull Watcher observer) {
+ mWatchable.registerObserver(observer);
+ }
+ /**
+ * Unregister the observer, which will no longer receive change notifications.
+ * @param observer The observer to unregister.
+ */
+ public void unregisterObserver(@NonNull Watcher observer) {
+ mWatchable.unregisterObserver(observer);
+ }
+ /**
+ * Notify listeners that the object has changd. The argument is a hint as to the
+ * source of the change.
+ * @param what The attribute or sub-object that changed, if not null.
+ */
+ public void dispatchChange(@Nullable Watchable what) {
+ mWatchable.dispatchChange(what);
+ }
+ /**
+ * Notify listeners that this object has changed.
+ */
+ protected void onChanged() {
+ dispatchChange(this);
+ }
+
+ @Override
+ public void addFilter(F f) {
+ super.addFilter(f);
+ onChanged();
+ }
+
+ @Override
+ public void removeFilter(F f) {
+ super.removeFilter(f);
+ onChanged();
+ }
+
+ @Override
+ protected void removeFilterInternal(F f) {
+ super.removeFilterInternal(f);
+ onChanged();
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ protected void sortResults(List<R> results) {
+ super.sortResults(results);
+ onChanged();
+ }
+}
diff --git a/services/core/java/com/android/server/vcn/Android.bp b/services/core/java/com/android/server/vcn/Android.bp
new file mode 100644
index 0000000..5ed204f
--- /dev/null
+++ b/services/core/java/com/android/server/vcn/Android.bp
@@ -0,0 +1,4 @@
+filegroup {
+ name: "framework-vcn-util-sources",
+ srcs: ["util/**/*.java"],
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
new file mode 100644
index 0000000..c060807
--- /dev/null
+++ b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.vcn;
+
+import static android.telephony.CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED;
+import static android.telephony.CarrierConfigManager.EXTRA_SLOT_INDEX;
+import static android.telephony.CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX;
+import static android.telephony.SubscriptionManager.INVALID_SIM_SLOT_INDEX;
+import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+import android.os.HandlerExecutor;
+import android.os.ParcelUuid;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
+import android.util.ArraySet;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.annotations.VisibleForTesting.Visibility;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * TelephonySubscriptionTracker provides a caching layer for tracking active subscription groups.
+ *
+ * <p>This class performs two roles:
+ *
+ * <ol>
+ * <li>De-noises subscription changes by ensuring that only changes in active and ready
+ * subscription groups are acted upon
+ * <li>Caches mapping between subIds and subscription groups
+ * </ol>
+ *
+ * <p>An subscription group is active and ready if any of its contained subIds has had BOTH the
+ * {@link CarrierConfigManager#isConfigForIdentifiedCarrier()} return true, AND the subscription is
+ * listed as active per SubscriptionManager#getAllSubscriptionInfoList().
+ *
+ * <p>Note that due to the asynchronous nature of callbacks and broadcasts, the output of this class
+ * is (only) eventually consistent.
+ *
+ * @hide
+ */
+public class TelephonySubscriptionTracker extends BroadcastReceiver {
+ @NonNull private static final String TAG = TelephonySubscriptionTracker.class.getSimpleName();
+ private static final boolean LOG_DBG = false; // STOPSHIP if true
+
+ @NonNull private final Context mContext;
+ @NonNull private final Handler mHandler;
+ @NonNull private final TelephonySubscriptionTrackerCallback mCallback;
+ @NonNull private final Dependencies mDeps;
+
+ @NonNull private final SubscriptionManager mSubscriptionManager;
+ @NonNull private final CarrierConfigManager mCarrierConfigManager;
+
+ // TODO (Android T+): Add ability to handle multiple subIds per slot.
+ @NonNull private final Map<Integer, Integer> mReadySubIdsBySlotId = new HashMap<>();
+ @NonNull private final OnSubscriptionsChangedListener mSubscriptionChangedListener;
+
+ @NonNull private TelephonySubscriptionSnapshot mCurrentSnapshot;
+
+ public TelephonySubscriptionTracker(
+ @NonNull Context context,
+ @NonNull Handler handler,
+ @NonNull TelephonySubscriptionTrackerCallback callback) {
+ this(context, handler, callback, new Dependencies());
+ }
+
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ TelephonySubscriptionTracker(
+ @NonNull Context context,
+ @NonNull Handler handler,
+ @NonNull TelephonySubscriptionTrackerCallback callback,
+ @NonNull Dependencies deps) {
+ mContext = Objects.requireNonNull(context, "Missing context");
+ mHandler = Objects.requireNonNull(handler, "Missing handler");
+ mCallback = Objects.requireNonNull(callback, "Missing callback");
+ mDeps = Objects.requireNonNull(deps, "Missing deps");
+
+ mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
+ mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class);
+
+ mSubscriptionChangedListener =
+ new OnSubscriptionsChangedListener() {
+ @Override
+ public void onSubscriptionsChanged() {
+ handleSubscriptionsChanged();
+ }
+ };
+ }
+
+ /** Registers the receivers, and starts tracking subscriptions. */
+ public void register() {
+ mContext.registerReceiver(
+ this, new IntentFilter(ACTION_CARRIER_CONFIG_CHANGED), null, mHandler);
+ mSubscriptionManager.addOnSubscriptionsChangedListener(
+ new HandlerExecutor(mHandler), mSubscriptionChangedListener);
+ }
+
+ /** Unregisters the receivers, and stops tracking subscriptions. */
+ public void unregister() {
+ mContext.unregisterReceiver(this);
+ mSubscriptionManager.removeOnSubscriptionsChangedListener(mSubscriptionChangedListener);
+ }
+
+ /**
+ * Handles subscription changes, correlating available subscriptions and loaded carrier configs
+ *
+ * <p>The subscription change listener is registered with a HandlerExecutor backed by mHandler,
+ * so callbacks & broadcasts are all serialized on mHandler, avoiding the need for locking.
+ */
+ public void handleSubscriptionsChanged() {
+ final Set<ParcelUuid> activeSubGroups = new ArraySet<>();
+ final Map<Integer, ParcelUuid> newSubIdToGroupMap = new HashMap<>();
+
+ final List<SubscriptionInfo> allSubs = mSubscriptionManager.getAllSubscriptionInfoList();
+ if (allSubs == null) {
+ return; // Telephony crashed; no way to verify subscriptions.
+ }
+
+ // If allSubs is empty, no subscriptions exist. Cache will be cleared by virtue of no active
+ // subscriptions
+ for (SubscriptionInfo subInfo : allSubs) {
+ if (subInfo.getGroupUuid() == null) {
+ continue;
+ }
+
+ // Build subId -> subGrp cache
+ newSubIdToGroupMap.put(subInfo.getSubscriptionId(), subInfo.getGroupUuid());
+
+ // Update subscription groups that are both ready, and active. For a group to be
+ // considered active, both of the following must be true:
+ //
+ // 1. A final CARRIER_CONFIG_CHANGED (where config is for an identified carrier)
+ // broadcast must have been received for the subId
+ // 2. A active subscription (is loaded into a SIM slot) must be part of the subscription
+ // group.
+ if (subInfo.getSimSlotIndex() != INVALID_SIM_SLOT_INDEX
+ && mReadySubIdsBySlotId.values().contains(subInfo.getSubscriptionId())) {
+ activeSubGroups.add(subInfo.getGroupUuid());
+ }
+ }
+
+ final TelephonySubscriptionSnapshot newSnapshot =
+ new TelephonySubscriptionSnapshot(newSubIdToGroupMap, activeSubGroups);
+
+ // If snapshot was meaningfully updated, fire the callback
+ if (!newSnapshot.equals(mCurrentSnapshot)) {
+ mCurrentSnapshot = newSnapshot;
+ mHandler.post(
+ () -> {
+ mCallback.onNewSnapshot(newSnapshot);
+ });
+ }
+ }
+
+ /**
+ * Broadcast receiver for ACTION_CARRIER_CONFIG_CHANGED
+ *
+ * <p>The broadcast receiver is registered with mHandler, so callbacks & broadcasts are all
+ * serialized on mHandler, avoiding the need for locking.
+ */
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ // Accept sticky broadcasts; if CARRIER_CONFIG_CHANGED was previously broadcast and it
+ // already was for an identified carrier, we can stop waiting for initial load to complete
+ if (!ACTION_CARRIER_CONFIG_CHANGED.equals(intent.getAction())) {
+ return;
+ }
+
+ final int subId = intent.getIntExtra(EXTRA_SUBSCRIPTION_INDEX, INVALID_SUBSCRIPTION_ID);
+ final int slotId = intent.getIntExtra(EXTRA_SLOT_INDEX, INVALID_SIM_SLOT_INDEX);
+
+ if (slotId == INVALID_SIM_SLOT_INDEX) {
+ return;
+ }
+
+ if (SubscriptionManager.isValidSubscriptionId(subId)) {
+ final PersistableBundle carrierConfigs = mCarrierConfigManager.getConfigForSubId(subId);
+ if (mDeps.isConfigForIdentifiedCarrier(carrierConfigs)) {
+ Slog.v(TAG, String.format("SubId %s ready for SlotId %s", subId, slotId));
+ mReadySubIdsBySlotId.put(slotId, subId);
+ handleSubscriptionsChanged();
+ }
+ } else {
+ Slog.v(TAG, "Slot unloaded: " + slotId);
+ mReadySubIdsBySlotId.remove(slotId);
+ handleSubscriptionsChanged();
+ }
+ }
+
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ void setReadySubIdsBySlotId(Map<Integer, Integer> readySubIdsBySlotId) {
+ mReadySubIdsBySlotId.putAll(readySubIdsBySlotId);
+ }
+
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ Map<Integer, Integer> getReadySubIdsBySlotId() {
+ return Collections.unmodifiableMap(mReadySubIdsBySlotId);
+ }
+
+ /** TelephonySubscriptionSnapshot is a class containing info about active subscriptions */
+ public static class TelephonySubscriptionSnapshot {
+ private final Map<Integer, ParcelUuid> mSubIdToGroupMap;
+ private final Set<ParcelUuid> mActiveGroups;
+
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ TelephonySubscriptionSnapshot(
+ @NonNull Map<Integer, ParcelUuid> subIdToGroupMap,
+ @NonNull Set<ParcelUuid> activeGroups) {
+ mSubIdToGroupMap = Collections.unmodifiableMap(
+ Objects.requireNonNull(subIdToGroupMap, "subIdToGroupMap was null"));
+ mActiveGroups = Collections.unmodifiableSet(
+ Objects.requireNonNull(activeGroups, "activeGroups was null"));
+ }
+
+ /** Returns the active subscription groups */
+ @NonNull
+ public Set<ParcelUuid> getActiveSubscriptionGroups() {
+ return mActiveGroups;
+ }
+
+ /** Returns the Subscription Group for a given subId. */
+ @Nullable
+ public ParcelUuid getGroupForSubId(int subId) {
+ return mSubIdToGroupMap.get(subId);
+ }
+
+ /**
+ * Returns all the subIds in a given group, including available, but inactive subscriptions.
+ */
+ @NonNull
+ public Set<Integer> getAllSubIdsInGroup(ParcelUuid subGrp) {
+ final Set<Integer> subIds = new ArraySet<>();
+
+ for (Entry<Integer, ParcelUuid> entry : mSubIdToGroupMap.entrySet()) {
+ if (subGrp.equals(entry.getValue())) {
+ subIds.add(entry.getKey());
+ }
+ }
+
+ return subIds;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mSubIdToGroupMap, mActiveGroups);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof TelephonySubscriptionSnapshot)) {
+ return false;
+ }
+
+ final TelephonySubscriptionSnapshot other = (TelephonySubscriptionSnapshot) obj;
+
+ return mSubIdToGroupMap.equals(other.mSubIdToGroupMap)
+ && mActiveGroups.equals(other.mActiveGroups);
+ }
+ }
+
+ /**
+ * Interface for listening to changes in subscriptions
+ *
+ * @see TelephonySubscriptionTracker
+ */
+ public interface TelephonySubscriptionTrackerCallback {
+ /**
+ * Called when subscription information changes, and a new subscription snapshot was taken
+ *
+ * @param snapshot the snapshot of subscription information.
+ */
+ void onNewSnapshot(@NonNull TelephonySubscriptionSnapshot snapshot);
+ }
+
+ /** External static dependencies for test injection */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ public static class Dependencies {
+ /** Checks if the given bundle is for an identified carrier */
+ public boolean isConfigForIdentifiedCarrier(PersistableBundle bundle) {
+ return CarrierConfigManager.isConfigForIdentifiedCarrier(bundle);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index 85fcd3d..1387311 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -39,12 +39,15 @@
import static com.android.server.wm.Task.ActivityState.DESTROYED;
import static com.android.server.wm.Task.ActivityState.DESTROYING;
+import android.annotation.NonNull;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
import android.app.IActivityClientController;
import android.app.PictureInPictureParams;
+import android.app.servertransaction.ClientTransaction;
+import android.app.servertransaction.EnterPipRequestedItem;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -736,6 +739,38 @@
return r;
}
+ /**
+ * Requests that an activity should enter picture-in-picture mode if possible. This method may
+ * be used by the implementation of non-phone form factors.
+ */
+ void requestPictureInPictureMode(@NonNull ActivityRecord r) {
+ if (r.inPinnedWindowingMode()) {
+ throw new IllegalStateException("Activity is already in PIP mode");
+ }
+
+ final boolean canEnterPictureInPicture = r.checkEnterPictureInPictureState(
+ "requestPictureInPictureMode", /* beforeStopping */ false);
+ if (!canEnterPictureInPicture) {
+ throw new IllegalStateException(
+ "Requested PIP on an activity that doesn't support it");
+ }
+
+ if (r.pictureInPictureArgs.isAutoEnterEnabled()) {
+ mService.enterPictureInPictureMode(r, r.pictureInPictureArgs);
+ return;
+ }
+
+ try {
+ final ClientTransaction transaction = ClientTransaction.obtain(
+ r.app.getThread(), r.token);
+ transaction.addCallback(EnterPipRequestedItem.obtain());
+ mService.getLifecycleManager().scheduleTransaction(transaction);
+ } catch (Exception e) {
+ Slog.w(TAG, "Failed to send enter pip requested item: "
+ + r.intent.getComponent(), e);
+ }
+ }
+
@Override
public void toggleFreeformWindowingMode(IBinder token) {
final long ident = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 4c18310..3390d67 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -219,7 +219,6 @@
import android.annotation.Nullable;
import android.annotation.Size;
import android.app.Activity;
-import android.app.ActivityManager;
import android.app.ActivityManager.TaskDescription;
import android.app.ActivityOptions;
import android.app.PendingIntent;
@@ -294,6 +293,7 @@
import android.view.WindowManager.LayoutParams;
import android.view.WindowManager.TransitionOldType;
import android.view.animation.Animation;
+import android.window.TaskSnapshot;
import android.window.WindowContainerToken;
import com.android.internal.R;
@@ -1756,9 +1756,12 @@
return false;
}
- final ActivityManager.TaskSnapshot snapshot =
+ final TaskSnapshot snapshot =
mWmService.mTaskSnapshotController.getSnapshot(task.mTaskId, task.mUserId,
false /* restoreFromDisk */, false /* isLowResolution */);
+ final int typeParameter = mWmService.mStartingSurfaceController
+ .makeStartingWindowTypeParameter(newTask, taskSwitch, processRunning,
+ allowTaskSnapshot, activityCreated);
final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
allowTaskSnapshot, activityCreated, snapshot);
@@ -1773,7 +1776,7 @@
return false;
}
}
- return createSnapshot(snapshot);
+ return createSnapshot(snapshot, typeParameter);
}
// If this is a translucent window, then don't show a starting window -- the current
@@ -1833,18 +1836,18 @@
ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Creating SplashScreenStartingData");
mStartingData = new SplashScreenStartingData(mWmService, pkg,
theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
- getMergedOverrideConfiguration());
+ getMergedOverrideConfiguration(), typeParameter);
scheduleAddStartingWindow();
return true;
}
- private boolean createSnapshot(ActivityManager.TaskSnapshot snapshot) {
+ private boolean createSnapshot(TaskSnapshot snapshot, int typeParams) {
if (snapshot == null) {
return false;
}
ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Creating SnapshotStartingData");
- mStartingData = new SnapshotStartingData(mWmService, snapshot);
+ mStartingData = new SnapshotStartingData(mWmService, snapshot, typeParams);
scheduleAddStartingWindow();
return true;
}
@@ -1923,7 +1926,7 @@
private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
boolean allowTaskSnapshot, boolean activityCreated,
- ActivityManager.TaskSnapshot snapshot) {
+ TaskSnapshot snapshot) {
if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
} else if (taskSwitch && allowTaskSnapshot) {
@@ -1944,7 +1947,7 @@
* rotation must be the same).
*/
@VisibleForTesting
- boolean isSnapshotCompatible(ActivityManager.TaskSnapshot snapshot) {
+ boolean isSnapshotCompatible(TaskSnapshot snapshot) {
if (snapshot == null) {
return false;
}
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index ecbf266..1b0bec5 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1883,7 +1883,7 @@
}
mSupervisor.getLaunchParamsController().calculate(targetTask, r.info.windowLayout, r,
- sourceRecord, mOptions, PHASE_BOUNDS, mLaunchParams, mRequest);
+ sourceRecord, mOptions, mRequest, PHASE_BOUNDS, mLaunchParams);
mPreferredTaskDisplayArea = mLaunchParams.hasPreferredTaskDisplayArea()
? mLaunchParams.mPreferredTaskDisplayArea
: mRootWindowContainer.getDefaultTaskDisplayArea();
@@ -2274,7 +2274,7 @@
// Preferred display id is the only state we need for now and it could be updated again
// after we located a reusable task (which might be resided in another display).
mSupervisor.getLaunchParamsController().calculate(inTask, r.info.windowLayout, r,
- sourceRecord, options, PHASE_DISPLAY, mLaunchParams, mRequest);
+ sourceRecord, options, mRequest, PHASE_DISPLAY, mLaunchParams);
mPreferredTaskDisplayArea = mLaunchParams.hasPreferredTaskDisplayArea()
? mLaunchParams.mPreferredTaskDisplayArea
: mRootWindowContainer.getDefaultTaskDisplayArea();
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index f8b3c1b..9ffedde 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -19,7 +19,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
-import android.app.ActivityManager;
import android.app.AppProtoEnums;
import android.app.IActivityManager;
import android.app.IApplicationThread;
@@ -34,6 +33,7 @@
import android.os.RemoteException;
import android.service.voice.IVoiceInteractionSession;
import android.util.proto.ProtoOutputStream;
+import android.window.TaskSnapshot;
import com.android.internal.app.IVoiceInteractor;
import com.android.server.am.PendingIntentRecord;
@@ -552,7 +552,7 @@
* <p>Warning! this may restore the snapshot from disk so can block, don't call in a latency
* sensitive environment.
*/
- public abstract ActivityManager.TaskSnapshot getTaskSnapshotBlocking(int taskId,
+ public abstract TaskSnapshot getTaskSnapshotBlocking(int taskId,
boolean isLowResolution);
/** Returns true if uid is considered foreground for activity start purposes. */
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index a2b0990..ce70978 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -148,8 +148,6 @@
import android.app.admin.DevicePolicyCache;
import android.app.assist.AssistContent;
import android.app.assist.AssistStructure;
-import android.app.servertransaction.ClientTransaction;
-import android.app.servertransaction.EnterPipRequestedItem;
import android.app.usage.UsageStatsManagerInternal;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
@@ -220,6 +218,7 @@
import android.view.RemoteAnimationDefinition;
import android.view.WindowManager;
import android.window.IWindowOrganizerController;
+import android.window.TaskSnapshot;
import android.window.WindowContainerTransaction;
import com.android.internal.R;
@@ -3252,23 +3251,15 @@
}
}
- @VisibleForTesting
- boolean isInPictureInPictureMode(ActivityRecord r) {
- return r != null
- && r.getRootTask() != null
- && r.inPinnedWindowingMode()
- && r.getRootTask().isInTask(r) != null;
- }
-
/**
* Puts the given activity in picture in picture mode if possible.
*
* @return true if the activity is now in picture-in-picture mode, or false if it could not
* enter picture-in-picture mode.
*/
- boolean enterPictureInPictureMode(ActivityRecord r, final PictureInPictureParams params) {
+ boolean enterPictureInPictureMode(@NonNull ActivityRecord r, PictureInPictureParams params) {
// If the activity is already in picture in picture mode, then just return early
- if (isInPictureInPictureMode(r)) {
+ if (r.inPinnedWindowingMode()) {
return true;
}
@@ -3463,7 +3454,7 @@
}
@Override
- public ActivityManager.TaskSnapshot getTaskSnapshot(int taskId, boolean isLowResolution) {
+ public TaskSnapshot getTaskSnapshot(int taskId, boolean isLowResolution) {
enforceCallerIsRecentsOrHasPermission(READ_FRAME_BUFFER, "getTaskSnapshot()");
final long ident = Binder.clearCallingIdentity();
try {
@@ -3473,7 +3464,7 @@
}
}
- private ActivityManager.TaskSnapshot getTaskSnapshot(int taskId, boolean isLowResolution,
+ private TaskSnapshot getTaskSnapshot(int taskId, boolean isLowResolution,
boolean restoreFromDisk) {
final Task task;
synchronized (mGlobalLock) {
@@ -3753,52 +3744,6 @@
}
}
- /**
- * Requests that an activity should enter picture-in-picture mode if possible.
- */
- @Override
- public void requestPictureInPictureMode(IBinder token) throws RemoteException {
- enforceTaskPermission("requestPictureInPictureMode");
- final long origId = Binder.clearCallingIdentity();
- try {
- synchronized (mGlobalLock) {
- final ActivityRecord activity = ActivityRecord.forTokenLocked(token);
- if (activity == null) {
- return;
- }
-
- if (isInPictureInPictureMode(activity)) {
- throw new IllegalStateException("Activity is already in PIP mode");
- }
-
- final boolean canEnterPictureInPicture = activity.checkEnterPictureInPictureState(
- "requestPictureInPictureMode", /* beforeStopping */ false);
- if (!canEnterPictureInPicture) {
- throw new IllegalStateException(
- "Requested PIP on an activity that doesn't support it");
- }
-
- if (activity.pictureInPictureArgs.isAutoEnterEnabled()) {
- enterPictureInPictureMode(activity, activity.pictureInPictureArgs);
- return;
- }
-
- try {
- final ClientTransaction transaction = ClientTransaction.obtain(
- activity.app.getThread(),
- activity.token);
- transaction.addCallback(EnterPipRequestedItem.obtain());
- getLifecycleManager().scheduleTransaction(transaction);
- } catch (Exception e) {
- Slog.w(TAG, "Failed to send enter pip requested item: "
- + activity.intent.getComponent(), e);
- }
- }
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
- }
-
void dumpLastANRLocked(PrintWriter pw) {
pw.println("ACTIVITY MANAGER LAST ANR (dumpsys activity lastanr)");
if (mLastANRState == null) {
@@ -6341,7 +6286,7 @@
}
@Override
- public ActivityManager.TaskSnapshot getTaskSnapshotBlocking(
+ public TaskSnapshot getTaskSnapshotBlocking(
int taskId, boolean isLowResolution) {
return ActivityTaskManagerService.this.getTaskSnapshot(taskId, isLowResolution,
true /* restoreFromDisk */);
diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java
index 07729d1..029056a 100644
--- a/services/core/java/com/android/server/wm/Dimmer.java
+++ b/services/core/java/com/android/server/wm/Dimmer.java
@@ -204,7 +204,7 @@
}
private void dim(SurfaceControl.Transaction t, WindowContainer container, int relativeLayer,
- float alpha) {
+ float alpha, int blurRadius) {
final DimState d = getDimState(container);
if (d == null) {
@@ -220,6 +220,7 @@
t.setLayer(d.mDimLayer, Integer.MAX_VALUE);
}
t.setAlpha(d.mDimLayer, alpha);
+ t.setBackgroundBlurRadius(d.mDimLayer, blurRadius);
d.mDimming = true;
}
@@ -247,7 +248,7 @@
* @param alpha The alpha at which to Dim.
*/
void dimAbove(SurfaceControl.Transaction t, float alpha) {
- dim(t, null, 1, alpha);
+ dim(t, null, 1, alpha, 0);
}
/**
@@ -260,19 +261,21 @@
* @param alpha The alpha at which to Dim.
*/
void dimAbove(SurfaceControl.Transaction t, WindowContainer container, float alpha) {
- dim(t, container, 1, alpha);
+ dim(t, container, 1, alpha, 0);
}
/**
* Like {@link #dimAbove} but places the dim below the given container.
*
- * @param t A transaction in which to apply the Dim.
- * @param container The container which to dim below. Should be a child of our host.
- * @param alpha The alpha at which to Dim.
+ * @param t A transaction in which to apply the Dim.
+ * @param container The container which to dim below. Should be a child of our host.
+ * @param alpha The alpha at which to Dim.
+ * @param blurRadius The amount of blur added to the Dim.
*/
- void dimBelow(SurfaceControl.Transaction t, WindowContainer container, float alpha) {
- dim(t, container, -1, alpha);
+ void dimBelow(SurfaceControl.Transaction t, WindowContainer container, float alpha,
+ int blurRadius) {
+ dim(t, container, -1, alpha, blurRadius);
}
/**
diff --git a/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java b/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java
index c475da3..53f7009 100644
--- a/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java
+++ b/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java
@@ -134,7 +134,7 @@
@Override
public DisplayAreaAppearedInfo createTaskDisplayArea(IDisplayAreaOrganizer organizer,
- int displayId, int rootFeatureId, String name) {
+ int displayId, int parentFeatureId, String name) {
enforceTaskPermission("createTaskDisplayArea()");
final long uid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
@@ -149,13 +149,26 @@
+ displayId);
}
- final DisplayArea root = display.getItemFromDisplayAreas(da ->
- da.asRootDisplayArea() != null && da.mFeatureId == rootFeatureId
- ? da
+ // The parentFeatureId can be either a RootDisplayArea or a TaskDisplayArea.
+ // Check if there is a RootDisplayArea with the given parentFeatureId.
+ final RootDisplayArea parentRoot = display.getItemFromDisplayAreas(da ->
+ da.asRootDisplayArea() != null && da.mFeatureId == parentFeatureId
+ ? da.asRootDisplayArea()
: null);
- if (root == null) {
- throw new IllegalArgumentException("Can't find RootDisplayArea with featureId="
- + rootFeatureId);
+ final TaskDisplayArea parentTda;
+ if (parentRoot == null) {
+ // There is no RootDisplayArea matching the parentFeatureId.
+ // Check if there is a TaskDisplayArea with the given parentFeatureId.
+ parentTda = display.getItemFromTaskDisplayAreas(taskDisplayArea ->
+ taskDisplayArea.mFeatureId == parentFeatureId
+ ? taskDisplayArea
+ : null);
+ } else {
+ parentTda = null;
+ }
+ if (parentRoot == null && parentTda == null) {
+ throw new IllegalArgumentException(
+ "Can't find a parent DisplayArea with featureId=" + parentFeatureId);
}
final int taskDisplayAreaFeatureId = mNextTaskDisplayAreaFeatureId++;
@@ -166,10 +179,13 @@
// Oh well...
}
- final TaskDisplayArea tda = createTaskDisplayArea(root.asRootDisplayArea(), name,
- taskDisplayAreaFeatureId);
- return organizeDisplayArea(organizer, tda,
+ final TaskDisplayArea tda = parentRoot != null
+ ? createTaskDisplayArea(parentRoot, name, taskDisplayAreaFeatureId)
+ : createTaskDisplayArea(parentTda, name, taskDisplayAreaFeatureId);
+ final DisplayAreaAppearedInfo tdaInfo = organizeDisplayArea(organizer, tda,
"DisplayAreaOrganizerController.createTaskDisplayArea");
+ mOrganizersByFeatureIds.put(taskDisplayAreaFeatureId, organizer);
+ return tdaInfo;
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -196,6 +212,7 @@
+ "TaskDisplayArea=" + taskDisplayArea);
}
+ mOrganizersByFeatureIds.remove(taskDisplayArea.mFeatureId);
deleteTaskDisplayArea(taskDisplayArea);
}
} finally {
@@ -253,6 +270,9 @@
new SurfaceControl(displayArea.getSurfaceControl(), callsite));
}
+ /**
+ * Creates a {@link TaskDisplayArea} as the topmost TDA below the given {@link RootDisplayArea}.
+ */
private TaskDisplayArea createTaskDisplayArea(RootDisplayArea root, String name,
int taskDisplayAreaFeatureId) {
final TaskDisplayArea taskDisplayArea = new TaskDisplayArea(root.mDisplayContent,
@@ -283,6 +303,21 @@
return taskDisplayArea;
}
+ /**
+ * Creates a {@link TaskDisplayArea} as the topmost child of the given {@link TaskDisplayArea}.
+ */
+ private TaskDisplayArea createTaskDisplayArea(TaskDisplayArea parentTda, String name,
+ int taskDisplayAreaFeatureId) {
+ final TaskDisplayArea taskDisplayArea = new TaskDisplayArea(parentTda.mDisplayContent,
+ parentTda.mWmService, name, taskDisplayAreaFeatureId,
+ true /* createdByOrganizer */);
+
+ // Insert the TaskDisplayArea on the top.
+ parentTda.addChild(taskDisplayArea, WindowContainer.POSITION_TOP);
+
+ return taskDisplayArea;
+ }
+
private void deleteTaskDisplayArea(TaskDisplayArea taskDisplayArea) {
taskDisplayArea.setOrganizer(null);
mService.mRootWindowContainer.mTaskSupervisor.beginDeferResume();
diff --git a/services/core/java/com/android/server/wm/DisplayAreaPolicy.java b/services/core/java/com/android/server/wm/DisplayAreaPolicy.java
index f8c3754..d4b319a 100644
--- a/services/core/java/com/android/server/wm/DisplayAreaPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayAreaPolicy.java
@@ -99,41 +99,23 @@
// Define the features that will be supported under the root of the whole logical
// display. The policy will build the DisplayArea hierarchy based on this.
- final HierarchyBuilder rootHierarchy = new HierarchyBuilder(root);
- if (content.isTrusted()) {
- // Only trusted display can have system decorations.
- configureTrustedHierarchyBuilder(rootHierarchy, wmService, content);
- }
- // Set the essential containers (even the display doesn't support IME).
- rootHierarchy.setImeContainer(imeContainer).setTaskDisplayAreas(tdaList);
-
- // Instantiate the policy with the hierarchy defined above. This will create and attach
- // all the necessary DisplayAreas to the root.
- return new DisplayAreaPolicyBuilder().setRootHierarchy(rootHierarchy).build(wmService);
- }
-
- private void configureTrustedHierarchyBuilder(HierarchyBuilder rootHierarchy,
- WindowManagerService wmService, DisplayContent content) {
- // WindowedMagnification should be on the top so that there is only one surface
- // to be magnified.
- rootHierarchy.addFeature(new Feature.Builder(wmService.mPolicy, "WindowedMagnification",
- FEATURE_WINDOWED_MAGNIFICATION)
- .upTo(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY)
- .except(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY)
- // Make the DA dimmable so that the magnify window also mirrors the dim layer.
- .setNewDisplayAreaSupplier(DisplayArea.Dimmable::new)
- .build());
- if (content.isDefaultDisplay) {
- // Only default display can have cutout.
- // See LocalDisplayAdapter.LocalDisplayDevice#getDisplayDeviceInfoLocked.
- rootHierarchy.addFeature(new Feature.Builder(wmService.mPolicy, "HideDisplayCutout",
- FEATURE_HIDE_DISPLAY_CUTOUT)
- .all()
- .except(TYPE_NAVIGATION_BAR, TYPE_NAVIGATION_BAR_PANEL,
- TYPE_STATUS_BAR, TYPE_NOTIFICATION_SHADE)
- .build());
- }
- rootHierarchy
+ HierarchyBuilder rootHierarchy = new HierarchyBuilder(root)
+ // WindowedMagnification should be on the top so that there is only one surface
+ // to be magnified.
+ .addFeature(new Feature.Builder(wmService.mPolicy, "WindowedMagnification",
+ FEATURE_WINDOWED_MAGNIFICATION)
+ .upTo(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY)
+ .except(TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY)
+ // Make the DA dimmable so that the magnify window also mirrors the dim
+ // layer
+ .setNewDisplayAreaSupplier(DisplayArea.Dimmable::new)
+ .build())
+ .addFeature(new Feature.Builder(wmService.mPolicy, "HideDisplayCutout",
+ FEATURE_HIDE_DISPLAY_CUTOUT)
+ .all()
+ .except(TYPE_NAVIGATION_BAR, TYPE_NAVIGATION_BAR_PANEL, TYPE_STATUS_BAR,
+ TYPE_NOTIFICATION_SHADE)
+ .build())
.addFeature(new Feature.Builder(wmService.mPolicy, "OneHanded",
FEATURE_ONE_HANDED)
.all()
@@ -149,7 +131,13 @@
.addFeature(new Feature.Builder(wmService.mPolicy, "ImePlaceholder",
FEATURE_IME_PLACEHOLDER)
.and(TYPE_INPUT_METHOD, TYPE_INPUT_METHOD_DIALOG)
- .build());
+ .build())
+ .setImeContainer(imeContainer)
+ .setTaskDisplayAreas(tdaList);
+
+ // Instantiate the policy with the hierarchy defined above. This will create and attach
+ // all the necessary DisplayAreas to the root.
+ return new DisplayAreaPolicyBuilder().setRootHierarchy(rootHierarchy).build(wmService);
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java b/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java
index c8fadf6..f505daa 100644
--- a/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java
+++ b/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java
@@ -365,7 +365,7 @@
*/
private void build(@Nullable List<HierarchyBuilder> displayAreaGroupHierarchyBuilders) {
final WindowManagerPolicy policy = mRoot.mWmService.mPolicy;
- final int maxWindowLayerCount = policy.getMaxWindowLayer();
+ final int maxWindowLayerCount = policy.getMaxWindowLayer() + 1;
final DisplayArea.Tokens[] displayAreaForLayer =
new DisplayArea.Tokens[maxWindowLayerCount];
final Map<Feature, List<DisplayArea<WindowContainer>>> featureAreas =
@@ -560,6 +560,7 @@
private final int mId;
private final boolean[] mLayers;
private NewDisplayAreaSupplier mNewDisplayAreaSupplier = DisplayArea::new;
+ private boolean mExcludeRoundedCorner = true;
/**
* Builds a new feature that applies to a set of window types as specified by the
@@ -578,7 +579,7 @@
mPolicy = policy;
mName = name;
mId = id;
- mLayers = new boolean[mPolicy.getMaxWindowLayer()];
+ mLayers = new boolean[mPolicy.getMaxWindowLayer() + 1];
}
/**
@@ -633,7 +634,18 @@
return this;
}
+ // TODO(b/155340867): consider to remove the logic after using pure Surface for rounded
+ // corner overlay.
+ Builder setExcludeRoundedCornerOverlay(boolean excludeRoundedCorner) {
+ mExcludeRoundedCorner = excludeRoundedCorner;
+ return this;
+ }
+
Feature build() {
+ if (mExcludeRoundedCorner) {
+ // Always put the rounded corner layer to the top most layer.
+ mLayers[mPolicy.getMaxWindowLayer()] = false;
+ }
return new Feature(mName, mId, mLayers.clone(), mNewDisplayAreaSupplier);
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index fc9753c..8457933 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -2300,10 +2300,9 @@
return count[0];
}
- @VisibleForTesting
@Nullable
Task getTopRootTask() {
- return getItemFromTaskDisplayAreas(TaskDisplayArea::getTopRootTask);
+ return getRootTask(t -> true);
}
/**
@@ -5479,12 +5478,12 @@
return;
}
- // Check if all task display areas have only the empty home stacks left.
- boolean hasNonEmptyHomeStack = forAllRootTasks(stack ->
- !stack.isActivityTypeHome() || stack.hasChild());
- if (!hasNonEmptyHomeStack && getRootTaskCount() > 0) {
- // Release this display if only empty home stack(s) are left. This display will be
- // released along with the stack(s) removal.
+ // Check if all task display areas have only the empty home root tasks left.
+ boolean hasNonEmptyHomeRootTask = forAllRootTasks(rootTask ->
+ !rootTask.isActivityTypeHome() || rootTask.hasChild());
+ if (!hasNonEmptyHomeRootTask && getRootTaskCount() > 0) {
+ // Release this display if only empty home root task(s) are left. This display will be
+ // released along with the root task(s) removal.
forAllRootTasks(Task::removeIfPossible);
} else if (getTopRootTask() == null) {
removeIfPossible();
@@ -5525,12 +5524,14 @@
return;
}
mInEnsureActivitiesVisible = true;
+ mAtmService.mTaskSupervisor.beginActivityVisibilityUpdate();
try {
- forAllTaskDisplayAreas(taskDisplayArea -> {
- taskDisplayArea.ensureActivitiesVisible(starting, configChanges,
- preserveWindows, notifyClients, userLeaving);
+ forAllRootTasks(rootTask -> {
+ rootTask.ensureActivitiesVisible(starting, configChanges, preserveWindows,
+ notifyClients, userLeaving);
});
} finally {
+ mAtmService.mTaskSupervisor.endActivityVisibilityUpdate();
mInEnsureActivitiesVisible = false;
}
}
diff --git a/services/core/java/com/android/server/wm/InputManagerCallback.java b/services/core/java/com/android/server/wm/InputManagerCallback.java
index 35f5615..6e89581 100644
--- a/services/core/java/com/android/server/wm/InputManagerCallback.java
+++ b/services/core/java/com/android/server/wm/InputManagerCallback.java
@@ -26,9 +26,7 @@
import android.annotation.NonNull;
import android.os.Debug;
import android.os.IBinder;
-import android.os.RemoteException;
import android.util.Slog;
-import android.view.IWindow;
import android.view.InputApplicationHandle;
import android.view.KeyEvent;
import android.view.WindowManager;
@@ -37,7 +35,6 @@
import com.android.server.input.InputManagerService;
import java.io.PrintWriter;
-import java.util.concurrent.atomic.AtomicReference;
final class InputManagerCallback implements InputManagerService.WindowManagerCallbacks {
private static final String TAG = TAG_WITH_CLASS_NAME ? "InputManagerCallback" : TAG_WM;
@@ -60,13 +57,6 @@
// which point the ActivityManager will enable dispatching.
private boolean mInputDispatchEnabled;
- // TODO(b/141749603)) investigate if this can be part of client focus change dispatch
- // Tracks the currently focused window used to update pointer capture state in clients
- private AtomicReference<IWindow> mFocusedWindow = new AtomicReference<>();
-
- // Tracks focused window pointer capture state
- private boolean mFocusedWindowHasCapture;
-
public InputManagerCallback(WindowManagerService service) {
mService = service;
}
@@ -234,59 +224,9 @@
}
@Override
- public boolean notifyFocusChanged(IBinder oldToken, IBinder newToken) {
- boolean requestRefreshConfiguration = false;
- final IWindow newFocusedWindow;
- final WindowState win;
-
- // TODO(b/141749603) investigate if this can be part of client focus change dispatch
- synchronized (mService.mGlobalLock) {
- win = mService.mInputToWindowMap.get(newToken);
- }
- newFocusedWindow = (win != null) ? win.mClient : null;
-
- final IWindow focusedWindow = mFocusedWindow.get();
- if (focusedWindow != null) {
- if (newFocusedWindow != null
- && newFocusedWindow.asBinder() == focusedWindow.asBinder()) {
- Slog.w(TAG, "notifyFocusChanged called with unchanged mFocusedWindow="
- + focusedWindow);
- return false;
- }
- requestRefreshConfiguration = dispatchPointerCaptureChanged(focusedWindow, false);
- }
- mFocusedWindow.set(newFocusedWindow);
- mService.mH.sendMessage(PooledLambda.obtainMessage(mService::reportFocusChanged,
- oldToken, newToken));
- return requestRefreshConfiguration;
- }
-
- @Override
- public boolean requestPointerCapture(IBinder windowToken, boolean enabled) {
- final IWindow focusedWindow = mFocusedWindow.get();
- if (focusedWindow == null || focusedWindow.asBinder() != windowToken) {
- Slog.e(TAG, "requestPointerCapture called for a window that has no focus: "
- + windowToken);
- return false;
- }
- if (mFocusedWindowHasCapture == enabled) {
- Slog.i(TAG, "requestPointerCapture: already " + (enabled ? "enabled" : "disabled"));
- return false;
- }
- return dispatchPointerCaptureChanged(focusedWindow, enabled);
- }
-
- private boolean dispatchPointerCaptureChanged(IWindow focusedWindow, boolean enabled) {
- if (mFocusedWindowHasCapture != enabled) {
- mFocusedWindowHasCapture = enabled;
- try {
- focusedWindow.dispatchPointerCaptureChanged(enabled);
- } catch (RemoteException ex) {
- /* ignore */
- }
- return true;
- }
- return false;
+ public void notifyFocusChanged(IBinder oldToken, IBinder newToken) {
+ mService.mH.sendMessage(PooledLambda.obtainMessage(
+ mService::reportFocusChanged, oldToken, newToken));
}
/** Waits until the built-in input devices have been configured. */
diff --git a/services/core/java/com/android/server/wm/LaunchParamsController.java b/services/core/java/com/android/server/wm/LaunchParamsController.java
index 8745e95..35653f9 100644
--- a/services/core/java/com/android/server/wm/LaunchParamsController.java
+++ b/services/core/java/com/android/server/wm/LaunchParamsController.java
@@ -73,11 +73,12 @@
* @param activity The {@link ActivityRecord} currently being positioned.
* @param source The {@link ActivityRecord} from which activity was started from.
* @param options The {@link ActivityOptions} specified for the activity.
- * @param result The resulting params.
* @param request The optional request from the activity starter.
+ * @param phase The {@link LaunchParamsModifier.Phase} that the resolution should finish.
+ * @param result The resulting params.
*/
void calculate(Task task, WindowLayout layout, ActivityRecord activity, ActivityRecord source,
- ActivityOptions options, int phase, LaunchParams result, @Nullable Request request) {
+ ActivityOptions options, @Nullable Request request, int phase, LaunchParams result) {
result.reset();
if (task != null || activity != null) {
@@ -92,8 +93,8 @@
mTmpResult.reset();
final LaunchParamsModifier modifier = mModifiers.get(i);
- switch(modifier.onCalculate(task, layout, activity, source, options, phase, mTmpCurrent,
- mTmpResult, request)) {
+ switch(modifier.onCalculate(task, layout, activity, source, options, request, phase,
+ mTmpCurrent, mTmpResult)) {
case RESULT_SKIP:
// Do not apply any results when we are told to skip
continue;
@@ -130,8 +131,8 @@
boolean layoutTask(Task task, WindowLayout layout, ActivityRecord activity,
ActivityRecord source, ActivityOptions options) {
- calculate(task, layout, activity, source, options, PHASE_BOUNDS, mTmpParams,
- null /* request */);
+ calculate(task, layout, activity, source, options, null /* request */, PHASE_BOUNDS,
+ mTmpParams);
// No changes, return.
if (mTmpParams.isEmpty()) {
@@ -308,17 +309,17 @@
* launched should have this be non-null.
* @param source the Activity that launched a new task. Could be {@code null}.
* @param options {@link ActivityOptions} used to start the activity with.
+ * @param request Optional data to give more context on the launch
* @param phase the calculation phase, see {@link Phase}
* @param currentParams launching params after the process of last {@link
* LaunchParamsModifier}.
* @param outParams the result params to be set.
- * @param request Optional data to give more context on the launch
* @return see {@link LaunchParamsModifier.Result}
*/
@Result
- int onCalculate(@Nullable Task task, WindowLayout layout, ActivityRecord activity,
- ActivityRecord source, ActivityOptions options, @Phase int phase,
- LaunchParams currentParams, LaunchParams outParams,
- @Nullable Request request);
+ int onCalculate(@Nullable Task task, @Nullable WindowLayout layout,
+ @Nullable ActivityRecord activity, @Nullable ActivityRecord source,
+ @Nullable ActivityOptions options, @Nullable Request request,
+ @Phase int phase, LaunchParams currentParams, LaunchParams outParams);
}
}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index 05dcd36..5bcb287 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -413,9 +413,10 @@
@Override
public void onRootTaskOrderChanged(Task rootTask) {
- ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "onStackOrderChanged(): stack=%s", rootTask);
- if (mDefaultTaskDisplayArea.getIndexOf(rootTask) == -1 || !rootTask.shouldBeVisible(null)) {
- // The stack is not visible, so ignore this change
+ ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "onRootTaskOrderChanged(): rootTask=%s", rootTask);
+ if (mDefaultTaskDisplayArea.getRootTask(t -> t == rootTask) == null
+ || !rootTask.shouldBeVisible(null)) {
+ // The root task is not visible, so ignore this change
return;
}
final RecentsAnimationController controller =
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index af9069f..388577c 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -33,7 +33,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
import android.app.WindowConfiguration;
import android.graphics.Point;
import android.graphics.Rect;
diff --git a/services/core/java/com/android/server/wm/RootDisplayArea.java b/services/core/java/com/android/server/wm/RootDisplayArea.java
index 393055e..505af05 100644
--- a/services/core/java/com/android/server/wm/RootDisplayArea.java
+++ b/services/core/java/com/android/server/wm/RootDisplayArea.java
@@ -115,15 +115,11 @@
@Nullable
DisplayArea.Tokens findAreaForToken(int windowType, boolean ownerCanManageAppTokens,
boolean roundedCornerOverlay) {
- // TODO(b/159767464): cover TYPE_INPUT_METHOD(_DIALOG) case here. mAreaForLayer doesn't
- // contain IME container.
int windowLayerFromType = mWmService.mPolicy.getWindowLayerFromTypeLw(windowType,
- ownerCanManageAppTokens);
+ ownerCanManageAppTokens, roundedCornerOverlay);
if (windowLayerFromType == APPLICATION_LAYER) {
throw new IllegalArgumentException(
"There shouldn't be WindowToken on APPLICATION_LAYER");
- } else if (roundedCornerOverlay) {
- windowLayerFromType = mAreaForLayer.length - 1;
}
return mAreaForLayer[windowLayerFromType];
}
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index d652393..d926a36 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -1828,19 +1828,19 @@
}
/**
- * @return a list of activities which are the top ones in each visible stack. The first
+ * @return a list of activities which are the top ones in each visible root task. The first
* entry will be the focused activity.
*/
List<IBinder> getTopVisibleActivities() {
final ArrayList<IBinder> topActivityTokens = new ArrayList<>();
- final Task topFocusedStack = getTopDisplayFocusedRootTask();
+ final Task topFocusedRootTask = getTopDisplayFocusedRootTask();
// Traverse all displays.
- forAllRootTasks(stack -> {
- // Get top activity from a visible stack and add it to the list.
- if (stack.shouldBeVisible(null /* starting */)) {
- final ActivityRecord top = stack.getTopNonFinishingActivity();
+ forAllRootTasks(rootTask -> {
+ // Get top activity from a visible root task and add it to the list.
+ if (rootTask.shouldBeVisible(null /* starting */)) {
+ final ActivityRecord top = rootTask.getTopNonFinishingActivity();
if (top != null) {
- if (stack == topFocusedStack) {
+ if (rootTask == topFocusedRootTask) {
topActivityTokens.add(0, top.appToken);
} else {
topActivityTokens.add(top.appToken);
@@ -1854,9 +1854,9 @@
@Nullable
Task getTopDisplayFocusedRootTask() {
for (int i = getChildCount() - 1; i >= 0; --i) {
- final Task focusedStack = getChildAt(i).getFocusedRootTask();
- if (focusedStack != null) {
- return focusedStack;
+ final Task focusedRootTask = getChildAt(i).getFocusedRootTask();
+ if (focusedRootTask != null) {
+ return focusedRootTask;
}
}
return null;
@@ -1864,15 +1864,15 @@
@Nullable
ActivityRecord getTopResumedActivity() {
- final Task focusedStack = getTopDisplayFocusedRootTask();
- if (focusedStack == null) {
+ final Task focusedRootTask = getTopDisplayFocusedRootTask();
+ if (focusedRootTask == null) {
return null;
}
- final ActivityRecord resumedActivity = focusedStack.getResumedActivity();
+ final ActivityRecord resumedActivity = focusedRootTask.getResumedActivity();
if (resumedActivity != null && resumedActivity.app != null) {
return resumedActivity;
}
- // The top focused stack might not have a resumed activity yet - look on all displays in
+ // The top focused root task might not have a resumed activity yet - look on all displays in
// focus order.
return getItemFromTaskDisplayAreas(TaskDisplayArea::getFocusedActivity);
}
@@ -1997,36 +1997,36 @@
}
boolean switchUser(int userId, UserState uss) {
- final Task topFocusedStack = getTopDisplayFocusedRootTask();
- final int focusStackId = topFocusedStack != null
- ? topFocusedStack.getRootTaskId() : INVALID_TASK_ID;
- // We dismiss the docked stack whenever we switch users.
+ final Task topFocusedRootTask = getTopDisplayFocusedRootTask();
+ final int focusRootTaskId = topFocusedRootTask != null
+ ? topFocusedRootTask.getRootTaskId() : INVALID_TASK_ID;
+ // We dismiss the docked root task whenever we switch users.
if (getDefaultTaskDisplayArea().isSplitScreenModeActivated()) {
getDefaultTaskDisplayArea().onSplitScreenModeDismissed();
}
- // Also dismiss the pinned stack whenever we switch users. Removing the pinned stack will
- // also cause all tasks to be moved to the fullscreen stack at a position that is
+ // Also dismiss the pinned root task whenever we switch users. Removing the pinned root task
+ // will also cause all tasks to be moved to the fullscreen root task at a position that is
// appropriate.
removeRootTasksInWindowingModes(WINDOWING_MODE_PINNED);
- mUserRootTaskInFront.put(mCurrentUser, focusStackId);
+ mUserRootTaskInFront.put(mCurrentUser, focusRootTaskId);
mCurrentUser = userId;
mTaskSupervisor.mStartingUsers.add(uss);
- forAllRootTasks(stack -> {
- stack.switchUser(userId);
+ forAllRootTasks(rootTask -> {
+ rootTask.switchUser(userId);
});
- final int restoreStackId = mUserRootTaskInFront.get(userId);
- Task stack = getRootTask(restoreStackId);
- if (stack == null) {
- stack = getDefaultTaskDisplayArea().getOrCreateRootHomeTask();
+ final int restoreRootTaskId = mUserRootTaskInFront.get(userId);
+ Task rootTask = getRootTask(restoreRootTaskId);
+ if (rootTask == null) {
+ rootTask = getDefaultTaskDisplayArea().getOrCreateRootHomeTask();
}
- final boolean homeInFront = stack.isActivityTypeHome();
- if (stack.isOnHomeDisplay()) {
- stack.moveToFront("switchUserOnHomeDisplay");
+ final boolean homeInFront = rootTask.isActivityTypeHome();
+ if (rootTask.isOnHomeDisplay()) {
+ rootTask.moveToFront("switchUserOnHomeDisplay");
} else {
- // Stack was moved to another display while user was swapped out.
+ // Root task was moved to another display while user was swapped out.
resumeHomeActivity(null, "switchUserOnOtherDisplay", getDefaultTaskDisplayArea());
}
return homeInFront;
@@ -2350,7 +2350,7 @@
return result;
}
- void applySleepTokens(boolean applyToStacks) {
+ void applySleepTokens(boolean applyToRootTasks) {
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
// Set the sleeping state of the display.
final DisplayContent display = getChildAt(displayNdx);
@@ -2360,17 +2360,17 @@
}
display.setIsSleeping(displayShouldSleep);
- if (!applyToStacks) {
+ if (!applyToRootTasks) {
continue;
}
- // Set the sleeping state of the stacks on the display.
- display.forAllRootTasks(stack -> {
+ // Set the sleeping state of the root tasks on the display.
+ display.forAllRootTasks(rootTask -> {
if (displayShouldSleep) {
- stack.goToSleepIfPossible(false /* shuttingDown */);
+ rootTask.goToSleepIfPossible(false /* shuttingDown */);
} else {
- stack.awakeFromSleepingLocked();
- if (stack.isFocusedStackOnDisplay()
+ rootTask.awakeFromSleepingLocked();
+ if (rootTask.isFocusedStackOnDisplay()
&& !mTaskSupervisor.getKeyguardController()
.isKeyguardOrAodShowing(display.mDisplayId)) {
// If the keyguard is unlocked - resume immediately.
@@ -2378,13 +2378,13 @@
// process the keyguard going away, which can happen before the sleep
// token is released. As a result, it is important we resume the
// activity here.
- stack.resumeTopActivityUncheckedLocked(null, null);
+ rootTask.resumeTopActivityUncheckedLocked(null, null);
}
// The visibility update must not be called before resuming the top, so the
// display orientation can be updated first if needed. Otherwise there may
// have redundant configuration changes due to apply outdated display
// orientation (from keyguard) to activity.
- stack.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
+ rootTask.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
false /* preserveWindows */);
}
});
@@ -2427,7 +2427,7 @@
task.fillTaskInfo(info);
// A task might be not attached to a display.
- info.position = taskDisplayArea != null ? taskDisplayArea.getIndexOf(task) : 0;
+ info.position = taskDisplayArea != null ? taskDisplayArea.getTaskIndexOf(task) : 0;
info.visible = task.shouldBeVisible(null);
task.getBounds(info.bounds);
@@ -2471,21 +2471,21 @@
}
RootTaskInfo getRootTaskInfo(int windowingMode, int activityType) {
- final Task stack = getRootTask(windowingMode, activityType);
- return (stack != null) ? getRootTaskInfo(stack) : null;
+ final Task rootTask = getRootTask(windowingMode, activityType);
+ return (rootTask != null) ? getRootTaskInfo(rootTask) : null;
}
RootTaskInfo getRootTaskInfo(int windowingMode, int activityType, int displayId) {
- final Task stack = getRootTask(windowingMode, activityType, displayId);
- return (stack != null) ? getRootTaskInfo(stack) : null;
+ final Task rootTask = getRootTask(windowingMode, activityType, displayId);
+ return (rootTask != null) ? getRootTaskInfo(rootTask) : null;
}
/** If displayId == INVALID_DISPLAY, this will get root task infos on all displays */
ArrayList<RootTaskInfo> getAllRootTaskInfos(int displayId) {
final ArrayList<RootTaskInfo> list = new ArrayList<>();
if (displayId == INVALID_DISPLAY) {
- forAllRootTasks(stack -> {
- list.add(getRootTaskInfo(stack));
+ forAllRootTasks(rootTask -> {
+ list.add(getRootTaskInfo(rootTask));
});
return list;
}
@@ -2493,8 +2493,8 @@
if (display == null) {
return list;
}
- display.forAllRootTasks(stack -> {
- list.add(getRootTaskInfo(stack));
+ display.forAllRootTasks(rootTask -> {
+ list.add(getRootTaskInfo(rootTask));
});
return list;
}
@@ -2955,8 +2955,8 @@
}
// If {@code r} is already in target display area and its task is the same as the candidate
- // task, the intention should be getting a launch stack for the reusable activity, so we can
- // use the existing stack.
+ // task, the intention should be getting a launch root task for the reusable activity, so we
+ // can use the existing root task.
if (candidateTask != null) {
final TaskDisplayArea attachedTaskDisplayArea = candidateTask.getDisplayArea();
if (attachedTaskDisplayArea == null || attachedTaskDisplayArea == taskDisplayArea) {
@@ -2965,9 +2965,9 @@
// Or the candidate task is already a root task that can be reused by reparenting
// it to the target display.
if (candidateTask.isRootTask()) {
- final Task stack = candidateTask.getRootTask();
- stack.reparent(taskDisplayArea, true /* onTop */);
- return stack;
+ final Task rootTask = candidateTask.getRootTask();
+ rootTask.reparent(taskDisplayArea, true /* onTop */);
+ return rootTask;
}
}
@@ -2984,16 +2984,16 @@
windowingMode = taskDisplayArea.validateWindowingMode(windowingMode, r, candidateTask,
r.getActivityType());
- // Return the topmost valid stack on the display.
+ // Return the topmost valid root task on the display.
final int targetWindowingMode = windowingMode;
- final Task topmostValidStack = taskDisplayArea.getRootTask(stack ->
- isValidLaunchRootTask(stack, r, targetWindowingMode));
- if (topmostValidStack != null) {
- return topmostValidStack;
+ final Task topmostValidRootTask = taskDisplayArea.getRootTask(rootTask ->
+ isValidLaunchRootTask(rootTask, r, targetWindowingMode));
+ if (topmostValidRootTask != null) {
+ return topmostValidRootTask;
}
- // If there is no valid stack on the secondary display area - check if new dynamic stack
- // will do.
+ // If there is no valid root task on the secondary display area - check if new dynamic root
+ // task will do.
if (taskDisplayArea != getDisplayContent(taskDisplayArea.getDisplayId())
.getDefaultTaskDisplayArea()) {
final int activityType =
@@ -3224,8 +3224,8 @@
}
void finishVoiceTask(IVoiceInteractionSession session) {
- forAllRootTasks(stack -> {
- stack.finishVoiceTask(session);
+ forAllRootTasks(rootTask -> {
+ rootTask.finishVoiceTask(session);
});
}
@@ -3284,8 +3284,8 @@
boolean allResumedActivitiesVisible() {
boolean[] foundResumed = {false};
- final boolean foundInvisibleResumedActivity = forAllRootTasks(stack -> {
- final ActivityRecord r = stack.getResumedActivity();
+ final boolean foundInvisibleResumedActivity = forAllRootTasks(rootTask -> {
+ final ActivityRecord r = rootTask.getResumedActivity();
if (r != null) {
if (!r.nowVisible) {
return true;
@@ -3529,9 +3529,9 @@
}
} else {
final ArrayList<ActivityRecord> activities = new ArrayList<>();
- forAllRootTasks(stack -> {
- if (!dumpVisibleStacksOnly || stack.shouldBeVisible(null)) {
- activities.addAll(stack.getDumpActivitiesLocked(name));
+ forAllRootTasks(rootTask -> {
+ if (!dumpVisibleStacksOnly || rootTask.shouldBeVisible(null)) {
+ activities.addAll(rootTask.getDumpActivitiesLocked(name));
}
});
return activities;
@@ -3581,11 +3581,11 @@
pw.print("Display #");
pw.print(displayContent.mDisplayId);
pw.println(" (activities from top to bottom):");
- displayContent.forAllRootTasks(stack -> {
+ displayContent.forAllRootTasks(rootTask -> {
if (needSep[0]) {
pw.println();
}
- needSep[0] = stack.dump(fd, pw, dumpAll, dumpClient, dumpPackage, false);
+ needSep[0] = rootTask.dump(fd, pw, dumpAll, dumpClient, dumpPackage, false);
printed[0] |= needSep[0];
});
displayContent.forAllTaskDisplayAreas(taskDisplayArea -> {
diff --git a/services/core/java/com/android/server/wm/SnapshotStartingData.java b/services/core/java/com/android/server/wm/SnapshotStartingData.java
index 3764122..2124ed6 100644
--- a/services/core/java/com/android/server/wm/SnapshotStartingData.java
+++ b/services/core/java/com/android/server/wm/SnapshotStartingData.java
@@ -16,7 +16,7 @@
package com.android.server.wm;
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
import com.android.server.policy.WindowManagerPolicy.StartingSurface;
@@ -28,14 +28,15 @@
private final WindowManagerService mService;
private final TaskSnapshot mSnapshot;
- SnapshotStartingData(WindowManagerService service, TaskSnapshot snapshot) {
- super(service);
+ SnapshotStartingData(WindowManagerService service, TaskSnapshot snapshot, int typeParams) {
+ super(service, typeParams);
mService = service;
mSnapshot = snapshot;
}
@Override
StartingSurface createStartingSurface(ActivityRecord activity) {
- return mService.mTaskSnapshotController.createStartingSurface(activity, mSnapshot);
+ return mService.mStartingSurfaceController.createTaskSnapshotSurface(activity,
+ mSnapshot);
}
}
diff --git a/services/core/java/com/android/server/wm/SplashScreenStartingData.java b/services/core/java/com/android/server/wm/SplashScreenStartingData.java
index 50a101d..185a317 100644
--- a/services/core/java/com/android/server/wm/SplashScreenStartingData.java
+++ b/services/core/java/com/android/server/wm/SplashScreenStartingData.java
@@ -38,8 +38,8 @@
SplashScreenStartingData(WindowManagerService service, String pkg, int theme,
CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon,
- int logo, int windowFlags, Configuration mergedOverrideConfiguration) {
- super(service);
+ int logo, int windowFlags, Configuration mergedOverrideConfiguration, int typeParams) {
+ super(service, typeParams);
mPkg = pkg;
mTheme = theme;
mCompatInfo = compatInfo;
diff --git a/services/core/java/com/android/server/wm/StartingData.java b/services/core/java/com/android/server/wm/StartingData.java
index 2e6e777..a5bd797 100644
--- a/services/core/java/com/android/server/wm/StartingData.java
+++ b/services/core/java/com/android/server/wm/StartingData.java
@@ -24,9 +24,11 @@
public abstract class StartingData {
protected final WindowManagerService mService;
+ protected final int mTypeParams;
- protected StartingData(WindowManagerService service) {
+ protected StartingData(WindowManagerService service, int typeParams) {
mService = service;
+ mTypeParams = typeParams;
}
/**
diff --git a/services/core/java/com/android/server/wm/StartingSurfaceController.java b/services/core/java/com/android/server/wm/StartingSurfaceController.java
index 6d7ddf6..94e14dd 100644
--- a/services/core/java/com/android/server/wm/StartingSurfaceController.java
+++ b/services/core/java/com/android/server/wm/StartingSurfaceController.java
@@ -16,9 +16,20 @@
package com.android.server.wm;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_CREATED;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_NEW_TASK;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_PROCESS_RUNNING;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_TASK_SWITCH;
+
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.os.SystemProperties;
+import android.util.Slog;
+import android.window.TaskSnapshot;
import com.android.server.policy.WindowManagerPolicy.StartingSurface;
@@ -26,7 +37,8 @@
* Managing to create and release a starting window surface.
*/
public class StartingSurfaceController {
-
+ private static final String TAG = TAG_WITH_CLASS_NAME
+ ? StartingSurfaceController.class.getSimpleName() : TAG_WM;
/** Set to {@code true} to enable shell starting surface drawer. */
private static final boolean DEBUG_ENABLE_SHELL_DRAWER =
SystemProperties.getBoolean("persist.debug.shell_starting_surface", false);
@@ -49,15 +61,79 @@
final Task task = activity.getTask();
if (task != null && mService.mAtmService.mTaskOrganizerController.addStartingWindow(task,
activity.token)) {
- return new SplashScreenContainerSurface(task);
+ return new ShellStartingSurface(task);
}
return null;
}
- private final class SplashScreenContainerSurface implements StartingSurface {
+ int makeStartingWindowTypeParameter(boolean newTask, boolean taskSwitch,
+ boolean processRunning, boolean allowTaskSnapshot, boolean activityCreated) {
+ int parameter = 0;
+ if (newTask) {
+ parameter |= TYPE_PARAMETER_NEW_TASK;
+ }
+ if (taskSwitch) {
+ parameter |= TYPE_PARAMETER_TASK_SWITCH;
+ }
+ if (processRunning) {
+ parameter |= TYPE_PARAMETER_PROCESS_RUNNING;
+ }
+ if (allowTaskSnapshot) {
+ parameter |= TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT;
+ }
+ if (activityCreated) {
+ parameter |= TYPE_PARAMETER_ACTIVITY_CREATED;
+ }
+ return parameter;
+ }
+
+ StartingSurface createTaskSnapshotSurface(ActivityRecord activity, TaskSnapshot taskSnapshot) {
+ final WindowState topFullscreenOpaqueWindow;
+ final Task task;
+ synchronized (mService.mGlobalLock) {
+ final WindowState mainWindow = activity.findMainWindow();
+ task = activity.getTask();
+ if (task == null) {
+ Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find task for activity="
+ + activity);
+ return null;
+ }
+ final ActivityRecord topFullscreenActivity =
+ activity.getTask().getTopFullscreenActivity();
+ if (topFullscreenActivity == null) {
+ Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find top fullscreen for task="
+ + task);
+ return null;
+ }
+ topFullscreenOpaqueWindow = topFullscreenActivity.getTopFullscreenOpaqueWindow();
+ if (mainWindow == null || topFullscreenOpaqueWindow == null) {
+ Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find main window for activity="
+ + activity);
+ return null;
+ }
+ if (topFullscreenActivity.getWindowConfiguration().getRotation()
+ != taskSnapshot.getRotation()) {
+ // The snapshot should have been checked by ActivityRecord#isSnapshotCompatible
+ // that the activity will be updated to the same rotation as the snapshot. Since
+ // the transition is not started yet, fixed rotation transform needs to be applied
+ // earlier to make the snapshot show in a rotated container.
+ activity.mDisplayContent.handleTopActivityLaunchingInDifferentOrientation(
+ topFullscreenActivity, false /* checkOpening */);
+ }
+ }
+ if (!DEBUG_ENABLE_SHELL_DRAWER) {
+ return mService.mTaskSnapshotController
+ .createStartingSurface(activity, taskSnapshot);
+ }
+ mService.mAtmService.mTaskOrganizerController.addStartingWindow(task, activity.token);
+ return new ShellStartingSurface(task);
+ }
+
+
+ private final class ShellStartingSurface implements StartingSurface {
private final Task mTask;
- SplashScreenContainerSurface(Task task) {
+ ShellStartingSurface(Task task) {
mTask = task;
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 69723ff..79a32e4 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -156,7 +156,6 @@
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.TaskDescription;
-import android.app.ActivityManager.TaskSnapshot;
import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
import android.app.AppGlobals;
@@ -207,6 +206,8 @@
import android.view.WindowManager;
import android.view.WindowManager.TransitionOldType;
import android.window.ITaskOrganizer;
+import android.window.StartingWindowInfo;
+import android.window.TaskSnapshot;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -3812,7 +3813,7 @@
mTaskDescription = taskDescription;
}
- void onSnapshotChanged(ActivityManager.TaskSnapshot snapshot) {
+ void onSnapshotChanged(TaskSnapshot snapshot) {
mAtmService.getTaskChangeNotificationController().notifyTaskSnapshotChanged(
mTaskId, snapshot);
}
@@ -4145,6 +4146,34 @@
return info;
}
+ StartingWindowInfo getStartingWindowInfo() {
+ final StartingWindowInfo info = new StartingWindowInfo();
+ info.taskInfo = getTaskInfo();
+
+ final ActivityRecord topActivity = getTopMostActivity();
+ if (topActivity != null) {
+ info.startingWindowTypeParameter =
+ topActivity.mStartingData != null
+ ? topActivity.mStartingData.mTypeParams
+ : 0;
+ final WindowState mainWindow = topActivity.findMainWindow();
+ if (mainWindow != null) {
+ info.mainWindowLayoutParams = mainWindow.getAttrs();
+ }
+ }
+ final ActivityRecord topFullscreenActivity = getTopFullscreenActivity();
+ if (topFullscreenActivity != null) {
+ final WindowState topFullscreenOpaqueWindow =
+ topFullscreenActivity.getTopFullscreenOpaqueWindow();
+ if (topFullscreenOpaqueWindow != null) {
+ info.topOpaqueWindowInsetsState =
+ topFullscreenOpaqueWindow.getInsetsStateWithVisibilityOverride();
+ info.topOpaqueWindowLayoutParams = topFullscreenOpaqueWindow.getAttrs();
+ }
+ }
+ return info;
+ }
+
boolean isTaskId(int taskId) {
return mTaskId == taskId;
}
@@ -5320,20 +5349,19 @@
final TaskDisplayArea taskDisplayArea = getDisplayArea();
if (inSplitScreenSecondaryWindowingMode()) {
- // If the stack is in split-screen secondary mode, we need to make sure we move the
- // primary split-screen stack forward in the case it is currently behind a fullscreen
- // stack so both halves of the split-screen appear on-top and the fullscreen stack isn't
- // cutting between them.
+ // If the root task is in split-screen secondary mode, we need to make sure we move the
+ // primary split-screen root task forward in the case it is currently behind a
+ // fullscreen root task so both halves of the split-screen appear on-top and the
+ // fullscreen root task isn't cutting between them.
// TODO(b/70677280): This is a workaround until we can fix as part of b/70677280.
- final Task topFullScreenStack =
+ final Task topFullScreenRootTask =
taskDisplayArea.getTopRootTaskInWindowingMode(WINDOWING_MODE_FULLSCREEN);
- if (topFullScreenStack != null) {
- final Task primarySplitScreenStack =
+ if (topFullScreenRootTask != null) {
+ final Task primarySplitScreenRootTask =
taskDisplayArea.getRootSplitScreenPrimaryTask();
- if (primarySplitScreenStack != null
- && taskDisplayArea.getIndexOf(topFullScreenStack)
- > taskDisplayArea.getIndexOf(primarySplitScreenStack)) {
- primarySplitScreenStack.moveToFront(reason + " splitScreenToTop");
+ if (primarySplitScreenRootTask != null
+ && topFullScreenRootTask.compareTo(primarySplitScreenRootTask) > 0) {
+ primarySplitScreenRootTask.moveToFront(reason + " splitScreenToTop");
}
}
}
@@ -5748,7 +5776,7 @@
}
/**
- * @return {@code true} if this is the focused stack on its current display, {@code false}
+ * @return {@code true} if this is the focused root task on its current display, {@code false}
* otherwise.
*/
boolean isFocusedStackOnDisplay() {
@@ -6700,18 +6728,21 @@
});
}
- /** @return true if the stack behind this one is a standard activity type. */
- private boolean inFrontOfStandardStack() {
+ /** @return true if the root task behind this one is a standard activity type. */
+ private boolean inFrontOfStandardRootTask() {
final TaskDisplayArea taskDisplayArea = getDisplayArea();
if (taskDisplayArea == null) {
return false;
}
- final int index = taskDisplayArea.getIndexOf(this);
+ final int index = taskDisplayArea.getTaskIndexOf(this);
if (index == 0) {
return false;
}
- final Task stackBehind = taskDisplayArea.getChildAt(index - 1);
- return stackBehind.isActivityTypeStandard();
+ final int[] indexCount = new int[1];
+ final Task rootTaskBehind = taskDisplayArea.getRootTask(
+ // From bottom to top, find the one behind this Task.
+ task -> ++indexCount[0] == index, false /* traverseTopToBottom */);
+ return rootTaskBehind.isActivityTypeStandard();
}
boolean shouldUpRecreateTaskLocked(ActivityRecord srec, String destAffinity) {
@@ -6732,7 +6763,7 @@
if (srec.isRootOfTask() && task.getBaseIntent() != null
&& task.getBaseIntent().isDocument()) {
// Okay, this activity is at the root of its task. What to do, what to do...
- if (!inFrontOfStandardStack()) {
+ if (!inFrontOfStandardRootTask()) {
// Finishing won't return to an application, so we need to recreate.
return true;
}
diff --git a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
index b4d069c..28ebe01 100644
--- a/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
+++ b/services/core/java/com/android/server/wm/TaskChangeNotificationController.java
@@ -18,7 +18,7 @@
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
import android.app.ITaskStackListener;
import android.app.TaskInfo;
import android.content.ComponentName;
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index 7fed840..866abbd 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -71,8 +71,10 @@
/**
* {@link DisplayArea} that represents a section of a screen that contains app window containers.
+ *
+ * The children can be either {@link Task} or {@link TaskDisplayArea}.
*/
-final class TaskDisplayArea extends DisplayArea<Task> {
+final class TaskDisplayArea extends DisplayArea<WindowContainer> {
DisplayContent mDisplayContent;
@@ -106,9 +108,9 @@
// TODO(b/159029784): Remove when getStack() behavior is cleaned-up
private Task mRootRecentsTask;
- private final ArrayList<Task> mTmpAlwaysOnTopRootTasks = new ArrayList<>();
- private final ArrayList<Task> mTmpNormalRootTasks = new ArrayList<>();
- private final ArrayList<Task> mTmpHomeRootTasks = new ArrayList<>();
+ private final ArrayList<WindowContainer> mTmpAlwaysOnTopChildren = new ArrayList<>();
+ private final ArrayList<WindowContainer> mTmpNormalChildren = new ArrayList<>();
+ private final ArrayList<WindowContainer> mTmpHomeChildren = new ArrayList<>();
private final IntArray mTmpNeedsZBoostIndexes = new IntArray();
private int mTmpLayerForSplitScreenDividerAnchor;
private int mTmpLayerForAnimationLayer;
@@ -179,9 +181,10 @@
}
/**
- * Returns the topmost stack on the display that is compatible with the input windowing mode
- * and activity type. Null is no compatible stack on the display.
+ * Returns the topmost root task on the display that is compatible with the input windowing mode
+ * and activity type. Null is no compatible root task on the display.
*/
+ @Nullable
Task getRootTask(int windowingMode, int activityType) {
if (activityType == ACTIVITY_TYPE_HOME) {
return mRootHomeTask;
@@ -193,30 +196,48 @@
} else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
return mRootSplitScreenPrimaryTask;
}
- for (int i = getChildCount() - 1; i >= 0; --i) {
- final Task stack = getChildAt(i);
+ return getRootTask(rootTask -> {
if (activityType == ACTIVITY_TYPE_UNDEFINED
- && windowingMode == stack.getWindowingMode()) {
- // Passing in undefined type means we want to match the topmost stack with the
+ && windowingMode == rootTask.getWindowingMode()) {
+ // Passing in undefined type means we want to match the topmost root task with the
// windowing mode.
- return stack;
+ return true;
}
- if (stack.isCompatible(windowingMode, activityType)) {
- return stack;
- }
- }
- return null;
+ return rootTask.isCompatible(windowingMode, activityType);
+ });
}
@VisibleForTesting
Task getTopRootTask() {
- final int count = getChildCount();
- return count > 0 ? getChildAt(count - 1) : null;
+ return getRootTask(t -> true);
}
- // TODO: Figure-out a way to remove since it might be a source of confusion.
- int getIndexOf(Task task) {
- return mChildren.indexOf(task);
+ // TODO(b/175832855): Figure-out a way to remove since it might be a source of confusion.
+ /**
+ * Gets the order of the given {@link Task} as its z-order in the hierarchy below this TDA.
+ * The Task can be a direct child of a child TaskDisplayArea. {@code -1} if not found.
+ */
+ int getTaskIndexOf(Task task) {
+ int index = 0;
+ final int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ final WindowContainer wc = getChildAt(i);
+ if (wc.asTask() != null) {
+ if (wc.asTask() == task) {
+ return index;
+ }
+ index++;
+ } else {
+ final TaskDisplayArea tda = wc.asTaskDisplayArea();
+ final int subIndex = tda.getTaskIndexOf(task);
+ if (subIndex > -1) {
+ return index + subIndex;
+ } else {
+ index += tda.getRootTaskCount();
+ }
+ }
+ }
+ return -1;
}
@Nullable
@@ -238,9 +259,11 @@
}
Task getRootSplitScreenSecondaryTask() {
+ // Only check the direct child Task for now, since the primary is also a direct child Task.
for (int i = mChildren.size() - 1; i >= 0; --i) {
- if (mChildren.get(i).inSplitScreenSecondaryWindowingMode()) {
- return mChildren.get(i);
+ final Task task = mChildren.get(i).asTask();
+ if (task != null && task.inSplitScreenSecondaryWindowingMode()) {
+ return task;
}
}
return null;
@@ -323,7 +346,22 @@
}
@Override
- void addChild(Task task, int position) {
+ void addChild(WindowContainer child, int position) {
+ if (child.asTaskDisplayArea() != null) {
+ if (DEBUG_ROOT_TASK) {
+ Slog.d(TAG_WM, "Set TaskDisplayArea=" + child + " on taskDisplayArea=" + this);
+ }
+ super.addChild(child, position);
+ } else if (child.asTask() != null) {
+ addChildTask(child.asTask(), position);
+ } else {
+ throw new IllegalArgumentException(
+ "TaskDisplayArea can only add Task and TaskDisplayArea, but found "
+ + child);
+ }
+ }
+
+ private void addChildTask(Task task, int position) {
if (DEBUG_ROOT_TASK) Slog.d(TAG_WM, "Set task=" + task + " on taskDisplayArea=" + this);
addRootTaskReferenceIfNeeded(task);
@@ -335,11 +373,23 @@
}
@Override
- protected void removeChild(Task stack) {
- super.removeChild(stack);
- onRootTaskRemoved(stack);
+ protected void removeChild(WindowContainer child) {
+ if (child.asTaskDisplayArea() != null) {
+ super.removeChild(child);
+ } else if (child.asTask() != null) {
+ removeChildTask(child.asTask());
+ } else {
+ throw new IllegalArgumentException(
+ "TaskDisplayArea can only remove Task and TaskDisplayArea, but found "
+ + child);
+ }
+ }
+
+ private void removeChildTask(Task task) {
+ super.removeChild(task);
+ onRootTaskRemoved(task);
mAtmService.updateSleepIfNeededLocked();
- removeRootTaskReferenceIfNeeded(stack);
+ removeRootTaskReferenceIfNeeded(task);
}
@Override
@@ -349,21 +399,33 @@
}
@Override
- void positionChildAt(int position, Task child, boolean includingParents) {
+ void positionChildAt(int position, WindowContainer child, boolean includingParents) {
+ if (child.asTaskDisplayArea() != null) {
+ super.positionChildAt(position, child, includingParents);
+ } else if (child.asTask() != null) {
+ positionChildTaskAt(position, child.asTask(), includingParents);
+ } else {
+ throw new IllegalArgumentException(
+ "TaskDisplayArea can only position Task and TaskDisplayArea, but found "
+ + child);
+ }
+ }
+
+ private void positionChildTaskAt(int position, Task child, boolean includingParents) {
final boolean moveToTop = position >= getChildCount() - 1;
final boolean moveToBottom = position <= 0;
final int oldPosition = mChildren.indexOf(child);
if (child.getWindowConfiguration().isAlwaysOnTop() && !moveToTop) {
- // This stack is always-on-top, override the default behavior.
- Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + this + " to bottom");
+ // This root task is always-on-top, override the default behavior.
+ Slog.w(TAG_WM, "Ignoring move of always-on-top root task=" + this + " to bottom");
// Moving to its current position, as we must call super but we don't want to
// perform any meaningful action.
super.positionChildAt(oldPosition, child, false /* includingParents */);
return;
}
- // We don't allow untrusted display to top when task stack moves to top,
+ // We don't allow untrusted display to top when root task moves to top,
// until user tapping this display to change display position as top intentionally.
if (!mDisplayContent.isTrusted() && !getParent().isOnTop()) {
includingParents = false;
@@ -432,41 +494,78 @@
@Override
boolean forAllTaskDisplayAreas(Function<TaskDisplayArea, Boolean> callback,
boolean traverseTopToBottom) {
- return callback.apply(this);
+ // Apply the callback to all TDAs at or below this container. If the callback returns true,
+ // stop early.
+ if (traverseTopToBottom) {
+ // When it is top to bottom, run on child TDA first as they are on top of the parent.
+ return super.forAllTaskDisplayAreas(callback, traverseTopToBottom)
+ || callback.apply(this);
+ }
+ return callback.apply(this) || super.forAllTaskDisplayAreas(callback, traverseTopToBottom);
}
@Override
void forAllTaskDisplayAreas(Consumer<TaskDisplayArea> callback, boolean traverseTopToBottom) {
- callback.accept(this);
+ if (traverseTopToBottom) {
+ super.forAllTaskDisplayAreas(callback, traverseTopToBottom);
+ callback.accept(this);
+ } else {
+ callback.accept(this);
+ super.forAllTaskDisplayAreas(callback, traverseTopToBottom);
+ }
}
@Nullable
@Override
<R> R reduceOnAllTaskDisplayAreas(BiFunction<TaskDisplayArea, R, R> accumulator,
@Nullable R initValue, boolean traverseTopToBottom) {
- return accumulator.apply(this, initValue);
+ if (traverseTopToBottom) {
+ final R result =
+ super.reduceOnAllTaskDisplayAreas(accumulator, initValue, traverseTopToBottom);
+ return accumulator.apply(this, result);
+ } else {
+ final R result = accumulator.apply(this, initValue);
+ return super.reduceOnAllTaskDisplayAreas(accumulator, result, traverseTopToBottom);
+
+ }
}
@Nullable
@Override
<R> R getItemFromTaskDisplayAreas(Function<TaskDisplayArea, R> callback,
boolean traverseTopToBottom) {
- return callback.apply(this);
+ if (traverseTopToBottom) {
+ final R item = super.getItemFromTaskDisplayAreas(callback, traverseTopToBottom);
+ return item != null ? item : callback.apply(this);
+ } else {
+ final R item = callback.apply(this);
+ return item != null
+ ? item
+ : super.getItemFromTaskDisplayAreas(callback, traverseTopToBottom);
+ }
}
/**
- * Assigns a priority number to stack types. This priority defines an order between the types
- * of stacks that are added to the task display area.
+ * Assigns a priority number to root task types. This priority defines an order between the
+ * types of root task that are added to the task display area.
*
- * Higher priority number indicates that the stack should have a higher z-order.
+ * Higher priority number indicates that the root task should have a higher z-order.
*
- * @return the priority of the stack
+ * For child {@link TaskDisplayArea}, it will be the priority of its top child.
+ *
+ * @return the priority of the root task
*/
- private int getPriority(Task stack) {
- if (mWmService.mAssistantOnTopOfDream && stack.isActivityTypeAssistant()) return 4;
- if (stack.isActivityTypeDream()) return 3;
- if (stack.inPinnedWindowingMode()) return 2;
- if (stack.isAlwaysOnTop()) return 1;
+ private int getPriority(WindowContainer child) {
+ final TaskDisplayArea tda = child.asTaskDisplayArea();
+ if (tda != null) {
+ // Use the top child priority as the TaskDisplayArea priority.
+ return tda.getPriority(tda.getTopChild());
+ }
+ final Task rootTask = child.asTask();
+ if (mWmService.mAssistantOnTopOfDream && rootTask.isActivityTypeAssistant()) return 4;
+ if (rootTask.isActivityTypeDream()) return 3;
+ if (rootTask.inPinnedWindowingMode()) return 2;
+ if (rootTask.isAlwaysOnTop()) return 1;
return 0;
}
@@ -481,10 +580,12 @@
}
if (rootTask.isAlwaysOnTop()) {
- // Since a stack could be repositioned while still being one of the children, we check
- // if this always-on-top stack already exists and if so, set the minPosition to its
- // previous position.
- final int currentIndex = getIndexOf(rootTask);
+ // Since a root task could be repositioned while still being one of the children, we
+ // check if this always-on-top root task already exists and if so, set the minPosition
+ // to its previous position.
+ // Use mChildren.indexOf instead of getTaskIndexOf because we need to place the rootTask
+ // as a direct child.
+ final int currentIndex = mChildren.indexOf(rootTask);
if (currentIndex > minPosition) {
minPosition = currentIndex;
}
@@ -494,9 +595,9 @@
private int findMaxPositionForRootTask(Task rootTask) {
for (int i = mChildren.size() - 1; i >= 0; --i) {
- final Task curr = mChildren.get(i);
- // Since a stack could be repositioned while still being one of the children, we check
- // if 'curr' is the same stack and skip it if so
+ final WindowContainer curr = mChildren.get(i);
+ // Since a root task could be repositioned while still being one of the children, we
+ // check if 'curr' is the same root task and skip it if so
final boolean sameRootTask = curr == rootTask;
if (getPriority(curr) <= getPriority(rootTask) && !sameRootTask) {
return i;
@@ -506,29 +607,29 @@
}
/**
- * When stack is added or repositioned, find a proper position for it.
+ * When root task is added or repositioned, find a proper position for it.
*
* The order is defined as:
* - Dream is on top of everything
* - PiP is directly below the Dream
- * - always-on-top stacks are directly below PiP; new always-on-top stacks are added above
- * existing ones
- * - other non-always-on-top stacks come directly below always-on-top stacks; new
- * non-always-on-top stacks are added directly below always-on-top stacks and above existing
- * non-always-on-top stacks
+ * - always-on-top root tasks are directly below PiP; new always-on-top root tasks are added
+ * above existing ones
+ * - other non-always-on-top root tasks come directly below always-on-top root tasks; new
+ * non-always-on-top root tasks are added directly below always-on-top root tasks and above
+ * existing non-always-on-top root tasks
* - if {@link #mAssistantOnTopOfDream} is enabled, then Assistant is on top of everything
- * (including the Dream); otherwise, it is a normal non-always-on-top stack
+ * (including the Dream); otherwise, it is a normal non-always-on-top root task
*
* @param requestedPosition Position requested by caller.
* @param rootTask Root task to be added or positioned.
- * @param adding Flag indicates whether we're adding a new stack or positioning an
- * existing.
- * @return The proper position for the stack.
+ * @param adding Flag indicates whether we're adding a new root task or positioning
+ * an existing.
+ * @return The proper position for the root task.
*/
private int findPositionForRootTask(int requestedPosition, Task rootTask, boolean adding) {
- // The max possible position we can insert the stack at.
+ // The max possible position we can insert the root task at.
int maxPosition = findMaxPositionForRootTask(rootTask);
- // The min possible position we can insert the stack at.
+ // The min possible position we can insert the root task at.
int minPosition = findMinPositionForRootTask(rootTask);
// Cap the requested position to something reasonable for the previous position check
@@ -547,8 +648,8 @@
// The positions we calculated above (maxPosition, minPosition) do not take into
// consideration the following edge cases.
// 1) We need to adjust the position depending on the value "adding".
- // 2) When we are moving a stack to another position, we also need to adjust the
- // position depending on whether the stack is moving to a higher or lower position.
+ // 2) When we are moving a root task to another position, we also need to adjust the
+ // position depending on whether the root task is moving to a higher or lower position.
if ((targetPosition != requestedPosition) && (adding || targetPosition < prevPosition)) {
targetPosition++;
}
@@ -579,13 +680,19 @@
private boolean forAllExitingAppTokenWindows(ToBooleanFunction<WindowState> callback,
boolean traverseTopToBottom) {
- // For legacy reasons we process the TaskStack.mExitingActivities first here before the
+ // For legacy reasons we process the RootTask.mExitingActivities first here before the
// app tokens.
// TODO: Investigate if we need to continue to do this or if we can just process them
// in-order.
if (traverseTopToBottom) {
for (int i = mChildren.size() - 1; i >= 0; --i) {
- final List<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
+ // Only run on those of direct Task child, because child TaskDisplayArea has run on
+ // its child in #forAllWindows()
+ if (mChildren.get(i).asTask() == null) {
+ continue;
+ }
+ final List<ActivityRecord> activities =
+ mChildren.get(i).asTask().mExitingActivities;
for (int j = activities.size() - 1; j >= 0; --j) {
if (activities.get(j).forAllWindowsUnchecked(callback,
traverseTopToBottom)) {
@@ -596,7 +703,13 @@
} else {
final int count = mChildren.size();
for (int i = 0; i < count; ++i) {
- final List<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
+ // Only run on those of direct Task child, because child TaskDisplayArea has run on
+ // its child in #forAllWindows()
+ if (mChildren.get(i).asTask() == null) {
+ continue;
+ }
+ final List<ActivityRecord> activities =
+ mChildren.get(i).asTask().mExitingActivities;
final int appTokensCount = activities.size();
for (int j = 0; j < appTokensCount; j++) {
if (activities.get(j).forAllWindowsUnchecked(callback,
@@ -612,9 +725,18 @@
@Override
int getOrientation(int candidate) {
mLastOrientationSource = null;
- if (!canSpecifyOrientation()) {
+ if (mIgnoreOrientationRequest) {
return SCREEN_ORIENTATION_UNSET;
}
+ if (!canSpecifyOrientation()) {
+ // We only respect orientation of the focused TDA, which can be a child of this TDA.
+ return reduceOnAllTaskDisplayAreas((taskDisplayArea, orientation) -> {
+ if (taskDisplayArea == this || orientation != SCREEN_ORIENTATION_UNSET) {
+ return orientation;
+ }
+ return taskDisplayArea.getOrientation(candidate);
+ }, SCREEN_ORIENTATION_UNSET);
+ }
if (isRootTaskVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)) {
// Apps and their containers are not allowed to specify an orientation while using
@@ -671,8 +793,7 @@
assignRootTaskOrdering(t);
for (int i = 0; i < mChildren.size(); i++) {
- final Task s = mChildren.get(i);
- s.assignChildLayers(t);
+ mChildren.get(i).assignChildLayers(t);
}
}
@@ -680,33 +801,49 @@
if (getParent() == null) {
return;
}
- mTmpAlwaysOnTopRootTasks.clear();
- mTmpHomeRootTasks.clear();
- mTmpNormalRootTasks.clear();
+ mTmpAlwaysOnTopChildren.clear();
+ mTmpHomeChildren.clear();
+ mTmpNormalChildren.clear();
for (int i = 0; i < mChildren.size(); ++i) {
- final Task s = mChildren.get(i);
- if (s.isAlwaysOnTop()) {
- mTmpAlwaysOnTopRootTasks.add(s);
- } else if (s.isActivityTypeHome()) {
- mTmpHomeRootTasks.add(s);
+ final WindowContainer child = mChildren.get(i);
+ final TaskDisplayArea childTda = child.asTaskDisplayArea();
+ if (childTda != null) {
+ final Task childTdaTopRootTask = childTda.getTopRootTask();
+ if (childTdaTopRootTask == null) {
+ mTmpNormalChildren.add(childTda);
+ } else if (childTdaTopRootTask.isAlwaysOnTop()) {
+ mTmpAlwaysOnTopChildren.add(childTda);
+ } else if (childTdaTopRootTask.isActivityTypeHome()) {
+ mTmpHomeChildren.add(childTda);
+ } else {
+ mTmpNormalChildren.add(childTda);
+ }
+ continue;
+ }
+
+ final Task childTask = child.asTask();
+ if (childTask.isAlwaysOnTop()) {
+ mTmpAlwaysOnTopChildren.add(childTask);
+ } else if (childTask.isActivityTypeHome()) {
+ mTmpHomeChildren.add(childTask);
} else {
- mTmpNormalRootTasks.add(s);
+ mTmpNormalChildren.add(childTask);
}
}
int layer = 0;
// Place home stacks to the bottom.
- layer = adjustRootTaskLayer(t, mTmpHomeRootTasks, layer, false /* normalStacks */);
+ layer = adjustRootTaskLayer(t, mTmpHomeChildren, layer, false /* normalRootTasks */);
// The home animation layer is between the home stacks and the normal stacks.
final int layerForHomeAnimationLayer = layer++;
mTmpLayerForSplitScreenDividerAnchor = layer++;
mTmpLayerForAnimationLayer = layer++;
- layer = adjustRootTaskLayer(t, mTmpNormalRootTasks, layer, true /* normalStacks */);
+ layer = adjustRootTaskLayer(t, mTmpNormalChildren, layer, true /* normalRootTasks */);
// The boosted animation layer is between the normal stacks and the always on top
// stacks.
final int layerForBoostedAnimationLayer = layer++;
- adjustRootTaskLayer(t, mTmpAlwaysOnTopRootTasks, layer, false /* normalStacks */);
+ adjustRootTaskLayer(t, mTmpAlwaysOnTopChildren, layer, false /* normalRootTasks */);
t.setLayer(mHomeAppAnimationLayer, layerForHomeAnimationLayer);
t.setLayer(mAppAnimationLayer, mTmpLayerForAnimationLayer);
@@ -714,13 +851,14 @@
t.setLayer(mBoostedAppAnimationLayer, layerForBoostedAnimationLayer);
}
- private int adjustNormalRootTaskLayer(Task s, int layer) {
- if (s.inSplitScreenWindowingMode()) {
+ private int adjustNormalRootTaskLayer(WindowContainer child, int layer) {
+ if (child.asTask() != null && child.inSplitScreenWindowingMode()) {
// The split screen divider anchor is located above the split screen window.
mTmpLayerForSplitScreenDividerAnchor = layer++;
}
- if (s.isAnimatingByRecents() || s.isAppTransitioning()) {
- // The animation layer is located above the highest animating stack and no
+ if ((child.asTask() != null && child.asTask().isAnimatingByRecents())
+ || child.isAppTransitioning()) {
+ // The animation layer is located above the highest animating root task and no
// higher.
mTmpLayerForAnimationLayer = layer++;
}
@@ -728,23 +866,30 @@
}
/**
- * Adjusts the layer of the stack which belongs to the same group.
- * Note that there are three stack groups: home stacks, always on top stacks, and normal stacks.
+ * Adjusts the layer of the root task which belongs to the same group.
+ * Note that there are three root task groups: home rootTasks, always on top rootTasks, and
+ * normal rootTasks.
*
- * @param startLayer The beginning layer of this group of stacks.
- * @param normalStacks Set {@code true} if this group is neither home nor always on top.
+ * @param startLayer The beginning layer of this group of rootTasks.
+ * @param normalRootTasks Set {@code true} if this group is neither home nor always on top.
* @return The adjusted layer value.
*/
- private int adjustRootTaskLayer(SurfaceControl.Transaction t, ArrayList<Task> stacks,
- int startLayer, boolean normalStacks) {
+ private int adjustRootTaskLayer(SurfaceControl.Transaction t,
+ ArrayList<WindowContainer> children, int startLayer, boolean normalRootTasks) {
mTmpNeedsZBoostIndexes.clear();
- final int stackSize = stacks.size();
- for (int i = 0; i < stackSize; i++) {
- final Task stack = stacks.get(i);
- if (!stack.needsZBoost()) {
- stack.assignLayer(t, startLayer++);
- if (normalStacks) {
- startLayer = adjustNormalRootTaskLayer(stack, startLayer);
+ final int childCount = children.size();
+ for (int i = 0; i < childCount; i++) {
+ final WindowContainer child = children.get(i);
+ final TaskDisplayArea childTda = child.asTaskDisplayArea();
+
+ boolean childNeedsZBoost = childTda != null
+ ? childTda.childrenNeedZBoost()
+ : child.needsZBoost();
+
+ if (!childNeedsZBoost) {
+ child.assignLayer(t, startLayer++);
+ if (normalRootTasks) {
+ startLayer = adjustNormalRootTaskLayer(child, startLayer);
}
} else {
mTmpNeedsZBoostIndexes.add(i);
@@ -753,15 +898,23 @@
final int zBoostSize = mTmpNeedsZBoostIndexes.size();
for (int i = 0; i < zBoostSize; i++) {
- final Task stack = stacks.get(mTmpNeedsZBoostIndexes.get(i));
- stack.assignLayer(t, startLayer++);
- if (normalStacks) {
- startLayer = adjustNormalRootTaskLayer(stack, startLayer);
+ final WindowContainer child = children.get(mTmpNeedsZBoostIndexes.get(i));
+ child.assignLayer(t, startLayer++);
+ if (normalRootTasks) {
+ startLayer = adjustNormalRootTaskLayer(child, startLayer);
}
}
return startLayer;
}
+ private boolean childrenNeedZBoost() {
+ final boolean[] needsZBoost = new boolean[1];
+ forAllRootTasks(task -> {
+ needsZBoost[0] |= task.needsZBoost();
+ });
+ return needsZBoost[0];
+ }
+
@Override
SurfaceControl getAppAnimationLayer(@AnimationLayer int animationLayer) {
switch (animationLayer) {
@@ -1027,15 +1180,25 @@
return null;
}
for (int i = mChildren.size() - 1; i >= 0; --i) {
- final Task t = mChildren.get(i);
- if (!t.mCreatedByOrganizer || t.getRequestedOverrideWindowingMode() != windowingMode) {
+ final WindowContainer child = mChildren.get(i);
+ if (child.asTaskDisplayArea() != null) {
+ final Task t = child.asTaskDisplayArea().updateLaunchRootTask(windowingMode);
+ if (t != null) {
+ return t;
+ }
+ continue;
+ }
+
+ final Task t = mChildren.get(i).asTask();
+ if (t == null || !t.mCreatedByOrganizer
+ || t.getRequestedOverrideWindowingMode() != windowingMode) {
continue;
}
// If not already set, pick a launch root which is not the one we are launching into.
if (mLaunchRootTask == null) {
for (int j = 0, n = mChildren.size(); j < n; ++j) {
- final Task tt = mChildren.get(j);
- if (tt.mCreatedByOrganizer && tt != t) {
+ final Task tt = mChildren.get(j).asTask();
+ if (tt != null && tt.mCreatedByOrganizer && tt != t) {
mLaunchRootTask = tt;
break;
}
@@ -1081,8 +1244,8 @@
}
/**
- * Get the preferred focusable stack in priority. If the preferred stack does not exist, find a
- * focusable and visible stack from the top of stacks in this display.
+ * Get the preferred focusable root task in priority. If the preferred root task does not exist,
+ * find a focusable and visible root task from the top of root tasks in this display.
*/
Task getFocusedRootTask() {
if (mPreferredTopFocusableRootTask != null) {
@@ -1090,9 +1253,18 @@
}
for (int i = mChildren.size() - 1; i >= 0; --i) {
- final Task stack = mChildren.get(i);
- if (stack.isFocusableAndVisible()) {
- return stack;
+ final WindowContainer child = mChildren.get(i);
+ if (child.asTaskDisplayArea() != null) {
+ final Task rootTask = child.asTaskDisplayArea().getFocusedRootTask();
+ if (rootTask != null) {
+ return rootTask;
+ }
+ continue;
+ }
+
+ final Task rootTask = mChildren.get(i).asTask();
+ if (rootTask.isFocusableAndVisible()) {
+ return rootTask;
}
}
@@ -1105,7 +1277,17 @@
Task candidate = null;
for (int i = mChildren.size() - 1; i >= 0; --i) {
- final Task rootTask = mChildren.get(i);
+ final WindowContainer child = mChildren.get(i);
+ if (child.asTaskDisplayArea() != null) {
+ final Task rootTask = child.asTaskDisplayArea()
+ .getNextFocusableRootTask(currentFocus, ignoreCurrent);
+ if (rootTask != null) {
+ return rootTask;
+ }
+ continue;
+ }
+
+ final Task rootTask = mChildren.get(i).asTask();
if (ignoreCurrent && rootTask == currentFocus) {
continue;
}
@@ -1115,18 +1297,19 @@
if (currentWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
&& candidate == null && rootTask.inSplitScreenPrimaryWindowingMode()) {
- // If the currently focused stack is in split-screen secondary we save off the
- // top primary split-screen stack as a candidate for focus because we might
- // prefer focus to move to an other stack to avoid primary split-screen stack
- // overlapping with a fullscreen stack when a fullscreen stack is higher in z
- // than the next split-screen stack. Assistant stack, I am looking at you...
- // We only move the focus to the primary-split screen stack if there isn't a
+ // If the currently focused root task is in split-screen secondary we save off the
+ // top primary split-screen root task as a candidate for focus because we might
+ // prefer focus to move to an other root task to avoid primary split-screen root
+ // task overlapping with a fullscreen root task when a fullscreen root task is
+ // higher in z than the next split-screen root task. Assistant root task, I am
+ // looking at you...
+ // We only move the focus to the primary-split screen root task if there isn't a
// better alternative.
candidate = rootTask;
continue;
}
if (candidate != null && rootTask.inSplitScreenSecondaryWindowingMode()) {
- // Use the candidate stack since we are now at the secondary split-screen.
+ // Use the candidate root task since we are now at the secondary split-screen.
return candidate;
}
return rootTask;
@@ -1135,21 +1318,21 @@
}
ActivityRecord getFocusedActivity() {
- final Task focusedStack = getFocusedRootTask();
- if (focusedStack == null) {
+ final Task focusedRootTask = getFocusedRootTask();
+ if (focusedRootTask == null) {
return null;
}
// TODO(b/111541062): Move this into ActivityStack#getResumedActivity()
- // Check if the focused stack has the resumed activity
- ActivityRecord resumedActivity = focusedStack.getResumedActivity();
+ // Check if the focused root task has the resumed activity
+ ActivityRecord resumedActivity = focusedRootTask.getResumedActivity();
if (resumedActivity == null || resumedActivity.app == null) {
- // If there is no registered resumed activity in the stack or it is not running -
+ // If there is no registered resumed activity in the root task or it is not running -
// try to use previously resumed one.
- resumedActivity = focusedStack.getPausingActivity();
+ resumedActivity = focusedRootTask.getPausingActivity();
if (resumedActivity == null || resumedActivity.app == null) {
// If previously resumed activity doesn't work either - find the topmost running
// activity that can be focused.
- resumedActivity = focusedStack.topRunningActivity(true /* focusableOnly */);
+ resumedActivity = focusedRootTask.topRunningActivity(true /* focusableOnly */);
}
}
return resumedActivity;
@@ -1184,27 +1367,35 @@
}
boolean allResumedActivitiesComplete() {
- for (int stackNdx = mChildren.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityRecord r = mChildren.get(stackNdx).getResumedActivity();
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ final WindowContainer child = mChildren.get(i);
+ if (child.asTaskDisplayArea() != null) {
+ if (!child.asTaskDisplayArea().allResumedActivitiesComplete()) {
+ return false;
+ }
+ continue;
+ }
+
+ final ActivityRecord r = mChildren.get(i).asTask().getResumedActivity();
if (r != null && !r.isState(RESUMED)) {
return false;
}
}
- final Task currentFocusedStack = getFocusedRootTask();
+ final Task currentFocusedRootTask = getFocusedRootTask();
if (ActivityTaskManagerDebugConfig.DEBUG_ROOT_TASK) {
- Slog.d(TAG_ROOT_TASK, "allResumedActivitiesComplete: mLastFocusedStack changing from="
- + mLastFocusedRootTask + " to=" + currentFocusedStack);
+ Slog.d(TAG_ROOT_TASK, "allResumedActivitiesComplete: currentFocusedRootTask "
+ + "changing from=" + mLastFocusedRootTask + " to=" + currentFocusedRootTask);
}
- mLastFocusedRootTask = currentFocusedStack;
+ mLastFocusedRootTask = currentFocusedRootTask;
return true;
}
/**
- * Pause all activities in either all of the stacks or just the back stacks. This is done before
- * resuming a new activity and to make sure that previously active activities are
- * paused in stacks that are no longer visible or in pinned windowing mode. This does not
- * pause activities in visible stacks, so if an activity is launched within the same stack/task,
- * then we should explicitly pause that stack's top activity.
+ * Pause all activities in either all of the root tasks or just the back root tasks. This is
+ * done before resuming a new activity and to make sure that previously active activities are
+ * paused in root tasks that are no longer visible or in pinned windowing mode. This does not
+ * pause activities in visible root tasks, so if an activity is launched within the same root
+ * task, hen we should explicitly pause that root task's top activity.
*
* @param userLeaving Passed to pauseActivity() to indicate whether to call onUserLeaving().
* @param resuming The resuming activity.
@@ -1217,10 +1408,10 @@
if (resumedActivity != null
&& (task.getVisibility(resuming) != TASK_VISIBILITY_VISIBLE
|| !task.isTopActivityFocusable())) {
- ProtoLog.d(WM_DEBUG_STATES, "pauseBackStacks: task=%s "
+ ProtoLog.d(WM_DEBUG_STATES, "pauseBackTasks: task=%s "
+ "mResumedActivity=%s", task, resumedActivity);
if (task.startPausingLocked(userLeaving, false /* uiSleeping*/,
- resuming, "pauseBackStacks")) {
+ resuming, "pauseBackTasks")) {
someActivityPaused[0]++;
}
}
@@ -1234,18 +1425,21 @@
void findTaskLocked(final ActivityRecord r, final boolean isPreferredDisplayArea,
RootWindowContainer.FindTaskResult result) {
mTmpFindTaskResult.clear();
- for (int stackNdx = mChildren.size() - 1; stackNdx >= 0; --stackNdx) {
- final Task stack = mChildren.get(stackNdx);
- if (!r.hasCompatibleActivityType(stack) && stack.isLeafTask()) {
- ProtoLog.d(WM_DEBUG_TASKS, "Skipping stack: (mismatch activity/stack) "
- + "%s", stack);
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ final Task rootTask = mChildren.get(i).asTask();
+ if (rootTask == null) {
+ continue;
+ }
+ if (!r.hasCompatibleActivityType(rootTask) && rootTask.isLeafTask()) {
+ ProtoLog.d(WM_DEBUG_TASKS, "Skipping rootTask: (mismatch activity/rootTask) "
+ + "%s", rootTask);
continue;
}
- mTmpFindTaskResult.process(r, stack);
- // It is possible to have tasks in multiple stacks with the same root affinity, so
+ mTmpFindTaskResult.process(r, rootTask);
+ // It is possible to have tasks in multiple root tasks with the same root affinity, so
// we should keep looking after finding an affinity match to see if there is a
- // better match in another stack. Also, task affinity isn't a good enough reason
+ // better match in another root task. Also, task affinity isn't a good enough reason
// to target a display which isn't the source of the intent, so skip any affinity
// matches not on the specified display.
if (mTmpFindTaskResult.mRecord != null) {
@@ -1253,9 +1447,9 @@
result.setTo(mTmpFindTaskResult);
return;
} else if (isPreferredDisplayArea) {
- // Note: since the traversing through the stacks is top down, the floating
+ // Note: since the traversing through the root tasks is top down, the floating
// tasks should always have lower priority than any affinity-matching tasks
- // in the fullscreen stacks
+ // in the fullscreen root tasks
result.setTo(mTmpFindTaskResult);
}
}
@@ -1474,20 +1668,29 @@
*/
ActivityRecord topRunningActivity(boolean considerKeyguardState) {
ActivityRecord topRunning = null;
- final Task focusedStack = getFocusedRootTask();
- if (focusedStack != null) {
- topRunning = focusedStack.topRunningActivity();
+ final Task focusedRootTask = getFocusedRootTask();
+ if (focusedRootTask != null) {
+ topRunning = focusedRootTask.topRunningActivity();
}
- // Look in other focusable stacks.
+ // Look in other focusable root tasks.
if (topRunning == null) {
for (int i = mChildren.size() - 1; i >= 0; --i) {
- final Task stack = mChildren.get(i);
- // Only consider focusable stacks other than the current focused one.
- if (stack == focusedStack || !stack.isTopActivityFocusable()) {
+ final WindowContainer child = mChildren.get(i);
+ if (child.asTaskDisplayArea() != null) {
+ topRunning =
+ child.asTaskDisplayArea().topRunningActivity(considerKeyguardState);
+ if (topRunning != null) {
+ break;
+ }
continue;
}
- topRunning = stack.topRunningActivity();
+ final Task rootTask = mChildren.get(i).asTask();
+ // Only consider focusable root tasks other than the current focused one.
+ if (rootTask == focusedRootTask || !rootTask.isTopActivityFocusable()) {
+ continue;
+ }
+ topRunning = rootTask.topRunningActivity();
if (topRunning != null) {
break;
}
@@ -1593,35 +1796,44 @@
}
/**
- * Adjusts the {@param stack} behind the last visible stack in the display if necessary.
+ * Adjusts the {@param rootTask} behind the last visible rootTask in the display if necessary.
* Generally used in conjunction with {@link #moveRootTaskBehindRootTask}.
*/
// TODO(b/151575894): Remove special stack movement methods.
void moveRootTaskBehindBottomMostVisibleRootTask(Task rootTask) {
if (rootTask.shouldBeVisible(null)) {
- // Skip if the stack is already visible
+ // Skip if the root task is already visible
return;
}
- // Move the stack to the bottom to not affect the following visibility checks
+ // Move the root task to the bottom to not affect the following visibility checks
rootTask.getParent().positionChildAt(POSITION_BOTTOM, rootTask,
false /* includingParents */);
- // Find the next position where the stack should be placed
+ // Find the next position where the root task should be placed
final boolean isRootTask = rootTask.isRootTask();
final int numRootTasks =
isRootTask ? mChildren.size() : rootTask.getParent().getChildCount();
for (int rootTaskNdx = 0; rootTaskNdx < numRootTasks; rootTaskNdx++) {
- final Task s = isRootTask ? mChildren.get(rootTaskNdx)
- : (Task) rootTask.getParent().getChildAt(rootTaskNdx);
- if (s == rootTask) {
+ Task s;
+ if (isRootTask) {
+ final WindowContainer child = mChildren.get(rootTaskNdx);
+ if (child.asTaskDisplayArea() != null) {
+ s = child.asTaskDisplayArea().getBottomMostVisibleRootTask(rootTask);
+ } else {
+ s = child.asTask();
+ }
+ } else {
+ s = rootTask.getParent().getChildAt(rootTaskNdx).asTask();
+ }
+ if (s == rootTask || s == null) {
continue;
}
final int winMode = s.getWindowingMode();
final boolean isValidWindowingMode = winMode == WINDOWING_MODE_FULLSCREEN
|| winMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
if (s.shouldBeVisible(null) && isValidWindowingMode) {
- // Move the provided stack to behind this stack
+ // Move the provided root task to behind this root task
final int position = Math.max(0, rootTaskNdx - 1);
rootTask.getParent().positionChildAt(position, rootTask,
false /*includingParents */);
@@ -1630,6 +1842,16 @@
}
}
+ @Nullable
+ private Task getBottomMostVisibleRootTask(Task excludeRootTask) {
+ return getRootTask(task -> {
+ final int winMode = task.getWindowingMode();
+ final boolean isValidWindowingMode = winMode == WINDOWING_MODE_FULLSCREEN
+ || winMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+ return task.shouldBeVisible(null) && isValidWindowingMode;
+ }, false /* traverseTopToBottom */);
+ }
+
/**
* Moves the {@param stack} behind the given {@param behindStack} if possible. If
* {@param behindStack} is not currently in the display, then then the stack is moved to the
@@ -1735,77 +1957,82 @@
boolean preserveWindows, boolean notifyClients, boolean userLeaving) {
mAtmService.mTaskSupervisor.beginActivityVisibilityUpdate();
try {
- for (int stackNdx = mChildren.size() - 1; stackNdx >= 0; --stackNdx) {
- final Task stack = mChildren.get(stackNdx);
- stack.ensureActivitiesVisible(starting, configChanges, preserveWindows,
+ forAllRootTasks(rootTask -> {
+ rootTask.ensureActivitiesVisible(starting, configChanges, preserveWindows,
notifyClients, userLeaving);
- }
+ });
} finally {
mAtmService.mTaskSupervisor.endActivityVisibilityUpdate();
}
}
/**
- * Removes the stacks in the node applying the content removal node from the display.
+ * Removes the root tasks in the node applying the content removal node from the display.
*
- * @return last reparented stack, or {@code null} if the stacks had to be destroyed.
+ * @return last reparented root task, or {@code null} if the root tasks had to be destroyed.
*/
Task remove() {
mPreferredTopFocusableRootTask = null;
// TODO(b/153090332): Allow setting content removal mode per task display area
final boolean destroyContentOnRemoval = mDisplayContent.shouldDestroyContentOnRemove();
final TaskDisplayArea toDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
- Task lastReparentedStack = null;
+ Task lastReparentedRootTask = null;
- // Stacks could be reparented from the removed display area to other display area. After
- // reparenting the last stack of the removed display area, the display area becomes ready to
- // be released (no more ActivityStack-s). But, we cannot release it at that moment or the
- // related WindowContainer will also be removed. So, we set display area as removed after
- // reparenting stack finished.
+ // Root tasks could be reparented from the removed display area to other display area. After
+ // reparenting the last root task of the removed display area, the display area becomes
+ // ready to be released (no more ActivityStack-s). But, we cannot release it at that moment
+ // or the related WindowContainer will also be removed. So, we set display area as removed
+ // after reparenting root task finished.
// Keep the order from bottom to top.
- int numStacks = mChildren.size();
+ int numRootTasks = mChildren.size();
final boolean splitScreenActivated = toDisplayArea.isSplitScreenModeActivated();
- final Task rootStack = splitScreenActivated ? toDisplayArea
+ final Task splitScreenRoot = splitScreenActivated ? toDisplayArea
.getTopRootTaskInWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) : null;
- for (int stackNdx = 0; stackNdx < numStacks; stackNdx++) {
- final Task stack = mChildren.get(stackNdx);
- // Always finish non-standard type stacks and stacks created by a organizer.
+ for (int i = 0; i < numRootTasks; i++) {
+ final WindowContainer child = mChildren.get(i);
+ if (child.asTaskDisplayArea() != null) {
+ lastReparentedRootTask = child.asTaskDisplayArea().remove();
+ continue;
+ }
+ final Task task = mChildren.get(i).asTask();
+ // Always finish non-standard type root tasks and root tasks created by a organizer.
// TODO: For stacks created by organizer, consider reparenting children tasks if the use
// case arises in the future.
if (destroyContentOnRemoval
- || !stack.isActivityTypeStandardOrUndefined()
- || stack.mCreatedByOrganizer) {
- stack.finishAllActivitiesImmediately();
+ || !task.isActivityTypeStandardOrUndefined()
+ || task.mCreatedByOrganizer) {
+ task.finishAllActivitiesImmediately();
} else {
- // Reparent the stack to the root task of secondary-split-screen or display area.
- stack.reparent(stack.supportsSplitScreenWindowingMode() && rootStack != null
- ? rootStack : toDisplayArea, POSITION_TOP);
+ // Reparent the root task to the root task of secondary-split-screen or display
+ // area.
+ task.reparent(task.supportsSplitScreenWindowingMode() && splitScreenRoot != null
+ ? splitScreenRoot : toDisplayArea, POSITION_TOP);
- // Set the windowing mode to undefined by default to let the stack inherited the
+ // Set the windowing mode to undefined by default to let the root task inherited the
// windowing mode.
- stack.setWindowingMode(WINDOWING_MODE_UNDEFINED);
- lastReparentedStack = stack;
+ task.setWindowingMode(WINDOWING_MODE_UNDEFINED);
+ lastReparentedRootTask = task;
}
- // Stacks may be removed from this display. Ensure each stack will be processed
+ // Root task may be removed from this display. Ensure each root task will be processed
// and the loop will end.
- stackNdx -= numStacks - mChildren.size();
- numStacks = mChildren.size();
+ i -= numRootTasks - mChildren.size();
+ numRootTasks = mChildren.size();
}
- if (lastReparentedStack != null && splitScreenActivated) {
- if (!lastReparentedStack.supportsSplitScreenWindowingMode()) {
+ if (lastReparentedRootTask != null && splitScreenActivated) {
+ if (!lastReparentedRootTask.supportsSplitScreenWindowingMode()) {
mAtmService.getTaskChangeNotificationController()
.notifyActivityDismissingDockedStack();
- toDisplayArea.onSplitScreenModeDismissed(lastReparentedStack);
- } else if (rootStack != null) {
+ toDisplayArea.onSplitScreenModeDismissed(lastReparentedRootTask);
+ } else if (splitScreenRoot != null) {
// update focus
- rootStack.moveToFront("display-removed");
+ splitScreenRoot.moveToFront("display-removed");
}
}
mRemoved = true;
- return lastReparentedStack;
+ return lastReparentedRootTask;
}
/** Whether this task display area can request orientation. */
@@ -1842,8 +2069,13 @@
}
final String triplePrefix = doublePrefix + " ";
pw.println(doublePrefix + "Application tokens in top down Z order:");
- for (int rootTaskNdx = getChildCount() - 1; rootTaskNdx >= 0; --rootTaskNdx) {
- final Task rootTask = getChildAt(rootTaskNdx);
+ for (int index = getChildCount() - 1; index >= 0; --index) {
+ final WindowContainer child = getChildAt(index);
+ if (child.asTaskDisplayArea() != null) {
+ child.dump(pw, doublePrefix, dumpAll);
+ continue;
+ }
+ final Task rootTask = child.asTask();
pw.println(doublePrefix + "* " + rootTask);
rootTask.dump(pw, triplePrefix, dumpAll);
}
diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
index a7306c9..12f8611 100644
--- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
@@ -95,30 +95,22 @@
mSupervisor = supervisor;
}
- @VisibleForTesting
- int onCalculate(Task task, ActivityInfo.WindowLayout layout, ActivityRecord activity,
- ActivityRecord source, ActivityOptions options, LaunchParams currentParams,
- LaunchParams outParams) {
- return onCalculate(task, layout, activity, source, options, PHASE_BOUNDS, currentParams,
- outParams, null);
- }
-
@Override
- public int onCalculate(@Nullable Task task, @NonNull ActivityInfo.WindowLayout layout,
- @NonNull ActivityRecord activity, @Nullable ActivityRecord source,
- ActivityOptions options, int phase, LaunchParams currentParams, LaunchParams outParams,
- @Nullable Request request) {
+ public int onCalculate(@Nullable Task task, @Nullable ActivityInfo.WindowLayout layout,
+ @Nullable ActivityRecord activity, @Nullable ActivityRecord source,
+ @Nullable ActivityOptions options, @Nullable Request request, int phase,
+ LaunchParams currentParams, LaunchParams outParams) {
initLogBuilder(task, activity);
- final int result = calculate(task, layout, activity, source, options, phase, currentParams,
- outParams, request);
+ final int result = calculate(task, layout, activity, source, options, request, phase,
+ currentParams, outParams);
outputLog();
return result;
}
- private int calculate(@Nullable Task task, @NonNull ActivityInfo.WindowLayout layout,
- @NonNull ActivityRecord activity, @Nullable ActivityRecord source,
- ActivityOptions options, int phase, LaunchParams currentParams, LaunchParams outParams,
- @Nullable Request request) {
+ private int calculate(@Nullable Task task, @Nullable ActivityInfo.WindowLayout layout,
+ @Nullable ActivityRecord activity, @Nullable ActivityRecord source,
+ @Nullable ActivityOptions options, @Nullable Request request, int phase,
+ LaunchParams currentParams, LaunchParams outParams) {
final ActivityRecord root;
if (task != null) {
root = task.getRootActivity() == null ? activity : task.getRootActivity();
@@ -126,10 +118,6 @@
root = activity;
}
- // TODO: Investigate whether we can safely ignore all cases where we don't have root
- // activity available. Note we can't know if the bounds are valid if we're not sure of the
- // requested orientation of the root activity. Therefore if we found such a case we may need
- // to pass the activity into this modifier in that case.
if (root == null) {
// There is a case that can lead us here. The caller is moving the top activity that is
// in a task that has multiple activities to PIP mode. For that the caller is creating a
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 58aca20..929d7bf 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -39,6 +39,7 @@
import android.view.SurfaceControl;
import android.window.ITaskOrganizer;
import android.window.ITaskOrganizerController;
+import android.window.StartingWindowInfo;
import android.window.TaskAppearedInfo;
import android.window.WindowContainerToken;
@@ -116,10 +117,10 @@
}
void addStartingWindow(Task task, IBinder appToken) {
- final RunningTaskInfo taskInfo = task.getTaskInfo();
+ final StartingWindowInfo info = task.getStartingWindowInfo();
mDeferTaskOrgCallbacksConsumer.accept(() -> {
try {
- mTaskOrganizer.addStartingWindow(taskInfo, appToken);
+ mTaskOrganizer.addStartingWindow(info, appToken);
} catch (RemoteException e) {
Slog.e(TAG, "Exception sending onTaskStart callback", e);
}
@@ -127,10 +128,9 @@
}
void removeStartingWindow(Task task) {
- final RunningTaskInfo taskInfo = task.getTaskInfo();
mDeferTaskOrgCallbacksConsumer.accept(() -> {
try {
- mTaskOrganizer.removeStartingWindow(taskInfo);
+ mTaskOrganizer.removeStartingWindow(task.mTaskId);
} catch (RemoteException e) {
Slog.e(TAG, "Exception sending onStartTaskFinished callback", e);
}
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotCache.java b/services/core/java/com/android/server/wm/TaskSnapshotCache.java
index 0edfaa8..3c437ba 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotCache.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotCache.java
@@ -17,7 +17,7 @@
package com.android.server.wm;
import android.annotation.Nullable;
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
import android.util.ArrayMap;
import java.io.PrintWriter;
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index b2f3062..de9fb6a 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -24,7 +24,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
@@ -219,7 +219,8 @@
* Retrieves a snapshot. If {@param restoreFromDisk} equals {@code true}, DO NOT HOLD THE WINDOW
* MANAGER LOCK WHEN CALLING THIS METHOD!
*/
- @Nullable TaskSnapshot getSnapshot(int taskId, int userId, boolean restoreFromDisk,
+ @Nullable
+ TaskSnapshot getSnapshot(int taskId, int userId, boolean restoreFromDisk,
boolean isLowResolution) {
return mCache.getSnapshot(taskId, userId, restoreFromDisk, isLowResolution
&& mPersister.enableLowResSnapshots());
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotLoader.java b/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
index 9717e7e..cfdb6b3 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotLoader.java
@@ -20,7 +20,7 @@
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import android.app.ActivityManager;
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
import android.content.ComponentName;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
index 6dfcb41..60c4766 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
@@ -23,7 +23,7 @@
import android.annotation.NonNull;
import android.annotation.TestApi;
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.os.Process;
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index d2cd1a1..8c458a2 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -49,7 +49,6 @@
import android.annotation.Nullable;
import android.app.ActivityManager.TaskDescription;
-import android.app.ActivityManager.TaskSnapshot;
import android.app.ActivityThread;
import android.content.Context;
import android.graphics.Canvas;
@@ -78,6 +77,7 @@
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.window.ClientWindowFrames;
+import android.window.TaskSnapshot;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
@@ -100,7 +100,7 @@
* with a window with the exact same dimensions etc. However, these flags are not used in layout
* and might cause other side effects so we exclude them.
*/
- private static final int FLAG_INHERIT_EXCLUDES = FLAG_NOT_FOCUSABLE
+ static final int FLAG_INHERIT_EXCLUDES = FLAG_NOT_FOCUSABLE
| FLAG_NOT_TOUCHABLE
| FLAG_NOT_TOUCH_MODAL
| FLAG_ALT_FOCUSABLE_IM
@@ -180,34 +180,10 @@
synchronized (service.mGlobalLock) {
final WindowState mainWindow = activity.findMainWindow();
final Task task = activity.getTask();
- if (task == null) {
- Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find task for activity="
- + activity);
- return null;
- }
final ActivityRecord topFullscreenActivity =
activity.getTask().getTopFullscreenActivity();
- if (topFullscreenActivity == null) {
- Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find top fullscreen for task="
- + task);
- return null;
- }
+ // Already check the nullity in StartingSurfaceController#createTaskSnapshotSurface
topFullscreenOpaqueWindow = topFullscreenActivity.getTopFullscreenOpaqueWindow();
- if (mainWindow == null || topFullscreenOpaqueWindow == null) {
- Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find main window for activity="
- + activity);
- return null;
- }
- if (topFullscreenActivity.getWindowConfiguration().getRotation()
- != snapshot.getRotation()) {
- // The snapshot should have been checked by ActivityRecord#isSnapshotCompatible
- // that the activity will be updated to the same rotation as the snapshot. Since
- // the transition is not started yet, fixed rotation transform needs to be applied
- // earlier to make the snapshot show in a rotated container.
- activity.mDisplayContent.handleTopActivityLaunchingInDifferentOrientation(
- topFullscreenActivity, false /* checkOpening */);
- }
-
WindowManager.LayoutParams attrs = topFullscreenOpaqueWindow.mAttrs;
appearance = attrs.insetsFlags.appearance;
windowFlags = attrs.flags;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 0f2c2ac..1f3d15a 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -140,7 +140,7 @@
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.app.ActivityManager;
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
import android.app.ActivityManagerInternal;
import android.app.ActivityTaskManager;
import android.app.ActivityThread;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 32b84a8..4301072 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -3843,7 +3843,8 @@
if (task == null) {
return false;
}
- if (!inSplitScreenWindowingMode() && !inFreeformWindowingMode()) {
+ if (!inSplitScreenWindowingMode() && !inFreeformWindowingMode()
+ && !task.getRootTask().mCreatedByOrganizer) {
return false;
}
// TODO(157912944): formalize drag-resizing so that exceptions aren't hardcoded like this
@@ -5228,14 +5229,17 @@
if (!mAnimatingExit && mAppDied) {
mIsDimming = true;
getDimmer().dimAbove(getSyncTransaction(), this, DEFAULT_DIM_AMOUNT_DEAD_WINDOW);
- } else if ((mAttrs.flags & FLAG_DIM_BEHIND) != 0 && isVisibleNow() && !mHidden) {
- // Only show a dim behind when the following is satisfied:
- // 1. The window has the flag FLAG_DIM_BEHIND
+ } else if (((mAttrs.flags & FLAG_DIM_BEHIND) != 0 || mAttrs.backgroundBlurRadius != 0)
+ && isVisibleNow() && !mHidden) {
+ // Only show the Dimmer when the following is satisfied:
+ // 1. The window has the flag FLAG_DIM_BEHIND or background blur is requested
// 2. The WindowToken is not hidden so dims aren't shown when the window is exiting.
// 3. The WS is considered visible according to the isVisible() method
// 4. The WS is not hidden.
mIsDimming = true;
- getDimmer().dimBelow(getSyncTransaction(), this, mAttrs.dimAmount);
+ final float dimAmount = (mAttrs.flags & FLAG_DIM_BEHIND) != 0 ? mAttrs.dimAmount : 0;
+ getDimmer().dimBelow(
+ getSyncTransaction(), this, mAttrs.dimAmount, mAttrs.backgroundBlurRadius);
}
}
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 068d0df..585db1e 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -611,12 +611,11 @@
mDsDy = 1;
}
+ private boolean isInBlastSync() {
+ return mService.useBLASTSync() && mWin.useBLASTSync();
+ }
+
private boolean shouldConsumeMainWindowSizeTransaction() {
- // If we use BLASTSync we always consume the transaction when finishing
- // the sync.
- if (mService.useBLASTSync() && mWin.useBLASTSync()) {
- return false;
- }
// We only consume the transaction when the client is calling relayout
// because this is the only time we know the frameNumber will be valid
// due to the client renderer being paused. Put otherwise, only when
@@ -639,22 +638,6 @@
}
final WindowState w = mWin;
- final Task task = w.getTask();
-
- if (shouldConsumeMainWindowSizeTransaction()) {
- // Use pending transaction here instead of the transaction passed in because we want to
- // ensure the defer transaction is applied on the main transaction and not on the sync
- // transaction. This is because the sync transaction could contain the buffer and we'd
- // defer the transaction that contains the buffer we're deferring on.
- SurfaceControl.Transaction pendingTransaction = mWin.getPendingTransaction();
- pendingTransaction.deferTransactionUntil(
- task.getMainWindowSizeChangeTask().getSurfaceControl(),
- mWin.getClientViewRootSurface(), mWin.getFrameNumber());
- pendingTransaction.deferTransactionUntil(mSurfaceController.mSurfaceControl,
- mWin.getClientViewRootSurface(), mWin.getFrameNumber());
- pendingTransaction.merge(task.getMainWindowSizeChangeTransaction());
- task.setMainWindowSizeChangeTransaction(null);
- }
if (!w.mSeamlesslyRotated) {
// Used to offset the WSA when stack position changes before a resize.
@@ -673,6 +656,30 @@
setWallpaperPositionAndScale(t, xOffset, yOffset, mWallpaperScale);
}
}
+
+ final Task task = w.getTask();
+ if (shouldConsumeMainWindowSizeTransaction()) {
+ if (isInBlastSync()) {
+ // If we're in a sync transaction, there's no need to call defer transaction.
+ // The sync transaction will contain the buffer so the bounds change transaction
+ // will only be applied with the buffer.
+ t.merge(task.getMainWindowSizeChangeTransaction());
+ } else {
+ // Use pending transaction here instead of the transaction passed in because we
+ // want to ensure the defer transaction is applied on the main transaction and
+ // not on the sync transaction. This is because the sync transaction could
+ // contain the buffer and we'd defer the transaction that contains the buffer
+ // we're deferring on.
+ SurfaceControl.Transaction pendingTransaction = mWin.getPendingTransaction();
+ pendingTransaction.deferTransactionUntil(
+ task.getMainWindowSizeChangeTask().getSurfaceControl(),
+ mWin.getClientViewRootSurface(), mWin.getFrameNumber());
+ pendingTransaction.deferTransactionUntil(mSurfaceController.mSurfaceControl,
+ mWin.getClientViewRootSurface(), mWin.getFrameNumber());
+ pendingTransaction.merge(task.getMainWindowSizeChangeTransaction());
+ }
+ task.setMainWindowSizeChangeTransaction(null);
+ }
}
void prepareSurfaceLocked(SurfaceControl.Transaction t) {
@@ -795,7 +802,6 @@
if (displayed) {
w.mToken.hasVisible = true;
- mSurfaceController.setBackgroundBlurRadius(w.mAttrs.backgroundBlurRadius);
}
}
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index 788f004..f59eba9 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -64,8 +64,6 @@
private float mLastDsdy = 0;
private float mLastDtdy = 1;
- private int mLastBackgroundBlurRadius = 0;
-
private float mSurfaceAlpha = 0;
private int mSurfaceLayer = 0;
@@ -242,26 +240,6 @@
}
}
- void setBackgroundBlurRadius(int radius) {
- ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE backgroundBlur=%o: %s", radius, title);
-
- if (mSurfaceControl == null || radius == mLastBackgroundBlurRadius) {
- return;
- }
- mLastBackgroundBlurRadius = radius;
-
- if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setBackgroundBlurRadius");
- mService.openSurfaceTransaction();
- try {
- getGlobalTransaction().setBackgroundBlurRadius(mSurfaceControl, radius);
- } finally {
- mService.closeSurfaceTransaction("setBackgroundBlurRadius");
- if (SHOW_LIGHT_TRANSACTIONS) {
- Slog.i(TAG, "<<< CLOSE TRANSACTION setBackgroundBlurRadius");
- }
- }
- }
-
void setSecure(boolean isSecure) {
ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE isSecure=%b: %s", isSecure, title);
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 34875ed..9e0fee39 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -827,15 +827,15 @@
* system bars, or in other words extend outside of the "Decor Frame"
*/
boolean canLayerAboveSystemBars() {
- int layer = mWmService.mPolicy.getWindowLayerFromTypeLw(windowType,
- mOwnerCanManageAppTokens);
+ int layer = getWindowLayerFromType();
int navLayer = mWmService.mPolicy.getWindowLayerFromTypeLw(TYPE_NAVIGATION_BAR,
mOwnerCanManageAppTokens);
return mOwnerCanManageAppTokens && (layer > navLayer);
}
int getWindowLayerFromType() {
- return mWmService.mPolicy.getWindowLayerFromTypeLw(windowType, mOwnerCanManageAppTokens);
+ return mWmService.mPolicy.getWindowLayerFromTypeLw(windowType, mOwnerCanManageAppTokens,
+ mRoundedCornerOverlay);
}
int getOwnerUid() {
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 2c4eb1b..77ca4e9 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -40,6 +40,7 @@
"com_android_server_locksettings_SyntheticPasswordManager.cpp",
"com_android_server_net_NetworkStatsService.cpp",
"com_android_server_power_PowerManagerService.cpp",
+ "com_android_server_powerstats_PowerStatsService.cpp",
"com_android_server_security_VerityUtils.cpp",
"com_android_server_SerialService.cpp",
"com_android_server_soundtrigger_middleware_AudioSessionProviderImpl.cpp",
diff --git a/services/core/jni/OWNERS b/services/core/jni/OWNERS
index 7fc5565..995cfe9 100644
--- a/services/core/jni/OWNERS
+++ b/services/core/jni/OWNERS
@@ -23,6 +23,7 @@
per-file com_android_server_net_* = file:/services/core/java/com/android/server/net/OWNERS
per-file com_android_server_pm_* = file:/services/core/java/com/android/server/pm/OWNERS
per-file com_android_server_power_* = file:/services/core/java/com/android/server/power/OWNERS
+per-file com_android_server_powerstats_* = file:/services/core/java/com/android/server/powerstats/OWNERS
per-file com_android_server_se_* = file:/core/java/android/se/OWNERS
per-file com_android_server_security_* = file:/core/java/android/security/OWNERS
per-file com_android_server_tv_* = file:/media/java/android/media/tv/OWNERS
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 404b182..57d28ba 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -62,11 +62,11 @@
#include <nativehelper/ScopedPrimitiveArray.h>
#include <nativehelper/ScopedUtfChars.h>
-#include "com_android_server_power_PowerManagerService.h"
+#include "android_hardware_display_DisplayViewport.h"
#include "android_hardware_input_InputApplicationHandle.h"
#include "android_hardware_input_InputWindowHandle.h"
-#include "android_hardware_display_DisplayViewport.h"
#include "android_util_Binder.h"
+#include "com_android_server_power_PowerManagerService.h"
#include <vector>
@@ -101,6 +101,8 @@
jmethodID notifyConnectionUnresponsive;
jmethodID notifyConnectionResponsive;
jmethodID notifyFocusChanged;
+ jmethodID notifySensorEvent;
+ jmethodID notifySensorAccuracy;
jmethodID notifyUntrustedTouch;
jmethodID filterInputEvent;
jmethodID interceptKeyBeforeQueueing;
@@ -157,6 +159,29 @@
jmethodID size;
} gSparseArrayClassInfo;
+struct InputSensorInfoOffsets {
+ jclass clazz;
+ // fields
+ jfieldID name;
+ jfieldID vendor;
+ jfieldID version;
+ jfieldID handle;
+ jfieldID maxRange;
+ jfieldID resolution;
+ jfieldID power;
+ jfieldID minDelay;
+ jfieldID fifoReservedEventCount;
+ jfieldID fifoMaxEventCount;
+ jfieldID stringType;
+ jfieldID requiredPermission;
+ jfieldID maxDelay;
+ jfieldID flags;
+ jfieldID type;
+ jfieldID id;
+ // methods
+ jmethodID init;
+} gInputSensorInfo;
+
// --- Global functions ---
template<typename T>
@@ -224,7 +249,8 @@
const std::string& name);
base::Result<std::unique_ptr<InputChannel>> createInputMonitor(JNIEnv* env, int32_t displayId,
bool isGestureMonitor,
- const std::string& name);
+ const std::string& name,
+ int32_t pid);
status_t removeInputChannel(JNIEnv* env, const sp<IBinder>& connectionToken);
status_t pilferPointers(const sp<IBinder>& token);
@@ -240,8 +266,8 @@
void reloadCalibration();
void setPointerIconType(int32_t iconId);
void reloadPointerIcons();
+ void requestPointerCapture(const sp<IBinder>& windowToken, bool enabled);
void setCustomPointerIcon(const SpriteIcon& icon);
- void setPointerCapture(bool enabled);
void setMotionClassifierEnabled(bool enabled);
/* --- InputReaderPolicyInterface implementation --- */
@@ -267,6 +293,11 @@
void notifyConnectionResponsive(const sp<IBinder>& token) override;
void notifyInputChannelBroken(const sp<IBinder>& token) override;
void notifyFocusChanged(const sp<IBinder>& oldToken, const sp<IBinder>& newToken) override;
+ void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
+ InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
+ const std::vector<float>& values) override;
+ void notifySensorAccuracy(int32_t deviceId, InputDeviceSensorType sensorType,
+ InputDeviceSensorAccuracy accuracy) override;
void notifyUntrustedTouch(const std::string& obscuringPackage) override;
bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags) override;
void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override;
@@ -280,6 +311,7 @@
void pokeUserActivity(nsecs_t eventTime, int32_t eventType) override;
bool checkInjectEventsPermissionNonReentrant(int32_t injectorPid, int32_t injectorUid) override;
void onPointerDownOutsideFocus(const sp<IBinder>& touchedToken) override;
+ void setPointerCapture(bool enabled) override;
/* --- PointerControllerPolicyInterface implementation --- */
@@ -456,9 +488,11 @@
}
base::Result<std::unique_ptr<InputChannel>> NativeInputManager::createInputMonitor(
- JNIEnv* /* env */, int32_t displayId, bool isGestureMonitor, const std::string& name) {
+ JNIEnv* /* env */, int32_t displayId, bool isGestureMonitor, const std::string& name,
+ int32_t pid) {
ATRACE_CALL();
- return mInputManager->getDispatcher()->createInputMonitor(displayId, isGestureMonitor, name);
+ return mInputManager->getDispatcher()->createInputMonitor(displayId, isGestureMonitor, name,
+ pid);
}
status_t NativeInputManager::removeInputChannel(JNIEnv* /* env */,
@@ -819,6 +853,35 @@
checkAndClearExceptionFromCallback(env, "notifyFocusChanged");
}
+void NativeInputManager::notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
+ InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
+ const std::vector<float>& values) {
+#if DEBUG_INPUT_DISPATCHER_POLICY
+ ALOGD("notifySensorEvent");
+#endif
+ ATRACE_CALL();
+ JNIEnv* env = jniEnv();
+ ScopedLocalFrame localFrame(env);
+ jfloatArray arr = env->NewFloatArray(values.size());
+ env->SetFloatArrayRegion(arr, 0, values.size(), values.data());
+ env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifySensorEvent, deviceId,
+ static_cast<jint>(sensorType), accuracy, timestamp, arr);
+ checkAndClearExceptionFromCallback(env, "notifySensorEvent");
+}
+
+void NativeInputManager::notifySensorAccuracy(int32_t deviceId, InputDeviceSensorType sensorType,
+ InputDeviceSensorAccuracy accuracy) {
+#if DEBUG_INPUT_DISPATCHER_POLICY
+ ALOGD("notifySensorAccuracy");
+#endif
+ ATRACE_CALL();
+ JNIEnv* env = jniEnv();
+ ScopedLocalFrame localFrame(env);
+ env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifySensorAccuracy, deviceId,
+ static_cast<jint>(sensorType), accuracy);
+ checkAndClearExceptionFromCallback(env, "notifySensorAccuracy");
+}
+
void NativeInputManager::getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) {
ATRACE_CALL();
JNIEnv* env = jniEnv();
@@ -930,20 +993,8 @@
InputReaderConfiguration::CHANGE_SHOW_TOUCHES);
}
-void NativeInputManager::setPointerCapture(bool enabled) {
- { // acquire lock
- AutoMutex _l(mLock);
-
- if (mLocked.pointerCapture == enabled) {
- return;
- }
-
- ALOGI("Setting pointer capture to %s.", enabled ? "enabled" : "disabled");
- mLocked.pointerCapture = enabled;
- } // release lock
-
- mInputManager->getReader()->requestRefreshConfiguration(
- InputReaderConfiguration::CHANGE_POINTER_CAPTURE);
+void NativeInputManager::requestPointerCapture(const sp<IBinder>& windowToken, bool enabled) {
+ mInputManager->getDispatcher()->requestPointerCapture(windowToken, enabled);
}
void NativeInputManager::setInteractive(bool interactive) {
@@ -1215,7 +1266,6 @@
android_server_PowerManagerService_userActivity(eventTime, eventType);
}
-
bool NativeInputManager::checkInjectEventsPermissionNonReentrant(
int32_t injectorPid, int32_t injectorUid) {
ATRACE_CALL();
@@ -1238,6 +1288,22 @@
checkAndClearExceptionFromCallback(env, "onPointerDownOutsideFocus");
}
+void NativeInputManager::setPointerCapture(bool enabled) {
+ { // acquire lock
+ AutoMutex _l(mLock);
+
+ if (mLocked.pointerCapture == enabled) {
+ return;
+ }
+
+ ALOGV("%s pointer capture.", enabled ? "Enabling" : "Disabling");
+ mLocked.pointerCapture = enabled;
+ } // release lock
+
+ mInputManager->getReader()->requestRefreshConfiguration(
+ InputReaderConfiguration::CHANGE_POINTER_CAPTURE);
+}
+
void NativeInputManager::loadPointerIcon(SpriteIcon* icon, int32_t displayId) {
ATRACE_CALL();
JNIEnv* env = jniEnv();
@@ -1440,7 +1506,7 @@
}
static jobject nativeCreateInputMonitor(JNIEnv* env, jclass /* clazz */, jlong ptr, jint displayId,
- jboolean isGestureMonitor, jstring nameObj) {
+ jboolean isGestureMonitor, jstring nameObj, jint pid) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
if (displayId == ADISPLAY_ID_NONE) {
@@ -1453,7 +1519,7 @@
std::string name = nameChars.c_str();
base::Result<std::unique_ptr<InputChannel>> inputChannel =
- im->createInputMonitor(env, displayId, isGestureMonitor, name);
+ im->createInputMonitor(env, displayId, isGestureMonitor, name, pid);
if (!inputChannel) {
std::string message = inputChannel.error().message();
@@ -1631,11 +1697,12 @@
im->setFocusedDisplay(env, displayId);
}
-static void nativeSetPointerCapture(JNIEnv* env, jclass /* clazz */, jlong ptr,
- jboolean enabled) {
+static void nativeRequestPointerCapture(JNIEnv* env, jclass /* clazz */, jlong ptr,
+ jobject tokenObj, jboolean enabled) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+ sp<IBinder> windowToken = ibinderForJavaObject(env, tokenObj);
- im->setPointerCapture(enabled);
+ im->requestPointerCapture(windowToken, enabled);
}
static void nativeSetInputDispatchMode(JNIEnv* /* env */,
@@ -1906,6 +1973,111 @@
im->setMotionClassifierEnabled(enabled);
}
+static jobject createInputSensorInfo(JNIEnv* env, jstring name, jstring vendor, jint version,
+ jint handle, jint type, jfloat maxRange, jfloat resolution,
+ jfloat power, jfloat minDelay, jint fifoReservedEventCount,
+ jint fifoMaxEventCount, jstring stringType,
+ jstring requiredPermission, jint maxDelay, jint flags,
+ jint id) {
+ // SensorInfo sensorInfo = new Sensor();
+ jobject sensorInfo = env->NewObject(gInputSensorInfo.clazz, gInputSensorInfo.init, "");
+
+ if (sensorInfo != NULL) {
+ env->SetObjectField(sensorInfo, gInputSensorInfo.name, name);
+ env->SetObjectField(sensorInfo, gInputSensorInfo.vendor, vendor);
+ env->SetIntField(sensorInfo, gInputSensorInfo.version, version);
+ env->SetIntField(sensorInfo, gInputSensorInfo.handle, handle);
+ env->SetFloatField(sensorInfo, gInputSensorInfo.maxRange, maxRange);
+ env->SetFloatField(sensorInfo, gInputSensorInfo.resolution, resolution);
+ env->SetFloatField(sensorInfo, gInputSensorInfo.power, power);
+ env->SetIntField(sensorInfo, gInputSensorInfo.minDelay, minDelay);
+ env->SetIntField(sensorInfo, gInputSensorInfo.fifoReservedEventCount,
+ fifoReservedEventCount);
+ env->SetIntField(sensorInfo, gInputSensorInfo.fifoMaxEventCount, fifoMaxEventCount);
+ env->SetObjectField(sensorInfo, gInputSensorInfo.requiredPermission, requiredPermission);
+ env->SetIntField(sensorInfo, gInputSensorInfo.maxDelay, maxDelay);
+ env->SetIntField(sensorInfo, gInputSensorInfo.flags, flags);
+ env->SetObjectField(sensorInfo, gInputSensorInfo.stringType, stringType);
+ env->SetIntField(sensorInfo, gInputSensorInfo.type, type);
+ env->SetIntField(sensorInfo, gInputSensorInfo.id, id);
+ }
+ return sensorInfo;
+}
+
+static jobjectArray nativeGetSensorList(JNIEnv* env, jclass /* clazz */, jlong ptr, jint deviceId) {
+ NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+ std::vector<InputDeviceInfo> devices = im->getInputManager()->getReader()->getInputDevices();
+ // Find the input device by deviceId
+ auto it = std::find_if(devices.begin(), devices.end(),
+ [deviceId](InputDeviceInfo& info) { return info.getId() == deviceId; });
+
+ if (it == devices.end()) {
+ // Return an array of size 0
+ return env->NewObjectArray(0, gInputSensorInfo.clazz, nullptr);
+ }
+
+ std::vector<InputDeviceSensorType> types = it->getSensorTypes();
+ jobjectArray arr = env->NewObjectArray(types.size(), gInputSensorInfo.clazz, nullptr);
+ for (int i = 0; i < types.size(); i++) {
+ const InputDeviceSensorInfo* sensorInfo = it->getSensorInfo(types[i]);
+ if (sensorInfo == nullptr) {
+ ALOGW("Failed to get input device %d sensor info for type %s", deviceId,
+ NamedEnum::string(types[i]).c_str());
+ continue;
+ }
+
+ jobject info =
+ createInputSensorInfo(env, env->NewStringUTF(sensorInfo->name.c_str()),
+ env->NewStringUTF(sensorInfo->vendor.c_str()),
+ (jint)sensorInfo->version, 0 /* handle */,
+ (jint)sensorInfo->type, (jfloat)sensorInfo->maxRange,
+ (jfloat)sensorInfo->resolution, (jfloat)sensorInfo->power,
+ (jfloat)sensorInfo->minDelay,
+ (jint)sensorInfo->fifoReservedEventCount,
+ (jint)sensorInfo->fifoMaxEventCount,
+ env->NewStringUTF(sensorInfo->stringType.c_str()),
+ env->NewStringUTF("") /* requiredPermission */,
+ (jint)sensorInfo->maxDelay, (jint)sensorInfo->flags,
+ (jint)sensorInfo->id);
+ env->SetObjectArrayElement(arr, i, info);
+ env->DeleteLocalRef(info);
+ }
+ return arr;
+}
+
+static jboolean nativeEnableSensor(JNIEnv* env, jclass /* clazz */, jlong ptr, jint deviceId,
+ jint sensorType, jint samplingPeriodUs,
+ jint maxBatchReportLatencyUs) {
+ NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+
+ return im->getInputManager()
+ ->getReader()
+ ->enableSensor(deviceId, static_cast<InputDeviceSensorType>(sensorType),
+ std::chrono::microseconds(samplingPeriodUs),
+ std::chrono::microseconds(maxBatchReportLatencyUs));
+ return true;
+}
+
+static void nativeDisableSensor(JNIEnv* env, jclass /* clazz */, jlong ptr, jint deviceId,
+ jint sensorType) {
+ NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+
+ im->getInputManager()->getReader()->disableSensor(deviceId,
+ static_cast<InputDeviceSensorType>(
+ sensorType));
+}
+
+static jboolean nativeFlushSensor(JNIEnv* env, jclass /* clazz */, jlong ptr, jint deviceId,
+ jint sensorType) {
+ NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+
+ im->getInputManager()->getReader()->flushSensor(deviceId,
+ static_cast<InputDeviceSensorType>(sensorType));
+ return im->getInputManager()->getDispatcher()->flushSensor(deviceId,
+ static_cast<InputDeviceSensorType>(
+ sensorType));
+}
+
// ----------------------------------------------------------------------------
static const JNINativeMethod gInputManagerMethods[] = {
@@ -1923,7 +2095,7 @@
{"nativeHasKeys", "(JII[I[Z)Z", (void*)nativeHasKeys},
{"nativeCreateInputChannel", "(JLjava/lang/String;)Landroid/view/InputChannel;",
(void*)nativeCreateInputChannel},
- {"nativeCreateInputMonitor", "(JIZLjava/lang/String;)Landroid/view/InputChannel;",
+ {"nativeCreateInputMonitor", "(JIZLjava/lang/String;I)Landroid/view/InputChannel;",
(void*)nativeCreateInputMonitor},
{"nativeRemoveInputChannel", "(JLandroid/os/IBinder;)V", (void*)nativeRemoveInputChannel},
{"nativePilferPointers", "(JLandroid/os/IBinder;)V", (void*)nativePilferPointers},
@@ -1941,7 +2113,8 @@
{"nativeSetFocusedApplication", "(JILandroid/view/InputApplicationHandle;)V",
(void*)nativeSetFocusedApplication},
{"nativeSetFocusedDisplay", "(JI)V", (void*)nativeSetFocusedDisplay},
- {"nativeSetPointerCapture", "(JZ)V", (void*)nativeSetPointerCapture},
+ {"nativeRequestPointerCapture", "(JLandroid/os/IBinder;Z)V",
+ (void*)nativeRequestPointerCapture},
{"nativeSetInputDispatchMode", "(JZZ)V", (void*)nativeSetInputDispatchMode},
{"nativeSetSystemUiLightsOut", "(JZ)V", (void*)nativeSetSystemUiLightsOut},
{"nativeTransferTouchFocus", "(JLandroid/os/IBinder;Landroid/os/IBinder;)Z",
@@ -1970,6 +2143,11 @@
{"nativeCanDispatchToDisplay", "(JII)Z", (void*)nativeCanDispatchToDisplay},
{"nativeNotifyPortAssociationsChanged", "(J)V", (void*)nativeNotifyPortAssociationsChanged},
{"nativeSetMotionClassifierEnabled", "(JZ)V", (void*)nativeSetMotionClassifierEnabled},
+ {"nativeGetSensorList", "(JI)[Landroid/hardware/input/InputSensorInfo;",
+ (void*)nativeGetSensorList},
+ {"nativeEnableSensor", "(JIIII)Z", (void*)nativeEnableSensor},
+ {"nativeDisableSensor", "(JII)V", (void*)nativeDisableSensor},
+ {"nativeFlushSensor", "(JII)Z", (void*)nativeFlushSensor},
};
#define FIND_CLASS(var, className) \
@@ -2015,6 +2193,10 @@
GET_METHOD_ID(gServiceClassInfo.notifyFocusChanged, clazz,
"notifyFocusChanged", "(Landroid/os/IBinder;Landroid/os/IBinder;)V");
+ GET_METHOD_ID(gServiceClassInfo.notifySensorEvent, clazz, "notifySensorEvent", "(IIIJ[F)V");
+
+ GET_METHOD_ID(gServiceClassInfo.notifySensorAccuracy, clazz, "notifySensorAccuracy", "(III)V");
+
GET_METHOD_ID(gServiceClassInfo.notifyUntrustedTouch, clazz, "notifyUntrustedTouch",
"(Ljava/lang/String;)V");
@@ -2139,6 +2321,33 @@
GET_METHOD_ID(gSparseArrayClassInfo.valueAt, gSparseArrayClassInfo.clazz, "valueAt",
"(I)Ljava/lang/Object;");
GET_METHOD_ID(gSparseArrayClassInfo.size, gSparseArrayClassInfo.clazz, "size", "()I");
+ // InputSensorInfo
+ // android.hardware.input.InputDeviceSensorInfo
+ FIND_CLASS(clazz, "android/hardware/input/InputSensorInfo");
+ gInputSensorInfo.clazz = reinterpret_cast<jclass>(env->NewGlobalRef(clazz));
+
+ GET_FIELD_ID(gInputSensorInfo.name, gInputSensorInfo.clazz, "mName", "Ljava/lang/String;");
+ GET_FIELD_ID(gInputSensorInfo.vendor, gInputSensorInfo.clazz, "mVendor", "Ljava/lang/String;");
+ GET_FIELD_ID(gInputSensorInfo.version, gInputSensorInfo.clazz, "mVersion", "I");
+ GET_FIELD_ID(gInputSensorInfo.handle, gInputSensorInfo.clazz, "mHandle", "I");
+ GET_FIELD_ID(gInputSensorInfo.maxRange, gInputSensorInfo.clazz, "mMaxRange", "F");
+ GET_FIELD_ID(gInputSensorInfo.resolution, gInputSensorInfo.clazz, "mResolution", "F");
+ GET_FIELD_ID(gInputSensorInfo.power, gInputSensorInfo.clazz, "mPower", "F");
+ GET_FIELD_ID(gInputSensorInfo.minDelay, gInputSensorInfo.clazz, "mMinDelay", "I");
+ GET_FIELD_ID(gInputSensorInfo.fifoReservedEventCount, gInputSensorInfo.clazz,
+ "mFifoReservedEventCount", "I");
+ GET_FIELD_ID(gInputSensorInfo.fifoMaxEventCount, gInputSensorInfo.clazz, "mFifoMaxEventCount",
+ "I");
+ GET_FIELD_ID(gInputSensorInfo.stringType, gInputSensorInfo.clazz, "mStringType",
+ "Ljava/lang/String;");
+ GET_FIELD_ID(gInputSensorInfo.requiredPermission, gInputSensorInfo.clazz, "mRequiredPermission",
+ "Ljava/lang/String;");
+ GET_FIELD_ID(gInputSensorInfo.maxDelay, gInputSensorInfo.clazz, "mMaxDelay", "I");
+ GET_FIELD_ID(gInputSensorInfo.flags, gInputSensorInfo.clazz, "mFlags", "I");
+ GET_FIELD_ID(gInputSensorInfo.type, gInputSensorInfo.clazz, "mType", "I");
+ GET_FIELD_ID(gInputSensorInfo.id, gInputSensorInfo.clazz, "mId", "I");
+
+ GET_METHOD_ID(gInputSensorInfo.init, gInputSensorInfo.clazz, "<init>", "()V");
return 0;
}
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 0ec8b3a..066dbce 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -31,6 +31,7 @@
#include <android/hardware/gnss/2.1/IGnssMeasurement.h>
#include <android/hardware/gnss/3.0/IGnssPsds.h>
#include <android/hardware/gnss/BnGnss.h>
+#include <android/hardware/gnss/BnGnssMeasurementCallback.h>
#include <android/hardware/gnss/BnGnssPowerIndicationCallback.h>
#include <android/hardware/gnss/BnGnssPsdsCallback.h>
#include <android/hardware/gnss/measurement_corrections/1.0/IMeasurementCorrections.h>
@@ -1754,7 +1755,15 @@
// 1.1@IGnss can be paired {1.0, 1.1}@IGnssMeasurement
// 1.0@IGnss is paired with 1.0@IGnssMeasurement
gnssMeasurementIface = nullptr;
- if (gnssHal_V2_1 != nullptr) {
+ if (gnssHalAidl != nullptr) {
+ sp<hardware::gnss::IGnssMeasurementInterface> gnssMeasurement;
+ auto status = gnssHalAidl->getExtensionGnssMeasurement(&gnssMeasurement);
+ if (checkAidlStatus(status, "Unable to get a handle to GnssMeasurement AIDL interface.")) {
+ gnssMeasurementIface =
+ std::make_unique<android::gnss::GnssMeasurement>(gnssMeasurement);
+ }
+ }
+ if (gnssHal_V2_1 != nullptr && gnssMeasurementIface == nullptr) {
auto gnssMeasurement = gnssHal_V2_1->getExtensionGnssMeasurement_2_1();
if (checkHidlReturn(gnssMeasurement, "Unable to get a handle to GnssMeasurement_V2_1")) {
gnssMeasurementIface =
@@ -2696,7 +2705,8 @@
return JNI_FALSE;
}
- return gnssMeasurementIface->setCallback(sp<gnss::GnssMeasurementCallback>::make(mCallbacksObj),
+ return gnssMeasurementIface->setCallback(std::make_unique<gnss::GnssMeasurementCallback>(
+ mCallbacksObj),
enableFullTracking);
}
diff --git a/services/core/jni/com_android_server_powerstats_PowerStatsService.cpp b/services/core/jni/com_android_server_powerstats_PowerStatsService.cpp
new file mode 100644
index 0000000..f5b851f
--- /dev/null
+++ b/services/core/jni/com_android_server_powerstats_PowerStatsService.cpp
@@ -0,0 +1,440 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "PowerStatsService"
+
+#include <android/hardware/power/stats/1.0/IPowerStats.h>
+#include <jni.h>
+#include <nativehelper/JNIHelp.h>
+
+#include <log/log.h>
+
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+using android::hardware::power::stats::V1_0::EnergyData;
+using android::hardware::power::stats::V1_0::RailInfo;
+using android::hardware::power::stats::V1_0::Status;
+
+// ChannelInfo
+static jclass class_CI;
+static jmethodID method_CI_init;
+static jfieldID field_CI_channelId;
+static jfieldID field_CI_channelName;
+
+// EnergyMeasurement
+static jclass class_EM;
+static jmethodID method_EM_init;
+static jfieldID field_EM_channelId;
+static jfieldID field_EM_timestampMs;
+static jfieldID field_EM_durationMs;
+static jfieldID field_EM_energyUWs;
+
+// StateInfo
+static jclass class_SI;
+static jmethodID method_SI_init;
+static jfieldID field_SI_stateId;
+static jfieldID field_SI_stateName;
+
+// PowerEntityInfo
+static jclass class_PEI;
+static jmethodID method_PEI_init;
+static jfieldID field_PEI_powerEntityId;
+static jfieldID field_PEI_powerEntityName;
+static jfieldID field_PEI_states;
+
+// StateResidency
+static jclass class_SR;
+static jmethodID method_SR_init;
+static jfieldID field_SR_stateId;
+static jfieldID field_SR_totalTimeInStateMs;
+static jfieldID field_SR_totalStateEntryCount;
+static jfieldID field_SR_lastEntryTimestampMs;
+
+// StateResidencyResult
+static jclass class_SRR;
+static jmethodID method_SRR_init;
+static jfieldID field_SRR_powerEntityId;
+static jfieldID field_SRR_stateResidencyData;
+
+namespace android {
+
+static std::mutex gPowerStatsHalMutex;
+static sp<android::hardware::power::stats::V1_0::IPowerStats> gPowerStatsHalV1_0_ptr = nullptr;
+
+static void deinitPowerStats() {
+ gPowerStatsHalV1_0_ptr = nullptr;
+}
+
+struct PowerStatsHalDeathRecipient : virtual public hardware::hidl_death_recipient {
+ virtual void serviceDied(uint64_t cookie,
+ const wp<android::hidl::base::V1_0::IBase> &who) override {
+ // The HAL just died. Reset all handles to HAL services.
+ std::lock_guard<std::mutex> lock(gPowerStatsHalMutex);
+ deinitPowerStats();
+ }
+};
+
+sp<PowerStatsHalDeathRecipient> gPowerStatsHalDeathRecipient = new PowerStatsHalDeathRecipient();
+
+static bool connectToPowerStatsHal() {
+ if (gPowerStatsHalV1_0_ptr == nullptr) {
+ gPowerStatsHalV1_0_ptr = android::hardware::power::stats::V1_0::IPowerStats::getService();
+
+ if (gPowerStatsHalV1_0_ptr == nullptr) {
+ ALOGE("Unable to get power.stats HAL service.");
+ return false;
+ }
+
+ // Link death recipient to power.stats service handle
+ hardware::Return<bool> linked =
+ gPowerStatsHalV1_0_ptr->linkToDeath(gPowerStatsHalDeathRecipient, 0);
+ if (!linked.isOk()) {
+ ALOGE("Transaction error in linking to power.stats HAL death: %s",
+ linked.description().c_str());
+ deinitPowerStats();
+ return false;
+ } else if (!linked) {
+ ALOGW("Unable to link to power.stats HAL death notifications");
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool checkResult(const Return<void> &ret, const char *function) {
+ if (!ret.isOk()) {
+ ALOGE("%s failed: requested HAL service not available. Description: %s", function,
+ ret.description().c_str());
+ if (ret.isDeadObject()) {
+ deinitPowerStats();
+ }
+ return false;
+ }
+ return true;
+}
+
+static jobjectArray nativeGetPowerEntityInfo(JNIEnv *env, jclass clazz) {
+ std::lock_guard<std::mutex> lock(gPowerStatsHalMutex);
+
+ if (!connectToPowerStatsHal()) {
+ ALOGE("nativeGetPowerEntityInfo failed to connect to power.stats HAL");
+ return nullptr;
+ }
+
+ jobjectArray powerEntityInfoArray = nullptr;
+ Return<void> ret = gPowerStatsHalV1_0_ptr->getPowerEntityInfo(
+ [&env, &powerEntityInfoArray](auto infos, auto status) {
+ if (status != Status::SUCCESS) {
+ ALOGE("Error getting power entity info");
+ } else {
+ powerEntityInfoArray = env->NewObjectArray(infos.size(), class_PEI, nullptr);
+ for (int i = 0; i < infos.size(); i++) {
+ jstring powerEntityName =
+ env->NewStringUTF(infos[i].powerEntityName.c_str());
+ jobject powerEntityInfo = env->NewObject(class_PEI, method_PEI_init);
+ env->SetIntField(powerEntityInfo, field_PEI_powerEntityId,
+ infos[i].powerEntityId);
+ env->SetObjectField(powerEntityInfo, field_PEI_powerEntityName,
+ powerEntityName);
+ env->SetObjectArrayElement(powerEntityInfoArray, i, powerEntityInfo);
+ env->DeleteLocalRef(powerEntityName);
+ env->DeleteLocalRef(powerEntityInfo);
+ }
+ }
+ });
+ if (!checkResult(ret, __func__)) {
+ return nullptr;
+ }
+
+ ret = gPowerStatsHalV1_0_ptr->getPowerEntityStateInfo(
+ {}, [&env, &powerEntityInfoArray](auto infos, auto status) {
+ if (status != Status::SUCCESS) {
+ ALOGE("Error getting power entity state info");
+ } else {
+ for (int i = 0; i < infos.size(); i++) {
+ jobjectArray stateInfoArray =
+ env->NewObjectArray(infos[i].states.size(), class_SI, nullptr);
+ for (int j = 0; j < infos[i].states.size(); j++) {
+ jstring powerEntityStateName = env->NewStringUTF(
+ infos[i].states[j].powerEntityStateName.c_str());
+ jobject stateInfo = env->NewObject(class_SI, method_SI_init);
+ env->SetIntField(stateInfo, field_SI_stateId,
+ infos[i].states[j].powerEntityStateId);
+ env->SetObjectField(stateInfo, field_SI_stateName,
+ powerEntityStateName);
+ env->SetObjectArrayElement(stateInfoArray, j, stateInfo);
+ env->DeleteLocalRef(powerEntityStateName);
+ env->DeleteLocalRef(stateInfo);
+ }
+
+ for (int j = 0; j < env->GetArrayLength(powerEntityInfoArray); j++) {
+ jobject powerEntityInfo =
+ env->GetObjectArrayElement(powerEntityInfoArray, j);
+ if (env->GetIntField(powerEntityInfo, field_PEI_powerEntityId) ==
+ infos[i].powerEntityId) {
+ env->SetObjectField(powerEntityInfo, field_PEI_states,
+ stateInfoArray);
+ env->SetObjectArrayElement(powerEntityInfoArray, j,
+ powerEntityInfo);
+ break;
+ }
+ }
+ }
+ }
+ });
+ if (!checkResult(ret, __func__)) {
+ return nullptr;
+ }
+
+ return powerEntityInfoArray;
+}
+
+static jobjectArray nativeGetStateResidency(JNIEnv *env, jclass clazz, jintArray powerEntityIds) {
+ std::lock_guard<std::mutex> lock(gPowerStatsHalMutex);
+
+ if (!connectToPowerStatsHal()) {
+ ALOGE("nativeGetStateResidency failed to connect to power.stats HAL");
+ return nullptr;
+ }
+
+ size_t powerEntityIdCount = env->GetArrayLength(powerEntityIds);
+ hidl_vec<uint32_t> powerEntityIdVector(powerEntityIdCount);
+
+ jint *powerEntityIdElements = env->GetIntArrayElements(powerEntityIds, 0);
+ for (int i = 0; i < powerEntityIdCount; i++) {
+ powerEntityIdVector[i] = powerEntityIdElements[i];
+ }
+ env->ReleaseIntArrayElements(powerEntityIds, powerEntityIdElements, 0);
+
+ jobjectArray stateResidencyResultArray = nullptr;
+ Return<void> ret = gPowerStatsHalV1_0_ptr->getPowerEntityStateResidencyData(
+ powerEntityIdVector, [&env, &stateResidencyResultArray](auto results, auto status) {
+ if (status != Status::SUCCESS) {
+ ALOGE("Error getting power entity state residency data");
+ } else {
+ stateResidencyResultArray =
+ env->NewObjectArray(results.size(), class_SRR, nullptr);
+ for (int i = 0; i < results.size(); i++) {
+ jobjectArray stateResidencyArray =
+ env->NewObjectArray(results[i].stateResidencyData.size(), class_SR,
+ nullptr);
+ for (int j = 0; j < results[i].stateResidencyData.size(); j++) {
+ jobject stateResidency = env->NewObject(class_SR, method_SR_init);
+ env->SetIntField(stateResidency, field_SR_stateId,
+ results[i].stateResidencyData[j].powerEntityStateId);
+ env->SetLongField(stateResidency, field_SR_totalTimeInStateMs,
+ results[i].stateResidencyData[j].totalTimeInStateMs);
+ env->SetLongField(stateResidency, field_SR_totalStateEntryCount,
+ results[i]
+ .stateResidencyData[j]
+ .totalStateEntryCount);
+ env->SetLongField(stateResidency, field_SR_lastEntryTimestampMs,
+ results[i]
+ .stateResidencyData[j]
+ .lastEntryTimestampMs);
+ env->SetObjectArrayElement(stateResidencyArray, j, stateResidency);
+ env->DeleteLocalRef(stateResidency);
+ }
+ jobject stateResidencyResult = env->NewObject(class_SRR, method_SRR_init);
+ env->SetIntField(stateResidencyResult, field_SRR_powerEntityId,
+ results[i].powerEntityId);
+ env->SetObjectField(stateResidencyResult, field_SRR_stateResidencyData,
+ stateResidencyArray);
+ env->SetObjectArrayElement(stateResidencyResultArray, i,
+ stateResidencyResult);
+ env->DeleteLocalRef(stateResidencyResult);
+ }
+ }
+ });
+ if (!checkResult(ret, __func__)) {
+ return nullptr;
+ }
+
+ return stateResidencyResultArray;
+}
+
+static jobjectArray nativeGetEnergyMeterInfo(JNIEnv *env, jclass clazz) {
+ std::lock_guard<std::mutex> lock(gPowerStatsHalMutex);
+
+ if (!connectToPowerStatsHal()) {
+ ALOGE("nativeGetEnergyMeterInfo failed to connect to power.stats HAL");
+ return nullptr;
+ }
+
+ jobjectArray channelInfoArray = nullptr;
+ Return<void> ret = gPowerStatsHalV1_0_ptr->getRailInfo(
+ [&env, &channelInfoArray](auto railInfo, auto status) {
+ if (status != Status::SUCCESS) {
+ ALOGW("Error getting rail info");
+ } else {
+ channelInfoArray = env->NewObjectArray(railInfo.size(), class_CI, nullptr);
+ for (int i = 0; i < railInfo.size(); i++) {
+ jstring channelName = env->NewStringUTF(railInfo[i].railName.c_str());
+ jobject channelInfo = env->NewObject(class_CI, method_CI_init);
+ env->SetIntField(channelInfo, field_CI_channelId, railInfo[i].index);
+ env->SetObjectField(channelInfo, field_CI_channelName, channelName);
+ env->SetObjectArrayElement(channelInfoArray, i, channelInfo);
+ env->DeleteLocalRef(channelName);
+ env->DeleteLocalRef(channelInfo);
+ }
+ }
+ });
+
+ if (!checkResult(ret, __func__)) {
+ ALOGE("getRailInfo failed");
+ return nullptr;
+ }
+
+ return channelInfoArray;
+}
+
+static jobjectArray nativeReadEnergyMeters(JNIEnv *env, jclass clazz, jintArray channelIds) {
+ std::lock_guard<std::mutex> lock(gPowerStatsHalMutex);
+
+ if (!connectToPowerStatsHal()) {
+ ALOGE("nativeGetEnergy failed to connect to power.stats HAL");
+ }
+
+ size_t channelIdCount = env->GetArrayLength(channelIds);
+ hidl_vec<uint32_t> channelIdVector(channelIdCount);
+
+ jint *channelIdElements = env->GetIntArrayElements(channelIds, 0);
+ for (int i = 0; i < channelIdCount; i++) {
+ channelIdVector[i] = channelIdElements[i];
+ }
+ env->ReleaseIntArrayElements(channelIds, channelIdElements, 0);
+
+ jobjectArray energyMeasurementArray = nullptr;
+ Return<void> ret =
+ gPowerStatsHalV1_0_ptr
+ ->getEnergyData(channelIdVector,
+ [&env, &energyMeasurementArray](auto energyData, auto status) {
+ if (status != Status::SUCCESS) {
+ ALOGW("Error getting energy data");
+ } else {
+ energyMeasurementArray =
+ env->NewObjectArray(energyData.size(), class_EM,
+ nullptr);
+ for (int i = 0; i < energyData.size(); i++) {
+ jobject energyMeasurement =
+ env->NewObject(class_EM, method_EM_init);
+ env->SetIntField(energyMeasurement,
+ field_EM_channelId,
+ energyData[i].index);
+ env->SetLongField(energyMeasurement,
+ field_EM_timestampMs,
+ energyData[i].timestamp);
+ env->SetLongField(energyMeasurement,
+ field_EM_durationMs, -1);
+ env->SetLongField(energyMeasurement,
+ field_EM_energyUWs,
+ energyData[i].energy);
+ env->SetObjectArrayElement(energyMeasurementArray,
+ i, energyMeasurement);
+ env->DeleteLocalRef(energyMeasurement);
+ }
+ }
+ });
+
+ if (!checkResult(ret, __func__)) {
+ ALOGE("getEnergyData failed");
+ return nullptr;
+ }
+
+ return energyMeasurementArray;
+}
+
+static jboolean nativeInit(JNIEnv *env, jclass clazz) {
+ std::lock_guard<std::mutex> lock(gPowerStatsHalMutex);
+
+ // ChannelInfo
+ jclass temp = env->FindClass("android/hardware/power/stats/ChannelInfo");
+ class_CI = (jclass)env->NewGlobalRef(temp);
+ method_CI_init = env->GetMethodID(class_CI, "<init>", "()V");
+ field_CI_channelId = env->GetFieldID(class_CI, "channelId", "I");
+ field_CI_channelName = env->GetFieldID(class_CI, "channelName", "Ljava/lang/String;");
+
+ // EnergyMeasurement
+ temp = env->FindClass("android/hardware/power/stats/EnergyMeasurement");
+ class_EM = (jclass)env->NewGlobalRef(temp);
+ method_EM_init = env->GetMethodID(class_EM, "<init>", "()V");
+ field_EM_channelId = env->GetFieldID(class_EM, "channelId", "I");
+ field_EM_timestampMs = env->GetFieldID(class_EM, "timestampMs", "J");
+ field_EM_durationMs = env->GetFieldID(class_EM, "durationMs", "J");
+ field_EM_energyUWs = env->GetFieldID(class_EM, "energyUWs", "J");
+
+ // StateInfo
+ temp = env->FindClass("android/hardware/power/stats/StateInfo");
+ class_SI = (jclass)env->NewGlobalRef(temp);
+ method_SI_init = env->GetMethodID(class_SI, "<init>", "()V");
+ field_SI_stateId = env->GetFieldID(class_SI, "stateId", "I");
+ field_SI_stateName = env->GetFieldID(class_SI, "stateName", "Ljava/lang/String;");
+
+ // PowerEntityInfo
+ temp = env->FindClass("android/hardware/power/stats/PowerEntityInfo");
+ class_PEI = (jclass)env->NewGlobalRef(temp);
+ method_PEI_init = env->GetMethodID(class_PEI, "<init>", "()V");
+ field_PEI_powerEntityId = env->GetFieldID(class_PEI, "powerEntityId", "I");
+ field_PEI_powerEntityName = env->GetFieldID(class_PEI, "powerEntityName", "Ljava/lang/String;");
+ field_PEI_states =
+ env->GetFieldID(class_PEI, "states", "[Landroid/hardware/power/stats/StateInfo;");
+
+ // StateResidency
+ temp = env->FindClass("android/hardware/power/stats/StateResidency");
+ class_SR = (jclass)env->NewGlobalRef(temp);
+ method_SR_init = env->GetMethodID(class_SR, "<init>", "()V");
+ field_SR_stateId = env->GetFieldID(class_SR, "stateId", "I");
+ field_SR_totalTimeInStateMs = env->GetFieldID(class_SR, "totalTimeInStateMs", "J");
+ field_SR_totalStateEntryCount = env->GetFieldID(class_SR, "totalStateEntryCount", "J");
+ field_SR_lastEntryTimestampMs = env->GetFieldID(class_SR, "lastEntryTimestampMs", "J");
+
+ // StateResidencyResult
+ temp = env->FindClass("android/hardware/power/stats/StateResidencyResult");
+ class_SRR = (jclass)env->NewGlobalRef(temp);
+ method_SRR_init = env->GetMethodID(class_SRR, "<init>", "()V");
+ field_SRR_powerEntityId = env->GetFieldID(class_SRR, "powerEntityId", "I");
+ field_SRR_stateResidencyData =
+ env->GetFieldID(class_SRR, "stateResidencyData",
+ "[Landroid/hardware/power/stats/StateResidency;");
+
+ if (!connectToPowerStatsHal()) {
+ ALOGE("nativeInit failed to connect to power.stats HAL");
+ return false;
+ }
+
+ return true;
+}
+
+static const JNINativeMethod method_table[] = {
+ {"nativeInit", "()Z", (void *)nativeInit},
+ {"nativeGetPowerEntityInfo", "()[Landroid/hardware/power/stats/PowerEntityInfo;",
+ (void *)nativeGetPowerEntityInfo},
+ {"nativeGetStateResidency", "([I)[Landroid/hardware/power/stats/StateResidencyResult;",
+ (void *)nativeGetStateResidency},
+ {"nativeGetEnergyMeterInfo", "()[Landroid/hardware/power/stats/ChannelInfo;",
+ (void *)nativeGetEnergyMeterInfo},
+ {"nativeReadEnergyMeters", "([I)[Landroid/hardware/power/stats/EnergyMeasurement;",
+ (void *)nativeReadEnergyMeters},
+};
+
+int register_android_server_PowerStatsService(JNIEnv *env) {
+ return jniRegisterNativeMethods(env,
+ "com/android/server/powerstats/"
+ "PowerStatsHALWrapper$PowerStatsHAL10WrapperImpl",
+ method_table, NELEM(method_table));
+}
+
+}; // namespace android
diff --git a/services/core/jni/gnss/GnssMeasurement.cpp b/services/core/jni/gnss/GnssMeasurement.cpp
index efa8ce74..2261c38 100644
--- a/services/core/jni/gnss/GnssMeasurement.cpp
+++ b/services/core/jni/gnss/GnssMeasurement.cpp
@@ -23,6 +23,7 @@
using android::hardware::hidl_vec;
using android::hardware::Return;
+using IGnssMeasurementInterface = android::hardware::gnss::IGnssMeasurementInterface;
using IGnssMeasurement_V1_0 = android::hardware::gnss::V1_0::IGnssMeasurement;
using IGnssMeasurement_V1_1 = android::hardware::gnss::V1_1::IGnssMeasurement;
using IGnssMeasurement_V2_0 = android::hardware::gnss::V2_0::IGnssMeasurement;
@@ -43,17 +44,33 @@
namespace android::gnss {
+// Implementation of GnssMeasurement
+
+GnssMeasurement::GnssMeasurement(const sp<IGnssMeasurementInterface>& iGnssMeasurement)
+ : mIGnssMeasurement(iGnssMeasurement) {}
+
+jboolean GnssMeasurement::setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
+ bool enableFullTracking) {
+ auto status = mIGnssMeasurement->setCallback(callback->getAidl(), enableFullTracking);
+ return checkAidlStatus(status, "IGnssMeasurement setCallback() failed.");
+}
+
+jboolean GnssMeasurement::close() {
+ auto status = mIGnssMeasurement->close();
+ return checkAidlStatus(status, "IGnssMeasurement close() failed.");
+}
+
// Implementation of GnssMeasurement_V1_0
GnssMeasurement_V1_0::GnssMeasurement_V1_0(const sp<IGnssMeasurement_V1_0>& iGnssMeasurement)
: mIGnssMeasurement_V1_0(iGnssMeasurement) {}
-jboolean GnssMeasurement_V1_0::setCallback(const sp<GnssMeasurementCallback>& callback,
+jboolean GnssMeasurement_V1_0::setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
bool enableFullTracking) {
if (enableFullTracking == true) {
ALOGW("Full tracking is mode not supported in 1.0 GNSS HAL.");
}
- auto status = mIGnssMeasurement_V1_0->setCallback(callback);
+ auto status = mIGnssMeasurement_V1_0->setCallback(callback->getHidl());
if (!checkHidlReturn(status, "IGnssMeasurement setCallback() failed.")) {
return JNI_FALSE;
}
@@ -71,9 +88,9 @@
GnssMeasurement_V1_1::GnssMeasurement_V1_1(const sp<IGnssMeasurement_V1_1>& iGnssMeasurement)
: GnssMeasurement_V1_0{iGnssMeasurement}, mIGnssMeasurement_V1_1(iGnssMeasurement) {}
-jboolean GnssMeasurement_V1_1::setCallback(const sp<GnssMeasurementCallback>& callback,
+jboolean GnssMeasurement_V1_1::setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
bool enableFullTracking) {
- auto status = mIGnssMeasurement_V1_1->setCallback_1_1(callback, enableFullTracking);
+ auto status = mIGnssMeasurement_V1_1->setCallback_1_1(callback->getHidl(), enableFullTracking);
if (!checkHidlReturn(status, "IGnssMeasurement setCallback_V1_1() failed.")) {
return JNI_FALSE;
}
@@ -86,9 +103,9 @@
GnssMeasurement_V2_0::GnssMeasurement_V2_0(const sp<IGnssMeasurement_V2_0>& iGnssMeasurement)
: GnssMeasurement_V1_1{iGnssMeasurement}, mIGnssMeasurement_V2_0(iGnssMeasurement) {}
-jboolean GnssMeasurement_V2_0::setCallback(const sp<GnssMeasurementCallback>& callback,
+jboolean GnssMeasurement_V2_0::setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
bool enableFullTracking) {
- auto status = mIGnssMeasurement_V2_0->setCallback_2_0(callback, enableFullTracking);
+ auto status = mIGnssMeasurement_V2_0->setCallback_2_0(callback->getHidl(), enableFullTracking);
if (!checkHidlReturn(status, "IGnssMeasurement setCallback_2_0() failed.")) {
return JNI_FALSE;
}
@@ -101,9 +118,9 @@
GnssMeasurement_V2_1::GnssMeasurement_V2_1(const sp<IGnssMeasurement_V2_1>& iGnssMeasurement)
: GnssMeasurement_V2_0{iGnssMeasurement}, mIGnssMeasurement_V2_1(iGnssMeasurement) {}
-jboolean GnssMeasurement_V2_1::setCallback(const sp<GnssMeasurementCallback>& callback,
+jboolean GnssMeasurement_V2_1::setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
bool enableFullTracking) {
- auto status = mIGnssMeasurement_V2_1->setCallback_2_1(callback, enableFullTracking);
+ auto status = mIGnssMeasurement_V2_1->setCallback_2_1(callback->getHidl(), enableFullTracking);
if (!checkHidlReturn(status, "IGnssMeasurement setCallback_2_1() failed.")) {
return JNI_FALSE;
}
diff --git a/services/core/jni/gnss/GnssMeasurement.h b/services/core/jni/gnss/GnssMeasurement.h
index 0e41abb..e64336f 100644
--- a/services/core/jni/gnss/GnssMeasurement.h
+++ b/services/core/jni/gnss/GnssMeasurement.h
@@ -27,6 +27,7 @@
#include <android/hardware/gnss/1.1/IGnssMeasurement.h>
#include <android/hardware/gnss/2.0/IGnssMeasurement.h>
#include <android/hardware/gnss/2.1/IGnssMeasurement.h>
+#include <android/hardware/gnss/BnGnssMeasurementInterface.h>
#include <log/log.h>
#include "GnssMeasurementCallback.h"
#include "jni.h"
@@ -36,16 +37,27 @@
class GnssMeasurementInterface {
public:
virtual ~GnssMeasurementInterface() {}
- virtual jboolean setCallback(const sp<GnssMeasurementCallback>& callback,
+ virtual jboolean setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
bool enableFullTracking) = 0;
virtual jboolean close() = 0;
};
+class GnssMeasurement : public GnssMeasurementInterface {
+public:
+ GnssMeasurement(const sp<android::hardware::gnss::IGnssMeasurementInterface>& iGnssMeasurement);
+ jboolean setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
+ bool enableFullTracking) override;
+ jboolean close() override;
+
+private:
+ const sp<android::hardware::gnss::IGnssMeasurementInterface> mIGnssMeasurement;
+};
+
class GnssMeasurement_V1_0 : public GnssMeasurementInterface {
public:
GnssMeasurement_V1_0(
const sp<android::hardware::gnss::V1_0::IGnssMeasurement>& iGnssMeasurement);
- jboolean setCallback(const sp<GnssMeasurementCallback>& callback,
+ jboolean setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
bool enableFullTracking) override;
jboolean close() override;
@@ -57,7 +69,7 @@
public:
GnssMeasurement_V1_1(
const sp<android::hardware::gnss::V1_1::IGnssMeasurement>& iGnssMeasurement);
- jboolean setCallback(const sp<GnssMeasurementCallback>& callback,
+ jboolean setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
bool enableFullTracking) override;
private:
@@ -68,7 +80,7 @@
public:
GnssMeasurement_V2_0(
const sp<android::hardware::gnss::V2_0::IGnssMeasurement>& iGnssMeasurement);
- jboolean setCallback(const sp<GnssMeasurementCallback>& callback,
+ jboolean setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
bool enableFullTracking) override;
private:
@@ -79,7 +91,7 @@
public:
GnssMeasurement_V2_1(
const sp<android::hardware::gnss::V2_1::IGnssMeasurement>& iGnssMeasurement);
- jboolean setCallback(const sp<GnssMeasurementCallback>& callback,
+ jboolean setCallback(const std::unique_ptr<GnssMeasurementCallback>& callback,
bool enableFullTracking) override;
private:
diff --git a/services/core/jni/gnss/GnssMeasurementCallback.cpp b/services/core/jni/gnss/GnssMeasurementCallback.cpp
index 9f1826c..bb020f3 100644
--- a/services/core/jni/gnss/GnssMeasurementCallback.cpp
+++ b/services/core/jni/gnss/GnssMeasurementCallback.cpp
@@ -20,6 +20,12 @@
namespace android::gnss {
+using binder::Status;
+using hardware::gnss::ElapsedRealtime;
+using hardware::gnss::GnssClock;
+using hardware::gnss::GnssData;
+using hardware::gnss::GnssMeasurement;
+
jclass class_gnssMeasurementsEvent;
jclass class_gnssMeasurement;
jclass class_gnssClock;
@@ -47,174 +53,98 @@
method_gnssClockCtor = env->GetMethodID(class_gnssClock, "<init>", "()V");
}
-hardware::Return<void> GnssMeasurementCallback::gnssMeasurementCb_2_1(
- const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssData& data) {
- translateAndSetGnssData(data);
- return hardware::Void();
+void setMeasurementData(JNIEnv* env, jobject& callbacksObj, jobject clock,
+ jobjectArray measurementArray) {
+ jobject gnssMeasurementsEvent =
+ env->NewObject(class_gnssMeasurementsEvent, method_gnssMeasurementsEventCtor, clock,
+ measurementArray);
+
+ env->CallVoidMethod(callbacksObj, method_reportMeasurementData, gnssMeasurementsEvent);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ env->DeleteLocalRef(gnssMeasurementsEvent);
}
-hardware::Return<void> GnssMeasurementCallback::gnssMeasurementCb_2_0(
- const hardware::gnss::V2_0::IGnssMeasurementCallback::GnssData& data) {
- translateAndSetGnssData(data);
- return hardware::Void();
-}
+template <class T_Measurement, class T_Flags>
+void setMeasurementFields_V1_0(const T_Measurement& measurement, JavaObject& object) {
+ uint32_t flags = static_cast<uint32_t>(measurement.flags);
-hardware::Return<void> GnssMeasurementCallback::gnssMeasurementCb(
- const hardware::gnss::V1_1::IGnssMeasurementCallback::GnssData& data) {
- translateAndSetGnssData(data);
- return hardware::Void();
-}
-
-hardware::Return<void> GnssMeasurementCallback::GnssMeasurementCb(
- const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssData& data) {
- translateAndSetGnssData(data);
- return hardware::Void();
-}
-
-template <>
-size_t GnssMeasurementCallback::getMeasurementCount<
- hardware::gnss::V1_0::IGnssMeasurementCallback::GnssData>(
- const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssData& data) {
- return data.measurementCount;
-}
-
-// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
-template <>
-void GnssMeasurementCallback::translateSingleGnssMeasurement<
- hardware::gnss::V1_0::IGnssMeasurementCallback::GnssMeasurement>(
- const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssMeasurement* measurement,
- JavaObject& object) {
- uint32_t flags = static_cast<uint32_t>(measurement->flags);
-
- SET(Svid, static_cast<int32_t>(measurement->svid));
- SET(ConstellationType, static_cast<int32_t>(measurement->constellation));
- SET(TimeOffsetNanos, measurement->timeOffsetNs);
- SET(State, static_cast<int32_t>(measurement->state));
- SET(ReceivedSvTimeNanos, measurement->receivedSvTimeInNs);
- SET(ReceivedSvTimeUncertaintyNanos, measurement->receivedSvTimeUncertaintyInNs);
- SET(Cn0DbHz, measurement->cN0DbHz);
- SET(PseudorangeRateMetersPerSecond, measurement->pseudorangeRateMps);
- SET(PseudorangeRateUncertaintyMetersPerSecond, measurement->pseudorangeRateUncertaintyMps);
+ SET(Svid, static_cast<int32_t>(measurement.svid));
+ SET(TimeOffsetNanos, measurement.timeOffsetNs);
+ SET(State, static_cast<int32_t>(measurement.state));
+ SET(ReceivedSvTimeNanos, measurement.receivedSvTimeInNs);
+ SET(ReceivedSvTimeUncertaintyNanos, measurement.receivedSvTimeUncertaintyInNs);
+ SET(PseudorangeRateMetersPerSecond, measurement.pseudorangeRateMps);
+ SET(PseudorangeRateUncertaintyMetersPerSecond, measurement.pseudorangeRateUncertaintyMps);
SET(AccumulatedDeltaRangeState,
- (static_cast<int32_t>(measurement->accumulatedDeltaRangeState) &
+ (static_cast<int32_t>(measurement.accumulatedDeltaRangeState) &
~ADR_STATE_HALF_CYCLE_REPORTED)); // Half Cycle state not reported from Hardware in V1_0
- SET(AccumulatedDeltaRangeMeters, measurement->accumulatedDeltaRangeM);
- SET(AccumulatedDeltaRangeUncertaintyMeters, measurement->accumulatedDeltaRangeUncertaintyM);
-
- if (flags & static_cast<uint32_t>(GnssMeasurementFlags::HAS_CARRIER_FREQUENCY)) {
- SET(CarrierFrequencyHz, measurement->carrierFrequencyHz);
- }
+ SET(AccumulatedDeltaRangeMeters, measurement.accumulatedDeltaRangeM);
+ SET(AccumulatedDeltaRangeUncertaintyMeters, measurement.accumulatedDeltaRangeUncertaintyM);
// Intentionally not copying deprecated fields of carrierCycles,
// carrierPhase, carrierPhaseUncertainty
- SET(MultipathIndicator, static_cast<int32_t>(measurement->multipathIndicator));
+ SET(MultipathIndicator, static_cast<int32_t>(measurement.multipathIndicator));
- if (flags & static_cast<uint32_t>(GnssMeasurementFlags::HAS_SNR)) {
- SET(SnrInDb, measurement->snrDb);
+ if (flags & static_cast<uint32_t>(T_Flags::HAS_SNR)) {
+ SET(SnrInDb, measurement.snrDb);
}
- if (flags & static_cast<uint32_t>(GnssMeasurementFlags::HAS_AUTOMATIC_GAIN_CONTROL)) {
- SET(AutomaticGainControlLevelInDb, measurement->agcLevelDb);
+ if (flags & static_cast<uint32_t>(T_Flags::HAS_AUTOMATIC_GAIN_CONTROL)) {
+ SET(AutomaticGainControlLevelInDb, measurement.agcLevelDb);
}
}
-// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
-template <>
-void GnssMeasurementCallback::translateSingleGnssMeasurement<
- hardware::gnss::V1_1::IGnssMeasurementCallback::GnssMeasurement>(
- const hardware::gnss::V1_1::IGnssMeasurementCallback::GnssMeasurement* measurement_V1_1,
- JavaObject& object) {
- translateSingleGnssMeasurement(&(measurement_V1_1->v1_0), object);
+template <class T_Measurement, class T_Flags>
+void setMeasurementFields_V2_1(const T_Measurement& measurement, JavaObject& object) {
+ SET(BasebandCn0DbHz, measurement.basebandCN0DbHz);
- // Set the V1_1 flag, and mark that new field has valid information for Java Layer
- SET(AccumulatedDeltaRangeState,
- (static_cast<int32_t>(measurement_V1_1->accumulatedDeltaRangeState) |
- ADR_STATE_HALF_CYCLE_REPORTED));
-}
-
-// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
-template <>
-void GnssMeasurementCallback::translateSingleGnssMeasurement<
- hardware::gnss::V2_0::IGnssMeasurementCallback::GnssMeasurement>(
- const hardware::gnss::V2_0::IGnssMeasurementCallback::GnssMeasurement* measurement_V2_0,
- JavaObject& object) {
- JNIEnv* env = getJniEnv();
- translateSingleGnssMeasurement(&(measurement_V2_0->v1_1), object);
-
- jstring codeType = env->NewStringUTF(measurement_V2_0->codeType.c_str());
- SET(CodeType, codeType);
-
- // Overwrite with v2_0.state since v2_0->v1_1->v1_0.state is deprecated.
- SET(State, static_cast<int32_t>(measurement_V2_0->state));
-
- // Overwrite with v2_0.constellation since v2_0->v1_1->v1_0.constellation is deprecated.
- SET(ConstellationType, static_cast<int32_t>(measurement_V2_0->constellation));
-
- if (codeType) {
- env->DeleteLocalRef(codeType);
- }
-}
-
-// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
-template <>
-void GnssMeasurementCallback::translateSingleGnssMeasurement<
- hardware::gnss::V2_1::IGnssMeasurementCallback::GnssMeasurement>(
- const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssMeasurement* measurement_V2_1,
- JavaObject& object) {
- translateSingleGnssMeasurement(&(measurement_V2_1->v2_0), object);
-
- SET(BasebandCn0DbHz, measurement_V2_1->basebandCN0DbHz);
-
- if (measurement_V2_1->flags & GnssMeasurementFlags::HAS_FULL_ISB) {
- SET(FullInterSignalBiasNanos, measurement_V2_1->fullInterSignalBiasNs);
+ if (measurement.flags & T_Flags::HAS_FULL_ISB) {
+ SET(FullInterSignalBiasNanos, measurement.fullInterSignalBiasNs);
}
- if (measurement_V2_1->flags & GnssMeasurementFlags::HAS_FULL_ISB_UNCERTAINTY) {
- SET(FullInterSignalBiasUncertaintyNanos,
- measurement_V2_1->fullInterSignalBiasUncertaintyNs);
+ if (measurement.flags & T_Flags::HAS_FULL_ISB_UNCERTAINTY) {
+ SET(FullInterSignalBiasUncertaintyNanos, measurement.fullInterSignalBiasUncertaintyNs);
}
- if (measurement_V2_1->flags & GnssMeasurementFlags::HAS_SATELLITE_ISB) {
- SET(SatelliteInterSignalBiasNanos, measurement_V2_1->satelliteInterSignalBiasNs);
+ if (measurement.flags & T_Flags::HAS_SATELLITE_ISB) {
+ SET(SatelliteInterSignalBiasNanos, measurement.satelliteInterSignalBiasNs);
}
- if (measurement_V2_1->flags & GnssMeasurementFlags::HAS_SATELLITE_ISB_UNCERTAINTY) {
+ if (measurement.flags & T_Flags::HAS_SATELLITE_ISB_UNCERTAINTY) {
SET(SatelliteInterSignalBiasUncertaintyNanos,
- measurement_V2_1->satelliteInterSignalBiasUncertaintyNs);
+ measurement.satelliteInterSignalBiasUncertaintyNs);
}
}
-template <>
-void GnssMeasurementCallback::translateGnssClock(
- JavaObject& object,
- const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssClock& clock) {
+template <class T_Clock, class T_Flags>
+void setClockFields_V1_0(const T_Clock& clock, JavaObject& object) {
uint32_t flags = static_cast<uint32_t>(clock.gnssClockFlags);
- if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_LEAP_SECOND)) {
+ if (flags & static_cast<uint32_t>(T_Flags::HAS_LEAP_SECOND)) {
SET(LeapSecond, static_cast<int32_t>(clock.leapSecond));
}
- if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_TIME_UNCERTAINTY)) {
+ if (flags & static_cast<uint32_t>(T_Flags::HAS_TIME_UNCERTAINTY)) {
SET(TimeUncertaintyNanos, clock.timeUncertaintyNs);
}
- if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_FULL_BIAS)) {
+ if (flags & static_cast<uint32_t>(T_Flags::HAS_FULL_BIAS)) {
SET(FullBiasNanos, clock.fullBiasNs);
}
- if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_BIAS)) {
+ if (flags & static_cast<uint32_t>(T_Flags::HAS_BIAS)) {
SET(BiasNanos, clock.biasNs);
}
- if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_BIAS_UNCERTAINTY)) {
+ if (flags & static_cast<uint32_t>(T_Flags::HAS_BIAS_UNCERTAINTY)) {
SET(BiasUncertaintyNanos, clock.biasUncertaintyNs);
}
- if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_DRIFT)) {
+ if (flags & static_cast<uint32_t>(T_Flags::HAS_DRIFT)) {
SET(DriftNanosPerSecond, clock.driftNsps);
}
- if (flags & static_cast<uint32_t>(GnssClockFlags::HAS_DRIFT_UNCERTAINTY)) {
+ if (flags & static_cast<uint32_t>(T_Flags::HAS_DRIFT_UNCERTAINTY)) {
SET(DriftUncertaintyNanosPerSecond, clock.driftUncertaintyNsps);
}
@@ -222,10 +152,8 @@
SET(HardwareClockDiscontinuityCount, clock.hwClockDiscontinuityCount);
}
-template <>
-void GnssMeasurementCallback::translateGnssClock(
- JavaObject& object,
- const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssClock& clock) {
+template <class T_Clock, class T_Flags>
+void setClockFields_V2_1(const T_Clock& clock, JavaObject& object) {
JNIEnv* env = getJniEnv();
SET(ReferenceConstellationTypeForIsb,
static_cast<int32_t>(clock.referenceSignalTypeForIsb.constellation));
@@ -234,17 +162,216 @@
jstring referenceCodeTypeForIsb =
env->NewStringUTF(clock.referenceSignalTypeForIsb.codeType.c_str());
SET(ReferenceCodeTypeForIsb, referenceCodeTypeForIsb);
+ env->DeleteLocalRef(referenceCodeTypeForIsb);
+}
- translateGnssClock(object, clock.v1_0);
-
- if (referenceCodeTypeForIsb) {
- env->DeleteLocalRef(referenceCodeTypeForIsb);
+template <class T_ElapsedRealtime, class T_Flags>
+void setElapsedRealtimeFields(const T_ElapsedRealtime& elapsedRealtime, JavaObject& object) {
+ uint32_t flags = static_cast<uint32_t>(elapsedRealtime.flags);
+ if (flags & T_Flags::HAS_TIMESTAMP_NS) {
+ SET(ElapsedRealtimeNanos, static_cast<uint64_t>(elapsedRealtime.timestampNs));
+ }
+ if (flags & T_Flags::HAS_TIME_UNCERTAINTY_NS) {
+ SET(ElapsedRealtimeUncertaintyNanos,
+ static_cast<double>(elapsedRealtime.timeUncertaintyNs));
}
}
+// Implementation of GnssMeasurementCallbackAidl class.
+
+Status GnssMeasurementCallbackAidl::gnssMeasurementCb(const GnssData& data) {
+ ALOGD("%s", __func__);
+ translateAndSetGnssData(data);
+ return Status::ok();
+}
+
+void GnssMeasurementCallbackAidl::translateAndSetGnssData(const GnssData& data) {
+ JNIEnv* env = getJniEnv();
+
+ JavaObject gnssClockJavaObject(env, class_gnssClock, method_gnssClockCtor);
+ translateGnssClock(env, data, gnssClockJavaObject);
+ jobject clock = gnssClockJavaObject.get();
+
+ jobjectArray measurementArray = translateAllGnssMeasurements(env, data.measurements);
+ setMeasurementData(env, mCallbacksObj, clock, measurementArray);
+
+ env->DeleteLocalRef(clock);
+ env->DeleteLocalRef(measurementArray);
+}
+
+void GnssMeasurementCallbackAidl::translateSingleGnssMeasurement(JNIEnv* env,
+ const GnssMeasurement& measurement,
+ JavaObject& object) {
+ setMeasurementFields_V1_0<GnssMeasurement, GnssMeasurement>(measurement, object);
+ setMeasurementFields_V2_1<GnssMeasurement, GnssMeasurement>(measurement, object);
+
+ SET(Cn0DbHz, measurement.antennaCN0DbHz);
+ SET(ConstellationType, static_cast<int32_t>(measurement.signalType.constellation));
+
+ if (measurement.flags & static_cast<uint32_t>(GnssMeasurement::HAS_CARRIER_FREQUENCY)) {
+ SET(CarrierFrequencyHz, static_cast<float>(measurement.signalType.carrierFrequencyHz));
+ }
+
+ jstring codeType = env->NewStringUTF(measurement.signalType.codeType.c_str());
+ SET(CodeType, codeType);
+ env->DeleteLocalRef(codeType);
+}
+
+jobjectArray GnssMeasurementCallbackAidl::translateAllGnssMeasurements(
+ JNIEnv* env, const std::vector<GnssMeasurement>& measurements) {
+ if (measurements.size() == 0) {
+ return nullptr;
+ }
+
+ jobjectArray gnssMeasurementArray =
+ env->NewObjectArray(measurements.size(), class_gnssMeasurement,
+ nullptr /* initialElement */);
+
+ for (uint16_t i = 0; i < measurements.size(); ++i) {
+ JavaObject object(env, class_gnssMeasurement, method_gnssMeasurementCtor);
+ translateSingleGnssMeasurement(env, measurements[i], object);
+ jobject gnssMeasurement = object.get();
+ env->SetObjectArrayElement(gnssMeasurementArray, i, gnssMeasurement);
+ env->DeleteLocalRef(gnssMeasurement);
+ }
+
+ return gnssMeasurementArray;
+}
+
+void GnssMeasurementCallbackAidl::translateGnssClock(JNIEnv* env, const GnssData& data,
+ JavaObject& object) {
+ setElapsedRealtimeFields<ElapsedRealtime, ElapsedRealtime>(data.elapsedRealtime, object);
+ setClockFields_V1_0<GnssClock, GnssClock>(data.clock, object);
+ setClockFields_V2_1<GnssClock, GnssClock>(data.clock, object);
+}
+
+// Implementation of GnssMeasurementCallbackHidl class.
+
+hardware::Return<void> GnssMeasurementCallbackHidl::gnssMeasurementCb_2_1(
+ const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssData& data) {
+ translateAndSetGnssData(data);
+ return hardware::Void();
+}
+
+hardware::Return<void> GnssMeasurementCallbackHidl::gnssMeasurementCb_2_0(
+ const hardware::gnss::V2_0::IGnssMeasurementCallback::GnssData& data) {
+ translateAndSetGnssData(data);
+ return hardware::Void();
+}
+
+hardware::Return<void> GnssMeasurementCallbackHidl::gnssMeasurementCb(
+ const hardware::gnss::V1_1::IGnssMeasurementCallback::GnssData& data) {
+ translateAndSetGnssData(data);
+ return hardware::Void();
+}
+
+hardware::Return<void> GnssMeasurementCallbackHidl::GnssMeasurementCb(
+ const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssData& data) {
+ translateAndSetGnssData(data);
+ return hardware::Void();
+}
+
template <>
-void GnssMeasurementCallback::translateGnssClock(
- JavaObject& object, const hardware::gnss::V2_0::IGnssMeasurementCallback::GnssData& data) {
+size_t GnssMeasurementCallbackHidl::getMeasurementCount<
+ hardware::gnss::V1_0::IGnssMeasurementCallback::GnssData>(
+ const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssData& data) {
+ return data.measurementCount;
+}
+
+// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
+template <>
+void GnssMeasurementCallbackHidl::translateSingleGnssMeasurement<
+ hardware::gnss::V1_0::IGnssMeasurementCallback::GnssMeasurement>(
+ const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssMeasurement& measurement,
+ JavaObject& object) {
+ setMeasurementFields_V1_0<hardware::gnss::V1_0::IGnssMeasurementCallback::GnssMeasurement,
+ GnssMeasurementFlags>(measurement, object);
+
+ SET(ConstellationType, static_cast<int32_t>(measurement.constellation));
+ SET(Cn0DbHz, measurement.cN0DbHz);
+ if (measurement.flags & static_cast<uint32_t>(GnssMeasurementFlags::HAS_CARRIER_FREQUENCY)) {
+ SET(CarrierFrequencyHz, measurement.carrierFrequencyHz);
+ }
+}
+
+// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
+template <>
+void GnssMeasurementCallbackHidl::translateSingleGnssMeasurement<
+ hardware::gnss::V1_1::IGnssMeasurementCallback::GnssMeasurement>(
+ const hardware::gnss::V1_1::IGnssMeasurementCallback::GnssMeasurement& measurement_V1_1,
+ JavaObject& object) {
+ translateSingleGnssMeasurement(measurement_V1_1.v1_0, object);
+
+ // Set the V1_1 flag, and mark that new field has valid information for Java Layer
+ SET(AccumulatedDeltaRangeState,
+ (static_cast<int32_t>(measurement_V1_1.accumulatedDeltaRangeState) |
+ ADR_STATE_HALF_CYCLE_REPORTED));
+}
+
+// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
+template <>
+void GnssMeasurementCallbackHidl::translateSingleGnssMeasurement<
+ hardware::gnss::V2_0::IGnssMeasurementCallback::GnssMeasurement>(
+ const hardware::gnss::V2_0::IGnssMeasurementCallback::GnssMeasurement& measurement_V2_0,
+ JavaObject& object) {
+ JNIEnv* env = getJniEnv();
+ translateSingleGnssMeasurement(measurement_V2_0.v1_1, object);
+
+ jstring codeType = env->NewStringUTF(measurement_V2_0.codeType.c_str());
+ SET(CodeType, codeType);
+
+ // Overwrite with v2_0.state since V2_0.v1_1.v1_0.state is deprecated.
+ SET(State, static_cast<int32_t>(measurement_V2_0.state));
+
+ // Overwrite with v2_0.constellation since V2_0.v1_1.v1_0.constellation is deprecated.
+ SET(ConstellationType, static_cast<int32_t>(measurement_V2_0.constellation));
+
+ if (codeType) {
+ env->DeleteLocalRef(codeType);
+ }
+}
+
+// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
+template <>
+void GnssMeasurementCallbackHidl::translateSingleGnssMeasurement<
+ hardware::gnss::V2_1::IGnssMeasurementCallback::GnssMeasurement>(
+ const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssMeasurement& measurement_V2_1,
+ JavaObject& object) {
+ translateSingleGnssMeasurement(measurement_V2_1.v2_0, object);
+
+ setMeasurementFields_V2_1<hardware::gnss::V2_1::IGnssMeasurementCallback::GnssMeasurement,
+ GnssMeasurementFlags>(measurement_V2_1, object);
+}
+
+template <>
+void GnssMeasurementCallbackHidl::translateGnssClock(
+ const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssClock& clock,
+ JavaObject& object) {
+ setClockFields_V1_0<hardware::gnss::V1_0::IGnssMeasurementCallback::GnssClock,
+ GnssClockFlags>(clock, object);
+}
+
+template <>
+void GnssMeasurementCallbackHidl::translateGnssClock(
+ const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssClock& clock,
+ JavaObject& object) {
+ setClockFields_V2_1<hardware::gnss::V2_1::IGnssMeasurementCallback::GnssClock,
+ GnssClockFlags>(clock, object);
+ translateGnssClock(clock.v1_0, object);
+}
+
+template <>
+void GnssMeasurementCallbackHidl::translateGnssClock(
+ const hardware::gnss::V2_0::IGnssMeasurementCallback::GnssData& data, JavaObject& object) {
+ setElapsedRealtimeFields<hardware::gnss::V2_0::ElapsedRealtime,
+ hardware::gnss::V2_0::ElapsedRealtimeFlags>(data.elapsedRealtime,
+ object);
+ translateGnssClock(data.clock, object);
+}
+
+template <>
+void GnssMeasurementCallbackHidl::translateGnssClock(
+ const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssData& data, JavaObject& object) {
auto elapsedRealtime = data.elapsedRealtime;
uint16_t flags = static_cast<uint16_t>(elapsedRealtime.flags);
if (flags & hardware::gnss::V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS) {
@@ -254,33 +381,7 @@
SET(ElapsedRealtimeUncertaintyNanos,
static_cast<double>(elapsedRealtime.timeUncertaintyNs));
}
- translateGnssClock(object, data.clock);
-}
-
-template <>
-void GnssMeasurementCallback::translateGnssClock(
- JavaObject& object, const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssData& data) {
- auto elapsedRealtime = data.elapsedRealtime;
- uint16_t flags = static_cast<uint16_t>(elapsedRealtime.flags);
- if (flags & hardware::gnss::V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS) {
- SET(ElapsedRealtimeNanos, static_cast<uint64_t>(elapsedRealtime.timestampNs));
- }
- if (flags & hardware::gnss::V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS) {
- SET(ElapsedRealtimeUncertaintyNanos,
- static_cast<double>(elapsedRealtime.timeUncertaintyNs));
- }
- translateGnssClock(object, data.clock);
-}
-
-void GnssMeasurementCallback::setMeasurementData(JNIEnv* env, jobject clock,
- jobjectArray measurementArray) {
- jobject gnssMeasurementsEvent =
- env->NewObject(class_gnssMeasurementsEvent, method_gnssMeasurementsEventCtor, clock,
- measurementArray);
-
- env->CallVoidMethod(mCallbacksObj, method_reportMeasurementData, gnssMeasurementsEvent);
- checkAndClearExceptionFromCallback(env, __FUNCTION__);
- env->DeleteLocalRef(gnssMeasurementsEvent);
+ translateGnssClock(data.clock, object);
}
} // namespace android::gnss
diff --git a/services/core/jni/gnss/GnssMeasurementCallback.h b/services/core/jni/gnss/GnssMeasurementCallback.h
index 71c33a7..26f1243 100644
--- a/services/core/jni/gnss/GnssMeasurementCallback.h
+++ b/services/core/jni/gnss/GnssMeasurementCallback.h
@@ -27,6 +27,7 @@
#include <android/hardware/gnss/1.1/IGnssMeasurement.h>
#include <android/hardware/gnss/2.0/IGnssMeasurement.h>
#include <android/hardware/gnss/2.1/IGnssMeasurement.h>
+#include <android/hardware/gnss/BnGnssMeasurementCallback.h>
#include <log/log.h>
#include "Utils.h"
#include "jni.h"
@@ -44,12 +45,36 @@
void GnssMeasurement_class_init_once(JNIEnv* env, jclass& clazz);
+void setMeasurementData(JNIEnv* env, jobject& callbacksObj, jobject clock,
+ jobjectArray measurementArray);
+
+class GnssMeasurementCallbackAidl : public hardware::gnss::BnGnssMeasurementCallback {
+public:
+ GnssMeasurementCallbackAidl(jobject& callbacksObj) : mCallbacksObj(callbacksObj) {}
+ android::binder::Status gnssMeasurementCb(const hardware::gnss::GnssData& data) override;
+
+private:
+ void translateSingleGnssMeasurement(JNIEnv* env,
+ const hardware::gnss::GnssMeasurement& measurement,
+ JavaObject& object);
+
+ jobjectArray translateAllGnssMeasurements(
+ JNIEnv* env, const std::vector<hardware::gnss::GnssMeasurement>& measurements);
+
+ void translateAndSetGnssData(const hardware::gnss::GnssData& data);
+
+ void translateGnssClock(JNIEnv* env, const hardware::gnss::GnssData& data, JavaObject& object);
+
+ jobject& mCallbacksObj;
+};
+
/*
* GnssMeasurementCallback implements the callback methods required for the
* GnssMeasurement interface.
*/
-struct GnssMeasurementCallback : public hardware::gnss::V2_1::IGnssMeasurementCallback {
- GnssMeasurementCallback(jobject& callbacksObj) : mCallbacksObj(callbacksObj) {}
+class GnssMeasurementCallbackHidl : public hardware::gnss::V2_1::IGnssMeasurementCallback {
+public:
+ GnssMeasurementCallbackHidl(jobject& callbacksObj) : mCallbacksObj(callbacksObj) {}
hardware::Return<void> gnssMeasurementCb_2_1(
const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssData& data) override;
hardware::Return<void> gnssMeasurementCb_2_0(
@@ -61,7 +86,7 @@
private:
template <class T>
- void translateSingleGnssMeasurement(const T* measurement, JavaObject& object);
+ void translateSingleGnssMeasurement(const T& measurement, JavaObject& object);
template <class T>
jobjectArray translateAllGnssMeasurements(JNIEnv* env, const T* measurements, size_t count);
@@ -73,93 +98,114 @@
size_t getMeasurementCount(const T& data);
template <class T>
- void translateGnssClock(JavaObject& object, const T& data);
-
- void setMeasurementData(JNIEnv* env, jobject clock, jobjectArray measurementArray);
+ void translateGnssClock(const T& data, JavaObject& object);
jobject& mCallbacksObj;
};
+class GnssMeasurementCallback {
+public:
+ GnssMeasurementCallback(jobject& callbacksObj) : mCallbacksObj(callbacksObj) {}
+ sp<GnssMeasurementCallbackAidl> getAidl() {
+ if (callbackAidl == nullptr) {
+ callbackAidl = sp<GnssMeasurementCallbackAidl>::make(mCallbacksObj);
+ }
+ return callbackAidl;
+ }
+
+ sp<GnssMeasurementCallbackHidl> getHidl() {
+ if (callbackHidl == nullptr) {
+ callbackHidl = sp<GnssMeasurementCallbackHidl>::make(mCallbacksObj);
+ }
+ return callbackHidl;
+ }
+
+private:
+ jobject& mCallbacksObj;
+ sp<GnssMeasurementCallbackAidl> callbackAidl;
+ sp<GnssMeasurementCallbackHidl> callbackHidl;
+};
+
template <class T>
-void GnssMeasurementCallback::translateAndSetGnssData(const T& data) {
+void GnssMeasurementCallbackHidl::translateAndSetGnssData(const T& data) {
JNIEnv* env = getJniEnv();
JavaObject gnssClockJavaObject(env, class_gnssClock, method_gnssClockCtor);
- translateGnssClock(gnssClockJavaObject, data);
+ translateGnssClock(data, gnssClockJavaObject);
jobject clock = gnssClockJavaObject.get();
size_t count = getMeasurementCount(data);
jobjectArray measurementArray =
translateAllGnssMeasurements(env, data.measurements.data(), count);
- setMeasurementData(env, clock, measurementArray);
+ setMeasurementData(env, mCallbacksObj, clock, measurementArray);
env->DeleteLocalRef(clock);
env->DeleteLocalRef(measurementArray);
}
template <>
-size_t GnssMeasurementCallback::getMeasurementCount<
+size_t GnssMeasurementCallbackHidl::getMeasurementCount<
hardware::gnss::V1_0::IGnssMeasurementCallback::GnssData>(
const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssData& data);
template <class T>
-size_t GnssMeasurementCallback::getMeasurementCount(const T& data) {
+size_t GnssMeasurementCallbackHidl::getMeasurementCount(const T& data) {
return data.measurements.size();
}
// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
template <>
-void GnssMeasurementCallback::translateSingleGnssMeasurement<
+void GnssMeasurementCallbackHidl::translateSingleGnssMeasurement<
hardware::gnss::V1_0::IGnssMeasurementCallback::GnssMeasurement>(
- const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssMeasurement* measurement,
+ const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssMeasurement& measurement,
JavaObject& object);
// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
template <>
-void GnssMeasurementCallback::translateSingleGnssMeasurement<
+void GnssMeasurementCallbackHidl::translateSingleGnssMeasurement<
hardware::gnss::V1_1::IGnssMeasurementCallback::GnssMeasurement>(
- const hardware::gnss::V1_1::IGnssMeasurementCallback::GnssMeasurement* measurement_V1_1,
+ const hardware::gnss::V1_1::IGnssMeasurementCallback::GnssMeasurement& measurement_V1_1,
JavaObject& object);
// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
template <>
-void GnssMeasurementCallback::translateSingleGnssMeasurement<
+void GnssMeasurementCallbackHidl::translateSingleGnssMeasurement<
hardware::gnss::V2_0::IGnssMeasurementCallback::GnssMeasurement>(
- const hardware::gnss::V2_0::IGnssMeasurementCallback::GnssMeasurement* measurement_V2_0,
+ const hardware::gnss::V2_0::IGnssMeasurementCallback::GnssMeasurement& measurement_V2_0,
JavaObject& object);
// Preallocate object as: JavaObject object(env, "android/location/GnssMeasurement");
template <>
-void GnssMeasurementCallback::translateSingleGnssMeasurement<
+void GnssMeasurementCallbackHidl::translateSingleGnssMeasurement<
hardware::gnss::V2_1::IGnssMeasurementCallback::GnssMeasurement>(
- const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssMeasurement* measurement_V2_1,
+ const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssMeasurement& measurement_V2_1,
JavaObject& object);
template <class T>
-void GnssMeasurementCallback::translateGnssClock(JavaObject& object, const T& data) {
- translateGnssClock(object, data.clock);
+void GnssMeasurementCallbackHidl::translateGnssClock(const T& data, JavaObject& object) {
+ translateGnssClock(data.clock, object);
}
template <>
-void GnssMeasurementCallback::translateGnssClock(
- JavaObject& object, const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssClock& clock);
+void GnssMeasurementCallbackHidl::translateGnssClock(
+ const hardware::gnss::V1_0::IGnssMeasurementCallback::GnssClock& clock, JavaObject& object);
template <>
-void GnssMeasurementCallback::translateGnssClock(
- JavaObject& object, const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssClock& clock);
+void GnssMeasurementCallbackHidl::translateGnssClock(
+ const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssClock& clock, JavaObject& object);
template <>
-void GnssMeasurementCallback::translateGnssClock(
- JavaObject& object, const hardware::gnss::V2_0::IGnssMeasurementCallback::GnssData& data);
+void GnssMeasurementCallbackHidl::translateGnssClock(
+ const hardware::gnss::V2_0::IGnssMeasurementCallback::GnssData& data, JavaObject& object);
template <>
-void GnssMeasurementCallback::translateGnssClock(
- JavaObject& object, const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssData& data);
+void GnssMeasurementCallbackHidl::translateGnssClock(
+ const hardware::gnss::V2_1::IGnssMeasurementCallback::GnssData& data, JavaObject& object);
template <class T>
-jobjectArray GnssMeasurementCallback::translateAllGnssMeasurements(JNIEnv* env,
- const T* measurements,
- size_t count) {
+jobjectArray GnssMeasurementCallbackHidl::translateAllGnssMeasurements(JNIEnv* env,
+ const T* measurements,
+ size_t count) {
if (count == 0) {
return nullptr;
}
@@ -169,7 +215,7 @@
for (uint16_t i = 0; i < count; ++i) {
JavaObject object(env, class_gnssMeasurement, method_gnssMeasurementCtor);
- translateSingleGnssMeasurement(&(measurements[i]), object);
+ translateSingleGnssMeasurement(measurements[i], object);
jobject gnssMeasurement = object.get();
env->SetObjectArrayElement(gnssMeasurementArray, i, gnssMeasurement);
env->DeleteLocalRef(gnssMeasurement);
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index 5a0d08a..85ef394 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -29,6 +29,7 @@
int register_android_server_InputManager(JNIEnv* env);
int register_android_server_LightsService(JNIEnv* env);
int register_android_server_PowerManagerService(JNIEnv* env);
+int register_android_server_PowerStatsService(JNIEnv* env);
int register_android_server_storage_AppFuse(JNIEnv* env);
int register_android_server_SerialService(JNIEnv* env);
int register_android_server_SystemServer(JNIEnv* env);
@@ -82,6 +83,7 @@
register_android_server_broadcastradio_BroadcastRadioService(env);
register_android_server_broadcastradio_Tuner(vm, env);
register_android_server_PowerManagerService(env);
+ register_android_server_PowerStatsService(env);
register_android_server_SerialService(env);
register_android_server_InputManager(env);
register_android_server_LightsService(env);
diff --git a/services/core/xsd/display-device-config/display-device-config.xsd b/services/core/xsd/display-device-config/display-device-config.xsd
index bbd8de2..d670991 100644
--- a/services/core/xsd/display-device-config/display-device-config.xsd
+++ b/services/core/xsd/display-device-config/display-device-config.xsd
@@ -29,12 +29,19 @@
<xs:annotation name="nonnull"/>
<xs:annotation name="final"/>
</xs:element>
+ <xs:element type="displayQuirks" name="quirks" minOccurs="0" maxOccurs="1" />
</xs:sequence>
</xs:complexType>
</xs:element>
<!-- Type definitions -->
+ <xs:complexType name="displayQuirks">
+ <xs:sequence>
+ <xs:element name="quirk" type="xs:string" minOccurs="0" maxOccurs="unbounded" />
+ </xs:sequence>
+ </xs:complexType>
+
<xs:complexType name="nitsMap">
<xs:sequence>
<xs:element name="point" type="point" maxOccurs="unbounded" minOccurs="2">
diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt
index 7a35642..e68ca26 100644
--- a/services/core/xsd/display-device-config/schema/current.txt
+++ b/services/core/xsd/display-device-config/schema/current.txt
@@ -3,10 +3,17 @@
public class DisplayConfiguration {
ctor public DisplayConfiguration();
+ method public com.android.server.display.config.DisplayQuirks getQuirks();
method @NonNull public final com.android.server.display.config.NitsMap getScreenBrightnessMap();
+ method public void setQuirks(com.android.server.display.config.DisplayQuirks);
method public final void setScreenBrightnessMap(@NonNull com.android.server.display.config.NitsMap);
}
+ public class DisplayQuirks {
+ ctor public DisplayQuirks();
+ method public java.util.List<java.lang.String> getQuirk();
+ }
+
public class NitsMap {
ctor public NitsMap();
method @NonNull public final java.util.List<com.android.server.display.config.Point> getPoint();
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java
index c766ca0..7ec5ff0 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java
@@ -413,7 +413,6 @@
policy.mPermissionPolicy = permissionPolicy;
}
- parser.next();
int outerDepth = parser.getDepth();
policy.mLockTaskPackages.clear();
policy.mAdminList.clear();
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index d1294fe..0e0fe4c 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -124,6 +124,7 @@
import android.app.AlarmManager;
import android.app.AppGlobals;
import android.app.AppOpsManager;
+import android.app.AppOpsManager.Mode;
import android.app.BroadcastOptions;
import android.app.IActivityManager;
import android.app.IActivityTaskManager;
@@ -198,7 +199,6 @@
import android.media.IAudioService;
import android.net.ConnectivityManager;
import android.net.IIpConnectivityMetrics;
-import android.net.NetworkUtils;
import android.net.ProxyInfo;
import android.net.Uri;
import android.net.metrics.IpConnectivityLog;
@@ -269,6 +269,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.internal.net.NetworkUtilsInternal;
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.os.BackgroundThread;
import com.android.internal.statusbar.IStatusBarService;
@@ -1024,23 +1025,6 @@
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.newBuilder(mContext).setReason(reason).build().factoryReset();
- } 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.
*/
@@ -3373,6 +3357,18 @@
PREVENT_SETTING_PASSWORD_QUALITY_ON_PARENT, packageName, userId);
}
+ private boolean isPasswordLimitingAdminTargetingP(CallerIdentity caller) {
+ if (!caller.hasAdminComponent()) {
+ return false;
+ }
+
+ synchronized (getLockObject()) {
+ return getActiveAdminWithPolicyForUidLocked(
+ caller.getComponentName(), DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD,
+ caller.getUid()) != null;
+ }
+ }
+
@Override
public void setPasswordQuality(ComponentName who, int quality, boolean parent) {
if (!mHasFeature) {
@@ -3383,7 +3379,8 @@
final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(
- isProfileOwner(caller) || isDeviceOwner(caller) || isSystemUid(caller));
+ isProfileOwner(caller) || isDeviceOwner(caller) || isSystemUid(caller)
+ || isPasswordLimitingAdminTargetingP(caller));
final boolean qualityMayApplyToParent =
canSetPasswordQualityOnParent(who.getPackageName(), caller.getUserId());
@@ -6161,6 +6158,7 @@
(admin != null) || hasCallingOrSelfPermission(permission.MASTER_CLEAR),
"No active admin for user %d and caller %d does not hold MASTER_CLEAR permission",
caller.getUserId(), caller.getUid());
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_WIPE_DATA);
if (TextUtils.isEmpty(wipeReasonForUser)) {
if (calledByProfileOwnerOnOrgOwnedDevice && !calledOnParentInstance) {
@@ -9798,6 +9796,7 @@
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_LOGOUT_USER);
final int callingUserId = caller.getUserId();
synchronized (getLockObject()) {
@@ -9983,6 +9982,7 @@
throw new SecurityException("Profile owner cannot set user restriction " + key);
}
}
+ checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_USER_RESTRICTION);
// Save the restriction to ActiveAdmin.
final Bundle restrictions = activeAdmin.ensureUserRestrictions();
@@ -11766,13 +11766,8 @@
}
@Override
- public ComponentName getProfileOwnerAsUser(@UserIdInt int userId) {
- return DevicePolicyManagerService.this.getProfileOwnerAsUser(userId);
- }
-
- @Override
- public int getDeviceOwnerUserId() {
- return DevicePolicyManagerService.this.getDeviceOwnerUserId();
+ public ComponentName getProfileOwnerAsUser(int userHandle) {
+ return DevicePolicyManagerService.this.getProfileOwnerAsUser(userHandle);
}
@Override
@@ -11795,6 +11790,28 @@
return profileOwnerInCallingUser != null
&& packageName.equals(profileOwnerInCallingUser.getPackageName());
}
+
+ @Override
+ public boolean supportsResetOp(int op) {
+ return op == AppOpsManager.OP_INTERACT_ACROSS_PROFILES
+ && LocalServices.getService(CrossProfileAppsInternal.class) != null;
+ }
+
+ @Override
+ public void resetOp(int op, String packageName, @UserIdInt int userId) {
+ if (op != AppOpsManager.OP_INTERACT_ACROSS_PROFILES) {
+ throw new IllegalArgumentException("Unsupported op for DPM reset: " + op);
+ }
+ LocalServices.getService(CrossProfileAppsInternal.class)
+ .setInteractAcrossProfilesAppOp(
+ packageName, findInteractAcrossProfilesResetMode(packageName), userId);
+ }
+
+ private @Mode int findInteractAcrossProfilesResetMode(String packageName) {
+ return getDefaultCrossProfilePackages().contains(packageName)
+ ? AppOpsManager.MODE_ALLOWED
+ : AppOpsManager.opToDefaultMode(AppOpsManager.OP_INTERACT_ACROSS_PROFILES);
+ }
}
private Intent createShowAdminSupportIntent(ComponentName admin, int userId) {
@@ -14602,7 +14619,7 @@
return PRIVATE_DNS_SET_NO_ERROR;
case PRIVATE_DNS_MODE_PROVIDER_HOSTNAME:
if (TextUtils.isEmpty(privateDnsHost)
- || !NetworkUtils.isWeaklyValidatedHostname(privateDnsHost)) {
+ || !NetworkUtilsInternal.isWeaklyValidatedHostname(privateDnsHost)) {
throw new IllegalArgumentException(
String.format("Provided hostname %s is not valid", privateDnsHost));
}
diff --git a/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerPerUserService.java b/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerPerUserService.java
index e258ef0..3531512 100644
--- a/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerPerUserService.java
+++ b/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerPerUserService.java
@@ -113,7 +113,8 @@
mRemoteService = new RemoteMusicRecognitionService(getContext(),
serviceComponent, mUserId, this,
- mRemoteServiceCallback, mMaster.isBindInstantServiceAllowed(), mMaster.verbose);
+ mRemoteServiceCallback, mMaster.isBindInstantServiceAllowed(),
+ mMaster.verbose);
}
return mRemoteService;
@@ -167,7 +168,8 @@
recognitionRequest.getIgnoreBeginningFrames() * BYTES_PER_SAMPLE;
audioRecord.startRecording();
while (bytesRead >= 0 && totalBytesRead
- < audioRecord.getBufferSizeInFrames() * BYTES_PER_SAMPLE) {
+ < audioRecord.getBufferSizeInFrames() * BYTES_PER_SAMPLE
+ && mRemoteService != null) {
bytesRead = audioRecord.read(byteBuffer, 0, byteBuffer.length);
if (bytesRead > 0) {
totalBytesRead += bytesRead;
@@ -215,6 +217,7 @@
} catch (RemoteException ignored) {
// Ignored.
}
+ destroyService();
}
@Override
@@ -224,6 +227,7 @@
} catch (RemoteException ignored) {
// Ignored.
}
+ destroyService();
}
}
@@ -235,6 +239,17 @@
// Ignored.
}
Slog.w(TAG, "remote service died: " + service);
+ destroyService();
+ }
+
+ @GuardedBy("mLock")
+ private void destroyService() {
+ synchronized (mLock) {
+ if (mRemoteService != null) {
+ mRemoteService.destroy();
+ mRemoteService = null;
+ }
+ }
}
/** Establishes an audio stream from the DSP audio source. */
diff --git a/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerService.java b/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerService.java
index b4cb337..9123daf 100644
--- a/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerService.java
+++ b/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerService.java
@@ -16,6 +16,7 @@
package com.android.server.musicrecognition;
+import static android.Manifest.permission.MANAGE_MUSIC_RECOGNITION;
import static android.content.PermissionChecker.PERMISSION_GRANTED;
import static android.media.musicrecognition.MusicRecognitionManager.RECOGNITION_FAILED_SERVICE_UNAVAILABLE;
@@ -28,11 +29,14 @@
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
import android.os.UserHandle;
import com.android.server.infra.AbstractMasterSystemService;
import com.android.server.infra.FrameworkResourcesServiceNameResolver;
+import java.io.FileDescriptor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -45,6 +49,7 @@
MusicRecognitionManagerPerUserService> {
private static final String TAG = MusicRecognitionManagerService.class.getSimpleName();
+ private static final int MAX_TEMP_SERVICE_SUBSTITUTION_DURATION_MS = 60_000;
private MusicRecognitionManagerStub mMusicRecognitionManagerStub;
final ExecutorService mExecutorService = Executors.newCachedThreadPool();
@@ -90,6 +95,16 @@
throw new SecurityException(msg);
}
+ @Override
+ protected void enforceCallingPermissionForManagement() {
+ getContext().enforceCallingPermission(MANAGE_MUSIC_RECOGNITION, TAG);
+ }
+
+ @Override
+ protected int getMaximumTemporaryServiceDurationMs() {
+ return MAX_TEMP_SERVICE_SUBSTITUTION_DURATION_MS;
+ }
+
final class MusicRecognitionManagerStub extends IMusicRecognitionManager.Stub {
@Override
public void beginRecognition(
@@ -112,5 +127,17 @@
}
}
}
+
+ @Override
+ public void onShellCommand(@Nullable FileDescriptor in,
+ @Nullable FileDescriptor out,
+ @Nullable FileDescriptor err,
+ @NonNull String[] args,
+ @Nullable ShellCallback callback,
+ @NonNull ResultReceiver resultReceiver) throws RemoteException {
+ new MusicRecognitionManagerServiceShellCommand(
+ MusicRecognitionManagerService.this).exec(this, in, out, err, args, callback,
+ resultReceiver);
+ }
}
}
diff --git a/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerServiceShellCommand.java b/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerServiceShellCommand.java
new file mode 100644
index 0000000..b020a24
--- /dev/null
+++ b/services/musicrecognition/java/com/android/server/musicrecognition/MusicRecognitionManagerServiceShellCommand.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.musicrecognition;
+
+import android.os.ShellCommand;
+
+import java.io.PrintWriter;
+
+/** Handles adb shell commands send to MusicRecognitionManagerService. */
+class MusicRecognitionManagerServiceShellCommand extends ShellCommand {
+
+ private final MusicRecognitionManagerService mService;
+
+ MusicRecognitionManagerServiceShellCommand(MusicRecognitionManagerService service) {
+ mService = service;
+ }
+
+ @Override
+ public int onCommand(String cmd) {
+ if (cmd == null) {
+ return handleDefaultCommands(cmd);
+ }
+ final PrintWriter pw = getOutPrintWriter();
+ if ("set".equals(cmd)) {
+ return requestSet(pw);
+ }
+ return handleDefaultCommands(cmd);
+ }
+
+ private int requestSet(PrintWriter pw) {
+ final String what = getNextArgRequired();
+ if ("temporary-service".equals(what)) {
+ return setTemporaryService(pw);
+ }
+ pw.println("Invalid set: " + what);
+ return -1;
+ }
+
+ private int setTemporaryService(PrintWriter pw) {
+ final int userId = Integer.parseInt(getNextArgRequired());
+ final String serviceName = getNextArg();
+ if (serviceName == null) {
+ mService.resetTemporaryService(userId);
+ return 0;
+ }
+ final int duration = Integer.parseInt(getNextArgRequired());
+ mService.setTemporaryService(userId, serviceName, duration);
+ pw.println("MusicRecognitionService temporarily set to " + serviceName + " for "
+ + duration + "ms");
+ return 0;
+ }
+
+ @Override
+ public void onHelp() {
+ try (PrintWriter pw = getOutPrintWriter();) {
+ pw.println("MusicRecognition Service (music_recognition) commands:");
+ pw.println(" help");
+ pw.println(" Prints this help text.");
+ pw.println("");
+ pw.println(" set temporary-service USER_ID [COMPONENT_NAME DURATION]");
+ pw.println(" Temporarily (for DURATION ms) changes the service implementation.");
+ pw.println(" To reset, call with just the USER_ID argument.");
+ pw.println("");
+ }
+ }
+}
diff --git a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
index 5fa809f..adf892a 100644
--- a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
+++ b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
@@ -37,7 +37,6 @@
import android.app.ActivityManagerInternal;
import android.app.AppOpsManager;
import android.app.AppOpsManager.Mode;
-import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyManagerInternal;
import android.content.ComponentName;
import android.content.ContextWrapper;
@@ -94,12 +93,15 @@
private static final int CALLING_PID = 1000;
private static final String CROSS_PROFILE_APP_PACKAGE_NAME =
"com.android.server.pm.crossprofileappsserviceimplrobotest.crossprofileapp";
- private static final int PERSONAL_PROFILE_USER_ID = 0;
+ @UserIdInt private static final int PERSONAL_PROFILE_USER_ID = 0;
private static final int PERSONAL_PROFILE_UID = 2222;
- private static final int WORK_PROFILE_USER_ID = 10;
+ @UserIdInt private static final int WORK_PROFILE_USER_ID = 10;
private static final int WORK_PROFILE_UID = 3333;
private static final int OTHER_PROFILE_WITHOUT_CROSS_PROFILE_APP_USER_ID = 20;
- private static final int OUTSIDE_PROFILE_GROUP_USER_ID = 30;
+ @UserIdInt private static final int OTHER_PROFILE_GROUP_USER_ID = 30;
+ private static final int OTHER_PROFILE_GROUP_UID = 4444;
+ @UserIdInt private static final int OTHER_PROFILE_GROUP_2_USER_ID = 31;
+ private static final int OTHER_PROFILE_GROUP_2_UID = 5555;
private final ContextWrapper mContext = ApplicationProvider.getApplicationContext();
private final UserManager mUserManager = mContext.getSystemService(UserManager.class);
@@ -138,6 +140,10 @@
mockCrossProfileAppInstalledOnProfile(
packageInfo, PERSONAL_PROFILE_USER_ID, PERSONAL_PROFILE_UID);
mockCrossProfileAppInstalledOnProfile(packageInfo, WORK_PROFILE_USER_ID, WORK_PROFILE_UID);
+ mockCrossProfileAppInstalledOnProfile(
+ packageInfo, OTHER_PROFILE_GROUP_USER_ID, OTHER_PROFILE_GROUP_UID);
+ mockCrossProfileAppInstalledOnProfile(
+ packageInfo, OTHER_PROFILE_GROUP_2_USER_ID, OTHER_PROFILE_GROUP_2_UID);
}
private void mockCrossProfileAppInstalledOnProfile(
@@ -200,16 +206,22 @@
@Before
public void setUpCrossProfileAppUidsAndPackageNames() {
+ setUpCrossProfileAppUidAndPackageName(
+ PERSONAL_PROFILE_UID, PERSONAL_PROFILE_USER_ID);
+ setUpCrossProfileAppUidAndPackageName(
+ WORK_PROFILE_UID, WORK_PROFILE_USER_ID);
+ setUpCrossProfileAppUidAndPackageName(
+ OTHER_PROFILE_GROUP_UID, OTHER_PROFILE_GROUP_USER_ID);
+ setUpCrossProfileAppUidAndPackageName(
+ OTHER_PROFILE_GROUP_2_UID, OTHER_PROFILE_GROUP_2_USER_ID);
+ }
+
+ private void setUpCrossProfileAppUidAndPackageName(int uid, @UserIdInt int userId) {
ShadowApplicationPackageManager.setPackageUidAsUser(
- CROSS_PROFILE_APP_PACKAGE_NAME, PERSONAL_PROFILE_UID, PERSONAL_PROFILE_USER_ID);
- ShadowApplicationPackageManager.setPackageUidAsUser(
- CROSS_PROFILE_APP_PACKAGE_NAME, WORK_PROFILE_UID, WORK_PROFILE_USER_ID);
- when(mPackageManagerInternal.getPackageUid(
- CROSS_PROFILE_APP_PACKAGE_NAME, /* flags= */ 0, PERSONAL_PROFILE_USER_ID))
- .thenReturn(PERSONAL_PROFILE_UID);
- when(mPackageManagerInternal.getPackageUid(
- CROSS_PROFILE_APP_PACKAGE_NAME, /* flags= */ 0, WORK_PROFILE_USER_ID))
- .thenReturn(WORK_PROFILE_UID);
+ CROSS_PROFILE_APP_PACKAGE_NAME, uid, userId);
+ when(mPackageManagerInternal
+ .getPackageUid(CROSS_PROFILE_APP_PACKAGE_NAME, /* flags= */ 0, userId))
+ .thenReturn(uid);
}
@Before
@@ -229,7 +241,9 @@
PERSONAL_PROFILE_USER_ID,
WORK_PROFILE_USER_ID,
OTHER_PROFILE_WITHOUT_CROSS_PROFILE_APP_USER_ID);
- shadowUserManager.addProfileIds(OUTSIDE_PROFILE_GROUP_USER_ID);
+ shadowUserManager.addProfileIds(
+ OTHER_PROFILE_GROUP_USER_ID,
+ OTHER_PROFILE_GROUP_2_USER_ID);
}
@Before
@@ -239,6 +253,8 @@
final int defaultMode = AppOpsManager.opToDefaultMode(OP_INTERACT_ACROSS_PROFILES);
explicitlySetInteractAcrossProfilesAppOp(PERSONAL_PROFILE_UID, defaultMode);
explicitlySetInteractAcrossProfilesAppOp(WORK_PROFILE_UID, defaultMode);
+ explicitlySetInteractAcrossProfilesAppOp(OTHER_PROFILE_GROUP_UID, defaultMode);
+ explicitlySetInteractAcrossProfilesAppOp(OTHER_PROFILE_GROUP_2_UID, defaultMode);
}
@Test
@@ -422,6 +438,27 @@
}
@Test
+ public void setInteractAcrossProfilesAppOp_userToSetInDifferentProfileGroupToCaller_setsAppOp() {
+ mCrossProfileAppsServiceImpl.getLocalService().setInteractAcrossProfilesAppOp(
+ CROSS_PROFILE_APP_PACKAGE_NAME, MODE_ALLOWED, OTHER_PROFILE_GROUP_USER_ID);
+ assertThat(getCrossProfileAppOp(OTHER_PROFILE_GROUP_UID)).isEqualTo(MODE_ALLOWED);
+ }
+
+ @Test
+ public void setInteractAcrossProfilesAppOp_userToSetInDifferentProfileGroupToCaller_setsAppOpOnOtherProfile() {
+ mCrossProfileAppsServiceImpl.getLocalService().setInteractAcrossProfilesAppOp(
+ CROSS_PROFILE_APP_PACKAGE_NAME, MODE_ALLOWED, OTHER_PROFILE_GROUP_USER_ID);
+ assertThat(getCrossProfileAppOp(OTHER_PROFILE_GROUP_2_UID)).isEqualTo(MODE_ALLOWED);
+ }
+
+ @Test
+ public void setInteractAcrossProfilesAppOp_userToSetInDifferentProfileGroupToCaller_doesNotSetCallerAppOp() {
+ mCrossProfileAppsServiceImpl.getLocalService().setInteractAcrossProfilesAppOp(
+ CROSS_PROFILE_APP_PACKAGE_NAME, MODE_ALLOWED, OTHER_PROFILE_GROUP_USER_ID);
+ assertThat(getCrossProfileAppOp()).isEqualTo(MODE_DEFAULT);
+ }
+
+ @Test
public void canConfigureInteractAcrossProfiles_packageNotInstalledInProfile_returnsFalse() {
mockUninstallCrossProfileAppFromWorkProfile();
assertThat(mCrossProfileAppsServiceImpl
@@ -530,7 +567,7 @@
@Test
public void canUserAttemptToConfigureInteractAcrossProfiles_profileOwnerOutsideProfileGroup_returnsTrue() {
- when(mDevicePolicyManagerInternal.getProfileOwnerAsUser(OUTSIDE_PROFILE_GROUP_USER_ID))
+ when(mDevicePolicyManagerInternal.getProfileOwnerAsUser(OTHER_PROFILE_GROUP_USER_ID))
.thenReturn(buildCrossProfileComponentName());
assertThat(mCrossProfileAppsServiceImpl
.canUserAttemptToConfigureInteractAcrossProfiles(CROSS_PROFILE_APP_PACKAGE_NAME))
@@ -601,8 +638,14 @@
private void mockCrossProfileAndroidPackage(AndroidPackage androidPackage) {
when(mPackageManagerInternal.getPackage(CROSS_PROFILE_APP_PACKAGE_NAME))
.thenReturn(androidPackage);
- when(mPackageManagerInternal.getPackage(PERSONAL_PROFILE_UID)).thenReturn(androidPackage);
- when(mPackageManagerInternal.getPackage(WORK_PROFILE_UID)).thenReturn(androidPackage);
+ when(mPackageManagerInternal.getPackage(PERSONAL_PROFILE_UID))
+ .thenReturn(androidPackage);
+ when(mPackageManagerInternal.getPackage(WORK_PROFILE_UID))
+ .thenReturn(androidPackage);
+ when(mPackageManagerInternal.getPackage(OTHER_PROFILE_GROUP_UID))
+ .thenReturn(androidPackage);
+ when(mPackageManagerInternal.getPackage(OTHER_PROFILE_GROUP_2_UID))
+ .thenReturn(androidPackage);
}
private void mockCrossProfileAppNotWhitelisted() {
diff --git a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsUpgradeTest.java b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsUpgradeTest.java
index 9f895c6..99693d2 100644
--- a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsUpgradeTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsUpgradeTest.java
@@ -36,7 +36,6 @@
import android.util.Log;
import android.util.SparseArray;
import android.util.TypedXmlPullParser;
-import android.util.TypedXmlSerializer;
import android.util.Xml;
import androidx.test.InstrumentationRegistry;
@@ -53,7 +52,6 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
/**
* Tests app ops version upgrades
@@ -183,8 +181,7 @@
boolean parse() {
try (FileInputStream stream = new FileInputStream(mFile)) {
- TypedXmlPullParser parser = Xml.newFastPullParser();
- parser.setInput(stream, StandardCharsets.UTF_8.name());
+ TypedXmlPullParser parser = Xml.resolvePullParser(stream);
int type;
while ((type = parser.next()) != XmlPullParser.START_TAG
&& type != XmlPullParser.END_DOCUMENT) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
index 5f6f61c..344a19a 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
@@ -1960,6 +1960,79 @@
.set(anyInt(), eq(expectedAlarmTime), eq(TAG_QUOTA_CHECK), any(), any());
}
+ /**
+ * Test that QC handles invalid cases where an app is in the NEVER bucket but has still run
+ * jobs.
+ */
+ @Test
+ public void testMaybeScheduleStartAlarmLocked_Never_EffectiveNotNever() {
+ // saveTimingSession calls maybeScheduleCleanupAlarmLocked which interferes with these tests
+ // because it schedules an alarm too. Prevent it from doing so.
+ spyOn(mQuotaController);
+ doNothing().when(mQuotaController).maybeScheduleCleanupAlarmLocked();
+
+ // The app is really in the NEVER bucket but is elevated somehow (eg via uidActive).
+ setStandbyBucket(NEVER_INDEX);
+ final int effectiveStandbyBucket = FREQUENT_INDEX;
+
+ // No sessions saved yet.
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.maybeScheduleStartAlarmLocked(
+ SOURCE_USER_ID, SOURCE_PACKAGE, effectiveStandbyBucket);
+ }
+ verify(mAlarmManager, never()).set(anyInt(), anyLong(), eq(TAG_QUOTA_CHECK), any(), any());
+
+ // Test with timing sessions out of window.
+ final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
+ mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
+ createTimingSession(now - 10 * HOUR_IN_MILLIS, 5 * MINUTE_IN_MILLIS, 1), false);
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.maybeScheduleStartAlarmLocked(
+ SOURCE_USER_ID, SOURCE_PACKAGE, effectiveStandbyBucket);
+ }
+ verify(mAlarmManager, never()).set(anyInt(), anyLong(), eq(TAG_QUOTA_CHECK), any(), any());
+
+ // Test with timing sessions in window but still in quota.
+ final long start = now - (6 * HOUR_IN_MILLIS);
+ final long expectedAlarmTime = start + 8 * HOUR_IN_MILLIS + mQcConstants.IN_QUOTA_BUFFER_MS;
+ mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
+ createTimingSession(start, 5 * MINUTE_IN_MILLIS, 1), false);
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.maybeScheduleStartAlarmLocked(
+ SOURCE_USER_ID, SOURCE_PACKAGE, effectiveStandbyBucket);
+ }
+ verify(mAlarmManager, never()).set(anyInt(), anyLong(), eq(TAG_QUOTA_CHECK), any(), any());
+
+ // Add some more sessions, but still in quota.
+ mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
+ createTimingSession(now - 3 * HOUR_IN_MILLIS, MINUTE_IN_MILLIS, 1), false);
+ mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
+ createTimingSession(now - HOUR_IN_MILLIS, 3 * MINUTE_IN_MILLIS, 1), false);
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.maybeScheduleStartAlarmLocked(
+ SOURCE_USER_ID, SOURCE_PACKAGE, effectiveStandbyBucket);
+ }
+ verify(mAlarmManager, never()).set(anyInt(), anyLong(), eq(TAG_QUOTA_CHECK), any(), any());
+
+ // Test when out of quota.
+ mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
+ createTimingSession(now - HOUR_IN_MILLIS, MINUTE_IN_MILLIS, 1), false);
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.maybeScheduleStartAlarmLocked(
+ SOURCE_USER_ID, SOURCE_PACKAGE, effectiveStandbyBucket);
+ }
+ verify(mAlarmManager, times(1))
+ .set(anyInt(), eq(expectedAlarmTime), eq(TAG_QUOTA_CHECK), any(), any());
+
+ // Alarm already scheduled, so make sure it's not scheduled again.
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.maybeScheduleStartAlarmLocked(
+ SOURCE_USER_ID, SOURCE_PACKAGE, effectiveStandbyBucket);
+ }
+ verify(mAlarmManager, times(1))
+ .set(anyInt(), eq(expectedAlarmTime), eq(TAG_QUOTA_CHECK), any(), any());
+ }
+
@Test
public void testMaybeScheduleStartAlarmLocked_Rare() {
// saveTimingSession calls maybeScheduleCleanupAlarmLocked which interferes with these tests
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/OWNERS b/services/tests/mockingservicestests/src/com/android/server/location/OWNERS
new file mode 100644
index 0000000..696a0c2
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/location/OWNERS
@@ -0,0 +1 @@
+file:/location/java/android/location/OWNERS
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java
index 98fd1c9..2b21cc5 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java
@@ -43,9 +43,9 @@
import android.location.GnssAntennaInfo.SphericalCorrections;
import android.location.GnssClock;
import android.location.GnssMeasurementCorrections;
+import android.location.GnssMeasurementRequest;
import android.location.GnssMeasurementsEvent;
import android.location.GnssNavigationMessage;
-import android.location.GnssRequest;
import android.location.GnssSingleSatCorrection;
import android.location.IGnssAntennaInfoListener;
import android.location.IGnssMeasurementsListener;
@@ -403,7 +403,7 @@
assertThrows(SecurityException.class,
() -> mGnssManagerService.addGnssMeasurementsListener(
- new GnssRequest.Builder().build(), mockGnssMeasurementsListener,
+ new GnssMeasurementRequest.Builder().build(), mockGnssMeasurementsListener,
TEST_PACKAGE, null));
mTestGnssMeasurementsProvider.onMeasurementsAvailable(gnssMeasurementsEvent);
@@ -422,7 +422,7 @@
enableLocationPermissions();
mGnssManagerService.addGnssMeasurementsListener(
- new GnssRequest.Builder().build(),
+ new GnssMeasurementRequest.Builder().build(),
mockGnssMeasurementsListener,
TEST_PACKAGE, null);
@@ -470,7 +470,8 @@
enableLocationPermissions();
- mGnssManagerService.addGnssMeasurementsListener(new GnssRequest.Builder().build(),
+ mGnssManagerService.addGnssMeasurementsListener(
+ new GnssMeasurementRequest.Builder().build(),
mockGnssMeasurementsListener,
TEST_PACKAGE, null);
@@ -494,7 +495,8 @@
enableLocationPermissions();
- mGnssManagerService.addGnssMeasurementsListener(new GnssRequest.Builder().build(),
+ mGnssManagerService.addGnssMeasurementsListener(
+ new GnssMeasurementRequest.Builder().build(),
mockGnssMeasurementsListener,
TEST_PACKAGE, null);
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
index edae08a3..015eead 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
@@ -68,12 +68,12 @@
import com.android.server.testutils.mock
import com.android.server.testutils.nullable
import com.android.server.testutils.whenever
+import com.android.server.utils.WatchedArrayMap
import org.junit.Assert
import org.junit.rules.TestRule
import org.junit.runner.Description
import org.junit.runners.model.Statement
import org.mockito.AdditionalMatchers.or
-import org.mockito.invocation.InvocationOnMock
import org.mockito.quality.Strictness
import java.io.File
import java.io.IOException
@@ -114,7 +114,7 @@
private val mPreExistingSettings = ArrayMap<String, PackageSetting>()
/** The active map simulating the in memory storage of Settings */
- private val mSettingsMap = ArrayMap<String, PackageSetting>()
+ private val mSettingsMap = WatchedArrayMap<String, PackageSetting>()
init {
val apply = ExtendedMockito.mockitoSession()
@@ -268,7 +268,7 @@
wheneverStatic { Environment.getPackageCacheDirectory() }.thenReturn(packageCacheDirectory)
wheneverStatic { SystemProperties.digestOf("ro.build.fingerprint") }.thenReturn("cacheName")
wheneverStatic { Environment.getRootDirectory() }.thenReturn(rootDirectory)
- wheneverStatic { SystemServerInitThreadPool.submit(any(Runnable::class.java), anyString())}
+ wheneverStatic { SystemServerInitThreadPool.submit(any(Runnable::class.java), anyString()) }
.thenAnswer { FutureTask<Any?>(it.getArgument(0), null) }
wheneverStatic { Environment.getDataDirectory() }.thenReturn(dataAppDirectory.parentFile)
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/OWNERS b/services/tests/mockingservicestests/src/com/android/server/pm/OWNERS
new file mode 100644
index 0000000..d825dfd
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/pm/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java b/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java
index 68adacd..32ca7b5 100644
--- a/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java
@@ -172,6 +172,7 @@
@After
public void tearDown() throws Exception {
+ InputManager.clearInstance();
LocalServices.removeServiceForTest(PackageManagerInternal.class);
LocalServices.removeServiceForTest(PowerManagerInternal.class);
}
@@ -838,7 +839,7 @@
private InputDevice createInputDeviceWithVibrator(int id) {
return new InputDevice(id, 0, 0, "name", 0, 0, "description", false, 0, 0,
- null, /* hasVibrator= */ true, false, false);
+ null, /* hasVibrator= */ true, false, false, false /* hasSensor */);
}
private static <T> void addLocalServiceMock(Class<T> clazz, T mock) {
diff --git a/services/tests/servicestests/src/com/android/server/am/MeasuredEnergySnapshotTest.java b/services/tests/servicestests/src/com/android/server/am/MeasuredEnergySnapshotTest.java
new file mode 100644
index 0000000..67d379a
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/MeasuredEnergySnapshotTest.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.util.SparseLongArray;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.power.MeasuredEnergyArray;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test class for {@link MeasuredEnergySnapshot}.
+ *
+ * To run the tests, use
+ * atest FrameworksServicesTests:com.android.server.am.MeasuredEnergySnapshotTest
+ */
+@SmallTest
+public final class MeasuredEnergySnapshotTest {
+ private static final int NUMBER_SUBSYSTEMS = 3;
+ private static final int SUBSYSTEM_DISPLAY = 0;
+ private static final int SUBSYSTEM_NEVER_USED = 1;
+ private static final int SUBSYSTEM_CATAPULT = 2;
+
+ private MeasuredEnergySnapshot mSnapshot;
+
+ // Basic MeasuredEnergyArray that supports all the subsystems. Out of order on purpose.
+ private final int[] mAllSubsystems =
+ {SUBSYSTEM_DISPLAY, SUBSYSTEM_CATAPULT, SUBSYSTEM_NEVER_USED};
+ // E.g. mAllSubsystems[mSubsystemIndices[SUBSYSTEM_CATAPULT]]=SUBSYSTEM_CATAPULT
+ private final int[] mSubsystemIndices = {0, 2, 1};
+ private final long[] mCurrentSubsystemEnergyUJ = {111, 0, 0};
+ private final MeasuredEnergyArray mOmniEnergyArray = new MeasuredEnergyArray() {
+ @Override
+ public int getSubsystem(int index) {
+ return mAllSubsystems[index];
+ }
+
+ @Override
+ public long getEnergy(int index) {
+ return mCurrentSubsystemEnergyUJ[index];
+ }
+
+ @Override
+ public int size() {
+ return mAllSubsystems.length;
+ }
+ };
+ private final MeasuredEnergyArray mJustDisplayEnergyArray = new MeasuredEnergyArray() {
+ @Override
+ public int getSubsystem(int index) {
+ return mAllSubsystems[0];
+ }
+
+ @Override
+ public long getEnergy(int index) {
+ return mCurrentSubsystemEnergyUJ[0];
+ }
+
+ @Override
+ public int size() {
+ return 1;
+ }
+ };
+
+ @Before
+ public void setUp() {
+ mSnapshot = new MeasuredEnergySnapshot(NUMBER_SUBSYSTEMS, mOmniEnergyArray);
+ }
+
+ @Test
+ public void testUpdateAndGetDelta() {
+ SparseLongArray result;
+
+ // Increment DISPLAY by 15
+ incrementEnergyOfSubsystem(SUBSYSTEM_DISPLAY, 15);
+ result = mSnapshot.updateAndGetDelta(mOmniEnergyArray);
+ assertEquals(1, result.size());
+ assertEquals(15, result.get(SUBSYSTEM_DISPLAY));
+
+ // Increment DISPLAY by 7
+ // Increment CATAPULT by 5. But do NOT include (pull) it in the passed in energy array.
+ incrementEnergyOfSubsystem(SUBSYSTEM_DISPLAY, 7);
+ incrementEnergyOfSubsystem(SUBSYSTEM_CATAPULT, 5);
+ result = mSnapshot.updateAndGetDelta(mJustDisplayEnergyArray); // Just pull display.
+ assertEquals(1, result.size());
+ assertEquals(7, result.get(SUBSYSTEM_DISPLAY));
+
+ // Increment CATAPULT by 64 (in addition to the previous increase of 5)
+ incrementEnergyOfSubsystem(SUBSYSTEM_CATAPULT, 64);
+ result = mSnapshot.updateAndGetDelta(mOmniEnergyArray);
+ assertEquals(1, result.size());
+ assertEquals(5 + 64, result.get(SUBSYSTEM_CATAPULT));
+
+ // Do nothing
+ result = mSnapshot.updateAndGetDelta(mOmniEnergyArray);
+ assertEquals("0 results should not appear at all", 0, result.size());
+
+ // Increment DISPLAY by 42
+ incrementEnergyOfSubsystem(SUBSYSTEM_DISPLAY, 42);
+ result = mSnapshot.updateAndGetDelta(mOmniEnergyArray);
+ assertEquals(1, result.size());
+ assertEquals(42, result.get(SUBSYSTEM_DISPLAY));
+
+ // Increment DISPLAY by 106 and CATAPULT by 13
+ incrementEnergyOfSubsystem(SUBSYSTEM_DISPLAY, 106);
+ incrementEnergyOfSubsystem(SUBSYSTEM_CATAPULT, 13);
+ result = mSnapshot.updateAndGetDelta(mOmniEnergyArray);
+ assertEquals(2, result.size());
+ assertEquals(106, result.get(SUBSYSTEM_DISPLAY));
+ assertEquals(13, result.get(SUBSYSTEM_CATAPULT));
+ }
+
+ private void incrementEnergyOfSubsystem(int subsystem, long energy) {
+ mCurrentSubsystemEnergyUJ[mSubsystemIndices[subsystem]] += energy;
+ }
+
+ @Test
+ public void testUpdateAndGetDelta_null() {
+ assertNull(mSnapshot.updateAndGetDelta(null));
+ }
+
+ @Test
+ public void testHasSubsystem() {
+ // Setup MeasuredEnergySnapshot which reported some of the subsystems.
+ final int[] subsystems = {SUBSYSTEM_DISPLAY, SUBSYSTEM_CATAPULT};
+ MeasuredEnergyArray measuredEnergyArray = new MeasuredEnergyArray() {
+ @Override
+ public int getSubsystem(int index) {
+ return subsystems[index];
+ }
+
+ @Override
+ public long getEnergy(int index) {
+ return 0; // Irrelevant for this test.
+ }
+
+ @Override
+ public int size() {
+ return subsystems.length;
+ }
+ };
+ final MeasuredEnergySnapshot snapshot =
+ new MeasuredEnergySnapshot(NUMBER_SUBSYSTEMS, measuredEnergyArray);
+
+ assertTrue(snapshot.hasSubsystem(SUBSYSTEM_DISPLAY));
+ assertTrue(snapshot.hasSubsystem(SUBSYSTEM_CATAPULT));
+ assertFalse(snapshot.hasSubsystem(SUBSYSTEM_NEVER_USED));
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/audio/OWNERS b/services/tests/servicestests/src/com/android/server/audio/OWNERS
new file mode 100644
index 0000000..894a1f5
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/audio/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/audio/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
index e588370..8c63bfc 100644
--- a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
@@ -190,6 +190,22 @@
}
@Test
+ public void testIsChangeEnabledForInvalidApp() throws Exception {
+ final long disabledChangeId = 1234L;
+ final long enabledChangeId = 1235L;
+ final long targetSdkChangeId = 1236L;
+ CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
+ .addEnabledChangeWithId(enabledChangeId)
+ .addDisabledChangeWithId(disabledChangeId)
+ .addEnableSinceSdkChangeWithId(42, targetSdkChangeId)
+ .build();
+
+ assertThat(compatConfig.isChangeEnabled(enabledChangeId, null)).isTrue();
+ assertThat(compatConfig.isChangeEnabled(disabledChangeId, null)).isFalse();
+ assertThat(compatConfig.isChangeEnabled(targetSdkChangeId, null)).isTrue();
+ }
+
+ @Test
public void testPreventAddOverride() throws Exception {
final long changeId = 1234L;
CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/TransferOwnershipMetadataManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/TransferOwnershipMetadataManagerTest.java
index 07ea855..2d76537 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/TransferOwnershipMetadataManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/TransferOwnershipMetadataManagerTest.java
@@ -37,6 +37,7 @@
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -83,6 +84,7 @@
}
@Test
+ @Ignore
public void testFileContentValid() {
TransferOwnershipMetadataManager paramsManager = getOwnerTransferParams();
assertThat(paramsManager.saveMetadataFile(TEST_PARAMS)).isTrue();
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/DevicePowerStatusActionTest.java b/services/tests/servicestests/src/com/android/server/hdmi/DevicePowerStatusActionTest.java
new file mode 100644
index 0000000..da9dcb7
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/hdmi/DevicePowerStatusActionTest.java
@@ -0,0 +1,217 @@
+/*
+ * 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.hdmi;
+
+import static com.android.server.hdmi.Constants.ADDR_TV;
+import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.hardware.hdmi.HdmiControlManager;
+import android.hardware.hdmi.IHdmiControlCallback;
+import android.hardware.tv.cec.V1_0.SendMessageResult;
+import android.media.AudioManager;
+import android.os.Handler;
+import android.os.IPowerManager;
+import android.os.IThermalService;
+import android.os.Looper;
+import android.os.PowerManager;
+import android.os.test.TestLooper;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+
+/** Tests for {@link DevicePowerStatusAction} */
+@SmallTest
+@RunWith(JUnit4.class)
+public class DevicePowerStatusActionTest {
+
+ private static final int TIMEOUT_MS = HdmiConfig.TIMEOUT_MS + 1;
+
+ private Context mContextSpy;
+ private HdmiControlService mHdmiControlService;
+ private HdmiCecLocalDevice mPlaybackDevice;
+ private FakeNativeWrapper mNativeWrapper;
+
+ private TestLooper mTestLooper = new TestLooper();
+ private ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>();
+ private int mPhysicalAddress;
+
+ private DevicePowerStatusAction mDevicePowerStatusAction;
+
+ @Mock private IHdmiControlCallback mCallbackMock;
+ @Mock private IPowerManager mIPowerManagerMock;
+ @Mock private IThermalService mIThermalServiceMock;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
+
+ PowerManager powerManager = new PowerManager(mContextSpy, mIPowerManagerMock,
+ mIThermalServiceMock, new Handler(mTestLooper.getLooper()));
+ when(mContextSpy.getSystemService(Context.POWER_SERVICE)).thenReturn(powerManager);
+ when(mContextSpy.getSystemService(PowerManager.class)).thenReturn(powerManager);
+ when(mIPowerManagerMock.isInteractive()).thenReturn(true);
+
+ HdmiCecConfig hdmiCecConfig = new FakeHdmiCecConfig(mContextSpy);
+
+ mHdmiControlService = new HdmiControlService(mContextSpy) {
+ @Override
+ AudioManager getAudioManager() {
+ return new AudioManager() {
+ @Override
+ public void setWiredDeviceConnectionState(
+ int type, int state, String address, String name) {
+ // Do nothing.
+ }
+ };
+ }
+
+ @Override
+ void wakeUp() {
+ }
+
+ @Override
+ boolean isPowerStandby() {
+ return false;
+ }
+
+ @Override
+ protected PowerManager getPowerManager() {
+ return powerManager;
+ }
+
+ @Override
+ protected void writeStringSystemProperty(String key, String value) {
+ // do nothing
+ }
+
+ @Override
+ protected HdmiCecConfig getHdmiCecConfig() {
+ return hdmiCecConfig;
+ }
+ };
+
+ Looper looper = mTestLooper.getLooper();
+ mHdmiControlService.setIoLooper(looper);
+ mNativeWrapper = new FakeNativeWrapper();
+ HdmiCecController hdmiCecController = HdmiCecController.createWithNativeWrapper(
+ this.mHdmiControlService, mNativeWrapper, mHdmiControlService.getAtomWriter());
+ mHdmiControlService.setCecController(hdmiCecController);
+ mHdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(mHdmiControlService));
+ mHdmiControlService.setMessageValidator(new HdmiCecMessageValidator(mHdmiControlService));
+ mHdmiControlService.initService();
+ mPhysicalAddress = 0x2000;
+ mNativeWrapper.setPhysicalAddress(mPhysicalAddress);
+ mPlaybackDevice = new HdmiCecLocalDevicePlayback(
+ mHdmiControlService);
+ mPlaybackDevice.init();
+ mLocalDevices.add(mPlaybackDevice);
+ mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
+ mDevicePowerStatusAction = DevicePowerStatusAction.create(mPlaybackDevice, ADDR_TV,
+ mCallbackMock);
+ mTestLooper.dispatchAll();
+ }
+
+ @Test
+ public void queryDisplayStatus_sendsRequestAndHandlesResponse() throws Exception {
+ mPlaybackDevice.addAndStartAction(mDevicePowerStatusAction);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected = HdmiCecMessageBuilder.buildGiveDevicePowerStatus(
+ mPlaybackDevice.mAddress, ADDR_TV);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected);
+
+ HdmiCecMessage response = HdmiCecMessageBuilder.buildReportPowerStatus(
+ ADDR_TV, mPlaybackDevice.mAddress, HdmiControlManager.POWER_STATUS_STANDBY);
+ mNativeWrapper.onCecMessage(response);
+ mTestLooper.dispatchAll();
+
+ verify(mCallbackMock).onComplete(HdmiControlManager.POWER_STATUS_STANDBY);
+ }
+
+ @Test
+ public void queryDisplayStatus_sendsRequest_nack() throws Exception {
+ mNativeWrapper.setMessageSendResult(Constants.MESSAGE_GIVE_DEVICE_POWER_STATUS,
+ SendMessageResult.NACK);
+
+ mPlaybackDevice.addAndStartAction(mDevicePowerStatusAction);
+ mTestLooper.dispatchAll();
+
+ verify(mCallbackMock).onComplete(HdmiControlManager.POWER_STATUS_UNKNOWN);
+ }
+
+ @Test
+ public void queryDisplayStatus_sendsRequest_timeout_retriesSuccessfully() throws Exception {
+ mPlaybackDevice.addAndStartAction(mDevicePowerStatusAction);
+
+ HdmiCecMessage expected = HdmiCecMessageBuilder.buildGiveDevicePowerStatus(
+ mPlaybackDevice.mAddress, ADDR_TV);
+ mTestLooper.dispatchAll();
+
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected);
+
+ HdmiCecMessage response = HdmiCecMessageBuilder.buildReportPowerStatus(
+ ADDR_TV, mPlaybackDevice.mAddress, HdmiControlManager.POWER_STATUS_STANDBY);
+ mNativeWrapper.onCecMessage(response);
+ mTestLooper.dispatchAll();
+
+ verify(mCallbackMock).onComplete(HdmiControlManager.POWER_STATUS_STANDBY);
+ }
+
+ @Test
+ public void queryDisplayStatus_sendsRequest_timeout_retriesFailure() throws Exception {
+ mPlaybackDevice.addAndStartAction(mDevicePowerStatusAction);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage expected = HdmiCecMessageBuilder.buildGiveDevicePowerStatus(
+ mPlaybackDevice.mAddress, ADDR_TV);
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+
+ assertThat(mNativeWrapper.getResultMessages()).contains(expected);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+
+ verify(mCallbackMock).onComplete(HdmiControlManager.POWER_STATUS_UNKNOWN);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/FakeHdmiCecConfig.java b/services/tests/servicestests/src/com/android/server/hdmi/FakeHdmiCecConfig.java
index 227e8c7..e5bcedb 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/FakeHdmiCecConfig.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/FakeHdmiCecConfig.java
@@ -77,6 +77,15 @@
+ " </allowed-values>"
+ " <default-value int-value=\"1\" />"
+ " </setting>"
+ + " <setting name=\"hdmi_cec_enabled\""
+ + " value-type=\"int\""
+ + " user-configurable=\"true\">"
+ + " <allowed-values>"
+ + " <value int-value=\"0\" />"
+ + " <value int-value=\"1\" />"
+ + " </allowed-values>"
+ + " <default-value int-value=\"1\" />"
+ + " </setting>"
+ "</cec-settings>";
FakeHdmiCecConfig(@NonNull Context context) {
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 42f88dc..2f2e97c 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecControllerTest.java
@@ -30,6 +30,8 @@
import static com.android.server.hdmi.Constants.ADDR_UNREGISTERED;
import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
import android.content.Context;
import android.hardware.hdmi.HdmiControlManager;
@@ -257,4 +259,19 @@
mTestLooper.dispatchAll();
assertEquals(ADDR_UNREGISTERED, mLogicalAddress);
}
+
+ @Test
+ public void testIsLanguage() {
+ assertTrue(HdmiCecController.isLanguage("en"));
+ assertTrue(HdmiCecController.isLanguage("eng"));
+ assertTrue(HdmiCecController.isLanguage("ger"));
+ assertTrue(HdmiCecController.isLanguage("zh"));
+ assertTrue(HdmiCecController.isLanguage("zhi"));
+ assertTrue(HdmiCecController.isLanguage("zho"));
+
+ assertFalse(HdmiCecController.isLanguage(null));
+ assertFalse(HdmiCecController.isLanguage(""));
+ assertFalse(HdmiCecController.isLanguage("e"));
+ assertFalse(HdmiCecController.isLanguage("一")); // language code must be ASCII
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
index f7d52b6..7aea4ff 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
@@ -1334,4 +1334,31 @@
assertThat(mNativeWrapper.getResultMessages()).contains(userControlReleased);
assertThat(mStandby).isFalse();
}
+
+ @Test
+ public void shouldHandleTvPowerKey_CecDisabled() {
+ mHdmiCecLocalDevicePlayback.mService.getHdmiCecConfig().setIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED,
+ HdmiControlManager.HDMI_CEC_CONTROL_DISABLED);
+ assertThat(mHdmiControlService.shouldHandleTvPowerKey()).isFalse();
+ }
+
+ @Test
+ public void shouldHandleTvPowerKey_PowerControlModeNone() {
+ mHdmiCecLocalDevicePlayback.mService.getHdmiCecConfig().setStringValue(
+ HdmiControlManager.CEC_SETTING_NAME_POWER_CONTROL_MODE,
+ HdmiControlManager.POWER_CONTROL_MODE_NONE);
+ assertThat(mHdmiControlService.shouldHandleTvPowerKey()).isFalse();
+ }
+
+ @Test
+ public void shouldHandleTvPowerKey_CecEnabled_PowerControlModeTv() {
+ mHdmiCecLocalDevicePlayback.mService.getHdmiCecConfig().setIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED,
+ HdmiControlManager.HDMI_CEC_CONTROL_ENABLED);
+ mHdmiCecLocalDevicePlayback.mService.getHdmiCecConfig().setStringValue(
+ HdmiControlManager.CEC_SETTING_NAME_POWER_CONTROL_MODE,
+ HdmiControlManager.POWER_CONTROL_MODE_TV);
+ assertThat(mHdmiControlService.shouldHandleTvPowerKey()).isTrue();
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
index d24b376..81f55d8 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
@@ -192,4 +192,15 @@
assertThat(mHdmiControlService.getActiveSource().getPhysicalAddress()).isEqualTo(
externalDevice.getPhysicalAddress());
}
+
+ @Test
+ public void shouldHandleTvPowerKey_CecEnabled_PowerControlModeTv() {
+ mHdmiCecLocalDeviceTv.mService.getHdmiCecConfig().setIntValue(
+ HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED,
+ HdmiControlManager.HDMI_CEC_CONTROL_ENABLED);
+ mHdmiCecLocalDeviceTv.mService.getHdmiCecConfig().setStringValue(
+ HdmiControlManager.CEC_SETTING_NAME_POWER_CONTROL_MODE,
+ HdmiControlManager.POWER_CONTROL_MODE_TV);
+ assertThat(mHdmiControlService.shouldHandleTvPowerKey()).isFalse();
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/location/timezone/ControllerImplTest.java b/services/tests/servicestests/src/com/android/server/location/timezone/ControllerImplTest.java
index 00cef8f..dc81237 100644
--- a/services/tests/servicestests/src/com/android/server/location/timezone/ControllerImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/location/timezone/ControllerImplTest.java
@@ -15,17 +15,16 @@
*/
package com.android.server.location.timezone;
-import static com.android.internal.location.timezone.LocationTimeZoneEvent.EVENT_TYPE_PERMANENT_FAILURE;
-import static com.android.internal.location.timezone.LocationTimeZoneEvent.EVENT_TYPE_SUCCESS;
-import static com.android.internal.location.timezone.LocationTimeZoneEvent.EVENT_TYPE_UNCERTAIN;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_DISABLED;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_ENABLED_CERTAIN;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_ENABLED_INITIALIZING;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_ENABLED_UNCERTAIN;
import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_PERM_FAILED;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_CERTAIN;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_INITIALIZING;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_UNCERTAIN;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STOPPED;
import static com.android.server.location.timezone.TestSupport.USER1_CONFIG_GEO_DETECTION_DISABLED;
import static com.android.server.location.timezone.TestSupport.USER1_CONFIG_GEO_DETECTION_ENABLED;
import static com.android.server.location.timezone.TestSupport.USER2_CONFIG_GEO_DETECTION_ENABLED;
+import static com.android.server.location.timezone.TimeZoneProviderEvent.createPermanentFailureEvent;
+import static com.android.server.location.timezone.TimeZoneProviderEvent.createUncertainEvent;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -37,9 +36,9 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.platform.test.annotations.Presubmit;
+import android.service.timezone.TimeZoneProviderSuggestion;
import android.util.IndentingPrintWriter;
-import com.android.internal.location.timezone.LocationTimeZoneEvent;
import com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.ProviderStateEnum;
import com.android.server.timezonedetector.ConfigurationInternal;
import com.android.server.timezonedetector.GeolocationTimeZoneSuggestion;
@@ -61,14 +60,14 @@
private static final long ARBITRARY_TIME_MILLIS = 12345L;
- private static final LocationTimeZoneEvent USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1 =
- createLocationTimeZoneEvent(EVENT_TYPE_SUCCESS, asList("Europe/London"));
- private static final LocationTimeZoneEvent USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2 =
- createLocationTimeZoneEvent(EVENT_TYPE_SUCCESS, asList("Europe/Paris"));
- private static final LocationTimeZoneEvent USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT =
- createLocationTimeZoneEvent(EVENT_TYPE_UNCERTAIN, null);
- private static final LocationTimeZoneEvent USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT =
- createLocationTimeZoneEvent(EVENT_TYPE_PERMANENT_FAILURE, null);
+ private static final TimeZoneProviderEvent USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1 =
+ createSuggestionEvent(asList("Europe/London"));
+ private static final TimeZoneProviderEvent USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2 =
+ createSuggestionEvent(asList("Europe/Paris"));
+ private static final TimeZoneProviderEvent USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT =
+ createUncertainEvent();
+ private static final TimeZoneProviderEvent USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT =
+ createPermanentFailureEvent("Test");
private TestThreadingDomain mTestThreadingDomain;
private TestCallback mTestCallback;
@@ -89,7 +88,7 @@
}
@Test
- public void initialState_enabled() {
+ public void initialState_started() {
ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
TestEnvironment testEnvironment = new TestEnvironment(
@@ -98,16 +97,16 @@
.plus(testEnvironment.getProviderInitializationTimeoutFuzz());
// Initialize. After initialization the providers must be initialized and one should be
- // enabled.
+ // started.
controllerImpl.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertInitialized();
mTestSecondaryLocationTimeZoneProvider.assertInitialized();
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestPrimaryLocationTimeZoneProvider.assertInitializationTimeoutSet(expectedInitTimeout);
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
}
@@ -120,14 +119,14 @@
mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_DISABLED);
// Initialize. After initialization the providers must be initialized but neither should be
- // enabled.
+ // started.
controllerImpl.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertInitialized();
mTestSecondaryLocationTimeZoneProvider.assertInitialized();
- mTestPrimaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ mTestPrimaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
}
@@ -143,8 +142,8 @@
controllerImpl.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
@@ -152,11 +151,11 @@
mTestThreadingDomain.executeNext();
// The primary should have reported uncertainty, which should trigger the controller to
- // start the uncertainty timeout and enable the secondary.
+ // start the uncertainty timeout and start the secondary.
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
@@ -167,9 +166,9 @@
// Now both initialization timeouts should have triggered. The uncertainty timeout should
// still not be triggered.
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
@@ -178,9 +177,9 @@
mTestThreadingDomain.executeNext();
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertUncertainSuggestionMadeAndCommit();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
}
@@ -196,21 +195,21 @@
controllerImpl.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// Simulate a location event being received from the primary provider. This should cause a
// suggestion to be made.
- mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertSuggestionMadeAndCommit(
- USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getTimeZoneIds());
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds());
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
}
@@ -225,8 +224,8 @@
controllerImpl.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
@@ -234,22 +233,22 @@
mTestThreadingDomain.executeNext();
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
// Simulate a location event being received from the primary provider. This should cause a
// suggestion to be made and the secondary to be shut down.
- mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertSuggestionMadeAndCommit(
- USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getTimeZoneIds());
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds());
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
}
@@ -264,8 +263,8 @@
controllerImpl.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
@@ -273,23 +272,23 @@
mTestThreadingDomain.executeNext();
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
// Simulate a location event being received from the secondary provider. This should cause a
// suggestion to be made.
- mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertSuggestionMadeAndCommit(
- USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getTimeZoneIds());
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds());
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
}
@@ -304,42 +303,42 @@
controllerImpl.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// Simulate a location event being received from the primary provider. This should cause a
// suggestion to be made.
- mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertSuggestionMadeAndCommit(
- USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getTimeZoneIds());
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds());
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// A second, identical event should not cause another suggestion.
- mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// And a third, different event should cause another suggestion.
- mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertSuggestionMadeAndCommit(
- USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getTimeZoneIds());
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getSuggestion().getTimeZoneIds());
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
}
@@ -354,8 +353,8 @@
controllerImpl.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
@@ -363,46 +362,46 @@
mTestThreadingDomain.executeNext();
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
// Simulate a location event being received from the secondary provider. This should cause a
// suggestion to be made.
- mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertSuggestionMadeAndCommit(
- USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getTimeZoneIds());
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds());
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// A second, identical event should not cause another suggestion.
- mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// And a third, different event should cause another suggestion.
- mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertSuggestionMadeAndCommit(
- USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getTimeZoneIds());
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getSuggestion().getTimeZoneIds());
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
}
@@ -417,60 +416,60 @@
controllerImpl.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// Simulate a location event being received from the primary provider. This should cause a
// suggestion to be made and ensure the primary is considered initialized.
- mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertSuggestionMadeAndCommit(
- USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getTimeZoneIds());
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds());
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// Simulate an uncertain event being received from the primary provider. This should not
// cause a suggestion to be made straight away, but the uncertainty timeout should be
- // started and the secondary should be enabled.
- mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ // started and the secondary should be started.
+ mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
// Simulate a location event being received from the secondary provider. This should cause a
// suggestion to be made, cancel the uncertainty timeout and ensure the secondary is
// considered initialized.
- mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertSuggestionMadeAndCommit(
- USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getTimeZoneIds());
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getSuggestion().getTimeZoneIds());
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// Simulate an uncertain event being received from the secondary provider. This should not
// cause a suggestion to be made straight away, but the uncertainty timeout should be
- // started. Both providers are now enabled, with no initialization timeout set.
- mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ // started. Both providers are now started, with no initialization timeout set.
+ mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
@@ -479,9 +478,9 @@
mTestThreadingDomain.executeNext();
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertUncertainSuggestionMadeAndCommit();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
}
@@ -497,46 +496,46 @@
controllerImpl.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// Simulate a location event being received from the primary provider. This should cause a
// suggestion to be made.
- mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertSuggestionMadeAndCommit(
- USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getTimeZoneIds());
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds());
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// Uncertainty should not cause a suggestion to be made straight away, but the uncertainty
- // timeout should be started and the secondary should be enabled.
- mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ // timeout should be started and the secondary should be started.
+ mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
// And a success event from the primary provider should cause the controller to make another
// suggestion, the uncertainty timeout should be cancelled and the secondary should be
- // disabled again.
- mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ // stopped again.
+ mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertSuggestionMadeAndCommit(
- USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getTimeZoneIds());
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getSuggestion().getTimeZoneIds());
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
}
@@ -550,8 +549,8 @@
// Initialize and check initial state.
controllerImpl.initialize(testEnvironment, mTestCallback);
- mTestPrimaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ mTestPrimaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
@@ -559,16 +558,16 @@
testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// Now signal a config change so that geo detection is disabled.
testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_DISABLED);
- mTestPrimaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ mTestPrimaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
}
@@ -583,8 +582,8 @@
// Initialize and check initial state.
controllerImpl.initialize(testEnvironment, mTestCallback);
- mTestPrimaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ mTestPrimaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
@@ -592,20 +591,20 @@
testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// Simulate a success event being received from the primary provider.
- mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertSuggestionMadeAndCommit(
- USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getTimeZoneIds());
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds());
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// Now signal a config change so that geo detection is disabled.
@@ -614,8 +613,8 @@
// of the time zone.
testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_DISABLED);
- mTestPrimaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ mTestPrimaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertUncertainSuggestionMadeAndCommit();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
}
@@ -631,35 +630,35 @@
controllerImpl.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// Simulate the primary provider suggesting a time zone.
- mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
// Receiving a "success" provider event should cause a suggestion to be made synchronously,
// and also clear the scheduled uncertainty suggestion.
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertSuggestionMadeAndCommit(
- USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getTimeZoneIds());
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds());
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// Simulate the user change (but geo detection still enabled).
testEnvironment.simulateConfigChange(USER2_CONFIG_GEO_DETECTION_ENABLED);
- // We expect the provider to end up in PROVIDER_STATE_ENABLED, but it should have been
- // disabled when the user changed.
+ // We expect the provider to end up in PROVIDER_STATE_STARTED_INITIALIZING, but it should
+ // have been stopped when the user changed.
int[] expectedStateTransitions =
- { PROVIDER_STATE_DISABLED, PROVIDER_STATE_ENABLED_INITIALIZING };
+ { PROVIDER_STATE_STOPPED, PROVIDER_STATE_STARTED_INITIALIZING };
mTestPrimaryLocationTimeZoneProvider.assertStateChangesAndCommit(expectedStateTransitions);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfig(
- PROVIDER_STATE_ENABLED_INITIALIZING, USER2_CONFIG_GEO_DETECTION_ENABLED);
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ PROVIDER_STATE_STARTED_INITIALIZING, USER2_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
}
@@ -674,51 +673,51 @@
controllerImpl.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// Simulate a failure location event being received from the primary provider. This should
- // cause the secondary to be enabled.
- mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ // cause the secondary to be started.
+ mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT);
mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// Simulate uncertainty from the secondary.
- mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
// And a success event from the secondary provider should cause the controller to make
// another suggestion, the uncertainty timeout should be cancelled.
- mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertSuggestionMadeAndCommit(
- USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getTimeZoneIds());
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getSuggestion().getTimeZoneIds());
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// Simulate uncertainty from the secondary.
- mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
}
@@ -734,19 +733,19 @@
controllerImpl.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// Simulate a failure location event being received from the primary provider. This should
- // cause the secondary to be enabled.
- mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ // cause the secondary to be started.
+ mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT);
mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
@@ -754,7 +753,7 @@
testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_DISABLED);
mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
@@ -763,7 +762,7 @@
mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
}
@@ -779,52 +778,52 @@
controllerImpl.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
- // Simulate an uncertain event from the primary. This will enable the secondary, which will
+ // Simulate an uncertain event from the primary. This will start the secondary, which will
// give this test the opportunity to simulate its failure. Then it will be possible to
// demonstrate controller behavior with only the primary working.
- mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
// Simulate failure event from the secondary. This should just affect the secondary's state.
- mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
// And a success event from the primary provider should cause the controller to make
// a suggestion, the uncertainty timeout should be cancelled.
- mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestCallback.assertSuggestionMadeAndCommit(
- USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getTimeZoneIds());
+ USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2.getSuggestion().getTimeZoneIds());
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
- // Simulate uncertainty from the primary. The secondary cannot be enabled.
- mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ // Simulate uncertainty from the primary. The secondary cannot be started.
+ mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
@@ -841,30 +840,30 @@
controllerImpl.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
- // Simulate an uncertain event from the primary. This will enable the secondary, which will
+ // Simulate an uncertain event from the primary. This will start the secondary, which will
// give this test the opportunity to simulate its failure. Then it will be possible to
// demonstrate controller behavior with only the primary working.
- mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
// Simulate failure event from the secondary. This should just affect the secondary's state.
- mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestCallback.assertNoSuggestionMade();
assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
@@ -872,17 +871,17 @@
// Now signal a config change so that geo detection is disabled.
testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_DISABLED);
- mTestPrimaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ mTestPrimaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// Now signal a config change so that geo detection is enabled. Only the primary can be
- // enabled.
+ // started.
testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
@@ -899,23 +898,23 @@
controllerImpl.initialize(testEnvironment, mTestCallback);
mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
- mTestSecondaryLocationTimeZoneProvider.assertIsDisabledAndCommit();
+ PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
- // Simulate a failure event from the primary. This will enable the secondary.
- mTestPrimaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ // Simulate a failure event from the primary. This will start the secondary.
+ mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT);
mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
- PROVIDER_STATE_ENABLED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+ PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
mTestCallback.assertNoSuggestionMade();
assertFalse(controllerImpl.isUncertaintyTimeoutSet());
// Simulate failure event from the secondary.
- mTestSecondaryLocationTimeZoneProvider.simulateLocationTimeZoneEvent(
+ mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT);
mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
@@ -932,18 +931,14 @@
controller.getUncertaintyTimeoutDelayMillis());
}
- private static LocationTimeZoneEvent createLocationTimeZoneEvent(
- int eventType, @Nullable List<String> timeZoneIds) {
- LocationTimeZoneEvent.Builder builder = new LocationTimeZoneEvent.Builder()
- .setElapsedRealtimeMillis(ARBITRARY_TIME_MILLIS)
- .setEventType(eventType);
- if (timeZoneIds != null) {
- builder.setTimeZoneIds(timeZoneIds);
- }
- return builder.build();
+ private static TimeZoneProviderEvent createSuggestionEvent(@NonNull List<String> timeZoneIds) {
+ return TimeZoneProviderEvent.createSuggestionEvent(
+ new TimeZoneProviderSuggestion.Builder()
+ .setElapsedRealtimeMillis(ARBITRARY_TIME_MILLIS)
+ .setTimeZoneIds(timeZoneIds)
+ .build());
}
-
private static class TestEnvironment extends LocationTimeZoneProviderController.Environment {
// These timeouts are set deliberately so that:
@@ -1048,12 +1043,12 @@
}
@Override
- void onEnable(Duration initializationTimeout) {
+ void onStartUpdates(Duration initializationTimeout) {
// Nothing needed for tests.
}
@Override
- void onDisable() {
+ void onStopUpdates() {
// Nothing needed for tests.
}
@@ -1078,9 +1073,9 @@
mTestProviderState.commitLatest();
}
- void assertIsDisabledAndCommit() {
- // A disabled provider doesn't hold config.
- assertStateEnumAndConfig(PROVIDER_STATE_DISABLED, null /* config */);
+ void assertIsStoppedAndCommit() {
+ // A stopped provider doesn't hold config.
+ assertStateEnumAndConfig(PROVIDER_STATE_STOPPED, null /* config */);
mTestProviderState.commitLatest();
}
@@ -1107,7 +1102,7 @@
// If and only if the controller is initializing, the initialization timeout must be
// set.
- assertEquals(expectedStateEnum == PROVIDER_STATE_ENABLED_INITIALIZING,
+ assertEquals(expectedStateEnum == PROVIDER_STATE_STARTED_INITIALIZING,
isInitializationTimeoutSet());
assertConfig(expectedConfig);
@@ -1123,8 +1118,8 @@
assertEquals(expectedTimeout, getInitializationTimeoutDelay());
}
- void simulateLocationTimeZoneEvent(@NonNull LocationTimeZoneEvent event) {
- handleLocationTimeZoneEvent(event);
+ void simulateTimeZoneProviderEvent(@NonNull TimeZoneProviderEvent event) {
+ handleTimeZoneProviderEvent(event);
}
/**
diff --git a/services/tests/servicestests/src/com/android/server/location/timezone/NullLocationTimeZoneProviderTest.java b/services/tests/servicestests/src/com/android/server/location/timezone/NullLocationTimeZoneProviderTest.java
index 5403a65..e4a3ebd 100644
--- a/services/tests/servicestests/src/com/android/server/location/timezone/NullLocationTimeZoneProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/location/timezone/NullLocationTimeZoneProviderTest.java
@@ -15,9 +15,9 @@
*/
package com.android.server.location.timezone;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_DISABLED;
-import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_ENABLED_INITIALIZING;
import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_PERM_FAILED;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_INITIALIZING;
+import static com.android.server.location.timezone.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STOPPED;
import static com.android.server.location.timezone.TestSupport.USER1_CONFIG_GEO_DETECTION_ENABLED;
import static org.junit.Assert.assertEquals;
@@ -61,14 +61,14 @@
provider.initialize(providerState -> mTestController.onProviderStateChange(providerState));
ProviderState currentState = provider.getCurrentState();
- assertEquals(PROVIDER_STATE_DISABLED, currentState.stateEnum);
+ assertEquals(PROVIDER_STATE_STOPPED, currentState.stateEnum);
assertNull(currentState.currentUserConfiguration);
assertSame(provider, currentState.provider);
mTestThreadingDomain.assertQueueEmpty();
}
@Test
- public void enableSchedulesPermFailure() {
+ public void startSchedulesPermFailure() {
String providerName = "primary";
NullLocationTimeZoneProvider provider =
new NullLocationTimeZoneProvider(mTestThreadingDomain, providerName);
@@ -77,13 +77,14 @@
ConfigurationInternal config = USER1_CONFIG_GEO_DETECTION_ENABLED;
Duration arbitraryInitializationTimeout = Duration.ofMinutes(5);
Duration arbitraryInitializationTimeoutFuzz = Duration.ofMinutes(2);
- provider.enable(config, arbitraryInitializationTimeout, arbitraryInitializationTimeoutFuzz);
+ provider.startUpdates(config, arbitraryInitializationTimeout,
+ arbitraryInitializationTimeoutFuzz);
// The NullProvider should enter the enabled state, but have schedule an immediate runnable
// to switch to perm failure.
ProviderState currentState = provider.getCurrentState();
assertSame(provider, currentState.provider);
- assertEquals(PROVIDER_STATE_ENABLED_INITIALIZING, currentState.stateEnum);
+ assertEquals(PROVIDER_STATE_STARTED_INITIALIZING, currentState.stateEnum);
assertEquals(config, currentState.currentUserConfiguration);
mTestThreadingDomain.assertNextQueueItemIsImmediate();
// Entering enabled() does not trigger an onProviderStateChanged() as it is requested by the
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java
index 20f9b70..e3e7768 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java
@@ -28,7 +28,6 @@
import android.content.om.OverlayInfo;
import android.text.TextUtils;
import android.util.TypedXmlPullParser;
-import android.util.TypedXmlSerializer;
import android.util.Xml;
import androidx.test.runner.AndroidJUnit4;
@@ -40,7 +39,7 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
-import java.io.StringReader;
+import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -287,7 +286,7 @@
public void testPersistEmpty() throws Exception {
ByteArrayOutputStream os = new ByteArrayOutputStream();
mSettings.persist(os);
- String xml = new String(os.toByteArray(), "utf-8");
+ ByteArrayInputStream xml = new ByteArrayInputStream(os.toByteArray());
assertEquals(1, countXmlTags(xml, "overlays"));
assertEquals(0, countXmlTags(xml, "item"));
@@ -300,7 +299,7 @@
ByteArrayOutputStream os = new ByteArrayOutputStream();
mSettings.persist(os);
- final String xml = new String(os.toByteArray(), "utf-8");
+ ByteArrayInputStream xml = new ByteArrayInputStream(os.toByteArray());
assertEquals(1, countXmlTags(xml, "overlays"));
assertEquals(2, countXmlTags(xml, "item"));
@@ -319,7 +318,7 @@
ByteArrayOutputStream os = new ByteArrayOutputStream();
mSettings.persist(os);
- String xml = new String(os.toByteArray(), "utf-8");
+ ByteArrayInputStream xml = new ByteArrayInputStream(os.toByteArray());
assertEquals(1, countXmlTags(xml, "overlays"));
assertEquals(2, countXmlTags(xml, "item"));
@@ -338,7 +337,7 @@
ByteArrayOutputStream os = new ByteArrayOutputStream();
mSettings.persist(os);
- String xml = new String(os.toByteArray(), "utf-8");
+ ByteArrayInputStream xml = new ByteArrayInputStream(os.toByteArray());
assertEquals(1, countXmlAttributesWhere(xml, "item", "isEnabled", "true"));
}
@@ -391,8 +390,7 @@
ByteArrayOutputStream os = new ByteArrayOutputStream();
mSettings.persist(os);
- String xml = new String(os.toByteArray(), "utf-8");
- ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes("utf-8"));
+ ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
OverlayManagerSettings newSettings = new OverlayManagerSettings();
newSettings.restore(is);
@@ -403,10 +401,10 @@
assertEquals(OVERLAY_B1, b);
}
- private int countXmlTags(String xml, String tagToLookFor) throws Exception {
+ private int countXmlTags(InputStream in, String tagToLookFor) throws Exception {
+ in.reset();
int count = 0;
- TypedXmlPullParser parser = Xml.newFastPullParser();
- parser.setInput(new StringReader(xml));
+ TypedXmlPullParser parser = Xml.resolvePullParser(in);
int event = parser.getEventType();
while (event != XmlPullParser.END_DOCUMENT) {
if (event == XmlPullParser.START_TAG && tagToLookFor.equals(parser.getName())) {
@@ -417,11 +415,11 @@
return count;
}
- private int countXmlAttributesWhere(String xml, String tag, String attr, String value)
+ private int countXmlAttributesWhere(InputStream in, String tag, String attr, String value)
throws Exception {
+ in.reset();
int count = 0;
- TypedXmlPullParser parser = Xml.newFastPullParser();
- parser.setInput(new StringReader(xml));
+ TypedXmlPullParser parser = Xml.resolvePullParser(in);
int event = parser.getEventType();
while (event != XmlPullParser.END_DOCUMENT) {
if (event == XmlPullParser.START_TAG && tag.equals(parser.getName())) {
diff --git a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
index eec7d12..205548c 100644
--- a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
@@ -52,6 +52,7 @@
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.PackageImpl;
import com.android.server.pm.parsing.pkg.ParsedPackage;
+import com.android.server.utils.WatchableTester;
import org.junit.Before;
import org.junit.Test;
@@ -884,6 +885,104 @@
contains(hasProviderAppId, queriesProviderAppId));
}
+ @Test
+ public void testOnChangeReport() throws Exception {
+ final AppsFilter appsFilter =
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ mMockExecutor);
+ final WatchableTester watcher = new WatchableTester(appsFilter, "onChange");
+ watcher.register();
+ simulateAddBasicAndroid(appsFilter);
+ watcher.verifyChangeReported("addBasic");
+ appsFilter.onSystemReady();
+ watcher.verifyChangeReported("systemReady");
+
+ final int systemAppId = Process.FIRST_APPLICATION_UID - 1;
+ final int seesNothingAppId = Process.FIRST_APPLICATION_UID;
+ final int hasProviderAppId = Process.FIRST_APPLICATION_UID + 1;
+ final int queriesProviderAppId = Process.FIRST_APPLICATION_UID + 2;
+
+ PackageSetting system = simulateAddPackage(appsFilter, pkg("some.system.pkg"), systemAppId);
+ watcher.verifyChangeReported("addPackage");
+ PackageSetting seesNothing = simulateAddPackage(appsFilter, pkg("com.some.package"),
+ seesNothingAppId);
+ watcher.verifyChangeReported("addPackage");
+ PackageSetting hasProvider = simulateAddPackage(appsFilter,
+ pkgWithProvider("com.some.other.package", "com.some.authority"), hasProviderAppId);
+ watcher.verifyChangeReported("addPackage");
+ PackageSetting queriesProvider = simulateAddPackage(appsFilter,
+ pkgQueriesProvider("com.yet.some.other.package", "com.some.authority"),
+ queriesProviderAppId);
+ watcher.verifyChangeReported("addPackage");
+
+ final SparseArray<int[]> systemFilter =
+ appsFilter.getVisibilityAllowList(system, USER_ARRAY, mExisting);
+ assertThat(toList(systemFilter.get(SYSTEM_USER)),
+ contains(seesNothingAppId, hasProviderAppId, queriesProviderAppId));
+ watcher.verifyNoChangeReported("get");
+
+ final SparseArray<int[]> seesNothingFilter =
+ appsFilter.getVisibilityAllowList(seesNothing, USER_ARRAY, mExisting);
+ assertThat(toList(seesNothingFilter.get(SYSTEM_USER)),
+ contains(seesNothingAppId));
+ assertThat(toList(seesNothingFilter.get(SECONDARY_USER)),
+ contains(seesNothingAppId));
+ watcher.verifyNoChangeReported("get");
+
+ final SparseArray<int[]> hasProviderFilter =
+ appsFilter.getVisibilityAllowList(hasProvider, USER_ARRAY, mExisting);
+ assertThat(toList(hasProviderFilter.get(SYSTEM_USER)),
+ contains(hasProviderAppId, queriesProviderAppId));
+ watcher.verifyNoChangeReported("get");
+
+ SparseArray<int[]> queriesProviderFilter =
+ appsFilter.getVisibilityAllowList(queriesProvider, USER_ARRAY, mExisting);
+ assertThat(toList(queriesProviderFilter.get(SYSTEM_USER)),
+ contains(queriesProviderAppId));
+ watcher.verifyNoChangeReported("get");
+
+ // provider read
+ appsFilter.grantImplicitAccess(hasProviderAppId, queriesProviderAppId);
+ watcher.verifyChangeReported("grantImplicitAccess");
+
+ // ensure implicit access is included in the filter
+ queriesProviderFilter =
+ appsFilter.getVisibilityAllowList(queriesProvider, USER_ARRAY, mExisting);
+ assertThat(toList(queriesProviderFilter.get(SYSTEM_USER)),
+ contains(hasProviderAppId, queriesProviderAppId));
+ watcher.verifyNoChangeReported("get");
+
+ // remove a package
+ appsFilter.removePackage(seesNothing);
+ watcher.verifyChangeReported("removePackage");
+ }
+
+ @Test
+ public void testOnChangeReportedFilter() throws Exception {
+ final AppsFilter appsFilter =
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ mMockExecutor);
+ simulateAddBasicAndroid(appsFilter);
+ appsFilter.onSystemReady();
+ final WatchableTester watcher = new WatchableTester(appsFilter, "onChange filter");
+ watcher.register();
+
+ PackageSetting target = simulateAddPackage(appsFilter, pkg("com.some.package"),
+ DUMMY_TARGET_APPID);
+ PackageSetting instrumentation = simulateAddPackage(appsFilter,
+ pkgWithInstrumentation("com.some.other.package", "com.some.package"),
+ DUMMY_CALLING_APPID);
+ watcher.verifyChangeReported("addPackage");
+
+ assertFalse(
+ appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, instrumentation, target,
+ SYSTEM_USER));
+ assertFalse(
+ appsFilter.shouldFilterApplication(DUMMY_TARGET_APPID, target, instrumentation,
+ SYSTEM_USER));
+ watcher.verifyNoChangeReported("shouldFilterApplication");
+ }
+
private List<Integer> toList(int[] array) {
ArrayList<Integer> ret = new ArrayList<>(array.length);
for (int i = 0; i < array.length; i++) {
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index 4b90a5c..282047a 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -62,6 +62,7 @@
import com.android.server.pm.parsing.pkg.PackageImpl;
import com.android.server.pm.parsing.pkg.ParsedPackage;
import com.android.server.pm.permission.LegacyPermissionDataProvider;
+import com.android.server.utils.WatchableTester;
import com.google.common.truth.Truth;
@@ -178,6 +179,12 @@
PackageSetting ps = settings.getPackageLPr(PACKAGE_NAME_2);
assertThat(ps.getEnabled(0), is(COMPONENT_ENABLED_STATE_DISABLED_USER));
assertThat(ps.getEnabled(1), is(COMPONENT_ENABLED_STATE_DEFAULT));
+
+ // Verify that the snapshot passes the same test
+ Settings snapshot = settings.snapshot();
+ ps = snapshot.getPackageLPr(PACKAGE_NAME_2);
+ assertThat(ps.getEnabled(0), is(COMPONENT_ENABLED_STATE_DISABLED_USER));
+ assertThat(ps.getEnabled(1), is(COMPONENT_ENABLED_STATE_DEFAULT));
}
private static PersistableBundle createPersistableBundle(String packageName, long longVal,
@@ -197,21 +204,41 @@
final Context context = InstrumentationRegistry.getTargetContext();
final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, null,
lock);
+ final WatchableTester watcher =
+ new WatchableTester(settingsUnderTest, "noSuspendingPackage");
+ watcher.register();
settingsUnderTest.mPackages.put(PACKAGE_NAME_1, createPackageSetting(PACKAGE_NAME_1));
+ watcher.verifyChangeReported("put package 1");
+ // Collect a snapshot at the midway point (package 2 has not been added)
+ final Settings snapshot = settingsUnderTest.snapshot();
+ watcher.verifyNoChangeReported("snapshot");
settingsUnderTest.mPackages.put(PACKAGE_NAME_2, createPackageSetting(PACKAGE_NAME_2));
+ watcher.verifyChangeReported("put package 2");
settingsUnderTest.readPackageRestrictionsLPr(0);
- final PackageSetting ps1 = settingsUnderTest.mPackages.get(PACKAGE_NAME_1);
- final PackageUserState packageUserState1 = ps1.readUserState(0);
+ PackageSetting ps1 = settingsUnderTest.mPackages.get(PACKAGE_NAME_1);
+ PackageUserState packageUserState1 = ps1.readUserState(0);
assertThat(packageUserState1.suspended, is(true));
assertThat(packageUserState1.suspendParams.size(), is(1));
assertThat(packageUserState1.suspendParams.keyAt(0), is("android"));
assertThat(packageUserState1.suspendParams.valueAt(0), is(nullValue()));
- final PackageSetting ps2 = settingsUnderTest.mPackages.get(PACKAGE_NAME_2);
- final PackageUserState packageUserState2 = ps2.readUserState(0);
+ // Verify that the snapshot returns the same answers
+ ps1 = snapshot.mPackages.get(PACKAGE_NAME_1);
+ packageUserState1 = ps1.readUserState(0);
+ assertThat(packageUserState1.suspended, is(true));
+ assertThat(packageUserState1.suspendParams.size(), is(1));
+ assertThat(packageUserState1.suspendParams.keyAt(0), is("android"));
+ assertThat(packageUserState1.suspendParams.valueAt(0), is(nullValue()));
+
+ PackageSetting ps2 = settingsUnderTest.mPackages.get(PACKAGE_NAME_2);
+ PackageUserState packageUserState2 = ps2.readUserState(0);
assertThat(packageUserState2.suspended, is(false));
assertThat(packageUserState2.suspendParams, is(nullValue()));
+
+ // Verify that the snapshot returns different answers
+ ps2 = snapshot.mPackages.get(PACKAGE_NAME_2);
+ assertTrue(ps2 == null);
}
@Test
@@ -221,15 +248,23 @@
final Context context = InstrumentationRegistry.getTargetContext();
final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, null,
lock);
+ final WatchableTester watcher =
+ new WatchableTester(settingsUnderTest, "noSuspendParamsMap");
+ watcher.register();
settingsUnderTest.mPackages.put(PACKAGE_NAME_1, createPackageSetting(PACKAGE_NAME_1));
+ watcher.verifyChangeReported("put package 1");
settingsUnderTest.readPackageRestrictionsLPr(0);
+ watcher.verifyChangeReported("readPackageRestrictions");
final PackageSetting ps1 = settingsUnderTest.mPackages.get(PACKAGE_NAME_1);
+ watcher.verifyNoChangeReported("get package 1");
final PackageUserState packageUserState1 = ps1.readUserState(0);
+ watcher.verifyNoChangeReported("readUserState");
assertThat(packageUserState1.suspended, is(true));
assertThat(packageUserState1.suspendParams.size(), is(1));
assertThat(packageUserState1.suspendParams.keyAt(0), is(PACKAGE_NAME_3));
final PackageUserState.SuspendParams params = packageUserState1.suspendParams.valueAt(0);
+ watcher.verifyNoChangeReported("fetch user state");
assertThat(params, is(notNullValue()));
assertThat(params.appExtras.size(), is(1));
assertThat(params.appExtras.getString("app_extra_string"), is("value"));
@@ -249,6 +284,8 @@
final Context context = InstrumentationRegistry.getTargetContext();
final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, null,
new Object());
+ final WatchableTester watcher = new WatchableTester(settingsUnderTest, "suspendInfo");
+ watcher.register();
final PackageSetting ps1 = createPackageSetting(PACKAGE_NAME_1);
final PackageSetting ps2 = createPackageSetting(PACKAGE_NAME_2);
final PackageSetting ps3 = createPackageSetting(PACKAGE_NAME_3);
@@ -283,33 +320,46 @@
ps1.addOrUpdateSuspension("suspendingPackage2", dialogInfo2, appExtras2, launcherExtras2,
0);
settingsUnderTest.mPackages.put(PACKAGE_NAME_1, ps1);
+ watcher.verifyChangeReported("put package 1");
ps2.addOrUpdateSuspension("suspendingPackage3", null, appExtras1, null, 0);
settingsUnderTest.mPackages.put(PACKAGE_NAME_2, ps2);
+ watcher.verifyChangeReported("put package 2");
ps3.removeSuspension("irrelevant", 0);
settingsUnderTest.mPackages.put(PACKAGE_NAME_3, ps3);
+ watcher.verifyChangeReported("put package 3");
settingsUnderTest.writePackageRestrictionsLPr(0);
+ watcher.verifyChangeReported("writePackageRestrictions");
settingsUnderTest.mPackages.clear();
+ watcher.verifyChangeReported("clear packages");
settingsUnderTest.mPackages.put(PACKAGE_NAME_1, createPackageSetting(PACKAGE_NAME_1));
+ watcher.verifyChangeReported("put package 1");
settingsUnderTest.mPackages.put(PACKAGE_NAME_2, createPackageSetting(PACKAGE_NAME_2));
+ watcher.verifyChangeReported("put package 2");
settingsUnderTest.mPackages.put(PACKAGE_NAME_3, createPackageSetting(PACKAGE_NAME_3));
+ watcher.verifyChangeReported("put package 3");
// now read and verify
settingsUnderTest.readPackageRestrictionsLPr(0);
+ watcher.verifyChangeReported("readPackageRestrictions");
final PackageUserState readPus1 = settingsUnderTest.mPackages.get(PACKAGE_NAME_1)
.readUserState(0);
+ watcher.verifyNoChangeReported("package get 1");
assertThat(readPus1.suspended, is(true));
assertThat(readPus1.suspendParams.size(), is(2));
+ watcher.verifyNoChangeReported("read package param");
assertThat(readPus1.suspendParams.keyAt(0), is("suspendingPackage1"));
final PackageUserState.SuspendParams params11 = readPus1.suspendParams.valueAt(0);
+ watcher.verifyNoChangeReported("read package param");
assertThat(params11, is(notNullValue()));
assertThat(params11.dialogInfo, is(dialogInfo1));
assertThat(BaseBundle.kindofEquals(params11.appExtras, appExtras1), is(true));
assertThat(BaseBundle.kindofEquals(params11.launcherExtras, launcherExtras1),
is(true));
+ watcher.verifyNoChangeReported("read package param");
assertThat(readPus1.suspendParams.keyAt(1), is("suspendingPackage2"));
final PackageUserState.SuspendParams params12 = readPus1.suspendParams.valueAt(1);
@@ -318,6 +368,7 @@
assertThat(BaseBundle.kindofEquals(params12.appExtras, appExtras2), is(true));
assertThat(BaseBundle.kindofEquals(params12.launcherExtras, launcherExtras2),
is(true));
+ watcher.verifyNoChangeReported("read package param");
final PackageUserState readPus2 = settingsUnderTest.mPackages.get(PACKAGE_NAME_2)
.readUserState(0);
@@ -329,11 +380,13 @@
assertThat(params21.dialogInfo, is(nullValue()));
assertThat(BaseBundle.kindofEquals(params21.appExtras, appExtras1), is(true));
assertThat(params21.launcherExtras, is(nullValue()));
+ watcher.verifyNoChangeReported("read package param");
final PackageUserState readPus3 = settingsUnderTest.mPackages.get(PACKAGE_NAME_3)
.readUserState(0);
assertThat(readPus3.suspended, is(false));
assertThat(readPus3.suspendParams, is(nullValue()));
+ watcher.verifyNoChangeReported("package get 3");
}
@Test
@@ -467,14 +520,23 @@
final Object lock = new Object();
Settings settings = new Settings(context.getFilesDir(),
mRuntimePermissionsPersistence, mPermissionDataProvider, lock);
+ final WatchableTester watcher = new WatchableTester(settings, "testEnableDisable");
+ watcher.register();
assertThat(settings.readLPw(createFakeUsers()), is(true));
+ watcher.verifyChangeReported("readLPw");
// Enable/Disable a package
PackageSetting ps = settings.getPackageLPr(PACKAGE_NAME_1);
+ watcher.verifyNoChangeReported("getPackageLPr");
+ assertThat(ps.getEnabled(0), is(not(COMPONENT_ENABLED_STATE_DISABLED)));
+ assertThat(ps.getEnabled(1), is(not(COMPONENT_ENABLED_STATE_ENABLED)));
ps.setEnabled(COMPONENT_ENABLED_STATE_DISABLED, 0, null);
+ watcher.verifyChangeReported("setEnabled DISABLED");
ps.setEnabled(COMPONENT_ENABLED_STATE_ENABLED, 1, null);
+ watcher.verifyChangeReported("setEnabled ENABLED");
assertThat(ps.getEnabled(0), is(COMPONENT_ENABLED_STATE_DISABLED));
assertThat(ps.getEnabled(1), is(COMPONENT_ENABLED_STATE_ENABLED));
+ watcher.verifyNoChangeReported("getEnabled");
// Enable/Disable a component
ArraySet<String> components = new ArraySet<String>();
@@ -1152,7 +1214,8 @@
private void verifyKeySetMetaData(Settings settings)
throws ReflectiveOperationException, IllegalAccessException {
- ArrayMap<String, PackageSetting> packages = settings.mPackages;
+ ArrayMap<String, PackageSetting> packages =
+ settings.mPackages.untrackedMap();
KeySetManagerService ksms = settings.mKeySetManagerService;
/* verify keyset and public key ref counts */
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest4.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest4.java
index 583c3d4..7546c43 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest4.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest4.java
@@ -25,8 +25,16 @@
import android.os.Bundle;
import android.os.PersistableBundle;
import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Xml;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.runner.RunWith;
@SmallTest
+@RunWith(AndroidJUnit4.class)
public class ShortcutManagerTest4 extends BaseShortcutManagerTest {
private static Bundle sIntentExtras = makeBundle(
@@ -99,7 +107,10 @@
"x2", "value{?}"
);
+ @Test
public void testPersistingWeirdCharacters() {
+ Assume.assumeFalse(Xml.ENABLE_BINARY_DEFAULT);
+
final Intent intent = new Intent(Intent.ACTION_MAIN)
.putExtras(sIntentExtras);
diff --git a/services/tests/servicestests/src/com/android/server/pm/StagingManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/StagingManagerTest.java
index 4870c9e..79935c2 100644
--- a/services/tests/servicestests/src/com/android/server/pm/StagingManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/StagingManagerTest.java
@@ -33,8 +33,11 @@
import org.mockito.MockitoAnnotations;
import java.io.File;
+import java.util.function.Predicate;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
@@ -70,8 +73,8 @@
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);
+ StagingManager.StagedSession session1 = createSession(111, "com.foo", 1);
+ StagingManager.StagedSession session2 = createSession(222, "com.foo", 2);
mStagingManager.createSession(session1);
mStagingManager.createSession(session2);
@@ -82,7 +85,7 @@
() -> mStagingManager.checkNonOverlappingWithStagedSessions(session2));
}
- private PackageInstallerSession createSession(int sessionId, String packageName,
+ private StagingManager.StagedSession createSession(int sessionId, String packageName,
long committedMillis) {
PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
PackageInstaller.SessionParams.MODE_FULL_INSTALL);
@@ -121,8 +124,12 @@
/* stagedSessionErrorCode */ PackageInstaller.SessionInfo.STAGED_SESSION_NO_ERROR,
/* stagedSessionErrorMessage */ "no error");
- session = spy(session);
- doReturn(packageName).when(session).getPackageName();
- return session;
+ StagingManager.StagedSession stagedSession = spy(session.mStagedSession);
+ doReturn(packageName).when(stagedSession).getPackageName();
+ doAnswer(invocation -> {
+ Predicate<StagingManager.StagedSession> filter = invocation.getArgument(0);
+ return filter.test(stagedSession);
+ }).when(stagedSession).sessionContains(any());
+ return stagedSession;
}
}
diff --git a/services/tests/servicestests/src/com/android/server/powerstats/PowerStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/powerstats/PowerStatsServiceTest.java
index b26d1efe..08d4caa 100644
--- a/services/tests/servicestests/src/com/android/server/powerstats/PowerStatsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/powerstats/PowerStatsServiceTest.java
@@ -209,7 +209,7 @@
}
@Override
- public boolean initialize() {
+ public boolean isInitialized() {
return true;
}
}
diff --git a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java
index 035a2f1..b07b8fa 100644
--- a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java
@@ -21,6 +21,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doThrow;
@@ -33,6 +34,7 @@
import android.content.Context;
import android.content.IntentSender;
+import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.IPowerManager;
import android.os.IRecoverySystemProgressListener;
@@ -67,6 +69,9 @@
private FileWriter mUncryptUpdateFileWriter;
private LockSettingsInternal mLockSettingsInternal;
+ private static final String FAKE_OTA_PACKAGE_NAME = "fake.ota.package";
+ private static final String FAKE_OTHER_PACKAGE_NAME = "fake.other.package";
+
@Before
public void setup() {
mContext = mock(Context.class);
@@ -209,65 +214,99 @@
@Test(expected = SecurityException.class)
public void requestLskf_protected() {
- doThrow(SecurityException.class).when(mContext).enforceCallingOrSelfPermission(
- eq(android.Manifest.permission.RECOVERY), any());
- mRecoverySystemService.requestLskf("test", null);
- }
-
-
- @Test
- public void requestLskf_nullToken_failure() {
- assertThat(mRecoverySystemService.requestLskf(null, null), is(false));
+ when(mContext.checkCallingOrSelfPermission(anyString())).thenReturn(
+ PackageManager.PERMISSION_DENIED);
+ mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null);
}
@Test
public void requestLskf_success() throws Exception {
IntentSender intentSender = mock(IntentSender.class);
- assertThat(mRecoverySystemService.requestLskf("test", intentSender), is(true));
+ assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender),
+ is(true));
mRecoverySystemService.onPreparedForReboot(true);
verify(intentSender).sendIntent(any(), anyInt(), any(), any(), any());
}
@Test
- public void requestLskf_subsequentRequestClearsPrepared() throws Exception {
+ public void requestLskf_subsequentRequestNotClearPrepared() throws Exception {
IntentSender intentSender = mock(IntentSender.class);
- assertThat(mRecoverySystemService.requestLskf("test", intentSender), is(true));
+ assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender),
+ is(true));
mRecoverySystemService.onPreparedForReboot(true);
verify(intentSender).sendIntent(any(), anyInt(), any(), any(), any());
- assertThat(mRecoverySystemService.requestLskf("test2", null), is(true));
- assertThat(mRecoverySystemService.rebootWithLskf("test", null), is(false));
- assertThat(mRecoverySystemService.rebootWithLskf("test2", "foobar"), is(false));
-
- mRecoverySystemService.onPreparedForReboot(true);
- assertThat(mRecoverySystemService.rebootWithLskf("test2", "foobar"), is(true));
- verify(intentSender).sendIntent(any(), anyInt(), any(), any(), any());
+ assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null), is(true));
+ assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "foobar", true),
+ is(true));
verify(mIPowerManager).reboot(anyBoolean(), eq("foobar"), anyBoolean());
}
-
@Test
public void requestLskf_requestedButNotPrepared() throws Exception {
IntentSender intentSender = mock(IntentSender.class);
- assertThat(mRecoverySystemService.requestLskf("test", intentSender), is(true));
+ assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender),
+ is(true));
verify(intentSender, never()).sendIntent(any(), anyInt(), any(), any(), any());
}
+ @Test
+ public void isLskfCaptured_requestedButNotPrepared() throws Exception {
+ IntentSender intentSender = mock(IntentSender.class);
+ assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender),
+ is(true));
+ assertThat(mRecoverySystemService.isLskfCaptured(FAKE_OTA_PACKAGE_NAME), is(false));
+ }
+
+ @Test
+ public void isLskfCaptured_Prepared() throws Exception {
+ IntentSender intentSender = mock(IntentSender.class);
+ assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender),
+ is(true));
+ mRecoverySystemService.onPreparedForReboot(true);
+ verify(intentSender).sendIntent(any(), anyInt(), any(), any(), any());
+ assertThat(mRecoverySystemService.isLskfCaptured(FAKE_OTA_PACKAGE_NAME), is(true));
+ }
+
@Test(expected = SecurityException.class)
public void clearLskf_protected() {
- doThrow(SecurityException.class).when(mContext).enforceCallingOrSelfPermission(
- eq(android.Manifest.permission.RECOVERY), any());
- mRecoverySystemService.clearLskf();
+ when(mContext.checkCallingOrSelfPermission(anyString())).thenReturn(
+ PackageManager.PERMISSION_DENIED);
+ mRecoverySystemService.clearLskf(FAKE_OTA_PACKAGE_NAME);
}
@Test
public void clearLskf_requestedThenCleared() throws Exception {
IntentSender intentSender = mock(IntentSender.class);
- assertThat(mRecoverySystemService.requestLskf("test", intentSender), is(true));
+ assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender),
+ is(true));
mRecoverySystemService.onPreparedForReboot(true);
verify(intentSender).sendIntent(any(), anyInt(), any(), any(), any());
- assertThat(mRecoverySystemService.clearLskf(), is(true));
+ assertThat(mRecoverySystemService.clearLskf(FAKE_OTA_PACKAGE_NAME), is(true));
+ verify(mLockSettingsInternal).clearRebootEscrow();
+ }
+
+ @Test
+ public void clearLskf_callerNotRequested_Success() throws Exception {
+ IntentSender intentSender = mock(IntentSender.class);
+ assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender),
+ is(true));
+ assertThat(mRecoverySystemService.clearLskf(FAKE_OTHER_PACKAGE_NAME), is(true));
+ verify(mLockSettingsInternal, never()).clearRebootEscrow();
+ }
+
+ @Test
+ public void clearLskf_multiClient_BothClientsClear() throws Exception {
+ IntentSender intentSender = mock(IntentSender.class);
+ assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, intentSender),
+ is(true));
+ assertThat(mRecoverySystemService.requestLskf(FAKE_OTHER_PACKAGE_NAME, intentSender),
+ is(true));
+
+ assertThat(mRecoverySystemService.clearLskf(FAKE_OTA_PACKAGE_NAME), is(true));
+ verify(mLockSettingsInternal, never()).clearRebootEscrow();
+ assertThat(mRecoverySystemService.clearLskf(FAKE_OTHER_PACKAGE_NAME), is(true));
verify(mLockSettingsInternal).clearRebootEscrow();
}
@@ -279,27 +318,84 @@
@Test(expected = SecurityException.class)
public void rebootWithLskf_protected() {
- doThrow(SecurityException.class).when(mContext).enforceCallingOrSelfPermission(
- eq(android.Manifest.permission.RECOVERY), any());
- mRecoverySystemService.rebootWithLskf("test1", null);
+ when(mContext.checkCallingOrSelfPermission(anyString())).thenReturn(
+ PackageManager.PERMISSION_DENIED);
+ mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, null, true);
}
@Test
public void rebootWithLskf_Success() throws Exception {
- assertThat(mRecoverySystemService.requestLskf("test", null), is(true));
+ assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null), is(true));
mRecoverySystemService.onPreparedForReboot(true);
- assertThat(mRecoverySystemService.rebootWithLskf("test", "ab-update"), is(true));
+ assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "ab-update", true),
+ is(true));
verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean());
}
@Test
public void rebootWithLskf_withoutPrepare_Failure() throws Exception {
- assertThat(mRecoverySystemService.rebootWithLskf("test1", null), is(false));
+ assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, null, true),
+ is(false));
}
@Test
- public void rebootWithLskf_withNullUpdateToken_Failure() throws Exception {
- assertThat(mRecoverySystemService.rebootWithLskf(null, null), is(false));
+ public void rebootWithLskf_withNullCallerId_Failure() throws Exception {
+ assertThat(mRecoverySystemService.rebootWithLskf(null, null, true), is(false));
verifyNoMoreInteractions(mIPowerManager);
}
+
+ @Test
+ public void rebootWithLskf_multiClient_ClientASuccess() throws Exception {
+ assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null), is(true));
+ assertThat(mRecoverySystemService.requestLskf(FAKE_OTHER_PACKAGE_NAME, null), is(true));
+ mRecoverySystemService.onPreparedForReboot(true);
+
+ // Client B's clear won't affect client A's preparation.
+ assertThat(mRecoverySystemService.clearLskf(FAKE_OTHER_PACKAGE_NAME), is(true));
+ assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, "ab-update", true),
+ is(true));
+ verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean());
+ }
+
+
+ @Test
+ public void rebootWithLskf_multiClient_ClientBSuccess() throws Exception {
+ assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null), is(true));
+ mRecoverySystemService.onPreparedForReboot(true);
+ assertThat(mRecoverySystemService.requestLskf(FAKE_OTHER_PACKAGE_NAME, null), is(true));
+
+ assertThat(mRecoverySystemService.clearLskf(FAKE_OTA_PACKAGE_NAME), is(true));
+ assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, null, true),
+ is(false));
+ verifyNoMoreInteractions(mIPowerManager);
+
+ assertThat(mRecoverySystemService.requestLskf(FAKE_OTHER_PACKAGE_NAME, null), is(true));
+ assertThat(
+ mRecoverySystemService.rebootWithLskf(FAKE_OTHER_PACKAGE_NAME, "ab-update", true),
+ is(true));
+ verify(mIPowerManager).reboot(anyBoolean(), eq("ab-update"), anyBoolean());
+ }
+
+ @Test
+ public void rebootWithLskf_multiClient_BothClientsClear_Failure() throws Exception {
+ assertThat(mRecoverySystemService.requestLskf(FAKE_OTA_PACKAGE_NAME, null), is(true));
+ mRecoverySystemService.onPreparedForReboot(true);
+ assertThat(mRecoverySystemService.requestLskf(FAKE_OTHER_PACKAGE_NAME, null), is(true));
+
+ // Client A clears
+ assertThat(mRecoverySystemService.clearLskf(FAKE_OTA_PACKAGE_NAME), is(true));
+ assertThat(mRecoverySystemService.rebootWithLskf(FAKE_OTA_PACKAGE_NAME, null, true),
+ is(false));
+ verifyNoMoreInteractions(mIPowerManager);
+
+ // Client B clears
+ assertThat(mRecoverySystemService.clearLskf(FAKE_OTHER_PACKAGE_NAME), is(true));
+ verify(mLockSettingsInternal).clearRebootEscrow();
+ assertThat(
+ mRecoverySystemService.rebootWithLskf(FAKE_OTHER_PACKAGE_NAME, "ab-update", true),
+ is(false));
+ verifyNoMoreInteractions(mIPowerManager);
+ }
+
+ // TODO(xunchang) add more multi client tests
}
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java b/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java
index fa8e367..ac93ff6 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/InputDeviceDelegateTest.java
@@ -44,6 +44,7 @@
import androidx.test.InstrumentationRegistry;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -89,6 +90,11 @@
mContextSpy, new Handler(mTestLooper.getLooper()));
}
+ @After
+ public void tearDown() throws Exception {
+ InputManager.clearInstance();
+ }
+
@Test
public void onInputDeviceAdded_withSettingsDisabled_ignoresNewDevice() throws Exception {
when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[0]);
@@ -286,6 +292,6 @@
private InputDevice createInputDevice(int id, boolean hasVibrator) {
return new InputDevice(id, 0, 0, "name", 0, 0, "description", false, 0, 0,
- null, hasVibrator, false, false);
+ null, hasVibrator, false, false, false /* hasSensor */);
}
}
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 f7c655f..a18bce7 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -111,9 +111,9 @@
import android.content.ComponentName;
import android.content.ContentUris;
import android.content.Context;
-import android.content.IIntentSender;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.IIntentSender;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
@@ -1501,6 +1501,20 @@
}
@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/src/com/android/server/wm/ActivityDisplayTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
index 466b861..801a27d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
@@ -248,7 +248,7 @@
int topPosition = taskDisplayArea.getRootTaskCount() - 1;
// Ensure the new alwaysOnTop stack is put below the pinned stack, but on top of the
// existing alwaysOnTop stack.
- assertEquals(topPosition - 1, taskDisplayArea.getIndexOf(anotherAlwaysOnTopStack));
+ assertEquals(topPosition - 1, taskDisplayArea.getTaskIndexOf(anotherAlwaysOnTopStack));
final Task nonAlwaysOnTopStack = taskDisplayArea.createRootTask(
WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, true /* onTop */);
@@ -256,7 +256,7 @@
topPosition = taskDisplayArea.getRootTaskCount() - 1;
// Ensure the non-alwaysOnTop stack is put below the three alwaysOnTop stacks, but above the
// existing other non-alwaysOnTop stacks.
- assertEquals(topPosition - 3, taskDisplayArea.getIndexOf(nonAlwaysOnTopStack));
+ assertEquals(topPosition - 3, taskDisplayArea.getTaskIndexOf(nonAlwaysOnTopStack));
anotherAlwaysOnTopStack.setAlwaysOnTop(false);
taskDisplayArea.positionChildAt(POSITION_TOP, anotherAlwaysOnTopStack,
@@ -264,16 +264,16 @@
assertFalse(anotherAlwaysOnTopStack.isAlwaysOnTop());
// Ensure, when always on top is turned off for a stack, the stack is put just below all
// other always on top stacks.
- assertEquals(topPosition - 2, taskDisplayArea.getIndexOf(anotherAlwaysOnTopStack));
+ assertEquals(topPosition - 2, taskDisplayArea.getTaskIndexOf(anotherAlwaysOnTopStack));
anotherAlwaysOnTopStack.setAlwaysOnTop(true);
// Ensure always on top state changes properly when windowing mode changes.
anotherAlwaysOnTopStack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
assertFalse(anotherAlwaysOnTopStack.isAlwaysOnTop());
- assertEquals(topPosition - 2, taskDisplayArea.getIndexOf(anotherAlwaysOnTopStack));
+ assertEquals(topPosition - 2, taskDisplayArea.getTaskIndexOf(anotherAlwaysOnTopStack));
anotherAlwaysOnTopStack.setWindowingMode(WINDOWING_MODE_FREEFORM);
assertTrue(anotherAlwaysOnTopStack.isAlwaysOnTop());
- assertEquals(topPosition - 1, taskDisplayArea.getIndexOf(anotherAlwaysOnTopStack));
+ assertEquals(topPosition - 1, taskDisplayArea.getTaskIndexOf(anotherAlwaysOnTopStack));
final Task dreamStack = taskDisplayArea.createRootTask(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_DREAM, true /* onTop */);
@@ -282,7 +282,7 @@
topPosition = taskDisplayArea.getRootTaskCount() - 1;
// Ensure dream shows above all activities, including PiP
assertEquals(dreamStack, taskDisplayArea.getTopRootTask());
- assertEquals(topPosition - 1, taskDisplayArea.getIndexOf(pinnedStack));
+ assertEquals(topPosition - 1, taskDisplayArea.getTaskIndexOf(pinnedStack));
final Task assistStack = taskDisplayArea.createRootTask(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_ASSISTANT, true /* onTop */);
@@ -295,7 +295,7 @@
final boolean isAssistantOnTop = mContext.getResources()
.getBoolean(com.android.internal.R.bool.config_assistantOnTopOfDream);
assertEquals(isAssistantOnTop ? topPosition : topPosition - 4,
- taskDisplayArea.getIndexOf(assistStack));
+ taskDisplayArea.getTaskIndexOf(assistStack));
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 78cebf3..95a1b61 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -75,7 +75,6 @@
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.never;
-import android.app.ActivityManager.TaskSnapshot;
import android.app.ActivityOptions;
import android.app.WindowConfiguration;
import android.app.servertransaction.ActivityConfigurationChangeItem;
@@ -102,6 +101,7 @@
import android.view.RemoteAnimationTarget;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
+import android.window.TaskSnapshot;
import androidx.test.filters.MediumTest;
@@ -1662,7 +1662,8 @@
any() /* requestedVisibility */, any() /* outFrame */,
any() /* outDisplayCutout */, any() /* outInputChannel */,
any() /* outInsetsState */, any() /* outActiveControls */);
- TaskSnapshotSurface.create(mAtm.mWindowManager, activity, snapshot);
+ mAtm.mWindowManager.mStartingSurfaceController
+ .createTaskSnapshotSurface(activity, snapshot);
} catch (RemoteException ignored) {
} finally {
reset(session);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index 5504460..8ea95ae 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -167,7 +167,7 @@
null /* task */);
// Assert that stack is at the bottom.
- assertEquals(0, mDefaultTaskDisplayArea.getIndexOf(primarySplitScreen));
+ assertEquals(0, mDefaultTaskDisplayArea.getTaskIndexOf(primarySplitScreen));
// Ensure no longer in splitscreen.
assertEquals(WINDOWING_MODE_FULLSCREEN, primarySplitScreen.getWindowingMode());
@@ -748,10 +748,10 @@
doReturn(false).when(fullscreenStack).isTranslucent(any());
// Ensure that we don't move the home stack if it is already behind the top fullscreen stack
- int homeStackIndex = mDefaultTaskDisplayArea.getIndexOf(homeStack);
+ int homeStackIndex = mDefaultTaskDisplayArea.getTaskIndexOf(homeStack);
assertEquals(fullscreenStack, getRootTaskAbove(homeStack));
mDefaultTaskDisplayArea.moveRootTaskBehindBottomMostVisibleRootTask(homeStack);
- assertEquals(homeStackIndex, mDefaultTaskDisplayArea.getIndexOf(homeStack));
+ assertEquals(homeStackIndex, mDefaultTaskDisplayArea.getTaskIndexOf(homeStack));
}
@Test
@@ -766,10 +766,10 @@
doReturn(true).when(fullscreenStack).isTranslucent(any());
// Ensure that we don't move the home stack if it is already behind the top fullscreen stack
- int homeStackIndex = mDefaultTaskDisplayArea.getIndexOf(homeStack);
+ int homeStackIndex = mDefaultTaskDisplayArea.getTaskIndexOf(homeStack);
assertEquals(fullscreenStack, getRootTaskAbove(homeStack));
mDefaultTaskDisplayArea.moveRootTaskBehindBottomMostVisibleRootTask(homeStack);
- assertEquals(homeStackIndex, mDefaultTaskDisplayArea.getIndexOf(homeStack));
+ assertEquals(homeStackIndex, mDefaultTaskDisplayArea.getTaskIndexOf(homeStack));
}
@Test
@@ -784,10 +784,10 @@
doReturn(false).when(fullscreenStack).isTranslucent(any());
// Ensure we don't move the home stack if it is already on top
- int homeStackIndex = mDefaultTaskDisplayArea.getIndexOf(homeStack);
+ int homeStackIndex = mDefaultTaskDisplayArea.getTaskIndexOf(homeStack);
assertNull(getRootTaskAbove(homeStack));
mDefaultTaskDisplayArea.moveRootTaskBehindBottomMostVisibleRootTask(homeStack);
- assertEquals(homeStackIndex, mDefaultTaskDisplayArea.getIndexOf(homeStack));
+ assertEquals(homeStackIndex, mDefaultTaskDisplayArea.getTaskIndexOf(homeStack));
}
@Test
@@ -853,9 +853,9 @@
doReturn(false).when(fullscreenStack2).isTranslucent(any());
// Ensure we don't move the home stack behind itself
- int homeStackIndex = mDefaultTaskDisplayArea.getIndexOf(homeStack);
+ int homeStackIndex = mDefaultTaskDisplayArea.getTaskIndexOf(homeStack);
mDefaultTaskDisplayArea.moveRootTaskBehindRootTask(homeStack, homeStack);
- assertEquals(homeStackIndex, mDefaultTaskDisplayArea.getIndexOf(homeStack));
+ assertEquals(homeStackIndex, mDefaultTaskDisplayArea.getTaskIndexOf(homeStack));
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index 5695412..cde866b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -422,7 +422,7 @@
// verify that values are passed to the modifier. Values are passed thrice -- two for
// setting initial state, another when task is created.
verify(modifier, times(3)).onCalculate(any(), eq(windowLayout), any(), any(), eq(options),
- anyInt(), any(), any(), any());
+ any(), anyInt(), any(), any());
}
/**
@@ -512,8 +512,8 @@
}
private void assertNoTasks(DisplayContent display) {
- display.forAllRootTasks(stack -> {
- assertFalse(stack.hasChild());
+ display.forAllRootTasks(rootTask -> {
+ assertFalse(rootTask.hasChild());
});
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
index d34e2c4..285d887 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -98,7 +98,7 @@
doReturn(mockLifecycleManager).when(mAtm).getLifecycleManager();
doReturn(true).when(activity).checkEnterPictureInPictureState(anyString(), anyBoolean());
- mAtm.requestPictureInPictureMode(activity.token);
+ mAtm.mActivityClientController.requestPictureInPictureMode(activity);
verify(mockLifecycleManager).scheduleTransaction(mClientTransactionCaptor.capture());
final ClientTransaction transaction = mClientTransactionCaptor.getValue();
@@ -117,7 +117,7 @@
doReturn(false).when(activity).inPinnedWindowingMode();
doReturn(false).when(activity).checkEnterPictureInPictureState(anyString(), anyBoolean());
- mAtm.requestPictureInPictureMode(activity.token);
+ mAtm.mActivityClientController.requestPictureInPictureMode(activity);
// Check enter no transactions with enter pip requests are made.
verify(lifecycleManager, times(0)).scheduleTransaction(any());
@@ -130,7 +130,7 @@
ClientLifecycleManager lifecycleManager = mAtm.getLifecycleManager();
doReturn(true).when(activity).inPinnedWindowingMode();
- mAtm.requestPictureInPictureMode(activity.token);
+ mAtm.mActivityClientController.requestPictureInPictureMode(activity);
// Check that no transactions with enter pip requests are made.
verify(lifecycleManager, times(0)).scheduleTransaction(any());
@@ -219,7 +219,7 @@
//mock other operations
doReturn(true).when(record)
.checkEnterPictureInPictureState("enterPictureInPictureMode", false);
- doReturn(false).when(mAtm).isInPictureInPictureMode(any());
+ doReturn(false).when(record).inPinnedWindowingMode();
doReturn(false).when(mAtm).isKeyguardLocked();
//to simulate NPE
diff --git a/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java b/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java
index f7beb74..3beb7f2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java
@@ -199,7 +199,7 @@
mHost.addChild(child, 0);
final float alpha = 0.8f;
- mDimmer.dimBelow(mTransaction, child, alpha);
+ mDimmer.dimBelow(mTransaction, child, alpha, 0);
SurfaceControl dimLayer = getDimLayer();
assertNotNull("Dimmer should have created a surface", dimLayer);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaOrganizerTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaOrganizerTest.java
index 1198ee2..5597be9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaOrganizerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaOrganizerTest.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.view.Display.DEFAULT_DISPLAY;
+import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER;
import static android.window.DisplayAreaOrganizer.FEATURE_ROOT;
import static android.window.DisplayAreaOrganizer.FEATURE_RUNTIME_TASK_CONTAINER_FIRST;
import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST;
@@ -117,7 +118,7 @@
}
@Test
- public void testCreateTaskDisplayArea() {
+ public void testCreateTaskDisplayArea_topBelowRoot() {
final String newTdaName = "testTda";
final IDisplayAreaOrganizer organizer = createMockOrganizer(new Binder());
final DisplayAreaAppearedInfo tdaInfo = mOrganizerController.createTaskDisplayArea(
@@ -142,6 +143,30 @@
}
@Test
+ public void testCreateTaskDisplayArea_topBelowAnotherTaskDisplayArea() {
+ final String newTdaName = "testTda";
+ final TaskDisplayArea parentTda = mDisplayContent.getDefaultTaskDisplayArea();
+ final IDisplayAreaOrganizer organizer = createMockOrganizer(new Binder());
+ final DisplayAreaAppearedInfo tdaInfo = mOrganizerController.createTaskDisplayArea(
+ organizer, DEFAULT_DISPLAY, FEATURE_DEFAULT_TASK_CONTAINER, newTdaName);
+
+ final WindowContainer wc = parentTda.getChildAt(parentTda.getChildCount() - 1);
+
+ // A new TaskDisplayArea is created on the top.
+ assertThat(wc).isInstanceOf(TaskDisplayArea.class);
+ assertThat(tdaInfo.getDisplayAreaInfo().displayId).isEqualTo(DEFAULT_DISPLAY);
+ assertThat(tdaInfo.getDisplayAreaInfo().token)
+ .isEqualTo(wc.mRemoteToken.toWindowContainerToken());
+
+ final TaskDisplayArea tda = wc.asTaskDisplayArea();
+
+ assertThat(tda.getName()).isEqualTo(newTdaName);
+ assertThat(tda.mFeatureId).isEqualTo(tdaInfo.getDisplayAreaInfo().featureId);
+ assertThat(tda.mCreatedByOrganizer).isTrue();
+ assertThat(tda.mOrganizer).isEqualTo(organizer);
+ }
+
+ @Test
public void testCreateTaskDisplayArea_incrementalTdaFeatureId() {
final String newTdaName = "testTda";
final IDisplayAreaOrganizer organizer = createMockOrganizer(new Binder());
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java
index 8e78dce..b33bb7b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java
@@ -22,6 +22,7 @@
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
@@ -40,7 +41,6 @@
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertThrows;
@@ -101,7 +101,6 @@
mRoot = new SurfacelessDisplayAreaRoot(mWms);
mImeContainer = new DisplayArea.Tokens(mWms, ABOVE_TASKS, "ImeContainer");
mDisplayContent = mock(DisplayContent.class);
- doReturn(true).when(mDisplayContent).isTrusted();
mDefaultTaskDisplayArea = new TaskDisplayArea(mDisplayContent, mWms, "Tasks",
FEATURE_DEFAULT_TASK_CONTAINER);
mTaskDisplayAreaList = new ArrayList<>();
@@ -669,6 +668,15 @@
assertThat(token2.isDescendantOf(mGroupRoot2)).isTrue();
}
+ @Test
+ public void testFeatureNotThrowArrayIndexOutOfBoundsException() {
+ final Feature feature1 = new Feature.Builder(mWms.mPolicy, "feature1",
+ FEATURE_VENDOR_FIRST + 5)
+ .all()
+ .except(TYPE_POINTER)
+ .build();
+ }
+
private static Resources resourcesWithProvider(String provider) {
Resources mock = mock(Resources.class);
when(mock.getString(
@@ -692,7 +700,7 @@
private Map<DisplayArea<?>, Set<Integer>> calculateZSets(
DisplayAreaPolicyBuilder.Result policy,
DisplayArea.Tokens ime,
- DisplayArea<Task> tasks) {
+ TaskDisplayArea taskDisplayArea) {
Map<DisplayArea<?>, Set<Integer>> zSets = new HashMap<>();
int[] types = {TYPE_STATUS_BAR, TYPE_NAVIGATION_BAR, TYPE_PRESENTATION,
TYPE_APPLICATION_OVERLAY};
@@ -700,7 +708,7 @@
WindowToken token = tokenOfType(type);
recordLayer(policy.findAreaForToken(token), token.getWindowLayerFromType(), zSets);
}
- recordLayer(tasks, APPLICATION_LAYER, zSets);
+ recordLayer(taskDisplayArea, APPLICATION_LAYER, zSets);
recordLayer(ime, mPolicy.getWindowLayerFromTypeLw(TYPE_INPUT_METHOD), zSets);
return zSets;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyTests.java
index d451180..496b2b7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyTests.java
@@ -22,18 +22,15 @@
import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.server.wm.DisplayArea.Type.ABOVE_TASKS;
import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import android.platform.test.annotations.Presubmit;
-import android.util.Pair;
-import android.view.Display;
-import android.view.DisplayInfo;
import androidx.test.filters.SmallTest;
@@ -41,8 +38,9 @@
import com.google.android.collect.Lists;
+import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
-import org.junit.runner.RunWith;
import java.util.ArrayList;
import java.util.Collections;
@@ -56,65 +54,78 @@
*/
@SmallTest
@Presubmit
-@RunWith(WindowTestRunner.class)
-public class DisplayAreaPolicyTests extends WindowTestsBase {
+public class DisplayAreaPolicyTests {
+
+ @Rule
+ public final SystemServicesTestRule mSystemServices = new SystemServicesTestRule();
+
+ private DisplayAreaPolicyBuilder.Result mPolicy;
+ private TaskDisplayArea mTaskDisplayArea1;
+ private TaskDisplayArea mTaskDisplayArea2;
+ private RootDisplayArea mRoot;
+
+ @Before
+ public void setUp() throws Exception {
+ WindowManagerService wms = mSystemServices.getWindowManagerService();
+ mRoot = new SurfacelessDisplayAreaRoot(wms);
+ spyOn(mRoot);
+ DisplayArea.Tokens ime = new DisplayArea.Tokens(wms, ABOVE_TASKS, "Ime");
+ DisplayContent displayContent = mock(DisplayContent.class);
+ doReturn(true).when(displayContent).isTrusted();
+ mTaskDisplayArea1 = new TaskDisplayArea(displayContent, wms, "Tasks1",
+ FEATURE_DEFAULT_TASK_CONTAINER);
+ mTaskDisplayArea2 = new TaskDisplayArea(displayContent, wms, "Tasks2",
+ FEATURE_VENDOR_FIRST);
+ List<TaskDisplayArea> taskDisplayAreaList = new ArrayList<>();
+ taskDisplayAreaList.add(mTaskDisplayArea1);
+ taskDisplayAreaList.add(mTaskDisplayArea2);
+
+ mPolicy = new DisplayAreaPolicyBuilder()
+ .setRootHierarchy(new DisplayAreaPolicyBuilder.HierarchyBuilder(mRoot)
+ .setImeContainer(ime)
+ .setTaskDisplayAreas(taskDisplayAreaList))
+ .build(wms);
+ }
@Test
public void testGetDefaultTaskDisplayArea() {
- final Pair<DisplayAreaPolicy, List<TaskDisplayArea>> result =
- createPolicyWith2TaskDisplayAreas();
- final DisplayAreaPolicy policy = result.first;
- final TaskDisplayArea taskDisplayArea1 = result.second.get(0);
- assertEquals(taskDisplayArea1, policy.getDefaultTaskDisplayArea());
+ assertEquals(mTaskDisplayArea1, mPolicy.getDefaultTaskDisplayArea());
}
@Test
public void testTaskDisplayArea_taskPositionChanged_updatesTaskDisplayAreaPosition() {
- final Pair<DisplayAreaPolicy, List<TaskDisplayArea>> result =
- createPolicyWith2TaskDisplayAreas();
- final DisplayAreaPolicy policy = result.first;
- final TaskDisplayArea taskDisplayArea1 = result.second.get(0);
- final TaskDisplayArea taskDisplayArea2 = result.second.get(1);
- final Task stack1 = taskDisplayArea1.createRootTask(
+ final Task stack1 = mTaskDisplayArea1.createRootTask(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- final Task stack2 = taskDisplayArea2.createRootTask(
+ final Task stack2 = mTaskDisplayArea2.createRootTask(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
// Initial order
- assertTaskDisplayAreasOrder(policy, taskDisplayArea1, taskDisplayArea2);
+ assertTaskDisplayAreasOrder(mPolicy, mTaskDisplayArea1, mTaskDisplayArea2);
// Move stack in tda1 to top
stack1.getParent().positionChildAt(POSITION_TOP, stack1, true /* includingParents */);
- assertTaskDisplayAreasOrder(policy, taskDisplayArea2, taskDisplayArea1);
+ assertTaskDisplayAreasOrder(mPolicy, mTaskDisplayArea2, mTaskDisplayArea1);
// Move stack in tda2 to top, but not including parents
stack2.getParent().positionChildAt(POSITION_TOP, stack2, false /* includingParents */);
- assertTaskDisplayAreasOrder(policy, taskDisplayArea2, taskDisplayArea1);
+ assertTaskDisplayAreasOrder(mPolicy, mTaskDisplayArea2, mTaskDisplayArea1);
// Move stack in tda1 to bottom
stack1.getParent().positionChildAt(POSITION_BOTTOM, stack1, true /* includingParents */);
- assertTaskDisplayAreasOrder(policy, taskDisplayArea1, taskDisplayArea2);
+ assertTaskDisplayAreasOrder(mPolicy, mTaskDisplayArea1, mTaskDisplayArea2);
// Move stack in tda2 to bottom, but not including parents
stack2.getParent().positionChildAt(POSITION_BOTTOM, stack2, false /* includingParents */);
- assertTaskDisplayAreasOrder(policy, taskDisplayArea1, taskDisplayArea2);
- }
-
- @Test
- public void testEmptyFeaturesOnUntrustedDisplay() {
- final DisplayInfo info = new DisplayInfo(mDisplayInfo);
- info.flags &= ~Display.FLAG_TRUSTED;
- final DisplayContent untrustedDisplay = new TestDisplayContent.Builder(mAtm, info).build();
- assertTrue(untrustedDisplay.mFeatures.isEmpty());
+ assertTaskDisplayAreasOrder(mPolicy, mTaskDisplayArea1, mTaskDisplayArea2);
}
@Test
public void testDisplayAreaGroup_taskPositionChanged_updatesDisplayAreaGroupPosition() {
- final WindowManagerService wms = mWm;
+ final WindowManagerService wms = mSystemServices.getWindowManagerService();
final DisplayContent displayContent = mock(DisplayContent.class);
doReturn(true).when(displayContent).isTrusted();
final RootDisplayArea root = new SurfacelessDisplayAreaRoot(wms);
@@ -192,24 +203,4 @@
}, false /* traverseTopToBottom */);
assertEquals(expectOrder, actualOrder);
}
-
- private Pair<DisplayAreaPolicy, List<TaskDisplayArea>> createPolicyWith2TaskDisplayAreas() {
- final SurfacelessDisplayAreaRoot root = new SurfacelessDisplayAreaRoot(mWm);
- final DisplayArea.Tokens ime = new DisplayArea.Tokens(mWm, ABOVE_TASKS, "Ime");
- final DisplayContent displayContent = mock(DisplayContent.class);
- doReturn(true).when(displayContent).isTrusted();
- final TaskDisplayArea taskDisplayArea1 = new TaskDisplayArea(displayContent, mWm, "Tasks1",
- FEATURE_DEFAULT_TASK_CONTAINER);
- final TaskDisplayArea taskDisplayArea2 = new TaskDisplayArea(displayContent, mWm, "Tasks2",
- FEATURE_VENDOR_FIRST);
- final List<TaskDisplayArea> taskDisplayAreaList = new ArrayList<>();
- taskDisplayAreaList.add(taskDisplayArea1);
- taskDisplayAreaList.add(taskDisplayArea2);
-
- return Pair.create(new DisplayAreaPolicyBuilder()
- .setRootHierarchy(new DisplayAreaPolicyBuilder.HierarchyBuilder(root)
- .setImeContainer(ime)
- .setTaskDisplayAreas(taskDisplayAreaList))
- .build(mWm), taskDisplayAreaList);
- }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java
index 7c4f7db..33e8fc0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java
@@ -312,8 +312,7 @@
private String getStoredDisplayAttributeValue(TestStorage storage, String attr)
throws Exception {
try (InputStream stream = storage.openRead()) {
- TypedXmlPullParser parser = Xml.newFastPullParser();
- parser.setInput(stream, StandardCharsets.UTF_8.name());
+ TypedXmlPullParser parser = Xml.resolvePullParser(stream);
int type;
while ((type = parser.next()) != XmlPullParser.START_TAG
&& type != XmlPullParser.END_DOCUMENT) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
index a99e40c..089fd20 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
@@ -95,10 +95,10 @@
final ActivityOptions options = mock(ActivityOptions.class);
final Request request = new Request();
- mController.calculate(record.getTask(), layout, record, source, options, PHASE_BOUNDS,
- new LaunchParams(), request);
+ mController.calculate(record.getTask(), layout, record, source, options, request,
+ PHASE_BOUNDS, new LaunchParams());
verify(positioner, times(1)).onCalculate(eq(record.getTask()), eq(layout), eq(record),
- eq(source), eq(options), anyInt(), any(), any(), eq(request));
+ eq(source), eq(options), eq(request), anyInt(), any(), any());
}
/**
@@ -121,9 +121,9 @@
mPersister.putLaunchParams(userId, name, expected);
mController.calculate(activity.getTask(), null /*layout*/, activity, null /*source*/,
- null /*options*/, PHASE_BOUNDS, new LaunchParams(), null /* request */);
- verify(positioner, times(1)).onCalculate(any(), any(), any(), any(), any(), anyInt(),
- eq(expected), any(), any());
+ null /*options*/, null /*request*/, PHASE_BOUNDS, new LaunchParams());
+ verify(positioner, times(1)).onCalculate(any(), any(), any(), any(), any(), any(),
+ anyInt(), eq(expected), any());
}
/**
@@ -141,10 +141,10 @@
mController.registerModifier(earlyExitPositioner);
mController.calculate(null /*task*/, null /*layout*/, null /*activity*/,
- null /*source*/, null /*options*/, PHASE_BOUNDS, new LaunchParams(),
- null /* request */);
- verify(ignoredPositioner, never()).onCalculate(any(), any(), any(), any(), any(), anyInt(),
- any(), any(), any());
+ null /*source*/, null /*options*/, null /*request*/,
+ PHASE_BOUNDS, new LaunchParams());
+ verify(ignoredPositioner, never()).onCalculate(any(), any(), any(), any(), any(), any(),
+ anyInt(), any(), any());
}
/**
@@ -160,22 +160,22 @@
mController.registerModifier(firstPositioner);
mController.calculate(null /*task*/, null /*layout*/, null /*activity*/,
- null /*source*/, null /*options*/, PHASE_BOUNDS, new LaunchParams(),
- null /* request */);
- verify(firstPositioner, times(1)).onCalculate(any(), any(), any(), any(), any(), anyInt(),
- any(), any(), any());
+ null /*source*/, null /*options*/, null /*request*/, PHASE_BOUNDS,
+ new LaunchParams());
+ verify(firstPositioner, times(1)).onCalculate(any(), any(), any(), any(), any(), any(),
+ anyInt(), any(), any());
final LaunchParamsModifier secondPositioner = spy(earlyExitPositioner);
mController.registerModifier(secondPositioner);
mController.calculate(null /*task*/, null /*layout*/, null /*activity*/,
- null /*source*/, null /*options*/, PHASE_BOUNDS, new LaunchParams(),
- null /* request */);
- verify(firstPositioner, times(1)).onCalculate(any(), any(), any(), any(), any(), anyInt(),
- any(), any(), any());
- verify(secondPositioner, times(1)).onCalculate(any(), any(), any(), any(), any(), anyInt(),
- any(), any(), any());
+ null /*source*/, null /*options*/, null /*request*/, PHASE_BOUNDS,
+ new LaunchParams());
+ verify(firstPositioner, times(1)).onCalculate(any(), any(), any(), any(), any(), any(),
+ anyInt(), any(), any());
+ verify(secondPositioner, times(1)).onCalculate(any(), any(), any(), any(), any(), any(),
+ anyInt(), any(), any());
}
/**
@@ -197,10 +197,10 @@
mController.registerModifier(positioner2);
mController.calculate(null /*task*/, null /*layout*/, null /*activity*/, null /*source*/,
- null /*options*/, PHASE_BOUNDS, new LaunchParams(), null /* request */);
+ null /*options*/, null /*request*/, PHASE_BOUNDS, new LaunchParams());
- verify(positioner1, times(1)).onCalculate(any(), any(), any(), any(), any(), anyInt(),
- eq(positioner2.getLaunchParams()), any(), any());
+ verify(positioner1, times(1)).onCalculate(any(), any(), any(), any(), any(), any(),
+ anyInt(), eq(positioner2.getLaunchParams()), any());
}
/**
@@ -223,7 +223,7 @@
final LaunchParams result = new LaunchParams();
mController.calculate(null /*task*/, null /*layout*/, null /*activity*/, null /*source*/,
- null /*options*/, PHASE_BOUNDS, result, null /* request */);
+ null /*options*/, null /*request*/, PHASE_BOUNDS, result);
assertEquals(result, positioner2.getLaunchParams());
}
@@ -242,17 +242,17 @@
// VR activities should always land on default display.
mController.calculate(null /*task*/, null /*layout*/, vrActivity /*activity*/,
- null /*source*/, null /*options*/, PHASE_BOUNDS, result, null /* request */);
+ null /*source*/, null /*options*/, null/*request*/, PHASE_BOUNDS, result);
assertEquals(mRootWindowContainer.getDefaultTaskDisplayArea(),
result.mPreferredTaskDisplayArea);
// Otherwise, always lands on VR 2D display.
final ActivityRecord vr2dActivity = new ActivityBuilder(mAtm).build();
mController.calculate(null /*task*/, null /*layout*/, vr2dActivity /*activity*/,
- null /*source*/, null /*options*/, PHASE_BOUNDS, result, null /* request */);
+ null /*source*/, null /*options*/, null /*request*/, PHASE_BOUNDS, result);
assertEquals(vrDisplay.getDefaultTaskDisplayArea(), result.mPreferredTaskDisplayArea);
mController.calculate(null /*task*/, null /*layout*/, null /*activity*/, null /*source*/,
- null /*options*/, PHASE_BOUNDS, result, null /* request */);
+ null /*options*/, null /*request*/, PHASE_BOUNDS, result);
assertEquals(vrDisplay.getDefaultTaskDisplayArea(), result.mPreferredTaskDisplayArea);
mAtm.mVr2dDisplayId = INVALID_DISPLAY;
@@ -273,10 +273,10 @@
final WindowLayout layout = new WindowLayout(0, 0, 0, 0, 0, 0, 0);
final ActivityOptions options = mock(ActivityOptions.class);
- mController.calculate(record.getTask(), layout, record, source, options, PHASE_BOUNDS,
- new LaunchParams(), null /* request */);
+ mController.calculate(record.getTask(), layout, record, source, options, null/*request*/,
+ PHASE_BOUNDS, new LaunchParams());
verify(positioner, times(1)).onCalculate(eq(record.getTask()), eq(layout), eq(record),
- eq(source), eq(options), eq(PHASE_BOUNDS), any(), any(), any());
+ eq(source), eq(options), any(), eq(PHASE_BOUNDS), any(), any());
}
/**
@@ -408,9 +408,8 @@
@Override
public int onCalculate(Task task, WindowLayout layout, ActivityRecord activity,
- ActivityRecord source, ActivityOptions options, int phase,
- LaunchParams currentParams, LaunchParams outParams,
- Request request) {
+ ActivityRecord source, ActivityOptions options, Request request, int phase,
+ LaunchParams currentParams, LaunchParams outParams) {
outParams.set(mParams);
return mReturnVal;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index ea57588..4dce451 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -49,7 +49,7 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.os.Binder;
diff --git a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
index ecbfac8..eff6919 100644
--- a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
+++ b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
@@ -136,6 +136,11 @@
}
@Override
+ public SurfaceControl.Transaction setBackgroundBlurRadius(SurfaceControl sc, int radius) {
+ return this;
+ }
+
+ @Override
public SurfaceControl.Transaction setLayerStack(SurfaceControl sc, int layerStack) {
return this;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
index 269ce5d..99bdf9f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
@@ -36,6 +36,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.server.wm.ActivityStarter.Request;
+import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_BOUNDS;
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE;
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP;
@@ -60,6 +61,7 @@
import androidx.test.filters.SmallTest;
import com.android.server.wm.LaunchParamsController.LaunchParams;
+import com.android.server.wm.LaunchParamsController.LaunchParamsModifier.Result;
import org.junit.Before;
import org.junit.Test;
@@ -108,8 +110,7 @@
@Test
public void testReturnsSkipWithEmptyActivity() {
final Task task = new TaskBuilder(mSupervisor).build();
- assertEquals(RESULT_SKIP, mTarget.onCalculate(task, /* layout */ null,
- /* activity */ null, /* source */ null, /* options */ null, mCurrent, mResult));
+ assertEquals(RESULT_SKIP, new CalculateRequestBuilder().setActivity(null).calculate());
}
// =============================
@@ -119,8 +120,7 @@
public void testDefaultToPrimaryDisplayArea() {
createNewDisplayContent(WINDOWING_MODE_FREEFORM);
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
assertEquals(mRootWindowContainer.getDefaultTaskDisplayArea(),
mResult.mPreferredTaskDisplayArea);
@@ -133,8 +133,7 @@
mCurrent.mPreferredTaskDisplayArea = display.getDefaultTaskDisplayArea();
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
assertEquals(display.getDefaultTaskDisplayArea(), mResult.mPreferredTaskDisplayArea);
}
@@ -150,8 +149,7 @@
ActivityRecord source = createSourceActivity(fullscreenDisplay);
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, source, /* options */ null, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setSource(source).calculate());
assertEquals(fullscreenDisplay.getDefaultTaskDisplayArea(),
mResult.mPreferredTaskDisplayArea);
@@ -170,8 +168,8 @@
ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchDisplayId(fullscreenDisplay.mDisplayId);
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, source, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setSource(source).setOptions(options).calculate());
assertEquals(fullscreenDisplay.getDefaultTaskDisplayArea(),
mResult.mPreferredTaskDisplayArea);
@@ -191,8 +189,8 @@
options.setLaunchTaskDisplayArea(fullscreenDisplay.getDefaultTaskDisplayArea()
.mRemoteToken.toWindowContainerToken());
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, source, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setSource(source).setOptions(options).calculate());
assertEquals(fullscreenDisplay.getDefaultTaskDisplayArea(),
mResult.mPreferredTaskDisplayArea);
@@ -209,8 +207,11 @@
ActivityRecord reusableActivity = createSourceActivity(fullscreenDisplay);
ActivityRecord source = createSourceActivity(freeformDisplay);
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(reusableActivity.getTask(),
- /* layout */ null, mActivity, source, /* options */ null, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder()
+ .setTask(reusableActivity.getTask())
+ .setSource(source)
+ .calculate());
assertEquals(fullscreenDisplay.getDefaultTaskDisplayArea(),
mResult.mPreferredTaskDisplayArea);
@@ -222,8 +223,10 @@
WINDOWING_MODE_FREEFORM);
ActivityRecord source = createSourceActivity(freeformDisplay);
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(source.getTask(), null /* layout */,
- null /* activity */, null /* source */, null /* options */, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder()
+ .setTask(source.getTask())
+ .calculate());
assertEquals(freeformDisplay.getDefaultTaskDisplayArea(),
mResult.mPreferredTaskDisplayArea);
@@ -242,8 +245,11 @@
source.mHandoverLaunchDisplayId = freeformDisplay.mDisplayId;
source.noDisplay = true;
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(reusableActivity.getTask(),
- null /* layout */, mActivity, source, null /* options */, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder()
+ .setTask(reusableActivity.getTask())
+ .setSource(source)
+ .calculate());
assertEquals(freeformDisplay.getDefaultTaskDisplayArea(),
mResult.mPreferredTaskDisplayArea);
@@ -262,8 +268,11 @@
source.mHandoverTaskDisplayArea = freeformDisplay.getDefaultTaskDisplayArea();
source.noDisplay = true;
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(reusableActivity.getTask(),
- null /* layout */, mActivity, source, null /* options */, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder()
+ .setTask(reusableActivity.getTask())
+ .setSource(source)
+ .calculate());
assertEquals(freeformDisplay.getDefaultTaskDisplayArea(),
mResult.mPreferredTaskDisplayArea);
@@ -273,7 +282,6 @@
public void testUsesDisplayAreaFromTopMostActivityInApplicationIfAvailable() {
final String processName = "processName";
final int uid = 124214;
- final TestDisplayContent firstScreen = createNewDisplayContent(WINDOWING_MODE_FULLSCREEN);
final TestDisplayContent secondScreen = createNewDisplayContent(WINDOWING_MODE_FULLSCREEN);
final TaskDisplayArea expectedDisplayArea = secondScreen.getDefaultTaskDisplayArea();
final WindowProcessController controller = mock(WindowProcessController.class);
@@ -286,17 +294,7 @@
.when(mSupervisor.mService)
.getProcessController(processName, uid);
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(
- null /* task */,
- null /* layout */,
- mActivity /* activity */,
- null /* source */,
- null /* options */,
- -1 /* phase */,
- mCurrent,
- mResult,
- null /* request */
- ));
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
assertEquals(expectedDisplayArea, mResult.mPreferredTaskDisplayArea);
}
@@ -305,7 +303,6 @@
public void testUsesDisplayAreaFromLaunchingActivityIfApplicationLaunching() {
final String processName = "processName";
final int uid = 124214;
- final TestDisplayContent firstScreen = createNewDisplayContent(WINDOWING_MODE_FULLSCREEN);
final TestDisplayContent secondScreen = createNewDisplayContent(WINDOWING_MODE_FULLSCREEN);
final TaskDisplayArea expectedTaskDisplayArea = secondScreen.getDefaultTaskDisplayArea();
final WindowProcessController controller = mock(WindowProcessController.class);
@@ -322,17 +319,7 @@
.when(mSupervisor.mService)
.getProcessController(mActivity.launchedFromPid, mActivity.launchedFromUid);
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(
- null /* task */,
- null /* layout */,
- mActivity /* activity */,
- null /* source */,
- null /* options */,
- -1 /* phase */,
- mCurrent,
- mResult,
- null /* request */
- ));
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
assertEquals(expectedTaskDisplayArea, mResult.mPreferredTaskDisplayArea);
}
@@ -363,17 +350,7 @@
.when(mSupervisor.mService)
.getProcessController(mActivity.launchedFromPid, mActivity.launchedFromUid);
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(
- null /* task */,
- null /* layout */,
- mActivity /* activity */,
- null /* source */,
- null /* options */,
- -1 /* phase */,
- mCurrent,
- mResult,
- null /* request */
- ));
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
assertEquals(expectedTaskDisplayArea, mResult.mPreferredTaskDisplayArea);
}
@@ -403,17 +380,8 @@
.when(mSupervisor.mService)
.getProcessController(request.realCallingPid, request.realCallingUid);
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(
- null /* task */,
- null /* layout */,
- mActivity /* activity */,
- null /* source */,
- null /* options */,
- -1 /* phase */,
- mCurrent,
- mResult,
- request
- ));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setRequest(request).calculate());
assertEquals(expectedTaskDisplayArea, mResult.mPreferredTaskDisplayArea);
}
@@ -428,17 +396,7 @@
.when(mSupervisor.mService)
.getProcessController(mActivity.launchedFromPid, mActivity.launchedFromUid);
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(
- null /* task */,
- null /* layout */,
- mActivity /* activity */,
- null /* source */,
- null /* options */,
- -1 /* phase */,
- mCurrent,
- mResult,
- null /* request */
- ));
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
assertEquals(DEFAULT_DISPLAY, mResult.mPreferredTaskDisplayArea.getDisplayId());
}
@@ -456,8 +414,8 @@
mCurrent.mPreferredTaskDisplayArea = freeformDisplay.getDefaultTaskDisplayArea();
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setOptions(options).calculate());
assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
WINDOWING_MODE_FREEFORM);
@@ -470,8 +428,8 @@
mCurrent.mPreferredTaskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setOptions(options).calculate());
assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
WINDOWING_MODE_FULLSCREEN);
@@ -484,8 +442,8 @@
final ActivityRecord source = createSourceActivity(fullscreenDisplay);
source.setWindowingMode(WINDOWING_MODE_FREEFORM);
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, source, /* options */ null, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setSource(source).calculate());
assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
WINDOWING_MODE_FULLSCREEN);
@@ -501,8 +459,8 @@
mCurrent.mPreferredTaskDisplayArea = freeformDisplay.getDefaultTaskDisplayArea();
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setOptions(options).calculate());
assertEquivalentWindowingMode(WINDOWING_MODE_PINNED, mResult.mWindowingMode,
WINDOWING_MODE_FREEFORM);
@@ -519,8 +477,8 @@
mCurrent.mPreferredTaskDisplayArea = freeformDisplay.getDefaultTaskDisplayArea();
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setOptions(options).calculate());
assertEquivalentWindowingMode(WINDOWING_MODE_PINNED, mResult.mWindowingMode,
WINDOWING_MODE_FREEFORM);
@@ -533,8 +491,8 @@
mCurrent.mPreferredTaskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setOptions(options).calculate());
assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
WINDOWING_MODE_FULLSCREEN);
@@ -550,8 +508,8 @@
final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
.setWidth(120).setHeight(80).build();
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
- /* source */ null, /* options */ null, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setLayout(layout).calculate());
assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
WINDOWING_MODE_FREEFORM);
@@ -567,8 +525,8 @@
final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
.setGravity(Gravity.LEFT).build();
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
- /* source */ null, /* options */ null, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setLayout(layout).calculate());
assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
WINDOWING_MODE_FREEFORM);
@@ -581,8 +539,8 @@
mCurrent.mPreferredTaskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
- /* source */ null, /* options */ null, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setLayout(layout).calculate());
assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
WINDOWING_MODE_FULLSCREEN);
@@ -594,8 +552,7 @@
mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
mCurrent.mBounds.set(0, 0, 200, 100);
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
WINDOWING_MODE_FULLSCREEN);
@@ -609,8 +566,7 @@
mCurrent.mPreferredTaskDisplayArea = freeformDisplay.getDefaultTaskDisplayArea();
mCurrent.mWindowingMode = WINDOWING_MODE_FULLSCREEN;
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
WINDOWING_MODE_FREEFORM);
@@ -625,8 +581,7 @@
mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
mCurrent.mBounds.set(0, 0, 200, 100);
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
WINDOWING_MODE_FREEFORM);
@@ -648,8 +603,8 @@
mActivity.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setOptions(options).calculate());
assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
WINDOWING_MODE_FREEFORM);
@@ -673,8 +628,8 @@
mActivity.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setOptions(options).calculate());
assertEquals(expectedLaunchBounds, mResult.mBounds);
@@ -694,8 +649,8 @@
mActivity.info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setOptions(options).calculate());
assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
WINDOWING_MODE_FULLSCREEN);
@@ -706,8 +661,8 @@
final ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchDisplayId(DEFAULT_DISPLAY);
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setOptions(options).calculate());
assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
WINDOWING_MODE_FULLSCREEN);
@@ -722,8 +677,8 @@
options.setLaunchDisplayId(freeformDisplay.mDisplayId);
options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setOptions(options).calculate());
assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
WINDOWING_MODE_FREEFORM);
@@ -737,8 +692,8 @@
final ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchDisplayId(freeformDisplay.mDisplayId);
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setOptions(options).calculate());
assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
WINDOWING_MODE_FREEFORM);
@@ -754,8 +709,8 @@
mActivity.info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setOptions(options).calculate());
assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode,
WINDOWING_MODE_FREEFORM);
@@ -768,8 +723,8 @@
mActivity.info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setOptions(options).calculate());
assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode,
WINDOWING_MODE_FULLSCREEN);
@@ -791,8 +746,8 @@
mCurrent.mPreferredTaskDisplayArea = freeformDisplay.getDefaultTaskDisplayArea();
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setOptions(options).calculate());
assertEquals(expected, mResult.mBounds);
}
@@ -808,8 +763,8 @@
final Rect expected = new Rect(0, 0, 150, 150);
options.setLaunchBounds(expected);
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, source, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setSource(source).setOptions(options).calculate());
assertEquals(expected, mResult.mBounds);
}
@@ -824,8 +779,8 @@
final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
.setGravity(Gravity.LEFT).build();
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
- /* source */ null, /* options */ null, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setLayout(layout).calculate());
assertEquals(DISPLAY_STABLE_BOUNDS.left, mResult.mBounds.left);
}
@@ -840,8 +795,8 @@
final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
.setGravity(Gravity.TOP).build();
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
- /* source */ null, /* options */ null, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setLayout(layout).calculate());
assertEquals(DISPLAY_STABLE_BOUNDS.top, mResult.mBounds.top);
}
@@ -856,8 +811,8 @@
final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
.setGravity(Gravity.TOP | Gravity.LEFT).build();
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
- /* source */ null, /* options */ null, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setLayout(layout).calculate());
assertEquals(DISPLAY_STABLE_BOUNDS.left, mResult.mBounds.left);
assertEquals(DISPLAY_STABLE_BOUNDS.top, mResult.mBounds.top);
@@ -873,8 +828,8 @@
final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
.setGravity(Gravity.RIGHT).build();
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
- /* source */ null, /* options */ null, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setLayout(layout).calculate());
assertEquals(DISPLAY_STABLE_BOUNDS.right, mResult.mBounds.right);
}
@@ -889,8 +844,8 @@
final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
.setGravity(Gravity.BOTTOM).build();
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
- /* source */ null, /* options */ null, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setLayout(layout).calculate());
assertEquals(DISPLAY_STABLE_BOUNDS.bottom, mResult.mBounds.bottom);
}
@@ -905,8 +860,8 @@
final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
.setGravity(Gravity.BOTTOM | Gravity.RIGHT).build();
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
- /* source */ null, /* options */ null, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setLayout(layout).calculate());
assertEquals(DISPLAY_STABLE_BOUNDS.right, mResult.mBounds.right);
assertEquals(DISPLAY_STABLE_BOUNDS.bottom, mResult.mBounds.bottom);
@@ -922,8 +877,8 @@
final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
.setWidth(120).setHeight(80).build();
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
- /* source */ null, /* options */ null, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setLayout(layout).calculate());
assertEquals(new Rect(800, 400, 920, 480), mResult.mBounds);
}
@@ -938,8 +893,8 @@
final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
.setWidth(120).setHeight(80).setGravity(Gravity.LEFT).build();
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
- /* source */ null, /* options */ null, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setLayout(layout).calculate());
assertEquals(new Rect(100, 400, 220, 480), mResult.mBounds);
}
@@ -954,8 +909,8 @@
final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
.setWidth(120).setHeight(80).setGravity(Gravity.TOP).build();
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
- /* source */ null, /* options */ null, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setLayout(layout).calculate());
assertEquals(new Rect(800, 200, 920, 280), mResult.mBounds);
}
@@ -970,8 +925,8 @@
final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
.setWidth(120).setHeight(80).setGravity(Gravity.TOP | Gravity.LEFT).build();
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
- /* source */ null, /* options */ null, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setLayout(layout).calculate());
assertEquals(new Rect(100, 200, 220, 280), mResult.mBounds);
}
@@ -986,8 +941,8 @@
final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
.setWidth(120).setHeight(80).setGravity(Gravity.RIGHT).build();
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
- /* source */ null, /* options */ null, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setLayout(layout).calculate());
assertEquals(new Rect(1500, 400, 1620, 480), mResult.mBounds);
}
@@ -1002,8 +957,8 @@
final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
.setWidth(120).setHeight(80).setGravity(Gravity.BOTTOM).build();
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
- /* source */ null, /* options */ null, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setLayout(layout).calculate());
assertEquals(new Rect(800, 600, 920, 680), mResult.mBounds);
}
@@ -1018,8 +973,8 @@
final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
.setWidth(120).setHeight(80).setGravity(Gravity.BOTTOM | Gravity.RIGHT).build();
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
- /* source */ null, /* options */ null, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setLayout(layout).calculate());
assertEquals(new Rect(1500, 600, 1620, 680), mResult.mBounds);
}
@@ -1034,8 +989,8 @@
final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder()
.setWidthFraction(0.125f).setHeightFraction(0.1f).build();
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
- /* source */ null, /* options */ null, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setLayout(layout).calculate());
assertEquals(new Rect(765, 416, 955, 464), mResult.mBounds);
}
@@ -1049,8 +1004,7 @@
mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
mCurrent.mBounds.set(0, 0, 200, 100);
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
assertEquals(new Rect(0, 0, 200, 100), mResult.mBounds);
}
@@ -1064,8 +1018,7 @@
mCurrent.mWindowingMode = WINDOWING_MODE_FULLSCREEN;
mCurrent.mBounds.set(0, 0, 200, 100);
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
assertEquals(new Rect(0, 0, 200, 100), mResult.mBounds);
}
@@ -1081,8 +1034,8 @@
mActivity.info.screenOrientation = SCREEN_ORIENTATION_NOSENSOR;
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setOptions(options).calculate());
final int orientationForDisplay = orientationFromBounds(freeformDisplay.getBounds());
final int orientationForTask = orientationFromBounds(mResult.mBounds);
@@ -1105,8 +1058,8 @@
mActivity.info.screenOrientation = SCREEN_ORIENTATION_LANDSCAPE;
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setOptions(options).calculate());
assertEquals(SCREEN_ORIENTATION_LANDSCAPE, orientationFromBounds(mResult.mBounds));
}
@@ -1122,8 +1075,8 @@
mActivity.info.screenOrientation = SCREEN_ORIENTATION_PORTRAIT;
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setOptions(options).calculate());
assertEquals(SCREEN_ORIENTATION_PORTRAIT, orientationFromBounds(mResult.mBounds));
}
@@ -1138,8 +1091,8 @@
mActivity.info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setOptions(options).calculate());
final int resultWidth = mResult.mBounds.width();
final int displayWidth = freeformDisplay.getBounds().width();
@@ -1162,8 +1115,8 @@
mActivity.info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setOptions(options).calculate());
assertEquals("Distance to left and right should be equal.",
mResult.mBounds.left - DISPLAY_STABLE_BOUNDS.left,
@@ -1186,8 +1139,8 @@
mActivity.info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, source, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setSource(source).setOptions(options).calculate());
final Rect displayBounds = freeformDisplay.getBounds();
assertTrue("Left bounds should be larger than 0.", mResult.mBounds.left > 0);
@@ -1213,8 +1166,8 @@
mActivity.info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, source, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setSource(source).setOptions(options).calculate());
final Rect displayBounds = freeformDisplay.getBounds();
assertTrue("display bounds doesn't contain result. display bounds: "
@@ -1235,8 +1188,8 @@
mActivity.info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, source, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setSource(source).setOptions(options).calculate());
final Rect displayBounds = freeformDisplay.getBounds();
assertTrue("display bounds doesn't contain result. display bounds: "
@@ -1257,8 +1210,8 @@
mActivity.info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setOptions(options).calculate());
assertTrue("Result bounds should start from app bounds's origin, but it's "
+ mResult.mBounds,
@@ -1284,8 +1237,8 @@
mActivity.info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setOptions(options).calculate());
assertTrue("Result bounds should start from top-right corner of app bounds, but "
+ "it's " + mResult.mBounds,
@@ -1311,8 +1264,8 @@
mActivity.info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP;
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, layout, mActivity,
- /* source */ null, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setLayout(layout).setOptions(options).calculate());
assertEquals(500, mResult.mBounds.width());
assertEquals(800, mResult.mBounds.height());
@@ -1329,8 +1282,8 @@
mActivity.info.screenOrientation = SCREEN_ORIENTATION_PORTRAIT;
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setOptions(options).calculate());
assertEquals(new Rect(200, 0, 400, 400), mResult.mBounds);
}
@@ -1346,8 +1299,8 @@
options.setLaunchDisplayId(freeformDisplay.mDisplayId);
options.setLaunchBounds(new Rect(50, 50, 500, 300));
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setOptions(options).calculate());
assertEquals(new Rect(170, 50, 620, 300), mResult.mBounds);
}
@@ -1363,8 +1316,8 @@
options.setLaunchDisplayId(freeformDisplay.mDisplayId);
options.setLaunchBounds(new Rect(1720, 50, 1850, 300));
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setOptions(options).calculate());
assertEquals(new Rect(1600, 50, 1730, 300), mResult.mBounds);
}
@@ -1380,8 +1333,8 @@
options.setLaunchDisplayId(freeformDisplay.mDisplayId);
options.setLaunchBounds(new Rect(0, 0, 1800, 200));
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setOptions(options).calculate());
assertEquals(new Rect(120, 0, 1920, 200), mResult.mBounds);
}
@@ -1397,8 +1350,8 @@
options.setLaunchDisplayId(freeformDisplay.mDisplayId);
options.setLaunchBounds(new Rect(120, 0, 1860, 200));
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setOptions(options).calculate());
assertEquals(new Rect(0, 0, 1740, 200), mResult.mBounds);
}
@@ -1414,8 +1367,8 @@
options.setLaunchDisplayId(freeformDisplay.mDisplayId);
options.setLaunchBounds(new Rect(120, 0, 1800, 1013));
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setOptions(options).calculate());
assertEquals(new Rect(240, 67, 1920, 1080), mResult.mBounds);
}
@@ -1431,8 +1384,8 @@
options.setLaunchDisplayId(freeformDisplay.mDisplayId);
options.setLaunchBounds(new Rect(120, 67, 1800, 1020));
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setOptions(options).calculate());
assertEquals(new Rect(0, 0, 1680, 953), mResult.mBounds);
}
@@ -1443,8 +1396,7 @@
mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
mCurrent.mBounds.set(0, 0, 200, 100);
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
// Returned bounds with in fullscreen mode will be set to last non-fullscreen bounds.
assertEquals(new Rect(0, 0, 200, 100), mResult.mBounds);
@@ -1462,8 +1414,8 @@
final ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchDisplayId(freeformDisplay.mDisplayId);
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, options, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE,
+ new CalculateRequestBuilder().setOptions(options).calculate());
assertEquals(new Rect(100, 200, 400, 500), mResult.mBounds);
}
@@ -1479,8 +1431,7 @@
mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM;
mCurrent.mBounds.set(0, 0, 200, 100);
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
assertEquals(new Rect(120, 0, 320, 100), mResult.mBounds);
}
@@ -1510,8 +1461,7 @@
try {
mAtm.mSupportsMultiDisplay = false;
- assertEquals(RESULT_CONTINUE, mTarget.onCalculate(/* task */ null, /* layout */ null,
- mActivity, /* source */ null, /* options */ null, mCurrent, mResult));
+ assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().calculate());
assertEquals(mRootWindowContainer.getDefaultTaskDisplayArea(),
mResult.mPreferredTaskDisplayArea);
} finally {
@@ -1592,6 +1542,53 @@
: SCREEN_ORIENTATION_PORTRAIT;
}
+ private class CalculateRequestBuilder {
+ private Task mTask;
+ private ActivityInfo.WindowLayout mLayout;
+ private ActivityRecord mActivity = TaskLaunchParamsModifierTests.this.mActivity;
+ private ActivityRecord mSource;
+ private ActivityOptions mOptions;
+ private Request mRequest;
+ private int mPhase = PHASE_BOUNDS;
+ private LaunchParams mCurrentParams = mCurrent;
+ private LaunchParams mOutParams = mResult;
+
+ private CalculateRequestBuilder setTask(Task task) {
+ mTask = task;
+ return this;
+ }
+
+ private CalculateRequestBuilder setLayout(ActivityInfo.WindowLayout layout) {
+ mLayout = layout;
+ return this;
+ }
+
+ private CalculateRequestBuilder setActivity(ActivityRecord activity) {
+ mActivity = activity;
+ return this;
+ }
+
+ private CalculateRequestBuilder setSource(ActivityRecord source) {
+ mSource = source;
+ return this;
+ }
+
+ private CalculateRequestBuilder setOptions(ActivityOptions options) {
+ mOptions = options;
+ return this;
+ }
+
+ private CalculateRequestBuilder setRequest(Request request) {
+ mRequest = request;
+ return this;
+ }
+
+ private @Result int calculate() {
+ return mTarget.onCalculate(mTask, mLayout, mActivity, mSource, mOptions, mRequest,
+ mPhase, mCurrentParams, mOutParams);
+ }
+ }
+
private static class WindowLayoutBuilder {
private int mWidth = -1;
private int mHeight = -1;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java
index f9f161a..98dee38 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotCacheTest.java
@@ -23,7 +23,7 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
index ec65085..4d37eb2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotControllerTest.java
@@ -33,7 +33,6 @@
import static org.junit.Assert.fail;
import static org.mockito.Mockito.when;
-import android.app.ActivityManager;
import android.app.WindowConfiguration;
import android.content.ComponentName;
import android.content.res.Configuration;
@@ -44,6 +43,7 @@
import android.hardware.HardwareBuffer;
import android.platform.test.annotations.Presubmit;
import android.util.ArraySet;
+import android.window.TaskSnapshot;
import androidx.test.filters.SmallTest;
@@ -145,8 +145,8 @@
final Point taskSize = new Point(5, 6);
try {
- ActivityManager.TaskSnapshot.Builder builder =
- new ActivityManager.TaskSnapshot.Builder();
+ TaskSnapshot.Builder builder =
+ new TaskSnapshot.Builder();
builder.setId(id);
builder.setTopActivityComponent(activityComponent);
builder.setAppearance(appearance);
@@ -163,7 +163,7 @@
// Not part of TaskSnapshot itself, used in screenshot process
assertEquals(pixelFormat, builder.getPixelFormat());
- ActivityManager.TaskSnapshot snapshot = builder.build();
+ TaskSnapshot snapshot = builder.build();
assertEquals(id, snapshot.getId());
assertEquals(activityComponent, snapshot.getTopActivityComponent());
assertEquals(appearance, snapshot.getAppearance());
@@ -211,8 +211,8 @@
doReturn(true).when(mAppWindow.mWinAnimator).getShown();
doReturn(true).when(mAppWindow.mActivityRecord).isSurfaceShowing();
- final ActivityManager.TaskSnapshot.Builder builder =
- new ActivityManager.TaskSnapshot.Builder();
+ final TaskSnapshot.Builder builder =
+ new TaskSnapshot.Builder();
boolean success = mWm.mTaskSnapshotController.prepareTaskSnapshot(
mAppWindow.mActivityRecord.getTask(), PixelFormat.UNKNOWN, builder);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotLowResDisabledTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotLowResDisabledTest.java
index 8f913dd..ec0ca01 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotLowResDisabledTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotLowResDisabledTest.java
@@ -22,7 +22,7 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
index 8b90824..70d71bc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterLoaderTest.java
@@ -31,7 +31,7 @@
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.SystemClock;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
index fcd46a3..d9a794a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
@@ -28,7 +28,7 @@
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
import android.content.ComponentName;
import android.content.ContextWrapper;
import android.content.res.Resources;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
index 5ea73b8..aa638690 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
@@ -36,9 +36,8 @@
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
-import android.app.ActivityManager;
import android.app.ActivityManager.TaskDescription;
-import android.app.ActivityManager.TaskSnapshot;
+import android.window.TaskSnapshot;
import android.content.ComponentName;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -93,8 +92,8 @@
ACTIVITY_TYPE_STANDARD, new InsetsState());
}
- private ActivityManager.TaskSnapshot createTaskSnapshot(int width, int height, Point taskSize,
- Rect contentInsets) {
+ private TaskSnapshot createTaskSnapshot(int width, int height,
+ Point taskSize, Rect contentInsets) {
final HardwareBuffer buffer = HardwareBuffer.create(width, height, HardwareBuffer.RGBA_8888,
1, HardwareBuffer.USAGE_CPU_READ_RARELY);
return new TaskSnapshot(
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
index b78d6bb..001afe3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
@@ -116,10 +116,6 @@
}
@Override
- public void dispatchPointerCaptureChanged(boolean hasCapture) {
- }
-
- @Override
public void requestScrollCapture(IScrollCaptureCallbacks callbacks) throws RemoteException {
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
index 3c82685..b7101c8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -74,6 +74,7 @@
import android.view.SurfaceControl;
import android.window.ITaskOrganizer;
import android.window.IWindowContainerTransactionCallback;
+import android.window.StartingWindowInfo;
import android.window.TaskAppearedInfo;
import android.window.WindowContainerTransaction;
@@ -506,12 +507,12 @@
public void testTileAddRemoveChild() {
ITaskOrganizer listener = new ITaskOrganizer.Stub() {
@Override
- public void addStartingWindow(ActivityManager.RunningTaskInfo info, IBinder appToken) {
+ public void addStartingWindow(StartingWindowInfo info, IBinder appToken) {
}
@Override
- public void removeStartingWindow(ActivityManager.RunningTaskInfo info) { }
+ public void removeStartingWindow(int taskId) { }
@Override
public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) { }
@@ -571,12 +572,12 @@
final boolean[] called = {false};
ITaskOrganizer listener = new ITaskOrganizer.Stub() {
@Override
- public void addStartingWindow(ActivityManager.RunningTaskInfo info, IBinder appToken) {
+ public void addStartingWindow(StartingWindowInfo info, IBinder appToken) {
}
@Override
- public void removeStartingWindow(ActivityManager.RunningTaskInfo info) { }
+ public void removeStartingWindow(int taskId) { }
@Override
public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) { }
@@ -642,12 +643,12 @@
final ArrayMap<IBinder, RunningTaskInfo> lastReportedTiles = new ArrayMap<>();
ITaskOrganizer listener = new ITaskOrganizer.Stub() {
@Override
- public void addStartingWindow(ActivityManager.RunningTaskInfo info, IBinder appToken) {
+ public void addStartingWindow(StartingWindowInfo info, IBinder appToken) {
}
@Override
- public void removeStartingWindow(ActivityManager.RunningTaskInfo info) { }
+ public void removeStartingWindow(int taskId) { }
@Override
public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) { }
@@ -786,9 +787,9 @@
RunningTaskInfo mInfo;
@Override
- public void addStartingWindow(ActivityManager.RunningTaskInfo info, IBinder appToken) { }
+ public void addStartingWindow(StartingWindowInfo info, IBinder appToken) { }
@Override
- public void removeStartingWindow(ActivityManager.RunningTaskInfo info) { }
+ public void removeStartingWindow(int taskId) { }
@Override
public void onTaskAppeared(RunningTaskInfo info, SurfaceControl leash) {
mInfo = info;
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index e13a595..0d31d38 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -84,6 +84,7 @@
import android.view.WindowManager;
import android.view.WindowManager.DisplayImePolicy;
import android.window.ITaskOrganizer;
+import android.window.StartingWindowInfo;
import com.android.internal.util.ArrayUtils;
import com.android.server.AttributeCache;
@@ -1090,10 +1091,10 @@
mMoveToSecondaryOnEnter = move;
}
@Override
- public void addStartingWindow(ActivityManager.RunningTaskInfo info, IBinder appToken) {
+ public void addStartingWindow(StartingWindowInfo info, IBinder appToken) {
}
@Override
- public void removeStartingWindow(ActivityManager.RunningTaskInfo info) {
+ public void removeStartingWindow(int taskId) {
}
@Override
public void onTaskAppeared(ActivityManager.RunningTaskInfo info, SurfaceControl leash) {
@@ -1121,9 +1122,9 @@
mService.mTaskOrganizerController.setLaunchRoot(mDisplayId,
mSecondary.mRemoteToken.toWindowContainerToken());
DisplayContent dc = mService.mRootWindowContainer.getDisplayContent(mDisplayId);
- dc.forAllRootTasks(stack -> {
- if (!WindowConfiguration.isSplitScreenWindowingMode(stack.getWindowingMode())) {
- stack.reparent(mSecondary, POSITION_BOTTOM);
+ dc.forAllRootTasks(rootTask -> {
+ if (!WindowConfiguration.isSplitScreenWindowingMode(rootTask.getWindowingMode())) {
+ rootTask.reparent(mSecondary, POSITION_BOTTOM);
}
});
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index b5bb2a8..ec371bf 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -420,8 +420,9 @@
+ interactorInfo + ")");
}
- // Initializing settings, look for an interactor first (but only on non-svelte).
- if (curInteractorInfo == null && mEnableService) {
+ // Initializing settings. Look for an interactor first, but only on non-svelte and only
+ // if the user hasn't explicitly unset it.
+ if (curInteractorInfo == null && mEnableService && !"".equals(curInteractorStr)) {
curInteractorInfo = findAvailInteractor(userHandle, null);
}
@@ -1751,8 +1752,13 @@
if (isPackageAppearing(pkgName) != PACKAGE_UNCHANGED) {
return;
}
+ final String curInteractorStr = Settings.Secure.getStringForUser(
+ mContext.getContentResolver(),
+ Settings.Secure.VOICE_INTERACTION_SERVICE, mCurUser);
final ComponentName curInteractor = getCurInteractor(mCurUser);
- if (curInteractor == null) {
+ // If there's no interactor and the user hasn't explicitly unset it, check if the
+ // modified package offers one.
+ if (curInteractor == null && !"".equals(curInteractorStr)) {
final VoiceInteractionServiceInfo availInteractorInfo
= findAvailInteractor(mCurUser, pkgName);
if (availInteractorInfo != null) {
diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
index 556df88..515d329 100644
--- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
@@ -683,4 +683,23 @@
throw new SecurityException(message + ": Only shell user can call it");
}
+
+ /**
+ * Returns the target SDK version number for a given package name.
+ *
+ * This call MUST be invoked before clearing the calling UID.
+ *
+ * @return target SDK if the package is found or INT_MAX.
+ */
+ public static int getTargetSdk(Context c, String packageName) {
+ try {
+ final ApplicationInfo ai = c.getPackageManager().getApplicationInfoAsUser(
+ packageName, 0, UserHandle.getUserHandleForUid(Binder.getCallingUid()));
+ if (ai != null) return ai.targetSdkVersion;
+ } catch (PackageManager.NameNotFoundException unexpected) {
+ Log.e(LOG_TAG, "Failed to get package info for pkg="
+ + packageName + ", uid=" + Binder.getCallingUid());
+ }
+ return Integer.MAX_VALUE;
+ }
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 0939bf0..56345c0 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -17,6 +17,7 @@
package android.telephony;
import android.Manifest;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -2049,7 +2050,13 @@
* via {@link android.telecom.PhoneAccount#CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE}
* and can choose to hide or show the video calling icon based on whether a contact supports
* video.
+ *
+ * @deprecated No longer used in framework code, however it may still be used by applications
+ * that have not updated their code. This config should still be set to {@code true} if
+ * {@link Ims#KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL} is set to {@code true} and
+ * {@link Ims#KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL} is set to {@code true}.
*/
+ @Deprecated
public static final String KEY_USE_RCS_PRESENCE_BOOL = "use_rcs_presence_bool";
/**
@@ -3865,13 +3872,51 @@
* <p>
* If this key's value is set to false, the procedure for RCS contact capability exchange
* via SIP SUBSCRIBE/NOTIFY will also be disabled internally, and
- * {@link #KEY_USE_RCS_PRESENCE_BOOL} must also be set to false to ensure apps do not
- * improperly think that capability exchange via SIP PUBLISH is enabled.
+ * {@link Ims#KEY_ENABLE_PRESENCE_PUBLISH_BOOL} must also be set to false to ensure
+ * apps do not improperly think that capability exchange via SIP PUBLISH is enabled.
* <p> The default value for this key is {@code false}.
*/
public static final String KEY_ENABLE_PRESENCE_PUBLISH_BOOL =
KEY_PREFIX + "enable_presence_publish_bool";
+ /**
+ * Flag indicating whether or not this carrier supports the exchange of phone numbers with
+ * the carrier's RCS presence server in order to retrieve the RCS capabilities of requested
+ * contacts used in the RCS User Capability Exchange (UCE) procedure. See RCC.71, section 3
+ * for more information.
+ * <p>
+ * When presence is supported, the device uses the SIP SUBSCRIBE/NOTIFY procedure internally
+ * to retrieve the requested RCS capabilities. See
+ * {@link android.telephony.ims.RcsUceAdapter} for more information on how RCS capabilities
+ * can be retrieved from the carrier's network.
+ */
+ public static final String KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL =
+ KEY_PREFIX + "enable_presence_capability_exchange_bool";
+
+
+ /**
+ * Flag indicating whether or not the carrier expects the RCS UCE service to periodically
+ * refresh the RCS capabilities cache of the user's contacts as well as request the
+ * capabilities of call contacts when the SIM card is first inserted or when a new contact
+ * is added, removed, or modified. This corresponds to the RCC.07 A.19
+ * "DISABLE INITIAL ADDRESS BOOK SCAN" parameter.
+ * <p>
+ * If this flag is disabled, the capabilities cache will not be refreshed internally at all
+ * and will only be updated if the cached capabilities are stale when an application
+ * requests them.
+ */
+ public static final String KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL =
+ KEY_PREFIX + "rcs_bulk_capability_exchange_bool";
+
+ /**
+ * Flag indicating whether or not the carrier supports capability exchange with a list of
+ * contacts. When {@code true}, the device will batch together multiple requests and
+ * construct a RLMI document in the SIP SUBSCRIBE request (see RFC 4662). If {@code false},
+ * the request will be split up into one SIP SUBSCRIBE request per contact.
+ */
+ public static final String KEY_ENABLE_PRESENCE_GROUP_SUBSCRIBE_BOOL =
+ KEY_PREFIX + "enable_presence_group_subscribe_bool";
+
private Ims() {}
private static PersistableBundle getDefaults() {
@@ -3879,6 +3924,510 @@
defaults.putInt(KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT, 4000);
defaults.putBoolean(KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, false);
defaults.putBoolean(KEY_ENABLE_PRESENCE_PUBLISH_BOOL, false);
+ defaults.putBoolean(KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL, false);
+ defaults.putBoolean(KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL, false);
+ defaults.putBoolean(KEY_ENABLE_PRESENCE_GROUP_SUBSCRIBE_BOOL, true);
+ return defaults;
+ }
+ }
+
+ /**
+ * Configs used for epdg tunnel bring up.
+ *
+ * @see <a href="https://tools.ietf.org/html/rfc7296">RFC 7296, Internet Key Exchange Protocol
+ * Version 2 (IKEv2)</a>
+ */
+ public static final class Iwlan {
+ /** Prefix of all Epdg.KEY_* constants. */
+ public static final String KEY_PREFIX = "iwlan.";
+
+ /**
+ * Time in seconds after which the child security association session is terminated if rekey
+ * procedure is not successful. If not set or set to <= 0, the default value is 3600
+ * seconds.
+ */
+ public static final String KEY_CHILD_SA_REKEY_HARD_TIMER_SEC_INT =
+ KEY_PREFIX + "child_sa_rekey_hard_timer_sec_int";
+
+ /**
+ * Time in seconds after which the child session rekey procedure is started. If not set or
+ * set to <= 0, default value is 3000 seconds.
+ */
+ public static final String KEY_CHILD_SA_REKEY_SOFT_TIMER_SEC_INT =
+ KEY_PREFIX + "child_sa_rekey_soft_timer_sec_int";
+
+ /**
+ * Supported DH groups for IKE negotiation. Possible values are {@link #DH_GROUP_NONE},
+ * {@link #DH_GROUP_1024_BIT_MODP}, {@link #DH_GROUP_1536_BIT_MODP}, {@link
+ * #DH_GROUP_2048_BIT_MODP}
+ */
+ public static final String KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY =
+ KEY_PREFIX + "diffie_hellman_groups_int_array";
+
+ /**
+ * Time in seconds after which a dead peer detection (DPD) request is sent. If not set or
+ * set to <= 0, default value is 120 seconds.
+ */
+ public static final String KEY_DPD_TIMER_SEC_INT = KEY_PREFIX + "dpd_timer_sec_int";
+
+ /**
+ * Method used to authenticate epdg server. Possible values are {@link
+ * #AUTHENTICATION_METHOD_EAP_ONLY}, {@link #AUTHENTICATION_METHOD_CERT}
+ */
+ public static final String KEY_EPDG_AUTHENTICATION_METHOD_INT =
+ KEY_PREFIX + "epdg_authentication_method_int";
+
+ /**
+ * A priority list of ePDG addresses to be used. Possible values are {@link
+ * #EPDG_ADDRESS_STATIC}, {@link #EPDG_ADDRESS_PLMN}, {@link #EPDG_ADDRESS_PCO}, {@link
+ * #EPDG_ADDRESS_CELLULAR_LOC}
+ */
+ public static final String KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY =
+ KEY_PREFIX + "epdg_address_priority_int_array";
+
+ /** Epdg static IP address or FQDN */
+ public static final String KEY_EPDG_STATIC_ADDRESS_STRING =
+ KEY_PREFIX + "epdg_static_address_string";
+
+ /** Epdg static IP address or FQDN for roaming */
+ public static final String KEY_EPDG_STATIC_ADDRESS_ROAMING_STRING =
+ KEY_PREFIX + "epdg_static_address_roaming_string";
+
+ /**
+ * List of supported key sizes for AES Cipher Block Chaining (CBC) encryption mode of child
+ * session. Possible values are {@link #KEY_LEN_UNUSED}, {@link #KEY_LEN_AES_128}, {@link
+ * #KEY_LEN_AES_192}, {@link #KEY_LEN_AES_256}
+ */
+ public static final String KEY_CHILD_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY =
+ KEY_PREFIX + "child_session_aes_cbc_key_size_int_array";
+
+ /**
+ * List of supported key sizes for AES Counter (CTR) encryption mode of child session.
+ * Possible values are {@link #KEY_LEN_UNUSED},
+ * {@link #KEY_LEN_AES_128}, {@link #KEY_LEN_AES_192}, {@link #KEY_LEN_AES_256}
+ */
+ public static final String KEY_CHILD_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY =
+ KEY_PREFIX + "child_session_aes_ctr_key_size_int_array";
+
+ /**
+ * List of supported encryption algorithms for child session. Possible values are
+ * {@link #ENCRYPTION_ALGORITHM_AES_CBC}
+ */
+ public static final String KEY_SUPPORTED_CHILD_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY =
+ KEY_PREFIX + "supported_child_session_encryption_algorithms_int_array";
+
+ /**
+ * Time in seconds after which the IKE session is terminated if rekey procedure is not
+ * successful. If not set or set to <= 0, default value is 3600 seconds.
+ */
+ public static final String KEY_IKE_REKEY_HARD_TIMER_SEC_INT =
+ KEY_PREFIX + "ike_rekey_hard_timer_in_sec";
+
+ /**
+ * Time in seconds after which the IKE session rekey procedure is started. If not set or set
+ * to <= 0, default value is 3000 seconds.
+ */
+ public static final String KEY_IKE_REKEY_SOFT_TIMER_SEC_INT =
+ KEY_PREFIX + "ike_rekey_soft_timer_sec_int";
+
+ /**
+ * List of supported key sizes for AES Cipher Block Chaining (CBC) encryption mode of IKE
+ * session. Possible values - {@link #KEY_LEN_UNUSED}, {@link #KEY_LEN_AES_128}, {@link
+ * #KEY_LEN_AES_192}, {@link #KEY_LEN_AES_256}
+ */
+ public static final String KEY_IKE_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY =
+ KEY_PREFIX + "ike_session_encryption_aes_cbc_key_size_int_array";
+
+
+ /**
+ * List of supported key sizes for AES Counter (CTR) encryption mode of IKE session.
+ * Possible values - {@link #KEY_LEN_UNUSED}, {@link #KEY_LEN_AES_128},
+ * {@link #KEY_LEN_AES_192}, {@link #KEY_LEN_AES_256}
+ */
+ public static final String KEY_IKE_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY =
+ KEY_PREFIX + "ike_session_encryption_aes_ctr_key_size_int_array";
+
+ /**
+ * List of supported encryption algorithms for IKE session. Possible values are
+ * {@link #ENCRYPTION_ALGORITHM_AES_CBC}, {@link #ENCRYPTION_ALGORITHM_AES_CTR}
+ */
+ public static final String KEY_SUPPORTED_IKE_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY =
+ KEY_PREFIX + "supported_ike_session_encryption_algorithms_int_array";
+
+ /**
+ * List of supported integrity algorithms for IKE session Possible values are {@link
+ * #INTEGRITY_ALGORITHM_NONE}, {@link #INTEGRITY_ALGORITHM_HMAC_SHA1_96}, {@link
+ * #INTEGRITY_ALGORITHM_AES_XCBC_96}, {@link #INTEGRITY_ALGORITHM_HMAC_SHA2_256_128}, {@link
+ * #INTEGRITY_ALGORITHM_HMAC_SHA2_384_192}, {@link #INTEGRITY_ALGORITHM_HMAC_SHA2_512_256}
+ */
+ public static final String KEY_SUPPORTED_INTEGRITY_ALGORITHMS_INT_ARRAY =
+ KEY_PREFIX + "supported_integrity_algorithms_int_array";
+
+ /** Maximum number of retries for tunnel establishment. */
+ public static final String KEY_MAX_RETRIES_INT = KEY_PREFIX + "max_retries_int";
+
+ /**
+ * Time in seconds after which a NATT keep alive message is sent. If not set or set to <= 0,
+ * default value is 20 seconds.
+ */
+ public static final String KEY_NATT_KEEP_ALIVE_TIMER_SEC_INT =
+ KEY_PREFIX + "natt_keep_alive_timer_sec_int";
+
+ /** List of '-' separated MCC/MNCs used to create ePDG FQDN as per 3GPP TS 23.003 */
+ public static final String KEY_MCC_MNCS_STRING_ARRAY = KEY_PREFIX + "mcc_mncs_string_array";
+
+ /**
+ * List of supported pseudo random function algorithms for IKE session. Possible values are
+ * {@link #PSEUDORANDOM_FUNCTION_HMAC_SHA1}, {@link #PSEUDORANDOM_FUNCTION_AES128_XCBC},
+ * {@link #PSEUDORANDOM_FUNCTION_SHA2_256}, {@link #PSEUDORANDOM_FUNCTION_SHA2_384},
+ * {@link #PSEUDORANDOM_FUNCTION_SHA2_512}
+ */
+ public static final String KEY_SUPPORTED_PRF_ALGORITHMS_INT_ARRAY =
+ KEY_PREFIX + "supported_prf_algorithms_int_array";
+
+ /**
+ * List of IKE message retransmission timeouts in milliseconds, where each timeout
+ * is the waiting time before next retry, except the last timeout which is the waiting time
+ * before terminating the IKE Session. Min list length = 1, Max
+ * list length = 10 Min timeout = 500 ms, Max timeout = 1800000 ms
+ */
+ public static final String KEY_RETRANSMIT_TIMER_MSEC_INT_ARRAY =
+ KEY_PREFIX + "retransmit_timer_sec_int_array";
+
+ /** Controls if wifi mac Id should be added to network access identifier(NAI) */
+ public static final String KEY_ADD_WIFI_MAC_ADDR_TO_NAI_BOOL =
+ KEY_PREFIX + "add_wifi_mac_addr_to_nai_bool";
+
+ /**
+ * Specifies the local identity type for IKE negotiations. Possible values are {@link
+ * #ID_TYPE_FQDN}, {@link #ID_TYPE_RFC822_ADDR}, {@link #ID_TYPE_KEY_ID}
+ */
+ public static final String KEY_IKE_LOCAL_ID_TYPE_INT = KEY_PREFIX + "ike_local_id_type_int";
+
+ /**
+ * Specifies the remote identity type for IKE negotiations. Possible values are {@link
+ * #ID_TYPE_FQDN}, {@link #ID_TYPE_RFC822_ADDR}, {@link #ID_TYPE_KEY_ID}
+ */
+ public static final String KEY_IKE_REMOTE_ID_TYPE_INT =
+ KEY_PREFIX + "ike_remote_id_type_int";
+
+ /** Controls if KE payload should be added during child session local rekey procedure. */
+ public static final String KEY_ADD_KE_TO_CHILD_SESSION_REKEY_BOOL =
+ KEY_PREFIX + "add_ke_to_child_session_rekey_bool";
+
+ /** Specifies the PCO id for IPv6 Epdg server address */
+ public static final String KEY_EPDG_PCO_ID_IPV6_INT = KEY_PREFIX + "epdg_pco_id_ipv6_int";
+
+ /** Specifies the PCO id for IPv4 Epdg server address */
+ public static final String KEY_EPDG_PCO_ID_IPV4_INT = KEY_PREFIX + "epdg_pco_id_ipv4_int";
+
+ /** @hide */
+ @IntDef({AUTHENTICATION_METHOD_EAP_ONLY, AUTHENTICATION_METHOD_CERT})
+ public @interface AuthenticationMethodType {}
+
+ /**
+ * Certificate sent from the server is ignored. Only Extensible Authentication Protocol
+ * (EAP) is used to authenticate the server. EAP_ONLY_AUTH payload is added to IKE_AUTH
+ * request if supported.
+ *
+ * @see <a href="https://tools.ietf.org/html/rfc5998">RFC 5998</a>
+ */
+ public static final int AUTHENTICATION_METHOD_EAP_ONLY = 0;
+ /** Server is authenticated using its certificate. */
+ public static final int AUTHENTICATION_METHOD_CERT = 1;
+
+ /** @hide */
+ @IntDef({
+ EPDG_ADDRESS_STATIC,
+ EPDG_ADDRESS_PLMN,
+ EPDG_ADDRESS_PCO,
+ EPDG_ADDRESS_CELLULAR_LOC
+ })
+ public @interface EpdgAddressType {}
+
+ /** Use static epdg address. */
+ public static final int EPDG_ADDRESS_STATIC = 0;
+ /** Construct the epdg address using plmn. */
+ public static final int EPDG_ADDRESS_PLMN = 1;
+ /**
+ * Use the epdg address received in protocol configuration options (PCO) from the network.
+ */
+ public static final int EPDG_ADDRESS_PCO = 2;
+ /** Use cellular location to chose epdg server */
+ public static final int EPDG_ADDRESS_CELLULAR_LOC = 3;
+
+ /** @hide */
+ @IntDef({KEY_LEN_UNUSED, KEY_LEN_AES_128, KEY_LEN_AES_192, KEY_LEN_AES_256})
+ public @interface EncrpytionKeyLengthType {}
+
+ public static final int KEY_LEN_UNUSED = 0;
+ /** AES Encryption/Ciphering Algorithm key length 128 bits. */
+ public static final int KEY_LEN_AES_128 = 128;
+ /** AES Encryption/Ciphering Algorithm key length 192 bits. */
+ public static final int KEY_LEN_AES_192 = 192;
+ /** AES Encryption/Ciphering Algorithm key length 256 bits. */
+ public static final int KEY_LEN_AES_256 = 256;
+
+ /** @hide */
+ @IntDef({
+ DH_GROUP_NONE,
+ DH_GROUP_1024_BIT_MODP,
+ DH_GROUP_1536_BIT_MODP,
+ DH_GROUP_2048_BIT_MODP,
+ DH_GROUP_3072_BIT_MODP,
+ DH_GROUP_4096_BIT_MODP
+ })
+ public @interface DhGroup {}
+
+ /** None Diffie-Hellman Group. */
+ public static final int DH_GROUP_NONE = 0;
+ /**
+ * 1024-bit MODP Diffie-Hellman Group.
+ *
+ * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+ * Exchange Protocol Version 2 (IKEv2)</a>
+ */
+ public static final int DH_GROUP_1024_BIT_MODP = 2;
+ /**
+ * 1536-bit MODP Diffie-Hellman Group.
+ *
+ * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+ * Exchange Protocol Version 2 (IKEv2)</a>
+ */
+ public static final int DH_GROUP_1536_BIT_MODP = 5;
+ /**
+ * 2048-bit MODP Diffie-Hellman Group.
+ *
+ * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+ * Exchange Protocol Version 2 (IKEv2)</a>
+ */
+ public static final int DH_GROUP_2048_BIT_MODP = 14;
+ /**
+ * 3072-bit MODP Diffie-Hellman Group.
+ *
+ * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+ * Exchange Protocol Version 2 (IKEv2)</a>
+ */
+ public static final int DH_GROUP_3072_BIT_MODP = 15;
+ /**
+ * 4096-bit MODP Diffie-Hellman Group.
+ *
+ * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+ * Exchange Protocol Version 2 (IKEv2)</a>
+ */
+ public static final int DH_GROUP_4096_BIT_MODP = 16;
+
+ /** @hide */
+ @IntDef({ENCRYPTION_ALGORITHM_AES_CBC, ENCRYPTION_ALGORITHM_AES_CTR})
+ public @interface EncryptionAlgorithm {}
+
+ /**
+ * AES-CBC Encryption/Ciphering Algorithm.
+ *
+ * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+ * Exchange Protocol Version 2 (IKEv2)</a>
+ */
+ public static final int ENCRYPTION_ALGORITHM_AES_CBC = 12;
+
+ /**
+ * AES-CTR Encryption/Ciphering Algorithm.
+ *
+ * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+ * Exchange Protocol Version 2 (IKEv2)</a>
+ */
+ public static final int ENCRYPTION_ALGORITHM_AES_CTR = 13;
+
+ /** @hide */
+ @IntDef({
+ INTEGRITY_ALGORITHM_NONE,
+ INTEGRITY_ALGORITHM_HMAC_SHA1_96,
+ INTEGRITY_ALGORITHM_AES_XCBC_96,
+ INTEGRITY_ALGORITHM_HMAC_SHA2_256_128,
+ INTEGRITY_ALGORITHM_HMAC_SHA2_384_192,
+ INTEGRITY_ALGORITHM_HMAC_SHA2_512_256
+ })
+ public @interface IntegrityAlgorithm {}
+
+ /** None Authentication/Integrity Algorithm. */
+ public static final int INTEGRITY_ALGORITHM_NONE = 0;
+ /**
+ * HMAC-SHA1 Authentication/Integrity Algorithm.
+ *
+ * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+ * Exchange Protocol Version 2 (IKEv2)</a>
+ */
+ public static final int INTEGRITY_ALGORITHM_HMAC_SHA1_96 = 2;
+ /**
+ * AES-XCBC-96 Authentication/Integrity Algorithm.
+ *
+ * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+ * Exchange Protocol Version 2 (IKEv2)</a>
+ */
+ public static final int INTEGRITY_ALGORITHM_AES_XCBC_96 = 5;
+ /**
+ * HMAC-SHA256 Authentication/Integrity Algorithm with 128-bit truncation.
+ *
+ * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+ * Exchange Protocol Version 2 (IKEv2)</a>
+ */
+ public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_256_128 = 12;
+ /**
+ * HMAC-SHA384 Authentication/Integrity Algorithm with 192-bit truncation.
+ *
+ * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+ * Exchange Protocol Version 2 (IKEv2)</a>
+ */
+ public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_384_192 = 13;
+ /**
+ * HMAC-SHA512 Authentication/Integrity Algorithm with 256-bit truncation.
+ *
+ * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+ * Exchange Protocol Version 2 (IKEv2)</a>
+ */
+ public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_512_256 = 14;
+
+ /** @hide */
+ @IntDef({
+ PSEUDORANDOM_FUNCTION_HMAC_SHA1,
+ PSEUDORANDOM_FUNCTION_AES128_XCBC,
+ PSEUDORANDOM_FUNCTION_SHA2_256,
+ PSEUDORANDOM_FUNCTION_SHA2_384,
+ PSEUDORANDOM_FUNCTION_SHA2_512
+ })
+ public @interface PseudorandomFunction {}
+
+ /**
+ * HMAC-SHA1 Pseudorandom Function.
+ *
+ * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+ * Exchange Protocol Version 2 (IKEv2)</a>
+ */
+ public static final int PSEUDORANDOM_FUNCTION_HMAC_SHA1 = 2;
+ /**
+ * AES128-XCBC Pseudorandom Function.
+ *
+ * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+ * Exchange Protocol Version 2 (IKEv2)</a>
+ */
+ public static final int PSEUDORANDOM_FUNCTION_AES128_XCBC = 4;
+ /**
+ * HMAC-SHA2-256 Pseudorandom Function.
+ *
+ * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+ * Exchange Protocol Version 2 (IKEv2)</a>
+ */
+ public static final int PSEUDORANDOM_FUNCTION_SHA2_256 = 5;
+ /**
+ * HMAC-SHA2-384 Pseudorandom Function.
+ *
+ * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+ * Exchange Protocol Version 2 (IKEv2)</a>
+ */
+ public static final int PSEUDORANDOM_FUNCTION_SHA2_384 = 6;
+ /**
+ * HMAC-SHA2-384 Pseudorandom Function.
+ *
+ * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key
+ * Exchange Protocol Version 2 (IKEv2)</a>
+ */
+ public static final int PSEUDORANDOM_FUNCTION_SHA2_512 = 7;
+
+ /** @hide */
+ @IntDef({ID_TYPE_FQDN, ID_TYPE_RFC822_ADDR, ID_TYPE_KEY_ID})
+ public @interface IkeIdType {}
+
+ /**
+ * Ike Identification Fully Qualified Domain Name
+ *
+ * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.5">RFC 7296, Internet Key
+ * Exchange Protocol Version 2 (IKEv2)</a>
+ */
+ public static final int ID_TYPE_FQDN = 2;
+ /**
+ * Ike Identification Fully Qualified RFC 822 email address.
+ *
+ * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.5">RFC 7296, Internet Key
+ * Exchange Protocol Version 2 (IKEv2)</a>
+ */
+ public static final int ID_TYPE_RFC822_ADDR = 3;
+ /**
+ * Ike Identification opaque octet stream for vendor specific information
+ *
+ * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.5">RFC 7296, Internet Key
+ * Exchange Protocol Version 2 (IKEv2)</a>
+ */
+ public static final int ID_TYPE_KEY_ID = 11;
+
+ private Iwlan() {}
+
+ private static PersistableBundle getDefaults() {
+ PersistableBundle defaults = new PersistableBundle();
+ defaults.putInt(KEY_IKE_REKEY_SOFT_TIMER_SEC_INT, 7200);
+ defaults.putInt(KEY_IKE_REKEY_HARD_TIMER_SEC_INT, 14400);
+ defaults.putInt(KEY_CHILD_SA_REKEY_SOFT_TIMER_SEC_INT, 3600);
+ defaults.putInt(KEY_CHILD_SA_REKEY_HARD_TIMER_SEC_INT, 7200);
+ defaults.putIntArray(
+ KEY_RETRANSMIT_TIMER_MSEC_INT_ARRAY, new int[] {500, 1000, 2000, 4000, 8000});
+ defaults.putInt(KEY_DPD_TIMER_SEC_INT, 120);
+ defaults.putInt(KEY_MAX_RETRIES_INT, 3);
+ defaults.putIntArray(
+ KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY,
+ new int[] {
+ DH_GROUP_1024_BIT_MODP, DH_GROUP_1536_BIT_MODP, DH_GROUP_2048_BIT_MODP
+ });
+ defaults.putIntArray(
+ KEY_SUPPORTED_IKE_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY,
+ new int[] {ENCRYPTION_ALGORITHM_AES_CBC});
+ defaults.putIntArray(
+ KEY_SUPPORTED_CHILD_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY,
+ new int[] {ENCRYPTION_ALGORITHM_AES_CBC});
+ defaults.putIntArray(
+ KEY_SUPPORTED_INTEGRITY_ALGORITHMS_INT_ARRAY,
+ new int[] {
+ INTEGRITY_ALGORITHM_AES_XCBC_96,
+ INTEGRITY_ALGORITHM_HMAC_SHA1_96,
+ INTEGRITY_ALGORITHM_HMAC_SHA2_256_128,
+ INTEGRITY_ALGORITHM_HMAC_SHA2_384_192,
+ INTEGRITY_ALGORITHM_HMAC_SHA2_512_256,
+ });
+ defaults.putIntArray(
+ KEY_SUPPORTED_PRF_ALGORITHMS_INT_ARRAY,
+ new int[] {
+ PSEUDORANDOM_FUNCTION_HMAC_SHA1,
+ PSEUDORANDOM_FUNCTION_AES128_XCBC,
+ PSEUDORANDOM_FUNCTION_SHA2_256,
+ PSEUDORANDOM_FUNCTION_SHA2_384,
+ PSEUDORANDOM_FUNCTION_SHA2_512
+ });
+
+ defaults.putInt(KEY_EPDG_AUTHENTICATION_METHOD_INT, AUTHENTICATION_METHOD_EAP_ONLY);
+ defaults.putString(KEY_EPDG_STATIC_ADDRESS_STRING, "");
+ defaults.putString(KEY_EPDG_STATIC_ADDRESS_ROAMING_STRING, "");
+ // will be used after b/158036773 is fixed
+ defaults.putInt(KEY_NATT_KEEP_ALIVE_TIMER_SEC_INT, 20);
+ defaults.putIntArray(
+ KEY_IKE_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY,
+ new int[] {KEY_LEN_AES_128, KEY_LEN_AES_192, KEY_LEN_AES_256});
+ defaults.putIntArray(
+ KEY_CHILD_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY,
+ new int[] {KEY_LEN_AES_128, KEY_LEN_AES_192, KEY_LEN_AES_256});
+ defaults.putIntArray(
+ KEY_IKE_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY,
+ new int[] {KEY_LEN_AES_128, KEY_LEN_AES_192, KEY_LEN_AES_256});
+ defaults.putIntArray(
+ KEY_CHILD_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY,
+ new int[] {KEY_LEN_AES_128, KEY_LEN_AES_192, KEY_LEN_AES_256});
+ defaults.putIntArray(
+ KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY,
+ new int[] {EPDG_ADDRESS_PLMN, EPDG_ADDRESS_STATIC});
+ defaults.putStringArray(KEY_MCC_MNCS_STRING_ARRAY, new String[] {});
+ defaults.putBoolean(KEY_ADD_WIFI_MAC_ADDR_TO_NAI_BOOL, false);
+ defaults.putInt(KEY_IKE_LOCAL_ID_TYPE_INT, ID_TYPE_RFC822_ADDR);
+ defaults.putInt(KEY_IKE_REMOTE_ID_TYPE_INT, ID_TYPE_FQDN);
+ defaults.putBoolean(KEY_ADD_KE_TO_CHILD_SESSION_REKEY_BOOL, false);
+ defaults.putInt(KEY_EPDG_PCO_ID_IPV6_INT, 0);
+ defaults.putInt(KEY_EPDG_PCO_ID_IPV4_INT, 0);
+
return defaults;
}
}
@@ -4032,6 +4581,12 @@
public static final String KEY_USE_LOWER_MTU_VALUE_IF_BOTH_RECEIVED =
"use_lower_mtu_value_if_both_received";
+ /**
+ * Indicates if auto-configuration server is used for the RCS config
+ * Reference: GSMA RCC.14
+ */
+ public static final String KEY_USE_ACS_FOR_RCS_BOOL = "use_acs_for_rcs_bool";
+
/** The default value for every variable. */
private final static PersistableBundle sDefaults;
@@ -4551,6 +5106,7 @@
});
sDefaults.putBoolean(KEY_SUPPORT_WPS_OVER_IMS_BOOL, true);
sDefaults.putAll(Ims.getDefaults());
+ sDefaults.putAll(Iwlan.getDefaults());
sDefaults.putStringArray(KEY_CARRIER_CERTIFICATE_STRING_ARRAY, new String[0]);
sDefaults.putBoolean(KEY_FORMAT_INCOMING_NUMBER_TO_NATIONAL_FOR_JP_BOOL, false);
sDefaults.putIntArray(KEY_DISCONNECT_CAUSE_PLAY_BUSYTONE_INT_ARRAY,
@@ -4577,6 +5133,7 @@
sDefaults.putBoolean(KEY_SUPPORTS_CALL_COMPOSER_BOOL, false);
sDefaults.putString(KEY_CALL_COMPOSER_PICTURE_SERVER_URL_STRING, "");
sDefaults.putBoolean(KEY_USE_LOWER_MTU_VALUE_IF_BOTH_RECEIVED, false);
+ sDefaults.putBoolean(KEY_USE_ACS_FOR_RCS_BOOL, false);
}
/**
diff --git a/telephony/java/android/telephony/CellSignalStrengthLte.java b/telephony/java/android/telephony/CellSignalStrengthLte.java
index db7d10a..7addf33 100644
--- a/telephony/java/android/telephony/CellSignalStrengthLte.java
+++ b/telephony/java/android/telephony/CellSignalStrengthLte.java
@@ -443,10 +443,12 @@
/**
* Get table index for channel quality indicator
*
+ * Reference: 3GPP TS 136.213 section 7.2.3.
+ *
* @return the CQI table index if available or
* {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
*/
- /** @hide */
+ @IntRange(from = 1, to = 6)
public int getCqiTableIndex() {
return mCqiTableIndex;
}
@@ -454,9 +456,12 @@
/**
* Get channel quality indicator
*
+ * Reference: 3GPP TS 136.213 section 7.2.3.
+ *
* @return the CQI if available or
* {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
*/
+ @IntRange(from = 0, to = 15)
public int getCqi() {
return mCqi;
}
diff --git a/telephony/java/android/telephony/CellSignalStrengthNr.java b/telephony/java/android/telephony/CellSignalStrengthNr.java
index 1518190..bde62fb 100644
--- a/telephony/java/android/telephony/CellSignalStrengthNr.java
+++ b/telephony/java/android/telephony/CellSignalStrengthNr.java
@@ -294,9 +294,10 @@
*
* Reference: 3GPP TS 138.214 section 5.2.2.1.
*
- * Range [1, 3].
+ * @return the CQI table index if available or
+ * {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE} if unavailable.
*/
- /** @hide */
+ @IntRange(from = 1, to = 3)
public int getCsiCqiTableIndex() {
return mCsiCqiTableIndex;
}
@@ -310,10 +311,10 @@
*
* Reference: 3GPP TS 138.214 section 5.2.2.1.
*
- * Range [0, 15] for each CQI.
+ * @return the CQIs for all subbands if available or empty list if unavailable.
*/
- /** @hide */
@NonNull
+ @IntRange(from = 0, to = 15)
public List<Integer> getCsiCqiReport() {
return mCsiCqiReport;
}
diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java
index d502da9..99a77ae5 100644
--- a/telephony/java/android/telephony/DataFailCause.java
+++ b/telephony/java/android/telephony/DataFailCause.java
@@ -915,6 +915,8 @@
public static final int IPV6_PREFIX_UNAVAILABLE = 0x8CA;
/** System preference change back to SRAT during handoff */
public static final int HANDOFF_PREFERENCE_CHANGED = 0x8CB;
+ /** Data call fail due to the slice not being allowed for the data call. */
+ public static final int SLICE_REJECTED = 0x8CC;
//IKE error notifications message as specified in 3GPP TS 24.302 (Section 8.1.2.2).
@@ -985,7 +987,7 @@
* the authentication failed.
*/
public static final int IWLAN_IKEV2_AUTH_FAILURE = 0x4001;
- /** IKE message timeout, tunnel setup failed due to no response from EPDG */
+ /** IKE message timeout, tunnel setup failed due to no response from EPDG */
public static final int IWLAN_IKEV2_MSG_TIMEOUT = 0x4002;
/** IKE Certification validation failure */
public static final int IWLAN_IKEV2_CERT_INVALID = 0x4003;
@@ -1419,6 +1421,7 @@
sFailCauseMap.put(VSNCP_RECONNECT_NOT_ALLOWED, "VSNCP_RECONNECT_NOT_ALLOWED");
sFailCauseMap.put(IPV6_PREFIX_UNAVAILABLE, "IPV6_PREFIX_UNAVAILABLE");
sFailCauseMap.put(HANDOFF_PREFERENCE_CHANGED, "HANDOFF_PREFERENCE_CHANGED");
+ sFailCauseMap.put(SLICE_REJECTED, "SLICE_REJECTED");
sFailCauseMap.put(IWLAN_PDN_CONNECTION_REJECTION, "IWLAN_PDN_CONNECTION_REJECTION");
sFailCauseMap.put(IWLAN_MAX_CONNECTION_REACHED, "IWLAN_MAX_CONNECTION_REACHED");
sFailCauseMap.put(IWLAN_SEMANTIC_ERROR_IN_THE_TFT_OPERATION,
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 572aed3..e145fcf 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -3134,26 +3134,20 @@
/**
* Reset all cell broadcast ranges. Previously enabled ranges will become invalid after this.
- *
- * @return {@code true} if succeeded, otherwise {@code false}.
- *
- * // TODO: Unhide the API in S.
* @hide
*/
- public boolean resetAllCellBroadcastRanges() {
- boolean success = false;
-
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_CELL_BROADCASTS)
+ public void resetAllCellBroadcastRanges() {
try {
ISms iSms = getISmsService();
if (iSms != null) {
// If getSubscriptionId() returns INVALID or an inactive subscription, we will use
// the default phone internally.
- success = iSms.resetAllCellBroadcastRanges(getSubscriptionId());
+ iSms.resetAllCellBroadcastRanges(getSubscriptionId());
}
} catch (RemoteException ex) {
- // ignore it
+ ex.rethrowFromSystemServer();
}
-
- return success;
}
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 31a1249..d4565f3 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -8671,6 +8671,77 @@
return Collections.EMPTY_LIST;
}
+ /**
+ * Call composer status OFF from user setting.
+ */
+ public static final int CALL_COMPOSER_STATUS_OFF = 0;
+
+ /**
+ * Call composer status ON from user setting.
+ */
+ public static final int CALL_COMPOSER_STATUS_ON = 1;
+
+ /** @hide */
+ @IntDef(prefix = {"CALL_COMPOSER_STATUS_"},
+ value = {
+ CALL_COMPOSER_STATUS_ON,
+ CALL_COMPOSER_STATUS_OFF,
+ })
+ public @interface CallComposerStatus {}
+
+ /**
+ * Set the user-set status for enriched calling with call composer.
+ *
+ * @param status user-set status for enriched calling with call composer;
+ * it must be a value of either {@link #CALL_COMPOSER_STATUS_ON}
+ * or {@link #CALL_COMPOSER_STATUS_OFF}.
+ *
+ * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
+ * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}
+ *
+ * @throws IllegalArgumentException if requested state is invalid.
+ * @throws SecurityException if the caller does not have the permission.
+ */
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ public void setCallComposerStatus(@CallComposerStatus int status) {
+ if (status != CALL_COMPOSER_STATUS_ON && status != CALL_COMPOSER_STATUS_OFF) {
+ throw new IllegalArgumentException("requested status is invalid");
+ }
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ telephony.setCallComposerStatus(getSubId(), status);
+ }
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Error calling ITelephony#setCallComposerStatus", ex);
+ ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Get the user-set status for enriched calling with call composer.
+ *
+ * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
+ * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}
+ *
+ * @throws SecurityException if the caller does not have the permission.
+ *
+ * @return the user-set status for enriched calling with call composer either
+ * {@link #CALL_COMPOSER_STATUS_ON} or {@link #CALL_COMPOSER_STATUS_OFF}.
+ */
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public @CallComposerStatus int getCallComposerStatus() {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ return telephony.getCallComposerStatus(getSubId());
+ }
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Error calling ITelephony#getCallComposerStatus", ex);
+ ex.rethrowFromSystemServer();
+ }
+ return CALL_COMPOSER_STATUS_OFF;
+ }
/** @hide */
@SystemApi
diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java
index 556f2d5..e217e9a 100644
--- a/telephony/java/android/telephony/data/DataCallResponse.java
+++ b/telephony/java/android/telephony/data/DataCallResponse.java
@@ -137,6 +137,7 @@
private final int mPduSessionId;
private final Qos mDefaultQos;
private final List<QosSession> mQosSessions;
+ private final SliceInfo mSliceInfo;
/**
* @param cause Data call fail cause. {@link DataFailCause#NONE} indicates no error.
@@ -187,6 +188,7 @@
mPduSessionId = PDU_SESSION_ID_NOT_SET;
mDefaultQos = null;
mQosSessions = new ArrayList<>();
+ mSliceInfo = null;
}
private DataCallResponse(@DataFailureCause int cause, long suggestedRetryTime, int id,
@@ -195,7 +197,8 @@
@Nullable List<InetAddress> dnsAddresses, @Nullable List<InetAddress> gatewayAddresses,
@Nullable List<InetAddress> pcscfAddresses, int mtu, int mtuV4, int mtuV6,
@HandoverFailureMode int handoverFailureMode, int pduSessionId,
- @Nullable Qos defaultQos, @Nullable List<QosSession> qosSessions) {
+ @Nullable Qos defaultQos, @Nullable List<QosSession> qosSessions,
+ @Nullable SliceInfo sliceInfo) {
mCause = cause;
mSuggestedRetryTime = suggestedRetryTime;
mId = id;
@@ -217,6 +220,7 @@
mPduSessionId = pduSessionId;
mDefaultQos = defaultQos;
mQosSessions = qosSessions;
+ mSliceInfo = sliceInfo;
}
/** @hide */
@@ -244,6 +248,7 @@
mDefaultQos = source.readParcelable(Qos.class.getClassLoader());
mQosSessions = new ArrayList<>();
source.readList(mQosSessions, QosSession.class.getClassLoader());
+ mSliceInfo = source.readParcelable(SliceInfo.class.getClassLoader());
}
/**
@@ -370,7 +375,7 @@
}
/**
- * @return default QOS of the data call received from the network
+ * @return default QOS of the data connection received from the network
*
* @hide
*/
@@ -381,16 +386,24 @@
}
/**
- * @return All the dedicated bearer QOS sessions of the data call received from the network
+ * @return All the dedicated bearer QOS sessions of the data connection received from the
+ * network.
*
* @hide
*/
-
@NonNull
public List<QosSession> getQosSessions() {
return mQosSessions;
}
+ /**
+ * @return The slice info related to this data connection.
+ */
+ @Nullable
+ public SliceInfo getSliceInfo() {
+ return mSliceInfo;
+ }
+
@NonNull
@Override
public String toString() {
@@ -413,6 +426,7 @@
.append(" pduSessionId=").append(getPduSessionId())
.append(" defaultQos=").append(mDefaultQos)
.append(" qosSessions=").append(mQosSessions)
+ .append(" sliceInfo=").append(mSliceInfo)
.append("}");
return sb.toString();
}
@@ -456,7 +470,8 @@
&& mHandoverFailureMode == other.mHandoverFailureMode
&& mPduSessionId == other.mPduSessionId
&& isQosSame
- && isQosSessionsSame;
+ && isQosSessionsSame
+ && Objects.equals(mSliceInfo, other.mSliceInfo);
}
@Override
@@ -464,7 +479,7 @@
return Objects.hash(mCause, mSuggestedRetryTime, mId, mLinkStatus, mProtocolType,
mInterfaceName, mAddresses, mDnsAddresses, mGatewayAddresses, mPcscfAddresses,
mMtu, mMtuV4, mMtuV6, mHandoverFailureMode, mPduSessionId, mDefaultQos,
- mQosSessions);
+ mQosSessions, mSliceInfo);
}
@Override
@@ -499,6 +514,7 @@
dest.writeParcelable(null, flags);
}
dest.writeList(mQosSessions);
+ dest.writeParcelable(mSliceInfo, flags);
}
public static final @android.annotation.NonNull Parcelable.Creator<DataCallResponse> CREATOR =
@@ -582,6 +598,8 @@
private List<QosSession> mQosSessions = new ArrayList<>();
+ private SliceInfo mSliceInfo;
+
/**
* Default constructor for Builder.
*/
@@ -805,6 +823,21 @@
}
/**
+ * The Slice used for this data connection.
+ * <p/>
+ * If a handover occurs from EPDG to 5G,
+ * this is the {@link SliceInfo} used in {@link DataService#setupDataCall}.
+ *
+ * @param sliceInfo the slice info for the data call
+ *
+ * @return The same instance of the builder.
+ */
+ public @NonNull Builder setSliceInfo(@Nullable SliceInfo sliceInfo) {
+ mSliceInfo = sliceInfo;
+ return this;
+ }
+
+ /**
* Build the DataCallResponse.
*
* @return the DataCallResponse object.
@@ -813,7 +846,7 @@
return new DataCallResponse(mCause, mSuggestedRetryTime, mId, mLinkStatus,
mProtocolType, mInterfaceName, mAddresses, mDnsAddresses, mGatewayAddresses,
mPcscfAddresses, mMtu, mMtuV4, mMtuV6, mHandoverFailureMode, mPduSessionId,
- mDefaultQos, mQosSessions);
+ mDefaultQos, mQosSessions, mSliceInfo);
}
}
}
diff --git a/telephony/java/android/telephony/data/DataService.java b/telephony/java/android/telephony/data/DataService.java
index 2ec9651..03c2ef9 100644
--- a/telephony/java/android/telephony/data/DataService.java
+++ b/telephony/java/android/telephony/data/DataService.java
@@ -194,13 +194,19 @@
* The standard range of values are 1-15 while 0 means no pdu session id
* was attached to this call. Reference: 3GPP TS 24.007 section
* 11.2.3.1b.
+ * @param sliceInfo used within the data connection when a handover occurs from EPDG to 5G.
+ * The value is null unless the access network is
+ * {@link android.telephony.AccessNetworkConstants.AccessNetworkType#NGRAN} and a
+ * handover is occurring from EPDG to 5G. If the slice passed is rejected, then
+ * {@link DataCallResponse#getCause()} is
+ * {@link android.telephony.DataFailCause#SLICE_REJECTED}.
* @param callback The result callback for this request.
*/
public void setupDataCall(int accessNetworkType, @NonNull DataProfile dataProfile,
boolean isRoaming, boolean allowRoaming,
@SetupDataReason int reason,
@Nullable LinkProperties linkProperties,
- @IntRange(from = 0, to = 15) int pduSessionId,
+ @IntRange(from = 0, to = 15) int pduSessionId, @Nullable SliceInfo sliceInfo,
@NonNull DataServiceCallback callback) {
/* Call the old version since the new version isn't supported */
setupDataCall(accessNetworkType, dataProfile, isRoaming, allowRoaming, reason,
@@ -392,10 +398,11 @@
public final int reason;
public final LinkProperties linkProperties;
public final int pduSessionId;
+ public final SliceInfo sliceInfo;
public final IDataServiceCallback callback;
SetupDataCallRequest(int accessNetworkType, DataProfile dataProfile, boolean isRoaming,
boolean allowRoaming, int reason, LinkProperties linkProperties,
- int pduSessionId, IDataServiceCallback callback) {
+ int pduSessionId, SliceInfo sliceInfo, IDataServiceCallback callback) {
this.accessNetworkType = accessNetworkType;
this.dataProfile = dataProfile;
this.isRoaming = isRoaming;
@@ -403,6 +410,7 @@
this.linkProperties = linkProperties;
this.reason = reason;
this.pduSessionId = pduSessionId;
+ this.sliceInfo = sliceInfo;
this.callback = callback;
}
}
@@ -513,6 +521,7 @@
setupDataCallRequest.dataProfile, setupDataCallRequest.isRoaming,
setupDataCallRequest.allowRoaming, setupDataCallRequest.reason,
setupDataCallRequest.linkProperties, setupDataCallRequest.pduSessionId,
+ setupDataCallRequest.sliceInfo,
(setupDataCallRequest.callback != null)
? new DataServiceCallback(setupDataCallRequest.callback)
: null);
@@ -676,10 +685,12 @@
@Override
public void setupDataCall(int slotIndex, int accessNetworkType, DataProfile dataProfile,
boolean isRoaming, boolean allowRoaming, int reason,
- LinkProperties linkProperties, int pduSessionId, IDataServiceCallback callback) {
+ LinkProperties linkProperties, int pduSessionId, SliceInfo sliceInfo,
+ IDataServiceCallback callback) {
mHandler.obtainMessage(DATA_SERVICE_REQUEST_SETUP_DATA_CALL, slotIndex, 0,
new SetupDataCallRequest(accessNetworkType, dataProfile, isRoaming,
- allowRoaming, reason, linkProperties, pduSessionId, callback))
+ allowRoaming, reason, linkProperties, pduSessionId, sliceInfo,
+ callback))
.sendToTarget();
}
diff --git a/telephony/java/android/telephony/data/IDataService.aidl b/telephony/java/android/telephony/data/IDataService.aidl
index 3f1f033..e0b9a1a 100644
--- a/telephony/java/android/telephony/data/IDataService.aidl
+++ b/telephony/java/android/telephony/data/IDataService.aidl
@@ -19,6 +19,7 @@
import android.net.LinkProperties;
import android.telephony.data.DataProfile;
import android.telephony.data.IDataServiceCallback;
+import android.telephony.data.SliceInfo;
/**
* {@hide}
@@ -29,7 +30,7 @@
void removeDataServiceProvider(int slotId);
void setupDataCall(int slotId, int accessNetwork, in DataProfile dataProfile, boolean isRoaming,
boolean allowRoaming, int reason, in LinkProperties linkProperties,
- int pduSessionId, IDataServiceCallback callback);
+ int pduSessionId, in SliceInfo sliceInfo, IDataServiceCallback callback);
void deactivateDataCall(int slotId, int cid, int reason, IDataServiceCallback callback);
void setInitialAttachApn(int slotId, in DataProfile dataProfile, boolean isRoaming,
IDataServiceCallback callback);
diff --git a/telephony/java/android/telephony/data/SliceInfo.aidl b/telephony/java/android/telephony/data/SliceInfo.aidl
new file mode 100644
index 0000000..286ea5e
--- /dev/null
+++ b/telephony/java/android/telephony/data/SliceInfo.aidl
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/** @hide */
+package android.telephony.data;
+
+parcelable SliceInfo;
diff --git a/telephony/java/android/telephony/data/SliceInfo.java b/telephony/java/android/telephony/data/SliceInfo.java
new file mode 100644
index 0000000..51857a7
--- /dev/null
+++ b/telephony/java/android/telephony/data/SliceInfo.java
@@ -0,0 +1,342 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.data;
+
+import android.annotation.IntDef;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * Represents a S-NSSAI as defined in 3GPP TS 24.501.
+ *
+ * @hide
+ */
+@SystemApi
+public final class SliceInfo implements Parcelable {
+ /**
+ * When set on a Slice Differentiator, this value indicates that there is no corresponding
+ * Slice.
+ */
+ public static final int SLICE_DIFFERENTIATOR_NO_SLICE = -1;
+
+ /**
+ * Indicates that the service type is not present.
+ */
+ public static final int SLICE_SERVICE_TYPE_NONE = 0;
+
+ /**
+ * Slice suitable for the handling of 5G enhanced Mobile Broadband.
+ */
+ public static final int SLICE_SERVICE_TYPE_EMBB = 1;
+
+ /**
+ * Slice suitable for the handling of ultra-reliable low latency communications.
+ */
+ public static final int SLICE_SERVICE_TYPE_URLLC = 2;
+
+ /**
+ * Slice suitable for the handling of massive IoT.
+ */
+ public static final int SLICE_SERVICE_TYPE_MIOT = 3;
+
+ /**
+ * The min acceptable value for a Slice Differentiator
+ */
+ @SuppressLint("MinMaxConstant")
+ public static final int MIN_SLICE_DIFFERENTIATOR = -1;
+
+ /**
+ * The max acceptable value for a Slice Differentiator
+ */
+ @SuppressLint("MinMaxConstant")
+ public static final int MAX_SLICE_DIFFERENTIATOR = 0xFFFFFE;
+
+ /** @hide */
+ @IntDef(prefix = { "SLICE_SERVICE_TYPE_" }, value = {
+ SLICE_SERVICE_TYPE_NONE,
+ SLICE_SERVICE_TYPE_EMBB,
+ SLICE_SERVICE_TYPE_URLLC,
+ SLICE_SERVICE_TYPE_MIOT,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SliceServiceType {}
+
+
+ @SliceServiceType
+ private final int mSliceServiceType;
+ @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR)
+ private final int mSliceDifferentiator;
+ @SliceServiceType
+ private final int mMappedHplmnSliceServiceType;
+ @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR)
+ private final int mMappedHplmnSliceDifferentiator;
+
+ private SliceInfo(@SliceServiceType int sliceServiceType,
+ int sliceDifferentiator, int mappedHplmnSliceServiceType,
+ int mappedHplmnSliceDifferentiator) {
+ mSliceServiceType = sliceServiceType;
+ mSliceDifferentiator = sliceDifferentiator;
+ mMappedHplmnSliceDifferentiator = mappedHplmnSliceDifferentiator;
+ mMappedHplmnSliceServiceType = mappedHplmnSliceServiceType;
+ }
+
+ /**
+ * The type of service provided by the slice.
+ * <p/>
+ * see: 3GPP TS 24.501 Section 9.11.2.8.
+ */
+ @SliceServiceType
+ public int getSliceServiceType() {
+ return mSliceServiceType;
+ }
+
+ /**
+ * Identifies the slice from others with the same Slice Service Type.
+ * <p/>
+ * Returns {@link #SLICE_DIFFERENTIATOR_NO_SLICE} if {@link #getSliceServiceType} returns
+ * {@link #SLICE_SERVICE_TYPE_NONE}.
+ * <p/>
+ * see: 3GPP TS 24.501 Section 9.11.2.8.
+ */
+ @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR)
+ public int getSliceDifferentiator() {
+ return mSliceDifferentiator;
+ }
+
+ /**
+ * Corresponds to a Slice Info (S-NSSAI) of the HPLMN.
+ * <p/>
+ * see: 3GPP TS 24.501 Section 9.11.2.8.
+ */
+ @SliceServiceType
+ public int getMappedHplmnSliceServiceType() {
+ return mMappedHplmnSliceServiceType;
+ }
+
+ /**
+ * This Slice Differentiator corresponds to a {@link SliceInfo} (S-NSSAI) of the HPLMN;
+ * {@link #getSliceDifferentiator()} is mapped to this value.
+ * <p/>
+ * Returns {@link #SLICE_DIFFERENTIATOR_NO_SLICE} if either of the following are true:
+ * <ul>
+ * <li>{@link #getSliceDifferentiator()} returns {@link #SLICE_DIFFERENTIATOR_NO_SLICE}</li>
+ * <li>{@link #getMappedHplmnSliceServiceType()} returns {@link #SLICE_SERVICE_TYPE_NONE}</li>
+ * </ul>
+ * <p/>
+ * see: 3GPP TS 24.501 Section 9.11.2.8.
+ */
+ @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR)
+ public int getMappedHplmnSliceDifferentiator() {
+ return mMappedHplmnSliceDifferentiator;
+ }
+
+ private SliceInfo(@NonNull Parcel in) {
+ mSliceServiceType = in.readInt();
+ mSliceDifferentiator = in.readInt();
+ mMappedHplmnSliceServiceType = in.readInt();
+ mMappedHplmnSliceDifferentiator = in.readInt();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mSliceServiceType);
+ dest.writeInt(mSliceDifferentiator);
+ dest.writeInt(mMappedHplmnSliceServiceType);
+ dest.writeInt(mMappedHplmnSliceDifferentiator);
+ }
+
+ public static final @android.annotation.NonNull Parcelable.Creator<SliceInfo> CREATOR =
+ new Parcelable.Creator<SliceInfo>() {
+ @Override
+ @NonNull
+ public SliceInfo createFromParcel(@NonNull Parcel source) {
+ return new SliceInfo(source);
+ }
+
+ @Override
+ @NonNull
+ public SliceInfo[] newArray(int size) {
+ return new SliceInfo[size];
+ }
+ };
+
+ @Override
+ public String toString() {
+ return "SliceInfo{"
+ + "mSliceServiceType=" + sliceServiceTypeToString(mSliceServiceType)
+ + ", mSliceDifferentiator=" + mSliceDifferentiator
+ + ", mMappedHplmnSliceServiceType="
+ + sliceServiceTypeToString(mMappedHplmnSliceServiceType)
+ + ", mMappedHplmnSliceDifferentiator=" + mMappedHplmnSliceDifferentiator
+ + '}';
+ }
+
+ private static String sliceServiceTypeToString(@SliceServiceType int sliceServiceType) {
+ switch(sliceServiceType) {
+ case SLICE_SERVICE_TYPE_NONE:
+ return "NONE";
+ case SLICE_SERVICE_TYPE_EMBB:
+ return "EMBB";
+ case SLICE_SERVICE_TYPE_URLLC:
+ return "URLLC";
+ case SLICE_SERVICE_TYPE_MIOT:
+ return "MIOT";
+ default:
+ return Integer.toString(sliceServiceType);
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ SliceInfo sliceInfo = (SliceInfo) o;
+ return mSliceServiceType == sliceInfo.mSliceServiceType
+ && mSliceDifferentiator == sliceInfo.mSliceDifferentiator
+ && mMappedHplmnSliceServiceType == sliceInfo.mMappedHplmnSliceServiceType
+ && mMappedHplmnSliceDifferentiator == sliceInfo.mMappedHplmnSliceDifferentiator;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mSliceServiceType, mSliceDifferentiator, mMappedHplmnSliceServiceType,
+ mMappedHplmnSliceDifferentiator);
+ }
+
+ /**
+ * Provides a convenient way to set the fields of a {@link SliceInfo} when creating a
+ * new instance.
+ *
+ * <p>The example below shows how you might create a new {@code SliceInfo}:
+ *
+ * <pre><code>
+ *
+ * SliceInfo response = new SliceInfo.Builder()
+ * .setSliceServiceType(SLICE_SERVICE_TYPE_URLLC)
+ * .build();
+ * </code></pre>
+ */
+ public static final class Builder {
+ @SliceServiceType
+ private int mSliceServiceType = SLICE_SERVICE_TYPE_NONE;
+ @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR)
+ private int mSliceDifferentiator = SLICE_DIFFERENTIATOR_NO_SLICE;
+ @SliceServiceType
+ private int mMappedHplmnSliceServiceType = SLICE_SERVICE_TYPE_NONE;
+ @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR)
+ private int mMappedHplmnSliceDifferentiator = SLICE_DIFFERENTIATOR_NO_SLICE;
+
+ /**
+ * Default constructor for Builder.
+ */
+ public Builder() {
+ }
+
+ /**
+ * Set the Slice Service Type.
+ *
+ * @return The same instance of the builder.
+ */
+ @NonNull
+ public Builder setSliceServiceType(@SliceServiceType int mSliceServiceType) {
+ this.mSliceServiceType = mSliceServiceType;
+ return this;
+ }
+
+ /**
+ * Set the Slice Differentiator.
+ * <p/>
+ * A value of {@link #SLICE_DIFFERENTIATOR_NO_SLICE} indicates that there is no
+ * corresponding Slice.
+ *
+ * @throws IllegalArgumentException if the parameter is not between
+ * {@link #MIN_SLICE_DIFFERENTIATOR} and {@link #MAX_SLICE_DIFFERENTIATOR}.
+ *
+ * @return The same instance of the builder.
+ */
+ @NonNull
+ public Builder setSliceDifferentiator(
+ @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR)
+ int sliceDifferentiator) {
+ if (sliceDifferentiator < MIN_SLICE_DIFFERENTIATOR
+ || sliceDifferentiator > MAX_SLICE_DIFFERENTIATOR) {
+ throw new IllegalArgumentException("The slice diffentiator value is out of range");
+ }
+ this.mSliceDifferentiator = sliceDifferentiator;
+ return this;
+ }
+
+ /**
+ * Set the HPLMN Slice Service Type.
+ *
+ * @return The same instance of the builder.
+ */
+ @NonNull
+ public Builder setMappedHplmnSliceServiceType(
+ @SliceServiceType int mappedHplmnSliceServiceType) {
+ this.mMappedHplmnSliceServiceType = mappedHplmnSliceServiceType;
+ return this;
+ }
+
+ /**
+ * Set the HPLMN Slice Differentiator.
+ * <p/>
+ * A value of {@link #SLICE_DIFFERENTIATOR_NO_SLICE} indicates that there is no
+ * corresponding Slice of the HPLMN.
+ *
+ * @throws IllegalArgumentException if the parameter is not between
+ * {@link #MIN_SLICE_DIFFERENTIATOR} and {@link #MAX_SLICE_DIFFERENTIATOR}.
+ *
+ * @return The same instance of the builder.
+ */
+ @NonNull
+ public Builder setMappedHplmnSliceDifferentiator(
+ @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR)
+ int mappedHplmnSliceDifferentiator) {
+ if (mappedHplmnSliceDifferentiator < MIN_SLICE_DIFFERENTIATOR
+ || mappedHplmnSliceDifferentiator > MAX_SLICE_DIFFERENTIATOR) {
+ throw new IllegalArgumentException("The slice diffentiator value is out of range");
+ }
+ this.mMappedHplmnSliceDifferentiator = mappedHplmnSliceDifferentiator;
+ return this;
+ }
+
+ /**
+ * Build the {@link SliceInfo}.
+ *
+ * @return the {@link SliceInfo} object.
+ */
+ @NonNull
+ public SliceInfo build() {
+ return new SliceInfo(this.mSliceServiceType, this.mSliceDifferentiator,
+ this.mMappedHplmnSliceServiceType, this.mMappedHplmnSliceDifferentiator);
+ }
+ }
+}
diff --git a/telephony/java/android/telephony/ims/ImsRcsManager.java b/telephony/java/android/telephony/ims/ImsRcsManager.java
index 885ff9b..ad461c0 100644
--- a/telephony/java/android/telephony/ims/ImsRcsManager.java
+++ b/telephony/java/android/telephony/ims/ImsRcsManager.java
@@ -30,7 +30,6 @@
import android.provider.Settings;
import android.telephony.AccessNetworkConstants;
import android.telephony.BinderCacheManager;
-import android.telephony.CarrierConfigManager;
import android.telephony.TelephonyFrameworkInitializer;
import android.telephony.ims.aidl.IImsCapabilityCallback;
import android.telephony.ims.aidl.IImsRcsController;
@@ -62,9 +61,10 @@
* been enabled by the user can be queried using {@link RcsUceAdapter#isUceSettingEnabled()}.
* <p>
* This intent will always be handled by the system, however the application should only send
- * this Intent if the carrier supports RCS contact discovery, which can be queried using the key
- * {@link CarrierConfigManager#KEY_USE_RCS_PRESENCE_BOOL}. Otherwise, the RCS contact discovery
- * opt-in dialog will not be shown.
+ * this Intent if the carrier supports bulk RCS contact exchange, which will be true if either
+ * key {@link android.telephony.CarrierConfigManager.Ims#KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL}
+ * or {@link android.telephony.CarrierConfigManager#KEY_USE_RCS_PRESENCE_BOOL} is set to true.
+ * Otherwise, the RCS contact discovery opt-in dialog will not be shown.
* <p>
* Input: A mandatory {@link Settings#EXTRA_SUB_ID} extra containing the subscription that the
* setting will be be shown for.
@@ -396,6 +396,7 @@
* rather the subscription is capable of this service over IMS.
* @see #isAvailable(int)
* @see android.telephony.CarrierConfigManager#KEY_USE_RCS_PRESENCE_BOOL
+ * @see android.telephony.CarrierConfigManager.Ims#KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL
* @throws ImsException if the IMS service is not available when calling this method.
* See {@link ImsException#getCode()} for more information on the error codes.
* @hide
diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java
index 24ae979..f444c62 100644
--- a/telephony/java/android/telephony/ims/ProvisioningManager.java
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -21,6 +21,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.SdkConstant;
import android.annotation.StringDef;
import android.annotation.SystemApi;
import android.annotation.WorkerThread;
@@ -31,6 +32,7 @@
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyFrameworkInitializer;
import android.telephony.ims.aidl.IImsConfigCallback;
+import android.telephony.ims.aidl.IRcsConfigCallback;
import android.telephony.ims.feature.MmTelFeature;
import android.telephony.ims.feature.RcsFeature;
import android.telephony.ims.stub.ImsConfigImplBase;
@@ -936,6 +938,115 @@
private int mSubId;
/**
+ * The callback for RCS provisioning changes.
+ */
+ public static class RcsProvisioningCallback {
+ private static class CallbackBinder extends IRcsConfigCallback.Stub {
+
+ private final RcsProvisioningCallback mLocalCallback;
+ private Executor mExecutor;
+
+ private CallbackBinder(RcsProvisioningCallback localCallback) {
+ mLocalCallback = localCallback;
+ }
+
+ @Override
+ public void onConfigurationChanged(byte[] configXml) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mLocalCallback.onConfigurationChanged(configXml));
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void onAutoConfigurationErrorReceived(int errorCode, String errorString) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mLocalCallback.onAutoConfigurationErrorReceived(
+ errorCode, errorString));
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void onConfigurationReset() {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mLocalCallback.onConfigurationReset());
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void onRemoved() {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mLocalCallback.onRemoved());
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ private void setExecutor(Executor executor) {
+ mExecutor = executor;
+ }
+ }
+
+ private final CallbackBinder mBinder = new CallbackBinder(this);
+
+ /**
+ * RCS configuration received via OTA provisioning. Configuration may change
+ * due to various triggers defined in GSMA RCC.14 for ACS(auto configuration
+ * server) or other operator defined triggers. If RCS provisioning is already
+ * completed at the time of callback registration, then this method shall be
+ * invoked with the current configuration
+ * @param configXml The RCS configurationXML received OTA.
+ */
+ public void onConfigurationChanged(@NonNull byte[] configXml) {}
+
+ /**
+ * Errors during autoconfiguration connection setup are notified by the
+ * ACS(auto configuration server) client using this interface.
+ * @param errorCode HTTP error received during connection setup defined in
+ * GSMA RCC.14 2.4.3, like {@link java.net.HttpURLConnection#HTTP_UNAUTHORIZED},
+ * {@link java.net.HttpURLConnection#HTTP_FORBIDDEN}, etc.
+ * @param errorString reason phrase received with the error
+ */
+ public void onAutoConfigurationErrorReceived(int errorCode,
+ @NonNull String errorString) {}
+
+ /**
+ * When the previously valid RCS configuration is cleaned up by telephony for
+ * any case like SIM removed, default messaging application changed, etc.,
+ * this method will be invoked to notify the application regarding this change.
+ */
+ public void onConfigurationReset() {}
+
+ /**
+ * When the RCS application is no longer the Default messaging application,
+ * or when the subscription associated with this callback is removed (SIM
+ * removed, ESIM swap,etc...), callback will automatically be removed and
+ * the below method is invoked. There is a possibility that the method is
+ * invoked after the subscription has become inactive
+ */
+ public void onRemoved() {}
+
+ /**@hide*/
+ public final IRcsConfigCallback getBinder() {
+ return mBinder;
+ }
+
+ /**@hide*/
+ public void setExecutor(Executor executor) {
+ mBinder.setExecutor(executor);
+ }
+ }
+
+ /**
* Create a new {@link ProvisioningManager} for the subscription specified.
*
* @param subId The ID of the subscription that this ProvisioningManager will use.
@@ -1207,6 +1318,174 @@
}
+ /**
+ * Provides the single registration capability of the device and the carrier.
+ *
+ * <p>This intent only provides the capability and not the current provisioning status of
+ * the RCS VoLTE single registration feature. Only default messaging application may receive
+ * the intent.
+ *
+ * <p>Contains {@link #EXTRA_SUBSCRIPTION_INDEX} to specify the subscription index for which
+ * the intent is valid. and {@link #EXTRA_STATUS} to specify RCS VoLTE single registration
+ * status.
+ */
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE =
+ "android.telephony.ims.action.RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE";
+
+ /**
+ * Integer extra to specify subscription index.
+ */
+ public static final String EXTRA_SUBSCRIPTION_ID =
+ "android.telephony.ims.extra.SUBSCRIPTION_ID";
+
+ /**
+ * Integer extra to specify RCS single registration status
+ *
+ * <p>The value can be {@link #STATUS_CAPABLE}, {@link #STATUS_DEVICE_NOT_CAPABLE},
+ * {@link #STATUS_CARRIER_NOT_CAPABLE}, or bitwise OR of
+ * {@link #STATUS_DEVICE_NOT_CAPABLE} and {@link #STATUS_CARRIER_NOT_CAPABLE}.
+ */
+ public static final String EXTRA_STATUS = "android.telephony.ims.extra.STATUS";
+
+ /**
+ * RCS VoLTE single registration is supported by the device and carrier.
+ */
+ public static final int STATUS_CAPABLE = 0;
+
+ /**
+ * RCS VoLTE single registration is not supported by the device.
+ */
+ public static final int STATUS_DEVICE_NOT_CAPABLE = 0x01;
+
+ /**
+ * RCS VoLTE single registration is not supported by the carrier
+ */
+ public static final int STATUS_CARRIER_NOT_CAPABLE = 0x01 << 1;
+
+ /**
+ * Provide the client configuration parameters of the RCS application.
+ *
+ * <p>When this application is also the default messaging application, and RCS
+ * provisioning is done using autoconfiguration, then these parameters shall be
+ * sent in the HTTP get request to fetch the RCS provisioning. RCS client
+ * configuration must be provided by the application before registering for the
+ * provisioning status events {@link #registerRcsProvisioningChangedCallback()}
+ * @param rcc RCS client configuration {@link RcsClientConfiguration}
+ */
+ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+ public void setRcsClientConfiguration(
+ @NonNull RcsClientConfiguration rcc) throws ImsException {
+ try {
+ getITelephony().setRcsClientConfiguration(mSubId, rcc);
+ } catch (ServiceSpecificException e) {
+ throw new ImsException(e.getMessage(), e.errorCode);
+ } catch (RemoteException | IllegalStateException e) {
+ throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
+ }
+
+ /**
+ * Returns a flag to indicate if the device software and the carrier
+ * have the capability to support RCS Volte single IMS registration.
+ * @return true if this single registration is capable, false otherwise
+ * @throws ImsException If the remote ImsService is not available for
+ * any reason or the subscription associated with this instance is no
+ * longer active. See {@link ImsException#getCode()} for more
+ * information.
+ */
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public boolean isRcsVolteSingleRegistrationCapable() throws ImsException {
+ try {
+ return getITelephony().isRcsVolteSingleRegistrationCapable(mSubId);
+ } catch (RemoteException | IllegalStateException e) {
+ throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
+ }
+
+ /**
+ * Registers a new {@link RcsProvisioningCallback} to listen to changes to
+ * RCS provisioning xml.
+ *
+ * <p>RCS application must be the default messaging application and must
+ * have already registered its {@link RcsClientConfiguration} by using
+ * {@link #setRcsClientConfiguration} before it registers the provisioning
+ * callback. If ProvisioningManager has a valid RCS configuration at the
+ * time of callback registration and a reconfiguration is not required
+ * due to RCS client parameters change, then the callback shall be invoked
+ * immediately with the xml.
+ * When the subscription associated with this callback is removed (SIM removed,
+ * ESIM swap,etc...), this callback will automatically be removed.
+ *
+ * @param executor The {@link Executor} to call the callback methods on
+ * @param callback The rcs provisioning callback to be registered.
+ * @see #unregisterRcsProvisioningChangedCallback(RcsProvisioningCallback)
+ * @see SubscriptionManager.OnSubscriptionsChangedListener
+ * @throws IllegalArgumentException if the subscription associated with this
+ * callback is not active (SIM is not inserted, ESIM inactive) or the
+ * subscription is invalid.
+ * @throws ImsException if the subscription associated with this callback is
+ * valid, but the {@link ImsService} associated with the subscription is not
+ * available. This can happen if the service crashed, for example.
+ * It shall also throw this exception when the RCS client parameters for the
+ * application are not valid. In that case application must set the client
+ * params (See {@link #setRcsClientConfiguration()}) and re register the
+ * callback.
+ * See {@link ImsException#getCode()} for a more detailed reason.
+ */
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public void registerRcsProvisioningChangedCallback(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull RcsProvisioningCallback callback) throws ImsException {
+ callback.setExecutor(executor);
+ try {
+ getITelephony().registerRcsProvisioningChangedCallback(mSubId, callback.getBinder());
+ } catch (ServiceSpecificException e) {
+ throw new ImsException(e.getMessage(), e.errorCode);
+ } catch (RemoteException | IllegalStateException e) {
+ throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
+ }
+
+ /**
+ * Unregister an existing {@link RcsProvisioningCallback}. Application can
+ * unregister when its no longer interested in the provisioning updates
+ * like when a user disables RCS from the UI/settings.
+ * When the subscription associated with this callback is removed (SIM
+ * removed, ESIM swap, etc...), this callback will automatically be
+ * removed. If this method is called for an inactive subscription, it
+ * will result in a no-op.
+ * @param callback The existing {@link RcsProvisioningCallback} to be
+ * removed.
+ * @see #registerRcsProvisioningChangedCallback(RcsClientConfiguration,
+ * Executor, RcsProvisioningCallback) @throws IllegalArgumentException
+ * if the subscription associated with this callback is invalid.
+ */
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public void unregisterRcsProvisioningChangedCallback(
+ @NonNull RcsProvisioningCallback callback) {
+ try {
+ getITelephony().unregisterRcsProvisioningChangedCallback(
+ mSubId, callback.getBinder());
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Reconfiguration triggered by the RCS application. Most likely cause
+ * is the 403 forbidden to a HTTP request.
+ */
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public void triggerRcsReconfiguration() {
+ try {
+ getITelephony().triggerRcsReconfiguration(mSubId);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
private static ITelephony getITelephony() {
ITelephony binder = ITelephony.Stub.asInterface(
TelephonyFrameworkInitializer
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java b/telephony/java/android/telephony/ims/RcsClientConfiguration.aidl
similarity index 62%
copy from media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java
copy to telephony/java/android/telephony/ims/RcsClientConfiguration.aidl
index 52f2787..a702f0f 100644
--- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java
+++ b/telephony/java/android/telephony/ims/RcsClientConfiguration.aidl
@@ -14,19 +14,6 @@
* limitations under the License.
*/
-package com.android.mediatranscodingtest;
+package android.telephony.ims;
-/**
- *
- * This class has the names of the all the activity name and variables in the
- * instrumentation test.
- *
- */
-public class MediaConstants {
- /*
- * Source test files.
- */
- public static final String[] SOURCE_HEVC_VIDEO_ONLY_TEST_FILES = {
- "/sdcard/media_api/video/VideoOnlyHEVC.mp4",
- };
-}
+parcelable RcsClientConfiguration;
diff --git a/telephony/java/android/telephony/ims/RcsClientConfiguration.java b/telephony/java/android/telephony/ims/RcsClientConfiguration.java
new file mode 100644
index 0000000..793c377
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsClientConfiguration.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.ims;
+
+import android.annotation.NonNull;
+import android.annotation.StringDef;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * The container of RCS application related configs.
+ *
+ * @hide
+ */
+@SystemApi
+public final class RcsClientConfiguration implements Parcelable {
+
+ /**@hide*/
+ @StringDef(prefix = "RCS_PROFILE_",
+ value = {RCS_PROFILE_1_0, RCS_PROFILE_2_3})
+ public @interface StringRcsProfile {}
+
+ /**
+ * RCS profile UP 1.0
+ */
+ public static final String RCS_PROFILE_1_0 = "UP_1.0";
+ /**
+ * RCS profile UP 2.3
+ */
+ public static final String RCS_PROFILE_2_3 = "UP_2.3";
+
+ private String mRcsVersion;
+ private String mRcsProfile;
+ private String mClientVendor;
+ private String mClientVersion;
+
+ /**
+ * Create a RcsClientConfiguration object.
+ * Default messaging application must pass a valid configuration object
+ * @param rcsVersion The parameter identifies the RCS version supported
+ * by the client. Refer to GSMA RCC.07 "rcs_version" parameter.
+ * @param rcsProfile Identifies a fixed set of RCS services that are
+ * supported by the client. See {@link #RCS_PROFILE_1_0 } or
+ * {@link #RCS_PROFILE_2_3 }
+ * @param clientVendor Identifies the vendor providing the RCS client.
+ * @param clientVersion Identifies the RCS client version. Refer to GSMA
+ * RCC.07 "client_version" parameter.
+ * Example:client_version=RCSAndrd-1.0
+ */
+ public RcsClientConfiguration(@NonNull String rcsVersion,
+ @NonNull @StringRcsProfile String rcsProfile,
+ @NonNull String clientVendor, @NonNull String clientVersion) {
+ mRcsVersion = rcsVersion;
+ mRcsProfile = rcsProfile;
+ mClientVendor = clientVendor;
+ mClientVersion = clientVersion;
+ }
+
+ /**
+ * Returns RCS version supported.
+ */
+ public @NonNull String getRcsVersion() {
+ return mRcsVersion;
+ }
+
+ /**
+ * Returns RCS profile supported.
+ */
+ public @NonNull @StringRcsProfile String getRcsProfile() {
+ return mRcsProfile;
+ }
+
+ /**
+ * Returns the name of the vendor providing the RCS client.
+ */
+ public @NonNull String getClientVendor() {
+ return mClientVendor;
+ }
+
+ /**
+ * Returns the RCS client version.
+ */
+ public @NonNull String getClientVersion() {
+ return mClientVersion;
+ }
+
+ /**
+ * {@link Parcelable#writeToParcel}
+ */
+ @Override
+ public void writeToParcel(@NonNull Parcel out, int flags) {
+ out.writeString(mRcsVersion);
+ out.writeString(mRcsProfile);
+ out.writeString(mClientVendor);
+ out.writeString(mClientVersion);
+ }
+
+ /**
+ * {@link Parcelable.Creator}
+ *
+ */
+ public static final @android.annotation.NonNull Parcelable.Creator<
+ RcsClientConfiguration> CREATOR = new Creator<RcsClientConfiguration>() {
+ @Override
+ public RcsClientConfiguration createFromParcel(Parcel in) {
+ String rcsVersion = in.readString();
+ String rcsProfile = in.readString();
+ String clientVendor = in.readString();
+ String clientVersion = in.readString();
+ return new RcsClientConfiguration(rcsVersion, rcsProfile,
+ clientVendor, clientVersion);
+ }
+
+ @Override
+ public RcsClientConfiguration[] newArray(int size) {
+ return new RcsClientConfiguration[size];
+ }
+ };
+
+ /**
+ * {@link Parcelable#describeContents}
+ */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof RcsClientConfiguration)) {
+ return false;
+ }
+
+ RcsClientConfiguration other = (RcsClientConfiguration) obj;
+
+ return mRcsVersion.equals(other.mRcsVersion) && mRcsProfile.equals(other.mRcsProfile)
+ && mClientVendor.equals(other.mClientVendor)
+ && mClientVersion.equals(other.mClientVersion);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mRcsVersion, mRcsProfile, mClientVendor, mClientVersion);
+ }
+}
diff --git a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java b/telephony/java/android/telephony/ims/RcsConfig.aidl
similarity index 62%
copy from media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java
copy to telephony/java/android/telephony/ims/RcsConfig.aidl
index 52f2787..cfd93fb 100644
--- a/media/tests/MediaTranscodingTest/src/com/android/mediatranscodingtest/MediaConstants.java
+++ b/telephony/java/android/telephony/ims/RcsConfig.aidl
@@ -14,19 +14,6 @@
* limitations under the License.
*/
-package com.android.mediatranscodingtest;
+package android.telephony.ims;
-/**
- *
- * This class has the names of the all the activity name and variables in the
- * instrumentation test.
- *
- */
-public class MediaConstants {
- /*
- * Source test files.
- */
- public static final String[] SOURCE_HEVC_VIDEO_ONLY_TEST_FILES = {
- "/sdcard/media_api/video/VideoOnlyHEVC.mp4",
- };
-}
+parcelable RcsConfig;
diff --git a/telephony/java/android/telephony/ims/RcsConfig.java b/telephony/java/android/telephony/ims/RcsConfig.java
new file mode 100644
index 0000000..07e95cc
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsConfig.java
@@ -0,0 +1,306 @@
+/*
+ * 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.telephony.ims;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.os.Build;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.provider.Telephony.SimInfo;
+import android.text.TextUtils;
+
+import com.android.telephony.Rlog;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+/**
+ * RCS config data and methods to process the config
+ * @hide
+ */
+public final class RcsConfig implements Parcelable {
+ private static final String LOG_TAG = "RcsConfig";
+ private static final boolean DBG = Build.IS_ENG;
+
+ private final HashMap<String, String> mValues = new HashMap<>();
+
+ private RcsConfig(HashMap<String, String> values) {
+ mValues.putAll(values);
+ }
+
+ public RcsConfig(byte[] data) throws IllegalArgumentException {
+ if (data == null || data.length == 0) {
+ throw new IllegalArgumentException("Empty data");
+ }
+ ByteArrayInputStream inputStream = new ByteArrayInputStream(data);
+ try {
+ XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
+ factory.setNamespaceAware(true);
+ XmlPullParser xpp = factory.newPullParser();
+ xpp.setInput(inputStream, null);
+ int eventType = xpp.getEventType();
+ String tag = null;
+ while (eventType != XmlPullParser.END_DOCUMENT) {
+ if (eventType == XmlPullParser.START_TAG) {
+ tag = xpp.getName().trim();
+ } else if (eventType == XmlPullParser.END_TAG) {
+ tag = null;
+ } else if (eventType == XmlPullParser.TEXT) {
+ String value = xpp.getText().trim();
+ if (!TextUtils.isEmpty(tag) && !TextUtils.isEmpty(value)) {
+ mValues.put(tag, value);
+ }
+ }
+ eventType = xpp.next();
+ }
+ } catch (IOException | XmlPullParserException e) {
+ throw new IllegalArgumentException(e);
+ } finally {
+ try {
+ inputStream.close();
+ } catch (IOException e) {
+ loge("error to close input stream, skip.");
+ }
+ }
+ }
+
+ /**
+ * Retrieve a String value of the config item with the tag
+ *
+ * @param tag The name of the config to retrieve.
+ * @param defaultVal Value to return if the config does not exist.
+ *
+ * @return Returns the config value if it exists, or defaultVal.
+ */
+ public @Nullable String getString(@NonNull String tag, @Nullable String defaultVal) {
+ return mValues.containsKey(tag) ? mValues.get(tag) : defaultVal;
+ }
+
+ /**
+ * Retrieve a int value of the config item with the tag
+ *
+ * @param tag The name of the config to retrieve.
+ * @param defaultVal Value to return if the config does not exist or not valid.
+ *
+ * @return Returns the config value if it exists and is a valid int, or defaultVal.
+ */
+ public int getInteger(@NonNull String tag, int defaultVal) {
+ try {
+ return Integer.parseInt(mValues.get(tag));
+ } catch (NumberFormatException e) {
+ logd("error to getInteger for " + tag + " due to " + e);
+ }
+ return defaultVal;
+ }
+
+ /**
+ * Retrieve a boolean value of the config item with the tag
+ *
+ * @param tag The name of the config to retrieve.
+ * @param defaultVal Value to return if the config does not exist.
+ *
+ * @return Returns the config value if it exists, or defaultVal.
+ */
+ public boolean getBoolean(@NonNull String tag, boolean defaultVal) {
+ if (!mValues.containsKey(tag)) {
+ return defaultVal;
+ }
+ return Boolean.parseBoolean(mValues.get(tag));
+ }
+
+ /**
+ * Check whether the config item exists
+ *
+ * @param tag The name of the config to retrieve.
+ *
+ * @return Returns true if it exists, or false.
+ */
+ public boolean hasConfig(@NonNull String tag) {
+ return mValues.containsKey(tag);
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append("[RCS Config]");
+ if (DBG) {
+ mValues.forEach((t, v) -> {
+ sb.append("\n");
+ sb.append(t);
+ sb.append(" : ");
+ sb.append(v);
+ });
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof RcsConfig)) {
+ return false;
+ }
+
+ RcsConfig other = (RcsConfig) obj;
+
+ return mValues.equals(other.mValues);
+ }
+
+ @Override
+ public int hashCode() {
+ return mValues.hashCode();
+ }
+
+ /**
+ * compress the gzip format data
+ */
+ public static @Nullable byte[] compressGzip(@NonNull byte[] data) {
+ if (data == null || data.length == 0) {
+ return data;
+ }
+ byte[] out = null;
+ try {
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length);
+ GZIPOutputStream gzipCompressingStream =
+ new GZIPOutputStream(outputStream);
+ gzipCompressingStream.write(data);
+ gzipCompressingStream.close();
+ out = outputStream.toByteArray();
+ outputStream.close();
+ } catch (IOException e) {
+ loge("Error to compressGzip due to " + e);
+ }
+ return out;
+ }
+
+ /**
+ * decompress the gzip format data
+ */
+ public static @Nullable byte[] decompressGzip(@NonNull byte[] data) {
+ if (data == null || data.length == 0) {
+ return data;
+ }
+ byte[] out = null;
+ try {
+ ByteArrayInputStream inputStream = new ByteArrayInputStream(data);
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ GZIPInputStream gzipDecompressingStream =
+ new GZIPInputStream(inputStream);
+ byte[] buf = new byte[1024];
+ int size = gzipDecompressingStream.read(buf);
+ while (size >= 0) {
+ outputStream.write(buf, 0, size);
+ size = gzipDecompressingStream.read(buf);
+ }
+ gzipDecompressingStream.close();
+ inputStream.close();
+ out = outputStream.toByteArray();
+ outputStream.close();
+ } catch (IOException e) {
+ loge("Error to decompressGzip due to " + e);
+ }
+ return out;
+ }
+
+ /**
+ * save the config to siminfo db. It is only used internally.
+ */
+ public static void updateConfigForSub(@NonNull Context cxt, int subId,
+ @NonNull byte[] config, boolean isCompressed) {
+ //always store gzip compressed data
+ byte[] data = isCompressed ? config : compressGzip(config);
+ ContentValues values = new ContentValues();
+ values.put(SimInfo.COLUMN_RCS_CONFIG, data);
+ cxt.getContentResolver().update(SimInfo.CONTENT_URI, values,
+ SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID + "=" + subId, null);
+ }
+
+ /**
+ * load the config from siminfo db. It is only used internally.
+ */
+ public static @Nullable byte[] loadRcsConfigForSub(@NonNull Context cxt,
+ int subId, boolean isCompressed) {
+
+ byte[] data = null;
+
+ Cursor cursor = cxt.getContentResolver().query(SimInfo.CONTENT_URI, null,
+ SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID + "=" + subId, null, null);
+ try {
+ if (cursor != null && cursor.moveToFirst()) {
+ data = cursor.getBlob(cursor.getColumnIndexOrThrow(SimInfo.COLUMN_RCS_CONFIG));
+ }
+ } catch (Exception e) {
+ loge("error to load rcs config for sub:" + subId + " due to " + e);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
+ }
+ return isCompressed ? data : decompressGzip(data);
+ }
+
+ /**
+ * {@link Parcelable#writeToParcel}
+ */
+ public void writeToParcel(@NonNull Parcel out, int flags) {
+ out.writeMap(mValues);
+ }
+
+ /**
+ * {@link Parcelable.Creator}
+ *
+ */
+ public static final @NonNull Parcelable.Creator<RcsConfig>
+ CREATOR = new Creator<RcsConfig>() {
+ @Override
+ public RcsConfig createFromParcel(Parcel in) {
+ HashMap<String, String> values = in.readHashMap(null);
+ return values == null ? null : new RcsConfig(values);
+ }
+
+ @Override
+ public RcsConfig[] newArray(int size) {
+ return new RcsConfig[size];
+ }
+ };
+
+ /**
+ * {@link Parcelable#describeContents}
+ */
+ public int describeContents() {
+ return 0;
+ }
+
+ private static void logd(String msg) {
+ Rlog.d(LOG_TAG, msg);
+ }
+
+ private static void loge(String msg) {
+ Rlog.e(LOG_TAG, msg);
+ }
+}
diff --git a/telephony/java/android/telephony/ims/SipDelegateManager.java b/telephony/java/android/telephony/ims/SipDelegateManager.java
index 2ec88ff..2e9eb94 100644
--- a/telephony/java/android/telephony/ims/SipDelegateManager.java
+++ b/telephony/java/android/telephony/ims/SipDelegateManager.java
@@ -18,7 +18,9 @@
import android.Manifest;
import android.annotation.IntDef;
+import android.annotation.IntRange;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.content.Context;
@@ -372,4 +374,37 @@
+ " into this method");
}
}
+
+ /**
+ * Trigger a full network registration as required by receiving a SIP message containing a
+ * permanent error from the network or never receiving a response to a SIP transaction request.
+ *
+ * @param connection The {@link SipDelegateConnection} that was being used when this error was
+ * received.
+ * @param sipCode The SIP code response associated with the SIP message request that
+ * triggered this condition.
+ * @param sipReason The SIP reason code associated with the SIP message request that triggered
+ * this condition. May be {@code null} if there was no reason String provided from the
+ * network.
+ */
+ public void triggerFullNetworkRegistration(@NonNull SipDelegateConnection connection,
+ @IntRange(from = 100, to = 699) int sipCode, @Nullable String sipReason) {
+ if (connection == null) {
+ throw new IllegalArgumentException("invalid connection.");
+ }
+ if (connection instanceof SipDelegateConnectionAidlWrapper) {
+ SipDelegateConnectionAidlWrapper w = (SipDelegateConnectionAidlWrapper) connection;
+ try {
+ IImsRcsController controller = mBinderCache.getBinder();
+ controller.triggerNetworkRegistration(mSubId, w.getSipDelegateBinder(), sipCode,
+ sipReason);
+ } catch (RemoteException e) {
+ // Connection to telephony died, but this will signal destruction of SipDelegate
+ // eventually anyway, so return.
+ }
+ } else {
+ throw new IllegalArgumentException("Unknown SipDelegateConnection implementation passed"
+ + " into this method");
+ }
+ }
}
diff --git a/telephony/java/android/telephony/ims/aidl/IImsConfig.aidl b/telephony/java/android/telephony/ims/aidl/IImsConfig.aidl
index 57206c9..5eee389 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsConfig.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsConfig.aidl
@@ -18,8 +18,9 @@
package android.telephony.ims.aidl;
import android.os.PersistableBundle;
-
import android.telephony.ims.aidl.IImsConfigCallback;
+import android.telephony.ims.aidl.IRcsConfigCallback;
+import android.telephony.ims.RcsClientConfiguration;
import com.android.ims.ImsConfigListener;
@@ -41,4 +42,9 @@
int setConfigString(int item, String value);
void updateImsCarrierConfigs(in PersistableBundle bundle);
void notifyRcsAutoConfigurationReceived(in byte[] config, boolean isCompressed);
+ void notifyRcsAutoConfigurationRemoved();
+ void addRcsConfigCallback(IRcsConfigCallback c);
+ void removeRcsConfigCallback(IRcsConfigCallback c);
+ void triggerRcsReconfiguration();
+ void setRcsClientConfiguration(in RcsClientConfiguration rcc);
}
diff --git a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
index c6d9a86..3634989 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
@@ -67,6 +67,8 @@
ISipDelegateConnectionStateCallback delegateState,
ISipDelegateMessageCallback delegateMessage);
void destroySipDelegate(int subId, ISipDelegate connection, int reason);
+ void triggerNetworkRegistration(int subId, ISipDelegate connection, int sipCode,
+ String sipReason);
// Internal commands that should not be made public
void registerRcsFeatureCallback(int slotId, in IImsServiceFeatureCallback callback);
diff --git a/telephony/java/android/telephony/ims/aidl/IImsRegistration.aidl b/telephony/java/android/telephony/ims/aidl/IImsRegistration.aidl
index 4ae0a75..4fd9040 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsRegistration.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsRegistration.aidl
@@ -28,4 +28,7 @@
int getRegistrationTechnology();
oneway void addRegistrationCallback(IImsRegistrationCallback c);
oneway void removeRegistrationCallback(IImsRegistrationCallback c);
-}
\ No newline at end of file
+ oneway void triggerFullNetworkRegistration(int sipCode, String sipReason);
+ oneway void triggerUpdateSipDelegateRegistration();
+ oneway void triggerSipDelegateDeregistration();
+}
diff --git a/telephony/java/android/telephony/ims/aidl/IRcsConfigCallback.aidl b/telephony/java/android/telephony/ims/aidl/IRcsConfigCallback.aidl
new file mode 100644
index 0000000..5a8973e
--- /dev/null
+++ b/telephony/java/android/telephony/ims/aidl/IRcsConfigCallback.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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.telephony.ims.aidl;
+
+/**
+ * The callback for RCS provisioning changes.
+ * {@hide}
+ */
+oneway interface IRcsConfigCallback {
+ void onConfigurationChanged(in byte[] config);
+ void onAutoConfigurationErrorReceived(int errorCode, String errorString);
+ void onConfigurationReset();
+ void onRemoved();
+}
+
diff --git a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
index e757d9f..cc050be 100644
--- a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
@@ -23,8 +23,11 @@
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.telephony.ims.ProvisioningManager;
+import android.telephony.ims.RcsClientConfiguration;
+import android.telephony.ims.RcsConfig;
import android.telephony.ims.aidl.IImsConfig;
import android.telephony.ims.aidl.IImsConfigCallback;
+import android.telephony.ims.aidl.IRcsConfigCallback;
import android.util.Log;
import com.android.ims.ImsConfig;
@@ -202,7 +205,13 @@
@Override
public void notifyRcsAutoConfigurationReceived(byte[] config, boolean isCompressed)
throws RemoteException {
- getImsConfigImpl().notifyRcsAutoConfigurationReceived(config, isCompressed);
+ getImsConfigImpl().onNotifyRcsAutoConfigurationReceived(config, isCompressed);
+ }
+
+ @Override
+ public void notifyRcsAutoConfigurationRemoved()
+ throws RemoteException {
+ getImsConfigImpl().onNotifyRcsAutoConfigurationRemoved();
}
private void notifyImsConfigChanged(int item, int value) throws RemoteException {
@@ -228,6 +237,26 @@
notifyImsConfigChanged(item, value);
}
}
+
+ @Override
+ public void addRcsConfigCallback(IRcsConfigCallback c) throws RemoteException {
+ getImsConfigImpl().addRcsConfigCallback(c);
+ }
+
+ @Override
+ public void removeRcsConfigCallback(IRcsConfigCallback c) throws RemoteException {
+ getImsConfigImpl().removeRcsConfigCallback(c);
+ }
+
+ @Override
+ public void triggerRcsReconfiguration() throws RemoteException {
+ getImsConfigImpl().triggerAutoConfiguration();
+ }
+
+ @Override
+ public void setRcsClientConfiguration(RcsClientConfiguration rcc) throws RemoteException {
+ getImsConfigImpl().setRcsClientConfiguration(rcc);
+ }
}
/**
@@ -257,6 +286,9 @@
private final RemoteCallbackListExt<IImsConfigCallback> mCallbacks =
new RemoteCallbackListExt<>();
+ private final RemoteCallbackListExt<IRcsConfigCallback> mRcsCallbacks =
+ new RemoteCallbackListExt<>();
+ private byte[] mRcsConfigData;
ImsConfigStub mImsConfigStub;
/**
@@ -320,6 +352,50 @@
});
}
+ private void addRcsConfigCallback(IRcsConfigCallback c) {
+ mRcsCallbacks.register(c);
+ if (mRcsConfigData != null) {
+ try {
+ c.onConfigurationChanged(mRcsConfigData);
+ } catch (RemoteException e) {
+ Log.w(TAG, "dead binder to call onConfigurationChanged, skipping.");
+ }
+ }
+ }
+
+ private void removeRcsConfigCallback(IRcsConfigCallback c) {
+ mRcsCallbacks.unregister(c);
+ }
+
+ private void onNotifyRcsAutoConfigurationReceived(byte[] config, boolean isCompressed) {
+ mRcsConfigData = isCompressed ? RcsConfig.decompressGzip(config) : config;
+ // can be null in testing
+ if (mRcsCallbacks != null) {
+ mRcsCallbacks.broadcastAction(c -> {
+ try {
+ c.onConfigurationChanged(mRcsConfigData);
+ } catch (RemoteException e) {
+ Log.w(TAG, "dead binder in notifyRcsAutoConfigurationReceived, skipping.");
+ }
+ });
+ }
+ notifyRcsAutoConfigurationReceived(config, isCompressed);
+ }
+
+ private void onNotifyRcsAutoConfigurationRemoved() {
+ mRcsConfigData = null;
+ if (mRcsCallbacks != null) {
+ mRcsCallbacks.broadcastAction(c -> {
+ try {
+ c.onConfigurationReset();
+ } catch (RemoteException e) {
+ Log.w(TAG, "dead binder in notifyRcsAutoConfigurationRemoved, skipping.");
+ }
+ });
+ }
+ notifyRcsAutoConfigurationRemoved();
+ }
+
/**
* @hide
*/
@@ -369,6 +445,12 @@
}
/**
+ * The RCS autoconfiguration XML file is removed or invalid.
+ */
+ public void notifyRcsAutoConfigurationRemoved() {
+ }
+
+ /**
* Sets the configuration value for this ImsService.
*
* @param item an integer key.
@@ -421,4 +503,43 @@
public void updateImsCarrierConfigs(PersistableBundle bundle) {
// Base Implementation - Should be overridden
}
+
+ /**
+ * Default messaging application parameters are sent to the ACS client
+ * using this interface.
+ * @param rcc RCS client configuration {@link RcsClientConfiguration}
+ */
+ public void setRcsClientConfiguration(@NonNull RcsClientConfiguration rcc) {
+ // Base Implementation - Should be overridden
+ }
+
+ /**
+ * Reconfiguration triggered by the RCS application. Most likely cause
+ * is the 403 forbidden to a SIP/HTTP request
+ */
+ public void triggerAutoConfiguration() {
+ // Base Implementation - Should be overridden
+ }
+
+ /**
+ * Errors during autoconfiguration connection setup are notified by the
+ * ACS client using this interface.
+ * @param errorCode HTTP error received during connection setup.
+ * @param errorString reason phrase received with the error
+ */
+ public final void notifyAutoConfigurationErrorReceived(int errorCode,
+ @NonNull String errorString) {
+ // can be null in testing
+ if (mRcsCallbacks == null) {
+ return;
+ }
+ mRcsCallbacks.broadcastAction(c -> {
+ try {
+ //TODO compressed by default?
+ c.onAutoConfigurationErrorReceived(errorCode, errorString);
+ } catch (RemoteException e) {
+ Log.w(TAG, "dead binder in notifyAutoConfigurationErrorReceived, skipping.");
+ }
+ });
+ }
}
diff --git a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
index 153d687..088a7e2 100644
--- a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
@@ -38,6 +38,9 @@
/**
* Controls IMS registration for this ImsService and notifies the framework when the IMS
* registration for this ImsService has changed status.
+ * <p>
+ * Note: There is no guarantee on the thread that the calls from the framework will be called on. It
+ * is the implementors responsibility to handle moving the calls to a working thread if required.
* @hide
*/
@SystemApi
@@ -92,6 +95,21 @@
public void removeRegistrationCallback(IImsRegistrationCallback c) throws RemoteException {
ImsRegistrationImplBase.this.removeRegistrationCallback(c);
}
+
+ @Override
+ public void triggerFullNetworkRegistration(int sipCode, String sipReason) {
+ ImsRegistrationImplBase.this.triggerFullNetworkRegistration(sipCode, sipReason);
+ }
+
+ @Override
+ public void triggerUpdateSipDelegateRegistration() {
+ ImsRegistrationImplBase.this.updateSipDelegateRegistration();
+ }
+
+ @Override
+ public void triggerSipDelegateDeregistration() {
+ ImsRegistrationImplBase.this.triggerSipDelegateDeregistration();
+ }
};
private final RemoteCallbackListExt<IImsRegistrationCallback> mCallbacks =
@@ -133,7 +151,6 @@
* If the SIP delegate feature tag configuration has changed, then this method will be
* called in order to let the ImsService know that it can pick up these changes in the IMS
* registration.
- * @hide
*/
public void updateSipDelegateRegistration() {
// Stub implementation, ImsService should implement this
@@ -150,7 +167,6 @@
* <p>
* This should not affect the registration of features managed by the ImsService itself, such as
* feature tags related to MMTEL registration.
- * @hide
*/
public void triggerSipDelegateDeregistration() {
// Stub implementation, ImsService should implement this
@@ -169,9 +185,8 @@
* be carrier specific.
* @param sipReason The reason associated with the SIP error code. {@code null} if there was no
* reason associated with the error.
- * @hide
*/
- public void triggerNetworkReregistration(@IntRange(from = 100, to = 699) int sipCode,
+ public void triggerFullNetworkRegistration(@IntRange(from = 100, to = 699) int sipCode,
@Nullable String sipReason) {
// Stub implementation, ImsService should implement this
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 2da45ca..de4da38 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -52,6 +52,7 @@
import android.telephony.TelephonyHistogram;
import android.telephony.VisualVoicemailSmsFilterSettings;
import android.telephony.emergency.EmergencyNumber;
+import android.telephony.ims.RcsClientConfiguration;
import android.telephony.ims.aidl.IImsCapabilityCallback;
import android.telephony.ims.aidl.IImsConfig;
import android.telephony.ims.aidl.IImsConfigCallback;
@@ -59,6 +60,7 @@
import android.telephony.ims.aidl.IImsRcsFeature;
import android.telephony.ims.aidl.IImsRegistration;
import android.telephony.ims.aidl.IImsRegistrationCallback;
+import android.telephony.ims.aidl.IRcsConfigCallback;
import com.android.ims.internal.IImsServiceFeatureCallback;
import com.android.internal.telephony.CellNetworkScanResult;
import com.android.internal.telephony.IBooleanConsumer;
@@ -126,6 +128,15 @@
*/
boolean isRadioOnForSubscriberWithFeature(int subId, String callingPackage, String callingFeatureId);
+ /**
+ * Set the user-set status for enriched calling with call composer.
+ */
+ void setCallComposerStatus(int subId, int status);
+
+ /**
+ * Get the user-set status for enriched calling with call composer.
+ */
+ int getCallComposerStatus(int subId);
/**
* Supply a pin to unlock the SIM for particular subId.
@@ -2311,4 +2322,51 @@
* Return the release time for telephony to unbind GbaService.
*/
int getGbaReleaseTime(int subId);
+
+ /**
+ * Provide the client configuration parameters of the RCS application.
+ */
+ void setRcsClientConfiguration(int subId, in RcsClientConfiguration rcc);
+
+ /**
+ * return value to indicate whether the device and the carrier can support RCS VoLTE
+ * single registration.
+ */
+ boolean isRcsVolteSingleRegistrationCapable(int subId);
+
+ /**
+ * Register RCS provisioning callback.
+ */
+ void registerRcsProvisioningChangedCallback(int subId,
+ IRcsConfigCallback callback);
+
+ /**
+ * Unregister RCS provisioning callback.
+ */
+ void unregisterRcsProvisioningChangedCallback(int subId, IRcsConfigCallback callback);
+
+ /**
+ * trigger RCS reconfiguration.
+ */
+ void triggerRcsReconfiguration(int subId);
+
+ /**
+ * Overrides the config of RCS VoLTE single registration enabled for the device.
+ */
+ void setDeviceSingleRegistrationEnabledOverride(String enabled);
+
+ /**
+ * Gets the config of RCS VoLTE single registration enabled for the device.
+ */
+ boolean getDeviceSingleRegistrationEnabled();
+
+ /**
+ * Overrides the config of RCS VoLTE single registration enabled for the carrier/subscription.
+ */
+ boolean setCarrierSingleRegistrationEnabledOverride(int subId, String enabled);
+
+ /**
+ * Gets the config of RCS VoLTE single registration enabled for the carrier/subscription.
+ */
+ boolean getCarrierSingleRegistrationEnabled(int subId);
}
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 42dee0e..76243a5 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -522,6 +522,8 @@
int RIL_REQUEST_GET_SYSTEM_SELECTION_CHANNELS = 219;
int RIL_REQUEST_GET_HAL_DEVICE_CAPABILITIES = 220;
int RIL_REQUEST_SET_DATA_THROTTLING = 221;
+ int RIL_REQUEST_SET_ALLOWED_NETWORK_TYPE_BITMAP = 222;
+ int RIL_REQUEST_GET_ALLOWED_NETWORK_TYPE_BITMAP = 223;
/* Responses begin */
int RIL_RESPONSE_ACKNOWLEDGEMENT = 800;
diff --git a/test-mock/src/android/test/mock/MockContext.java b/test-mock/src/android/test/mock/MockContext.java
index cf3b03c..f7cebd1 100644
--- a/test-mock/src/android/test/mock/MockContext.java
+++ b/test-mock/src/android/test/mock/MockContext.java
@@ -817,6 +817,11 @@
}
@Override
+ public @NonNull Context createWindowContext(Display display, int type, Bundle options) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public boolean isRestricted() {
throw new UnsupportedOperationException();
}
diff --git a/test-mock/src/android/test/mock/OWNERS b/test-mock/src/android/test/mock/OWNERS
index 9551245..72e8ffc 100644
--- a/test-mock/src/android/test/mock/OWNERS
+++ b/test-mock/src/android/test/mock/OWNERS
@@ -1,3 +1 @@
-set noparent
-
*
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
index bd7e8d7..e4db55e 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
@@ -80,16 +80,39 @@
}
}
-fun WmAssertion.windowAlwaysVisible(
+fun WmAssertion.wallpaperWindowBecomesInvisible(
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all("wallpaperWindowBecomesInvisible", bugId, enabled) {
+ this.showsBelowAppWindow("Wallpaper")
+ .then()
+ .hidesBelowAppWindow("Wallpaper")
+ }
+}
+
+fun WmAssertion.appWindowAlwaysVisibleOnTop(
packageName: String,
bugId: Int = 0,
enabled: Boolean = bugId == 0
) {
- all("windowAlwaysVisible", bugId, enabled) {
+ all("appWindowAlwaysVisibleOnTop", bugId, enabled) {
this.showsAppWindowOnTop(packageName)
}
}
+fun WmAssertion.appWindowBecomesVisible(
+ appName: String,
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all("appWindowBecomesVisible", bugId, enabled) {
+ this.hidesAppWindow(appName)
+ .then()
+ .showsAppWindow(appName)
+ }
+}
+
@JvmOverloads
fun LayersAssertion.noUncoveredRegions(
beginRotation: Int,
@@ -214,6 +237,18 @@
}
}
+fun LayersAssertion.appLayerReplacesWallpaperLayer(
+ appName: String,
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all("appLayerReplacesWallpaperLayer", bugId, enabled) {
+ this.showsLayer("Wallpaper")
+ .then()
+ .replaceVisibleLayer("Wallpaper", appName)
+ }
+}
+
fun LayersAssertion.wallpaperLayerReplacesAppLayer(
testApp: IAppHelper,
bugId: Int = 0,
@@ -236,6 +271,30 @@
}
}
+fun LayersAssertion.layerBecomesVisible(
+ packageName: String,
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all("layerBecomesVisible", bugId, enabled) {
+ this.hidesLayer(packageName)
+ .then()
+ .showsLayer(packageName)
+ }
+}
+
+fun LayersAssertion.layerBecomesInvisible(
+ packageName: String,
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all("layerBecomesInvisible", bugId, enabled) {
+ this.showsLayer(packageName)
+ .then()
+ .hidesLayer(packageName)
+ }
+}
+
fun EventLogAssertion.focusChanges(
vararg windows: String,
bugId: Int = 0,
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
index 5798624..aa34b5d 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
@@ -65,6 +65,17 @@
}
}
+fun WmAssertion.imeWindowBecomesVisible(
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all("imeWindowBecomesVisible", bugId, enabled) {
+ this.hidesNonAppWindow(IME_WINDOW_TITLE)
+ .then()
+ .showsNonAppWindow(IME_WINDOW_TITLE)
+ }
+}
+
fun WmAssertion.imeWindowBecomesInvisible(
bugId: Int = 0,
enabled: Boolean = bugId == 0
@@ -76,6 +87,18 @@
}
}
+fun WmAssertion.imeAppWindowBecomesVisible(
+ windowName: String,
+ bugId: Int = 0,
+ enabled: Boolean = bugId == 0
+) {
+ all("imeAppWindowBecomesVisible", bugId, enabled) {
+ this.hidesAppWindow(windowName)
+ .then()
+ .showsAppWindow(windowName)
+ }
+}
+
fun WmAssertion.imeAppWindowBecomesInvisible(
testApp: IAppHelper,
bugId: Int = 0,
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt
index 64a8f30..28a8bd3 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt
@@ -33,6 +33,8 @@
import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
import com.android.server.wm.flicker.noUncoveredRegions
+import com.android.server.wm.flicker.appWindowAlwaysVisibleOnTop
+import com.android.server.wm.flicker.layerAlwaysVisible
import com.android.server.wm.flicker.repetitions
import com.android.server.wm.flicker.startRotation
import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
@@ -56,8 +58,6 @@
flickerSpec: Flicker
) : FlickerTestRunner(testName, flickerSpec) {
companion object {
- private const val IME_WINDOW_TITLE = "InputMethod"
-
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): List<Array<Any>> {
@@ -93,12 +93,8 @@
statusBarWindowIsAlwaysVisible()
visibleWindowsShownMoreThanOneConsecutiveEntry()
- all("imeWindowBecomesVisible") {
- this.skipUntilFirstAssertion()
- .hidesNonAppWindow(IME_WINDOW_TITLE)
- .then()
- .showsNonAppWindow(IME_WINDOW_TITLE)
- }
+ imeWindowBecomesVisible()
+ appWindowAlwaysVisibleOnTop(testApp.`package`)
}
layersTrace {
@@ -110,6 +106,7 @@
visibleLayersShownMoreThanOneConsecutiveEntry()
imeLayerBecomesVisible()
+ layerAlwaysVisible(testApp.`package`)
}
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
index 7bd96f5..c7114da 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
@@ -23,14 +23,27 @@
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.buildTestTag
import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper
import com.android.server.wm.flicker.helpers.reopenAppFromOverview
-import com.android.server.wm.flicker.helpers.hasWindow
+import com.android.server.wm.flicker.helpers.buildTestTag
import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.navBarLayerRotatesAndScales
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.wallpaperWindowBecomesInvisible
+import com.android.server.wm.flicker.appLayerReplacesWallpaperLayer
+import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
+import com.android.server.wm.flicker.noUncoveredRegions
import com.android.server.wm.flicker.repetitions
import com.android.server.wm.flicker.startRotation
+import com.android.server.wm.flicker.endRotation
+import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.testapp.ActivityOptions
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@@ -54,8 +67,9 @@
fun getParams(): List<Array<Any>> {
val instrumentation = InstrumentationRegistry.getInstrumentation()
val testApp = ImeAppAutoFocusHelper(instrumentation)
+ val testAppComponentName = ActivityOptions.IME_ACTIVITY_AUTO_FOCUS_COMPONENT_NAME
- return FlickerTestRunnerFactory(instrumentation, repetitions = 10)
+ return FlickerTestRunnerFactory(instrumentation, repetitions = 5)
.buildTest { configuration ->
withTestName { buildTestTag("reOpenImeAutoFocus", testApp, configuration) }
repeat { configuration.repetitions }
@@ -73,7 +87,7 @@
}
transitions {
device.reopenAppFromOverview()
- device.hasWindow(testApp.getPackage())
+ WindowManagerStateHelper().waitForFullScreenApp(testAppComponentName)
}
teardown {
eachRun {
@@ -84,6 +98,35 @@
this.setRotation(Surface.ROTATION_0)
}
}
+ assertions {
+ windowManagerTrace {
+ navBarWindowIsAlwaysVisible()
+ statusBarWindowIsAlwaysVisible()
+ visibleWindowsShownMoreThanOneConsecutiveEntry()
+
+ imeWindowBecomesVisible()
+ imeAppWindowBecomesVisible(testAppComponentName.className)
+ wallpaperWindowBecomesInvisible()
+ }
+
+ layersTrace {
+ noUncoveredRegions(Surface.ROTATION_0, configuration.endRotation,
+ bugId = 141361128)
+ navBarLayerRotatesAndScales(Surface.ROTATION_0,
+ configuration.endRotation)
+ statusBarLayerRotatesScales(Surface.ROTATION_0,
+ configuration.endRotation)
+ statusBarLayerIsAlwaysVisible(
+ enabled = Surface.ROTATION_0 == configuration.endRotation)
+ navBarLayerIsAlwaysVisible(
+ enabled = Surface.ROTATION_0 == configuration.endRotation)
+ visibleLayersShownMoreThanOneConsecutiveEntry(
+ enabled = Surface.ROTATION_0 == configuration.endRotation)
+
+ imeLayerBecomesVisible()
+ appLayerReplacesWallpaperLayer(testAppComponentName.className)
+ }
+ }
}
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/CommonAssertions.kt
index 72efdb1..71920f6 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/CommonAssertions.kt
@@ -17,20 +17,8 @@
package com.android.server.wm.flicker.launch
import android.platform.helpers.IAppHelper
-import com.android.server.wm.flicker.dsl.LayersAssertion
import com.android.server.wm.flicker.dsl.WmAssertion
-fun WmAssertion.wallpaperWindowBecomesInvisible(
- bugId: Int = 0,
- enabled: Boolean = bugId == 0
-) {
- all("wallpaperWindowBecomesInvisible", bugId, enabled) {
- this.showsBelowAppWindow("Wallpaper")
- .then()
- .hidesBelowAppWindow("Wallpaper")
- }
-}
-
fun WmAssertion.appWindowReplacesLauncherAsTopWindow(
testApp: IAppHelper,
bugId: Int = 0,
@@ -41,16 +29,4 @@
.then()
.showsAppWindowOnTop("Snapshot", testApp.getPackage())
}
-}
-
-fun LayersAssertion.appLayerReplacesWallpaperLayer(
- testApp: IAppHelper,
- bugId: Int = 0,
- enabled: Boolean = bugId == 0
-) {
- all("appLayerReplacesWallpaperLayer", bugId, enabled) {
- this.showsLayer("Wallpaper")
- .then()
- .replaceVisibleLayer("Wallpaper", testApp.getPackage())
- }
}
\ No newline at end of file
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
index 686ddcb..d81c24d 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
@@ -40,6 +40,8 @@
import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.flicker.wallpaperWindowBecomesInvisible
+import com.android.server.wm.flicker.appLayerReplacesWallpaperLayer
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@@ -107,7 +109,7 @@
statusBarLayerIsAlwaysVisible(enabled = false)
visibleLayersShownMoreThanOneConsecutiveEntry(bugId = 174541970)
- appLayerReplacesWallpaperLayer(testApp)
+ appLayerReplacesWallpaperLayer(testApp.`package`)
}
eventLog {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
index 5aef314..1b682c0 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
@@ -29,7 +29,6 @@
import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
import com.android.server.wm.flicker.helpers.StandardAppHelper
import com.android.server.wm.flicker.helpers.reopenAppFromOverview
-import com.android.server.wm.flicker.helpers.hasWindow
import com.android.server.wm.flicker.helpers.buildTestTag
import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
@@ -42,6 +41,10 @@
import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
import com.android.server.wm.flicker.statusBarLayerRotatesScales
import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.wallpaperWindowBecomesInvisible
+import com.android.server.wm.flicker.appLayerReplacesWallpaperLayer
+import com.android.server.wm.flicker.testapp.ActivityOptions
+import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@@ -83,7 +86,9 @@
}
transitions {
device.reopenAppFromOverview()
- device.hasWindow(testApp.getPackage())
+ WindowManagerStateHelper().waitForFullScreenApp(
+ ActivityOptions.SIMPLE_ACTIVITY_AUTO_FOCUS_COMPONENT_NAME
+ )
}
teardown {
test {
@@ -115,7 +120,7 @@
visibleLayersShownMoreThanOneConsecutiveEntry(
enabled = Surface.ROTATION_0 == configuration.endRotation)
- appLayerReplacesWallpaperLayer(testApp)
+ appLayerReplacesWallpaperLayer(testApp.`package`)
}
eventLog {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
index 9b4223a..3703d9c 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
@@ -40,6 +40,8 @@
import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry
import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
+import com.android.server.wm.flicker.wallpaperWindowBecomesInvisible
+import com.android.server.wm.flicker.appLayerReplacesWallpaperLayer
import org.junit.FixMethodOrder
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@@ -112,7 +114,7 @@
visibleLayersShownMoreThanOneConsecutiveEntry(
enabled = Surface.ROTATION_0 == configuration.endRotation)
- appLayerReplacesWallpaperLayer(testApp)
+ appLayerReplacesWallpaperLayer(testApp.`package`)
}
eventLog {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
index a1a7102..120354b 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
@@ -30,7 +30,7 @@
import com.android.server.wm.flicker.FlickerTestRunnerFactory
import com.android.server.wm.flicker.endRotation
import com.android.server.wm.flicker.focusDoesNotChange
-import com.android.server.wm.flicker.windowAlwaysVisible
+import com.android.server.wm.flicker.appWindowAlwaysVisibleOnTop
import com.android.server.wm.flicker.layerAlwaysVisible
import com.android.server.wm.flicker.helpers.WindowUtils
import com.android.server.wm.flicker.helpers.buildTestTag
@@ -146,7 +146,7 @@
navBarWindowIsAlwaysVisible(bugId = 140855415)
statusBarWindowIsAlwaysVisible(bugId = 140855415)
visibleWindowsShownMoreThanOneConsecutiveEntry()
- windowAlwaysVisible(configuration.intentPackageName)
+ appWindowAlwaysVisibleOnTop(configuration.intentPackageName)
}
layersTrace {
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java
index 1899411..f167e95 100644
--- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java
@@ -23,4 +23,10 @@
public static final ComponentName SEAMLESS_ACTIVITY_COMPONENT_NAME =
new ComponentName("com.android.server.wm.flicker.testapp",
"com.android.server.wm.flicker.testapp.SeamlessRotationActivity");
+ public static final ComponentName IME_ACTIVITY_AUTO_FOCUS_COMPONENT_NAME =
+ new ComponentName("com.android.server.wm.flicker.testapp",
+ "com.android.server.wm.flicker.testapp.ImeActivityAutoFocus");
+ public static final ComponentName SIMPLE_ACTIVITY_AUTO_FOCUS_COMPONENT_NAME =
+ new ComponentName("com.android.server.wm.flicker.testapp",
+ "com.android.server.wm.flicker.testapp.SimpleActivity");
}
diff --git a/tests/net/java/android/net/NetworkUtilsTest.java b/tests/net/java/android/net/NetworkUtilsTest.java
index 3158cc8..7748288 100644
--- a/tests/net/java/android/net/NetworkUtilsTest.java
+++ b/tests/net/java/android/net/NetworkUtilsTest.java
@@ -16,24 +16,10 @@
package android.net;
-import static android.system.OsConstants.AF_INET;
-import static android.system.OsConstants.AF_INET6;
-import static android.system.OsConstants.AF_UNIX;
-import static android.system.OsConstants.EPERM;
-import static android.system.OsConstants.SOCK_DGRAM;
-import static android.system.OsConstants.SOCK_STREAM;
-
import static junit.framework.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-import android.system.ErrnoException;
-import android.system.Os;
-
import androidx.test.runner.AndroidJUnit4;
-import libcore.io.IoUtils;
-
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -139,50 +125,4 @@
assertEquals(BigInteger.valueOf(7l - 4 + 4 + 16 + 65536),
NetworkUtils.routedIPv6AddressCount(set));
}
-
- private static void expectSocketSuccess(String msg, int domain, int type) {
- try {
- IoUtils.closeQuietly(Os.socket(domain, type, 0));
- } catch (ErrnoException e) {
- fail(msg + e.getMessage());
- }
- }
-
- private static void expectSocketPemissionError(String msg, int domain, int type) {
- try {
- IoUtils.closeQuietly(Os.socket(domain, type, 0));
- fail(msg);
- } catch (ErrnoException e) {
- assertEquals(msg, e.errno, EPERM);
- }
- }
-
- private static void expectHasNetworking() {
- expectSocketSuccess("Creating a UNIX socket should not have thrown ErrnoException",
- AF_UNIX, SOCK_STREAM);
- expectSocketSuccess("Creating a AF_INET socket shouldn't have thrown ErrnoException",
- AF_INET, SOCK_DGRAM);
- expectSocketSuccess("Creating a AF_INET6 socket shouldn't have thrown ErrnoException",
- AF_INET6, SOCK_DGRAM);
- }
-
- private static void expectNoNetworking() {
- expectSocketSuccess("Creating a UNIX socket should not have thrown ErrnoException",
- AF_UNIX, SOCK_STREAM);
- expectSocketPemissionError(
- "Creating a AF_INET socket should have thrown ErrnoException(EPERM)",
- AF_INET, SOCK_DGRAM);
- expectSocketPemissionError(
- "Creating a AF_INET6 socket should have thrown ErrnoException(EPERM)",
- AF_INET6, SOCK_DGRAM);
- }
-
- @Test
- public void testSetAllowNetworkingForProcess() {
- expectHasNetworking();
- NetworkUtils.setAllowNetworkingForProcess(false);
- expectNoNetworking();
- NetworkUtils.setAllowNetworkingForProcess(true);
- expectHasNetworking();
- }
}
diff --git a/tests/net/java/com/android/internal/net/NetworkUtilsInternalTest.java b/tests/net/java/com/android/internal/net/NetworkUtilsInternalTest.java
new file mode 100644
index 0000000..3cfecd5
--- /dev/null
+++ b/tests/net/java/com/android/internal/net/NetworkUtilsInternalTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.net;
+
+import static android.system.OsConstants.AF_INET;
+import static android.system.OsConstants.AF_INET6;
+import static android.system.OsConstants.AF_UNIX;
+import static android.system.OsConstants.EPERM;
+import static android.system.OsConstants.SOCK_DGRAM;
+import static android.system.OsConstants.SOCK_STREAM;
+
+import static junit.framework.Assert.assertEquals;
+
+import static org.junit.Assert.fail;
+
+import android.system.ErrnoException;
+import android.system.Os;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import libcore.io.IoUtils;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@androidx.test.filters.SmallTest
+public class NetworkUtilsInternalTest {
+
+ private static void expectSocketSuccess(String msg, int domain, int type) {
+ try {
+ IoUtils.closeQuietly(Os.socket(domain, type, 0));
+ } catch (ErrnoException e) {
+ fail(msg + e.getMessage());
+ }
+ }
+
+ private static void expectSocketPemissionError(String msg, int domain, int type) {
+ try {
+ IoUtils.closeQuietly(Os.socket(domain, type, 0));
+ fail(msg);
+ } catch (ErrnoException e) {
+ assertEquals(msg, e.errno, EPERM);
+ }
+ }
+
+ private static void expectHasNetworking() {
+ expectSocketSuccess("Creating a UNIX socket should not have thrown ErrnoException",
+ AF_UNIX, SOCK_STREAM);
+ expectSocketSuccess("Creating a AF_INET socket shouldn't have thrown ErrnoException",
+ AF_INET, SOCK_DGRAM);
+ expectSocketSuccess("Creating a AF_INET6 socket shouldn't have thrown ErrnoException",
+ AF_INET6, SOCK_DGRAM);
+ }
+
+ private static void expectNoNetworking() {
+ expectSocketSuccess("Creating a UNIX socket should not have thrown ErrnoException",
+ AF_UNIX, SOCK_STREAM);
+ expectSocketPemissionError(
+ "Creating a AF_INET socket should have thrown ErrnoException(EPERM)",
+ AF_INET, SOCK_DGRAM);
+ expectSocketPemissionError(
+ "Creating a AF_INET6 socket should have thrown ErrnoException(EPERM)",
+ AF_INET6, SOCK_DGRAM);
+ }
+
+ @Test
+ public void testSetAllowNetworkingForProcess() {
+ expectHasNetworking();
+ NetworkUtilsInternal.setAllowNetworkingForProcess(false);
+ expectNoNetworking();
+ NetworkUtilsInternal.setAllowNetworkingForProcess(true);
+ expectHasNetworking();
+ }
+}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index b3bdd60..799b64e 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -39,6 +39,7 @@
import static android.net.ConnectivityManager.TYPE_MOBILE_FOTA;
import static android.net.ConnectivityManager.TYPE_MOBILE_MMS;
import static android.net.ConnectivityManager.TYPE_MOBILE_SUPL;
+import static android.net.ConnectivityManager.TYPE_VPN;
import static android.net.ConnectivityManager.TYPE_WIFI;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_DNS;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_FALLBACK;
@@ -101,6 +102,8 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.mockito.AdditionalMatchers.aryEq;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.argThat;
@@ -132,6 +135,7 @@
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
@@ -140,6 +144,8 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.location.LocationManager;
@@ -176,6 +182,7 @@
import android.net.NetworkCapabilities;
import android.net.NetworkFactory;
import android.net.NetworkInfo;
+import android.net.NetworkInfo.DetailedState;
import android.net.NetworkRequest;
import android.net.NetworkSpecifier;
import android.net.NetworkStack;
@@ -332,12 +339,13 @@
private static final String WIFI_WOL_IFNAME = "test_wlan_wol";
private static final String VPN_IFNAME = "tun10042";
private static final String TEST_PACKAGE_NAME = "com.android.test.package";
- private static final String[] EMPTY_STRING_ARRAY = new String[0];
+ private static final String ALWAYS_ON_PACKAGE = "com.android.test.alwaysonvpn";
private static final String INTERFACE_NAME = "interface";
private MockContext mServiceContext;
private HandlerThread mCsHandlerThread;
+ private ConnectivityService.Dependencies mDeps;
private ConnectivityService mService;
private WrappedConnectivityManager mCm;
private TestNetworkAgentWrapper mWiFiNetworkAgent;
@@ -353,6 +361,7 @@
@Mock IIpConnectivityMetrics mIpConnectivityMetrics;
@Mock IpConnectivityMetrics.Logger mMetricsService;
@Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
+ @Mock DeviceIdleInternal mDeviceIdleInternal;
@Mock INetworkManagementService mNetworkManagementService;
@Mock INetworkStatsService mStatsService;
@Mock IBatteryStats mBatteryStatsService;
@@ -450,6 +459,15 @@
}
@Override
+ public ComponentName startService(Intent service) {
+ final String action = service.getAction();
+ if (!VpnConfig.SERVICE_INTERFACE.equals(action)) {
+ fail("Attempt to start unknown service, action=" + action);
+ }
+ return new ComponentName(service.getPackage(), "com.android.test.Service");
+ }
+
+ @Override
public Object getSystemService(String name) {
if (Context.CONNECTIVITY_SERVICE.equals(name)) return mCm;
if (Context.NOTIFICATION_SERVICE.equals(name)) return mNotificationManager;
@@ -1055,9 +1073,19 @@
private VpnInfo mVpnInfo;
public MockVpn(int userId) {
- super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
- mMockNetd, userId, mock(KeyStore.class));
- mConfig = new VpnConfig();
+ super(startHandlerThreadAndReturnLooper(), mServiceContext,
+ new Dependencies() {
+ @Override
+ public boolean isCallerSystem() {
+ return true;
+ }
+
+ @Override
+ public DeviceIdleInternal getDeviceIdleInternal() {
+ return mDeviceIdleInternal;
+ }
+ },
+ mNetworkManagementService, mMockNetd, userId, mock(KeyStore.class));
}
public void setUids(Set<UidRange> uids) {
@@ -1086,9 +1114,16 @@
return mVpnType;
}
+ private LinkProperties makeLinkProperties() {
+ final LinkProperties lp = new LinkProperties();
+ lp.setInterfaceName(VPN_IFNAME);
+ return lp;
+ }
+
private void registerAgent(boolean isAlwaysMetered, Set<UidRange> uids, LinkProperties lp)
throws Exception {
if (mAgentRegistered) throw new IllegalStateException("already registered");
+ mConfig = new VpnConfig();
setUids(uids);
if (!isAlwaysMetered) mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_METERED);
mInterface = VPN_IFNAME;
@@ -1101,12 +1136,13 @@
verify(mMockNetd, never())
.networkRemoveUidRanges(eq(mMockVpn.getNetId()), any());
mAgentRegistered = true;
+ updateState(NetworkInfo.DetailedState.CONNECTED, "registerAgent");
mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities());
mNetworkAgent = mMockNetworkAgent.getNetworkAgent();
}
private void registerAgent(Set<UidRange> uids) throws Exception {
- registerAgent(false /* isAlwaysMetered */, uids, new LinkProperties());
+ registerAgent(false /* isAlwaysMetered */, uids, makeLinkProperties());
}
private void connect(boolean validated, boolean hasInternet, boolean isStrictMode) {
@@ -1142,12 +1178,12 @@
public void establishForMyUid(boolean validated, boolean hasInternet, boolean isStrictMode)
throws Exception {
final int uid = Process.myUid();
- establish(new LinkProperties(), uid, uidRangesForUid(uid), validated, hasInternet,
+ establish(makeLinkProperties(), uid, uidRangesForUid(uid), validated, hasInternet,
isStrictMode);
}
public void establishForMyUid() throws Exception {
- establishForMyUid(new LinkProperties());
+ establishForMyUid(makeLinkProperties());
}
public void sendLinkProperties(LinkProperties lp) {
@@ -1155,7 +1191,10 @@
}
public void disconnect() {
- if (mMockNetworkAgent != null) mMockNetworkAgent.disconnect();
+ if (mMockNetworkAgent != null) {
+ mMockNetworkAgent.disconnect();
+ updateState(NetworkInfo.DetailedState.DISCONNECTED, "disconnect");
+ }
mAgentRegistered = false;
}
@@ -1229,6 +1268,17 @@
fail("ConditionVariable was blocked for more than " + TIMEOUT_MS + "ms");
}
+ private void registerNetworkCallbackAsUid(NetworkRequest request, NetworkCallback callback,
+ int uid) {
+ when(mDeps.getCallingUid()).thenReturn(uid);
+ try {
+ mCm.registerNetworkCallback(request, callback);
+ waitForIdle();
+ } finally {
+ returnRealCallingUid();
+ }
+ }
+
private static final int VPN_USER = 0;
private static final int APP1_UID = UserHandle.getUid(VPN_USER, 10100);
private static final int APP2_UID = UserHandle.getUid(VPN_USER, 10101);
@@ -1271,7 +1321,8 @@
initAlarmManager(mAlarmManager, mAlarmManagerThread.getThreadHandler());
mCsHandlerThread = new HandlerThread("TestConnectivityService");
- final ConnectivityService.Dependencies deps = makeDependencies();
+ mDeps = makeDependencies();
+ returnRealCallingUid();
mService = new ConnectivityService(mServiceContext,
mNetworkManagementService,
mStatsService,
@@ -1279,9 +1330,9 @@
mMockDnsResolver,
mock(IpConnectivityLog.class),
mMockNetd,
- deps);
+ mDeps);
mService.mLingerDelayMs = TEST_LINGER_DELAY_MS;
- verify(deps).makeMultinetworkPolicyTracker(any(), any(), any());
+ verify(mDeps).makeMultinetworkPolicyTracker(any(), any(), any());
final ArgumentCaptor<INetworkPolicyListener> policyListenerCaptor =
ArgumentCaptor.forClass(INetworkPolicyListener.class);
@@ -1301,6 +1352,10 @@
setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
}
+ private void returnRealCallingUid() {
+ doAnswer((invocationOnMock) -> Binder.getCallingUid()).when(mDeps).getCallingUid();
+ }
+
private ConnectivityService.Dependencies makeDependencies() {
doReturn(TEST_TCP_INIT_RWND).when(mSystemProperties)
.getInt("net.tcp.default_init_rwnd", 0);
@@ -1376,13 +1431,13 @@
}
private void mockDefaultPackages() throws Exception {
- final String testPackageName = mContext.getPackageName();
- final PackageInfo testPackageInfo = mContext.getPackageManager().getPackageInfo(
- testPackageName, PackageManager.GET_PERMISSIONS);
+ final String myPackageName = mContext.getPackageName();
+ final PackageInfo myPackageInfo = mContext.getPackageManager().getPackageInfo(
+ myPackageName, PackageManager.GET_PERMISSIONS);
when(mPackageManager.getPackagesForUid(Binder.getCallingUid())).thenReturn(
- new String[] {testPackageName});
- when(mPackageManager.getPackageInfoAsUser(eq(testPackageName), anyInt(),
- eq(UserHandle.getCallingUserId()))).thenReturn(testPackageInfo);
+ new String[] {myPackageName});
+ when(mPackageManager.getPackageInfoAsUser(eq(myPackageName), anyInt(),
+ eq(UserHandle.getCallingUserId()))).thenReturn(myPackageInfo);
when(mPackageManager.getInstalledPackages(eq(GET_PERMISSIONS | MATCH_ANY_USER))).thenReturn(
Arrays.asList(new PackageInfo[] {
@@ -1390,6 +1445,25 @@
buildPackageInfo(/* SYSTEM */ false, APP2_UID),
buildPackageInfo(/* SYSTEM */ false, VPN_UID)
}));
+
+ // Create a fake always-on VPN package.
+ final int userId = UserHandle.getCallingUserId();
+ final ApplicationInfo applicationInfo = new ApplicationInfo();
+ applicationInfo.targetSdkVersion = Build.VERSION_CODES.R; // Always-on supported in N+.
+ when(mPackageManager.getApplicationInfoAsUser(eq(ALWAYS_ON_PACKAGE), anyInt(),
+ eq(userId))).thenReturn(applicationInfo);
+
+ // Minimal mocking to keep Vpn#isAlwaysOnPackageSupported happy.
+ ResolveInfo rInfo = new ResolveInfo();
+ rInfo.serviceInfo = new ServiceInfo();
+ rInfo.serviceInfo.metaData = new Bundle();
+ final List<ResolveInfo> services = Arrays.asList(new ResolveInfo[]{rInfo});
+ when(mPackageManager.queryIntentServicesAsUser(any(), eq(PackageManager.GET_META_DATA),
+ eq(userId))).thenReturn(services);
+ when(mPackageManager.getPackageUidAsUser(TEST_PACKAGE_NAME, userId))
+ .thenReturn(Process.myUid());
+ when(mPackageManager.getPackageUidAsUser(ALWAYS_ON_PACKAGE, userId))
+ .thenReturn(VPN_UID);
}
private void verifyActiveNetwork(int transport) {
@@ -2252,10 +2326,10 @@
}
private void grantUsingBackgroundNetworksPermissionForUid(final int uid) throws Exception {
- final String testPackageName = mContext.getPackageName();
- when(mPackageManager.getPackageInfo(eq(testPackageName), eq(GET_PERMISSIONS)))
+ final String myPackageName = mContext.getPackageName();
+ when(mPackageManager.getPackageInfo(eq(myPackageName), eq(GET_PERMISSIONS)))
.thenReturn(buildPackageInfo(true, uid));
- mService.mPermissionMonitor.onPackageAdded(testPackageName, uid);
+ mService.mPermissionMonitor.onPackageAdded(myPackageName, uid);
}
@Test
@@ -5831,10 +5905,21 @@
assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
}
+ private void assertDefaultNetworkCapabilities(int userId, NetworkAgentWrapper... networks) {
+ final NetworkCapabilities[] defaultCaps = mService.getDefaultNetworkCapabilitiesForUser(
+ userId, "com.android.calling.package");
+ final String defaultCapsString = Arrays.toString(defaultCaps);
+ assertEquals(defaultCapsString, defaultCaps.length, networks.length);
+ final Set<NetworkCapabilities> defaultCapsSet = new ArraySet<>(defaultCaps);
+ for (NetworkAgentWrapper network : networks) {
+ final NetworkCapabilities nc = mCm.getNetworkCapabilities(network.getNetwork());
+ final String msg = "Did not find " + nc + " in " + Arrays.toString(defaultCaps);
+ assertTrue(msg, defaultCapsSet.contains(nc));
+ }
+ }
+
@Test
public void testVpnSetUnderlyingNetworks() throws Exception {
- final int uid = Process.myUid();
-
final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
.removeCapability(NET_CAPABILITY_NOT_VPN)
@@ -5857,6 +5942,9 @@
// A VPN without underlying networks is not suspended.
assertTrue(nc.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+ final int userId = UserHandle.getUserId(Process.myUid());
+ assertDefaultNetworkCapabilities(userId /* no networks */);
+
// Connect cell and use it as an underlying network.
mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellNetworkAgent.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
@@ -5870,6 +5958,7 @@
&& caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
&& !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
&& caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+ assertDefaultNetworkCapabilities(userId, mCellNetworkAgent);
mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
mWiFiNetworkAgent.addCapability(NET_CAPABILITY_NOT_METERED);
@@ -5884,6 +5973,7 @@
&& caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
&& !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
&& caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+ assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
// Don't disconnect, but note the VPN is not using wifi any more.
mService.setUnderlyingNetworksForVpn(
@@ -5894,6 +5984,9 @@
&& caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
&& !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
&& caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+ // The return value of getDefaultNetworkCapabilitiesForUser always includes the default
+ // network (wifi) as well as the underlying networks (cell).
+ assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
// Remove NOT_SUSPENDED from the only network and observe VPN is now suspended.
mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
@@ -5922,6 +6015,7 @@
&& !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
&& caps.hasCapability(NET_CAPABILITY_NOT_METERED)
&& caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+ assertDefaultNetworkCapabilities(userId, mWiFiNetworkAgent);
// Use both again.
mService.setUnderlyingNetworksForVpn(
@@ -5932,6 +6026,7 @@
&& caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
&& !caps.hasCapability(NET_CAPABILITY_NOT_METERED)
&& caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
+ assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
// Cell is suspended again. As WiFi is not, this should not cause a callback.
mCellNetworkAgent.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
@@ -5949,6 +6044,7 @@
// a bug in ConnectivityService, but as the SUSPENDED and RESUMED callbacks have never
// been public and are deprecated and slated for removal, there is no sense in spending
// resources fixing this bug now.
+ assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
// Use both again.
mService.setUnderlyingNetworksForVpn(
@@ -5961,6 +6057,7 @@
&& caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
// As above, the RESUMED callback not being sent here is a bug, but not a bug that's
// worth anybody's time to fix.
+ assertDefaultNetworkCapabilities(userId, mCellNetworkAgent, mWiFiNetworkAgent);
// Disconnect cell. Receive update without even removing the dead network from the
// underlying networks – it's dead anyway. Not metered any more.
@@ -5969,6 +6066,7 @@
(caps) -> caps.hasTransport(TRANSPORT_VPN)
&& !caps.hasTransport(TRANSPORT_CELLULAR) && caps.hasTransport(TRANSPORT_WIFI)
&& caps.hasCapability(NET_CAPABILITY_NOT_METERED));
+ assertDefaultNetworkCapabilities(userId, mWiFiNetworkAgent);
// Disconnect wifi too. No underlying networks means this is now metered.
mWiFiNetworkAgent.disconnect();
@@ -5976,6 +6074,11 @@
(caps) -> caps.hasTransport(TRANSPORT_VPN)
&& !caps.hasTransport(TRANSPORT_CELLULAR) && !caps.hasTransport(TRANSPORT_WIFI)
&& !caps.hasCapability(NET_CAPABILITY_NOT_METERED));
+ // When a network disconnects, the callbacks are fired before all state is updated, so for a
+ // short time, synchronous calls will behave as if the network is still connected. Wait for
+ // things to settle.
+ waitForIdle();
+ assertDefaultNetworkCapabilities(userId /* no networks */);
mMockVpn.disconnect();
}
@@ -6276,6 +6379,7 @@
// Despite VPN using WiFi (which is unmetered), VPN itself is marked as always metered.
assertTrue(mCm.isActiveNetworkMetered());
+
// VPN explicitly declares WiFi as its underlying network.
mService.setUnderlyingNetworksForVpn(
new Network[] { mWiFiNetworkAgent.getNetwork() });
@@ -6389,6 +6493,189 @@
mCm.unregisterNetworkCallback(defaultCallback);
}
+ private void expectNetworkRejectNonSecureVpn(InOrder inOrder, boolean add,
+ UidRangeParcel... expected) throws Exception {
+ inOrder.verify(mMockNetd).networkRejectNonSecureVpn(eq(add), aryEq(expected));
+ }
+
+ private void checkNetworkInfo(NetworkInfo ni, int type, DetailedState state) {
+ assertNotNull(ni);
+ assertEquals(type, ni.getType());
+ assertEquals(ConnectivityManager.getNetworkTypeName(type), state, ni.getDetailedState());
+ }
+
+ private void assertActiveNetworkInfo(int type, DetailedState state) {
+ checkNetworkInfo(mCm.getActiveNetworkInfo(), type, state);
+ }
+ private void assertNetworkInfo(int type, DetailedState state) {
+ checkNetworkInfo(mCm.getNetworkInfo(type), type, state);
+ }
+
+ @Test
+ public void testNetworkBlockedStatusAlwaysOnVpn() throws Exception {
+ mServiceContext.setPermission(
+ Manifest.permission.CONTROL_ALWAYS_ON_VPN, PERMISSION_GRANTED);
+ mServiceContext.setPermission(
+ Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED);
+ mServiceContext.setPermission(
+ Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED);
+
+ final TestNetworkCallback callback = new TestNetworkCallback();
+ final NetworkRequest request = new NetworkRequest.Builder()
+ .removeCapability(NET_CAPABILITY_NOT_VPN)
+ .build();
+ mCm.registerNetworkCallback(request, callback);
+
+ final TestNetworkCallback defaultCallback = new TestNetworkCallback();
+ mCm.registerDefaultNetworkCallback(defaultCallback);
+
+ final TestNetworkCallback vpnUidCallback = new TestNetworkCallback();
+ final NetworkRequest vpnUidRequest = new NetworkRequest.Builder().build();
+ registerNetworkCallbackAsUid(vpnUidRequest, vpnUidCallback, VPN_UID);
+
+ final int uid = Process.myUid();
+ final int userId = UserHandle.getUserId(uid);
+ final ArrayList<String> allowList = new ArrayList<>();
+ mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList);
+
+ UidRangeParcel firstHalf = new UidRangeParcel(1, VPN_UID - 1);
+ UidRangeParcel secondHalf = new UidRangeParcel(VPN_UID + 1, 99999);
+ InOrder inOrder = inOrder(mMockNetd);
+ expectNetworkRejectNonSecureVpn(inOrder, true, firstHalf, secondHalf);
+
+ // Connect a network when lockdown is active, expect to see it blocked.
+ mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.connect(false /* validated */);
+ callback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent);
+ defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent);
+ vpnUidCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+ assertNull(mCm.getActiveNetwork());
+ assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
+ // Mobile is BLOCKED even though it's not actually connected.
+ assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
+ assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
+
+ // Disable lockdown, expect to see the network unblocked.
+ // There are no callbacks because they are not implemented yet.
+ mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList);
+ expectNetworkRejectNonSecureVpn(inOrder, false, firstHalf, secondHalf);
+ vpnUidCallback.assertNoCallback();
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+ assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
+ assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+
+ // Add our UID to the allowlist and re-enable lockdown, expect network is not blocked.
+ allowList.add(TEST_PACKAGE_NAME);
+ mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList);
+ callback.assertNoCallback();
+ defaultCallback.assertNoCallback();
+ vpnUidCallback.assertNoCallback();
+
+ // The following requires that the UID of this test package is greater than VPN_UID. This
+ // is always true in practice because a plain AOSP build with no apps installed has almost
+ // 200 packages installed.
+ final UidRangeParcel piece1 = new UidRangeParcel(1, VPN_UID - 1);
+ final UidRangeParcel piece2 = new UidRangeParcel(VPN_UID + 1, uid - 1);
+ final UidRangeParcel piece3 = new UidRangeParcel(uid + 1, 99999);
+ expectNetworkRejectNonSecureVpn(inOrder, true, piece1, piece2, piece3);
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+ assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
+ assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+
+ // Connect a new network, expect it to be unblocked.
+ mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+ mCellNetworkAgent.connect(false /* validated */);
+ callback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
+ defaultCallback.assertNoCallback();
+ vpnUidCallback.expectAvailableCallbacksUnvalidated(mCellNetworkAgent);
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+ // Cellular is DISCONNECTED because it's not the default and there are no requests for it.
+ assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
+ assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+
+ // Disable lockdown, remove our UID from the allowlist, and re-enable lockdown.
+ // Everything should now be blocked.
+ mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList);
+ expectNetworkRejectNonSecureVpn(inOrder, false, piece1, piece2, piece3);
+ allowList.clear();
+ mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList);
+ expectNetworkRejectNonSecureVpn(inOrder, true, firstHalf, secondHalf);
+ vpnUidCallback.assertNoCallback();
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+ assertNull(mCm.getActiveNetwork());
+ assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
+ assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
+ assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
+
+ // Disable lockdown. Everything is unblocked.
+ mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList);
+ vpnUidCallback.assertNoCallback();
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+ assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
+ assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+
+ // Enable and disable an always-on VPN package without lockdown. Expect no changes.
+ reset(mMockNetd);
+ mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, false /* lockdown */, allowList);
+ inOrder.verify(mMockNetd, never()).networkRejectNonSecureVpn(anyBoolean(), any());
+ callback.assertNoCallback();
+ defaultCallback.assertNoCallback();
+ vpnUidCallback.assertNoCallback();
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+ assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
+ assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+
+ mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList);
+ inOrder.verify(mMockNetd, never()).networkRejectNonSecureVpn(anyBoolean(), any());
+ callback.assertNoCallback();
+ defaultCallback.assertNoCallback();
+ vpnUidCallback.assertNoCallback();
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+ assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+ assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
+ assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+
+ // Enable lockdown and connect a VPN. The VPN is not blocked.
+ mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList);
+ vpnUidCallback.assertNoCallback();
+ assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
+ assertNull(mCm.getActiveNetwork());
+ assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
+ assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
+ assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
+
+ mMockVpn.establishForMyUid();
+ defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
+ vpnUidCallback.assertNoCallback(); // vpnUidCallback has NOT_VPN capability.
+ assertEquals(mMockVpn.getNetwork(), mCm.getActiveNetwork());
+ assertEquals(null, mCm.getActiveNetworkForUid(VPN_UID)); // BUG?
+ assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+ assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
+ assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
+ assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+
+ mMockVpn.disconnect();
+ defaultCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
+ defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent);
+ assertNull(mCm.getActiveNetwork());
+
+ mCm.unregisterNetworkCallback(callback);
+ mCm.unregisterNetworkCallback(defaultCallback);
+ mCm.unregisterNetworkCallback(vpnUidCallback);
+ }
+
@Test
public final void testLoseTrusted() throws Exception {
final NetworkRequest trustedRequest = new NetworkRequest.Builder()
@@ -7822,7 +8109,16 @@
@Test
public void testDumpDoesNotCrash() {
- StringWriter stringWriter = new StringWriter();
+ // Filing a couple requests prior to testing the dump.
+ final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
+ final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
+ final NetworkRequest genericRequest = new NetworkRequest.Builder()
+ .clearCapabilities().build();
+ final NetworkRequest wifiRequest = new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_WIFI).build();
+ mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
+ mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
+ final StringWriter stringWriter = new StringWriter();
mService.dump(new FileDescriptor(), new PrintWriter(stringWriter), new String[0]);
@@ -7844,11 +8140,11 @@
mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
- ConnectivityService.NetworkRequestInfo[] nriOutput = mService.requestsSortedById();
+ final ConnectivityService.NetworkRequestInfo[] nriOutput = mService.requestsSortedById();
assertTrue(nriOutput.length > 1);
for (int i = 0; i < nriOutput.length - 1; i++) {
- boolean isRequestIdInOrder =
+ final boolean isRequestIdInOrder =
nriOutput[i].mRequests.get(0).requestId
< nriOutput[i + 1].mRequests.get(0).requestId;
assertTrue(isRequestIdInOrder);
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index 6e380be..cc47317 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -228,7 +228,6 @@
R.string.config_customVpnAlwaysOnDisconnectedDialogComponent));
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS))
.thenReturn(true);
- when(mSystemServices.isCallerSystem()).thenReturn(true);
// Used by {@link Notification.Builder}
ApplicationInfo applicationInfo = new ApplicationInfo();
@@ -1102,6 +1101,11 @@
}
@Override
+ public boolean isCallerSystem() {
+ return true;
+ }
+
+ @Override
public void startService(final String serviceName) {
mRunningServices.put(serviceName, true);
}
diff --git a/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java b/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java
index fb0cfc0..89146f9 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsCollectionTest.java
@@ -23,11 +23,11 @@
import static android.net.NetworkStats.UID_ALL;
import static android.net.NetworkStatsHistory.FIELD_ALL;
import static android.net.NetworkTemplate.buildTemplateMobileAll;
-import static android.net.NetworkUtils.multiplySafeByRational;
import static android.os.Process.myUid;
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
+import static com.android.internal.net.NetworkUtilsInternal.multiplySafeByRational;
import static com.android.testutils.MiscAsserts.assertThrows;
import static org.junit.Assert.assertArrayEquals;
diff --git a/tests/vcn/java/android/net/vcn/VcnConfigTest.java b/tests/vcn/java/android/net/vcn/VcnConfigTest.java
new file mode 100644
index 0000000..77944de
--- /dev/null
+++ b/tests/vcn/java/android/net/vcn/VcnConfigTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.vcn;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Collections;
+import java.util.Set;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class VcnConfigTest {
+ private static final Set<VcnGatewayConnectionConfig> GATEWAY_CONNECTION_CONFIGS =
+ Collections.singleton(VcnGatewayConnectionConfigTest.buildTestConfig());
+
+ // Public visibility for VcnManagementServiceTest
+ public static VcnConfig buildTestConfig() {
+ VcnConfig.Builder builder = new VcnConfig.Builder();
+
+ for (VcnGatewayConnectionConfig gatewayConnectionConfig : GATEWAY_CONNECTION_CONFIGS) {
+ builder.addGatewayConnectionConfig(gatewayConnectionConfig);
+ }
+
+ return builder.build();
+ }
+
+ @Test
+ public void testBuilderRequiresGatewayConnectionConfig() {
+ try {
+ new VcnConfig.Builder().build();
+ fail("Expected exception due to no VcnGatewayConnectionConfigs provided");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ @Test
+ public void testBuilderAndGetters() {
+ final VcnConfig config = buildTestConfig();
+
+ assertEquals(GATEWAY_CONNECTION_CONFIGS, config.getGatewayConnectionConfigs());
+ }
+
+ @Test
+ public void testPersistableBundle() {
+ final VcnConfig config = buildTestConfig();
+
+ assertEquals(config, new VcnConfig(config.toPersistableBundle()));
+ }
+
+ @Test
+ public void testParceling() {
+ final VcnConfig config = buildTestConfig();
+
+ Parcel parcel = Parcel.obtain();
+ config.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+
+ assertEquals(config, VcnConfig.CREATOR.createFromParcel(parcel));
+ }
+}
diff --git a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
new file mode 100644
index 0000000..e98b6ef
--- /dev/null
+++ b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.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 android.net.vcn;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import android.net.NetworkCapabilities;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class VcnGatewayConnectionConfigTest {
+ private static final int[] EXPOSED_CAPS =
+ new int[] {
+ NetworkCapabilities.NET_CAPABILITY_INTERNET, NetworkCapabilities.NET_CAPABILITY_MMS
+ };
+ private static final int[] UNDERLYING_CAPS = new int[] {NetworkCapabilities.NET_CAPABILITY_DUN};
+ private static final long[] RETRY_INTERVALS_MS =
+ new long[] {
+ TimeUnit.SECONDS.toMillis(5),
+ TimeUnit.SECONDS.toMillis(30),
+ TimeUnit.MINUTES.toMillis(1),
+ TimeUnit.MINUTES.toMillis(5),
+ TimeUnit.MINUTES.toMillis(15),
+ TimeUnit.MINUTES.toMillis(30)
+ };
+ private static final int MAX_MTU = 1360;
+
+ // Package protected for use in VcnConfigTest
+ static VcnGatewayConnectionConfig buildTestConfig() {
+ final VcnGatewayConnectionConfig.Builder builder =
+ new VcnGatewayConnectionConfig.Builder()
+ .setRetryInterval(RETRY_INTERVALS_MS)
+ .setMaxMtu(MAX_MTU);
+
+ for (int caps : EXPOSED_CAPS) {
+ builder.addExposedCapability(caps);
+ }
+
+ for (int caps : UNDERLYING_CAPS) {
+ builder.addRequiredUnderlyingCapability(caps);
+ }
+
+ return builder.build();
+ }
+
+ @Test
+ public void testBuilderRequiresNonEmptyExposedCaps() {
+ try {
+ new VcnGatewayConnectionConfig.Builder()
+ .addRequiredUnderlyingCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ .build();
+
+ fail("Expected exception due to invalid exposed capabilities");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ @Test
+ public void testBuilderRequiresNonEmptyUnderlyingCaps() {
+ try {
+ new VcnGatewayConnectionConfig.Builder()
+ .addExposedCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ .build();
+
+ fail("Expected exception due to invalid required underlying capabilities");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ @Test
+ public void testBuilderRequiresNonNullRetryInterval() {
+ try {
+ new VcnGatewayConnectionConfig.Builder().setRetryInterval(null);
+ fail("Expected exception due to invalid retryIntervalMs");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ @Test
+ public void testBuilderRequiresNonEmptyRetryInterval() {
+ try {
+ new VcnGatewayConnectionConfig.Builder().setRetryInterval(new long[0]);
+ fail("Expected exception due to invalid retryIntervalMs");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ @Test
+ public void testBuilderRequiresValidMtu() {
+ try {
+ new VcnGatewayConnectionConfig.Builder()
+ .setMaxMtu(VcnGatewayConnectionConfig.MIN_MTU_V6 - 1);
+ fail("Expected exception due to invalid mtu");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ @Test
+ public void testBuilderAndGetters() {
+ final VcnGatewayConnectionConfig config = buildTestConfig();
+
+ for (int cap : EXPOSED_CAPS) {
+ config.hasExposedCapability(cap);
+ }
+ for (int cap : UNDERLYING_CAPS) {
+ config.requiresUnderlyingCapability(cap);
+ }
+
+ assertArrayEquals(RETRY_INTERVALS_MS, config.getRetryIntervalsMs());
+ assertEquals(MAX_MTU, config.getMaxMtu());
+ }
+
+ @Test
+ public void testPersistableBundle() {
+ final VcnGatewayConnectionConfig config = buildTestConfig();
+
+ assertEquals(config, new VcnGatewayConnectionConfig(config.toPersistableBundle()));
+ }
+}
diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
index c91fdbf..1cc9532 100644
--- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
+++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
@@ -16,42 +16,123 @@
package com.android.server;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import android.content.Context;
import android.net.ConnectivityManager;
+import android.net.vcn.VcnConfig;
+import android.net.vcn.VcnConfigTest;
+import android.os.ParcelUuid;
+import android.os.PersistableBundle;
+import android.os.Process;
+import android.os.UserHandle;
import android.os.test.TestLooper;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.server.vcn.util.PersistableBundleUtils;
+
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.io.FileNotFoundException;
+import java.util.Collections;
+import java.util.Map;
+import java.util.UUID;
+
/** Tests for {@link VcnManagementService}. */
@RunWith(AndroidJUnit4.class)
@SmallTest
public class VcnManagementServiceTest {
+ private static final ParcelUuid TEST_UUID_1 = new ParcelUuid(new UUID(0, 0));
+ private static final ParcelUuid TEST_UUID_2 = new ParcelUuid(new UUID(1, 1));
+ private static final VcnConfig TEST_VCN_CONFIG = VcnConfigTest.buildTestConfig();
+ private static final Map<ParcelUuid, VcnConfig> TEST_VCN_CONFIG_MAP =
+ Collections.unmodifiableMap(Collections.singletonMap(TEST_UUID_1, TEST_VCN_CONFIG));
+
+ private static final SubscriptionInfo TEST_SUBSCRIPTION_INFO =
+ new SubscriptionInfo(
+ 1 /* id */,
+ "" /* iccId */,
+ 0 /* simSlotIndex */,
+ "Carrier" /* displayName */,
+ "Carrier" /* carrierName */,
+ 0 /* nameSource */,
+ 255 /* iconTint */,
+ "12345" /* number */,
+ 0 /* roaming */,
+ null /* icon */,
+ "0" /* mcc */,
+ "0" /* mnc */,
+ "0" /* countryIso */,
+ false /* isEmbedded */,
+ null /* nativeAccessRules */,
+ null /* cardString */,
+ false /* isOpportunistic */,
+ TEST_UUID_1.toString() /* groupUUID */,
+ 0 /* carrierId */,
+ 0 /* profileClass */);
+
private final Context mMockContext = mock(Context.class);
private final VcnManagementService.Dependencies mMockDeps =
mock(VcnManagementService.Dependencies.class);
private final TestLooper mTestLooper = new TestLooper();
private final ConnectivityManager mConnMgr = mock(ConnectivityManager.class);
+ private final TelephonyManager mTelMgr = mock(TelephonyManager.class);
+ private final SubscriptionManager mSubMgr = mock(SubscriptionManager.class);
private final VcnManagementService mVcnMgmtSvc;
+ private final PersistableBundleUtils.LockingReadWriteHelper mConfigReadWriteHelper =
+ mock(PersistableBundleUtils.LockingReadWriteHelper.class);
- public VcnManagementServiceTest() {
- doReturn(Context.CONNECTIVITY_SERVICE)
- .when(mMockContext)
- .getSystemServiceName(ConnectivityManager.class);
- doReturn(mConnMgr).when(mMockContext).getSystemService(Context.CONNECTIVITY_SERVICE);
+ public VcnManagementServiceTest() throws Exception {
+ setupSystemService(mConnMgr, Context.CONNECTIVITY_SERVICE, ConnectivityManager.class);
+ setupSystemService(mTelMgr, Context.TELEPHONY_SERVICE, TelephonyManager.class);
+ setupSystemService(
+ mSubMgr, Context.TELEPHONY_SUBSCRIPTION_SERVICE, SubscriptionManager.class);
doReturn(mTestLooper.getLooper()).when(mMockDeps).getLooper();
+ doReturn(Process.FIRST_APPLICATION_UID).when(mMockDeps).getBinderCallingUid();
+ doReturn(mConfigReadWriteHelper)
+ .when(mMockDeps)
+ .newPersistableBundleLockingReadWriteHelper(any());
+
+ final PersistableBundle bundle =
+ PersistableBundleUtils.fromMap(
+ TEST_VCN_CONFIG_MAP,
+ PersistableBundleUtils::fromParcelUuid,
+ VcnConfig::toPersistableBundle);
+ doReturn(bundle).when(mConfigReadWriteHelper).readFromDisk();
+
+ setupMockedCarrierPrivilege(true);
mVcnMgmtSvc = new VcnManagementService(mMockContext, mMockDeps);
}
+ private void setupSystemService(Object service, String name, Class<?> serviceClass) {
+ doReturn(name).when(mMockContext).getSystemServiceName(serviceClass);
+ doReturn(service).when(mMockContext).getSystemService(name);
+ }
+
+ private void setupMockedCarrierPrivilege(boolean isPrivileged) {
+ doReturn(Collections.singletonList(TEST_SUBSCRIPTION_INFO))
+ .when(mSubMgr)
+ .getSubscriptionsInGroup(any());
+ doReturn(isPrivileged)
+ .when(mTelMgr)
+ .hasCarrierPrivileges(eq(TEST_SUBSCRIPTION_INFO.getSubscriptionId()));
+ }
+
@Test
public void testSystemReady() throws Exception {
mVcnMgmtSvc.systemReady();
@@ -59,4 +140,119 @@
verify(mConnMgr)
.registerNetworkProvider(any(VcnManagementService.VcnNetworkProvider.class));
}
+
+ @Test
+ public void testNonSystemServerRealConfigFileAccessPermission() throws Exception {
+ // Attempt to build a real instance of the dependencies, and verify we cannot write to the
+ // file.
+ VcnManagementService.Dependencies deps = new VcnManagementService.Dependencies();
+ PersistableBundleUtils.LockingReadWriteHelper configReadWriteHelper =
+ deps.newPersistableBundleLockingReadWriteHelper(
+ VcnManagementService.VCN_CONFIG_FILE);
+
+ // Even tests should not be able to read/write configs from disk; SELinux policies restrict
+ // it to only the system server.
+ // Reading config should always return null since the file "does not exist", and writing
+ // should throw an IOException.
+ assertNull(configReadWriteHelper.readFromDisk());
+
+ try {
+ configReadWriteHelper.writeToDisk(new PersistableBundle());
+ fail("Expected IOException due to SELinux policy");
+ } catch (FileNotFoundException expected) {
+ }
+ }
+
+ @Test
+ public void testLoadVcnConfigsOnStartup() throws Exception {
+ mTestLooper.dispatchAll();
+
+ assertEquals(TEST_VCN_CONFIG_MAP, mVcnMgmtSvc.getConfigs());
+ verify(mConfigReadWriteHelper).readFromDisk();
+ }
+
+ @Test
+ public void testSetVcnConfigRequiresNonSystemServer() throws Exception {
+ doReturn(Process.SYSTEM_UID).when(mMockDeps).getBinderCallingUid();
+
+ try {
+ mVcnMgmtSvc.setVcnConfig(TEST_UUID_1, VcnConfigTest.buildTestConfig());
+ fail("Expected IllegalStateException exception for system server");
+ } catch (IllegalStateException expected) {
+ }
+ }
+
+ @Test
+ public void testSetVcnConfigRequiresSystemUser() throws Exception {
+ doReturn(UserHandle.getUid(UserHandle.MIN_SECONDARY_USER_ID, Process.FIRST_APPLICATION_UID))
+ .when(mMockDeps)
+ .getBinderCallingUid();
+
+ try {
+ mVcnMgmtSvc.setVcnConfig(TEST_UUID_1, VcnConfigTest.buildTestConfig());
+ fail("Expected security exception for non system user");
+ } catch (SecurityException expected) {
+ }
+ }
+
+ @Test
+ public void testSetVcnConfigRequiresCarrierPrivileges() throws Exception {
+ setupMockedCarrierPrivilege(false);
+
+ try {
+ mVcnMgmtSvc.setVcnConfig(TEST_UUID_1, VcnConfigTest.buildTestConfig());
+ fail("Expected security exception for missing carrier privileges");
+ } catch (SecurityException expected) {
+ }
+ }
+
+ @Test
+ public void testSetVcnConfig() throws Exception {
+ // Use a different UUID to simulate a new VCN config.
+ mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG);
+ assertEquals(TEST_VCN_CONFIG, mVcnMgmtSvc.getConfigs().get(TEST_UUID_2));
+ verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class));
+ }
+
+ @Test
+ public void testClearVcnConfigRequiresNonSystemServer() throws Exception {
+ doReturn(Process.SYSTEM_UID).when(mMockDeps).getBinderCallingUid();
+
+ try {
+ mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1);
+ fail("Expected IllegalStateException exception for system server");
+ } catch (IllegalStateException expected) {
+ }
+ }
+
+ @Test
+ public void testClearVcnConfigRequiresSystemUser() throws Exception {
+ doReturn(UserHandle.getUid(UserHandle.MIN_SECONDARY_USER_ID, Process.FIRST_APPLICATION_UID))
+ .when(mMockDeps)
+ .getBinderCallingUid();
+
+ try {
+ mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1);
+ fail("Expected security exception for non system user");
+ } catch (SecurityException expected) {
+ }
+ }
+
+ @Test
+ public void testClearVcnConfigRequiresCarrierPrivileges() throws Exception {
+ setupMockedCarrierPrivilege(false);
+
+ try {
+ mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1);
+ fail("Expected security exception for missing carrier privileges");
+ } catch (SecurityException expected) {
+ }
+ }
+
+ @Test
+ public void testClearVcnConfig() throws Exception {
+ mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1);
+ assertTrue(mVcnMgmtSvc.getConfigs().isEmpty());
+ verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class));
+ }
}
diff --git a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
new file mode 100644
index 0000000..17b8f64
--- /dev/null
+++ b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.vcn;
+
+import static android.telephony.CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED;
+import static android.telephony.CarrierConfigManager.EXTRA_SLOT_INDEX;
+import static android.telephony.CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX;
+import static android.telephony.SubscriptionManager.INVALID_SIM_SLOT_INDEX;
+import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+
+import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
+import static com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionTrackerCallback;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+import android.os.HandlerExecutor;
+import android.os.ParcelUuid;
+import android.os.test.TestLooper;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
+import android.util.ArraySet;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+/** Tests for TelephonySubscriptionTracker */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class TelephonySubscriptionTrackerTest {
+ private static final ParcelUuid TEST_PARCEL_UUID = new ParcelUuid(UUID.randomUUID());
+ private static final int TEST_SIM_SLOT_INDEX = 1;
+ private static final int TEST_SUBSCRIPTION_ID_1 = 2;
+ private static final SubscriptionInfo TEST_SUBINFO_1 = mock(SubscriptionInfo.class);
+ private static final int TEST_SUBSCRIPTION_ID_2 = 3;
+ private static final SubscriptionInfo TEST_SUBINFO_2 = mock(SubscriptionInfo.class);
+ private static final Map<Integer, ParcelUuid> TEST_SUBID_TO_GROUP_MAP;
+
+ static {
+ final Map<Integer, ParcelUuid> subIdToGroupMap = new HashMap<>();
+ subIdToGroupMap.put(TEST_SUBSCRIPTION_ID_1, TEST_PARCEL_UUID);
+ subIdToGroupMap.put(TEST_SUBSCRIPTION_ID_2, TEST_PARCEL_UUID);
+ TEST_SUBID_TO_GROUP_MAP = Collections.unmodifiableMap(subIdToGroupMap);
+ }
+
+ @NonNull private final Context mContext;
+ @NonNull private final TestLooper mTestLooper;
+ @NonNull private final Handler mHandler;
+ @NonNull private final TelephonySubscriptionTracker.Dependencies mDeps;
+
+ @NonNull private final SubscriptionManager mSubscriptionManager;
+ @NonNull private final CarrierConfigManager mCarrierConfigManager;
+
+ @NonNull private TelephonySubscriptionTrackerCallback mCallback;
+ @NonNull private TelephonySubscriptionTracker mTelephonySubscriptionTracker;
+
+ public TelephonySubscriptionTrackerTest() {
+ mContext = mock(Context.class);
+ mTestLooper = new TestLooper();
+ mHandler = new Handler(mTestLooper.getLooper());
+ mDeps = mock(TelephonySubscriptionTracker.Dependencies.class);
+
+ mSubscriptionManager = mock(SubscriptionManager.class);
+ mCarrierConfigManager = mock(CarrierConfigManager.class);
+
+ doReturn(Context.TELEPHONY_SUBSCRIPTION_SERVICE)
+ .when(mContext)
+ .getSystemServiceName(SubscriptionManager.class);
+ doReturn(mSubscriptionManager)
+ .when(mContext)
+ .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+
+ doReturn(Context.CARRIER_CONFIG_SERVICE)
+ .when(mContext)
+ .getSystemServiceName(CarrierConfigManager.class);
+ doReturn(mCarrierConfigManager)
+ .when(mContext)
+ .getSystemService(Context.CARRIER_CONFIG_SERVICE);
+
+ // subId 1, 2 are in same subGrp, only subId 1 is active
+ doReturn(TEST_PARCEL_UUID).when(TEST_SUBINFO_1).getGroupUuid();
+ doReturn(TEST_PARCEL_UUID).when(TEST_SUBINFO_2).getGroupUuid();
+ doReturn(TEST_SIM_SLOT_INDEX).when(TEST_SUBINFO_1).getSimSlotIndex();
+ doReturn(INVALID_SIM_SLOT_INDEX).when(TEST_SUBINFO_2).getSimSlotIndex();
+ doReturn(TEST_SUBSCRIPTION_ID_1).when(TEST_SUBINFO_1).getSubscriptionId();
+ doReturn(TEST_SUBSCRIPTION_ID_2).when(TEST_SUBINFO_2).getSubscriptionId();
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ mCallback = mock(TelephonySubscriptionTrackerCallback.class);
+ mTelephonySubscriptionTracker =
+ new TelephonySubscriptionTracker(mContext, mHandler, mCallback, mDeps);
+ mTelephonySubscriptionTracker.register();
+
+ doReturn(true).when(mDeps).isConfigForIdentifiedCarrier(any());
+ doReturn(Arrays.asList(TEST_SUBINFO_1, TEST_SUBINFO_2))
+ .when(mSubscriptionManager)
+ .getAllSubscriptionInfoList();
+ }
+
+ private IntentFilter getIntentFilter() {
+ final ArgumentCaptor<IntentFilter> captor = ArgumentCaptor.forClass(IntentFilter.class);
+ verify(mContext).registerReceiver(any(), captor.capture(), any(), any());
+
+ return captor.getValue();
+ }
+
+ private OnSubscriptionsChangedListener getOnSubscriptionsChangedListener() {
+ final ArgumentCaptor<OnSubscriptionsChangedListener> captor =
+ ArgumentCaptor.forClass(OnSubscriptionsChangedListener.class);
+ verify(mSubscriptionManager).addOnSubscriptionsChangedListener(any(), captor.capture());
+
+ return captor.getValue();
+ }
+
+ private Intent buildTestBroadcastIntent(boolean hasValidSubscription) {
+ Intent intent = new Intent(ACTION_CARRIER_CONFIG_CHANGED);
+ intent.putExtra(EXTRA_SLOT_INDEX, TEST_SIM_SLOT_INDEX);
+ intent.putExtra(
+ EXTRA_SUBSCRIPTION_INDEX,
+ hasValidSubscription ? TEST_SUBSCRIPTION_ID_1 : INVALID_SUBSCRIPTION_ID);
+
+ return intent;
+ }
+
+ private TelephonySubscriptionSnapshot buildExpectedSnapshot(Set<ParcelUuid> activeSubGroups) {
+ return buildExpectedSnapshot(TEST_SUBID_TO_GROUP_MAP, activeSubGroups);
+ }
+
+ private TelephonySubscriptionSnapshot buildExpectedSnapshot(
+ Map<Integer, ParcelUuid> subIdToGroupMap, Set<ParcelUuid> activeSubGroups) {
+ return new TelephonySubscriptionSnapshot(subIdToGroupMap, activeSubGroups);
+ }
+
+ private void verifyNoActiveSubscriptions() {
+ verify(mCallback).onNewSnapshot(
+ argThat(snapshot -> snapshot.getActiveSubscriptionGroups().isEmpty()));
+ }
+
+ private void setupReadySubIds() {
+ mTelephonySubscriptionTracker.setReadySubIdsBySlotId(
+ Collections.singletonMap(TEST_SIM_SLOT_INDEX, TEST_SUBSCRIPTION_ID_1));
+ }
+
+ @Test
+ public void testRegister() throws Exception {
+ verify(mContext)
+ .registerReceiver(
+ eq(mTelephonySubscriptionTracker),
+ any(IntentFilter.class),
+ any(),
+ eq(mHandler));
+ final IntentFilter filter = getIntentFilter();
+ assertEquals(1, filter.countActions());
+ assertTrue(filter.hasAction(ACTION_CARRIER_CONFIG_CHANGED));
+
+ verify(mSubscriptionManager)
+ .addOnSubscriptionsChangedListener(any(HandlerExecutor.class), any());
+ assertNotNull(getOnSubscriptionsChangedListener());
+ }
+
+ @Test
+ public void testUnregister() throws Exception {
+ mTelephonySubscriptionTracker.unregister();
+
+ verify(mContext).unregisterReceiver(eq(mTelephonySubscriptionTracker));
+
+ final OnSubscriptionsChangedListener listener = getOnSubscriptionsChangedListener();
+ verify(mSubscriptionManager).removeOnSubscriptionsChangedListener(eq(listener));
+ }
+
+ @Test
+ public void testOnSubscriptionsChangedFired_NoReadySubIds() throws Exception {
+ final OnSubscriptionsChangedListener listener = getOnSubscriptionsChangedListener();
+ listener.onSubscriptionsChanged();
+ mTestLooper.dispatchAll();
+
+ verifyNoActiveSubscriptions();
+ }
+
+ @Test
+ public void testOnSubscriptionsChangedFired_WithReadySubIds() throws Exception {
+ setupReadySubIds();
+
+ final OnSubscriptionsChangedListener listener = getOnSubscriptionsChangedListener();
+ listener.onSubscriptionsChanged();
+ mTestLooper.dispatchAll();
+
+ final Set<ParcelUuid> activeSubGroups = Collections.singleton(TEST_PARCEL_UUID);
+ verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(activeSubGroups)));
+ }
+
+ @Test
+ public void testReceiveBroadcast_ConfigReadyWithSubscriptions() throws Exception {
+ mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true));
+ mTestLooper.dispatchAll();
+
+ final Set<ParcelUuid> activeSubGroups = Collections.singleton(TEST_PARCEL_UUID);
+ verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(activeSubGroups)));
+ }
+
+ @Test
+ public void testReceiveBroadcast_ConfigReadyNoSubscriptions() throws Exception {
+ doReturn(new ArrayList<SubscriptionInfo>())
+ .when(mSubscriptionManager)
+ .getAllSubscriptionInfoList();
+
+ mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true));
+ mTestLooper.dispatchAll();
+
+ // Expect an empty snapshot
+ verify(mCallback).onNewSnapshot(
+ eq(buildExpectedSnapshot(Collections.emptyMap(), Collections.emptySet())));
+ }
+
+ @Test
+ public void testReceiveBroadcast_SlotCleared() throws Exception {
+ setupReadySubIds();
+
+ mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(false));
+ mTestLooper.dispatchAll();
+
+ verifyNoActiveSubscriptions();
+ assertTrue(mTelephonySubscriptionTracker.getReadySubIdsBySlotId().isEmpty());
+ }
+
+ @Test
+ public void testReceiveBroadcast_ConfigNotReady() throws Exception {
+ doReturn(false).when(mDeps).isConfigForIdentifiedCarrier(any());
+
+ mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true));
+ mTestLooper.dispatchAll();
+
+ // No interactions expected; config was not loaded
+ verifyNoMoreInteractions(mCallback);
+ }
+
+ @Test
+ public void testSubscriptionsClearedAfterValidTriggersCallbacks() throws Exception {
+ final Set<ParcelUuid> activeSubGroups = Collections.singleton(TEST_PARCEL_UUID);
+
+ mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true));
+ mTestLooper.dispatchAll();
+ verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(activeSubGroups)));
+ assertNotNull(
+ mTelephonySubscriptionTracker.getReadySubIdsBySlotId().get(TEST_SIM_SLOT_INDEX));
+
+ doReturn(Collections.emptyList()).when(mSubscriptionManager).getAllSubscriptionInfoList();
+ mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true));
+ mTestLooper.dispatchAll();
+ verify(mCallback).onNewSnapshot(
+ eq(buildExpectedSnapshot(Collections.emptyMap(), Collections.emptySet())));
+ }
+
+ @Test
+ public void testSlotClearedAfterValidTriggersCallbacks() throws Exception {
+ final Set<ParcelUuid> activeSubGroups = Collections.singleton(TEST_PARCEL_UUID);
+
+ mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(true));
+ mTestLooper.dispatchAll();
+ verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(activeSubGroups)));
+ assertNotNull(
+ mTelephonySubscriptionTracker.getReadySubIdsBySlotId().get(TEST_SIM_SLOT_INDEX));
+
+ mTelephonySubscriptionTracker.onReceive(mContext, buildTestBroadcastIntent(false));
+ mTestLooper.dispatchAll();
+ verify(mCallback).onNewSnapshot(eq(buildExpectedSnapshot(Collections.emptySet())));
+ assertNull(mTelephonySubscriptionTracker.getReadySubIdsBySlotId().get(TEST_SIM_SLOT_INDEX));
+ }
+
+ @Test
+ public void testTelephonySubscriptionSnapshotGetGroupForSubId() throws Exception {
+ final TelephonySubscriptionSnapshot snapshot =
+ new TelephonySubscriptionSnapshot(TEST_SUBID_TO_GROUP_MAP, Collections.emptySet());
+
+ assertEquals(TEST_PARCEL_UUID, snapshot.getGroupForSubId(TEST_SUBSCRIPTION_ID_1));
+ assertEquals(TEST_PARCEL_UUID, snapshot.getGroupForSubId(TEST_SUBSCRIPTION_ID_2));
+ }
+
+ @Test
+ public void testTelephonySubscriptionSnapshotGetAllSubIdsInGroup() throws Exception {
+ final TelephonySubscriptionSnapshot snapshot =
+ new TelephonySubscriptionSnapshot(TEST_SUBID_TO_GROUP_MAP, Collections.emptySet());
+
+ assertEquals(
+ new ArraySet<>(Arrays.asList(TEST_SUBSCRIPTION_ID_1, TEST_SUBSCRIPTION_ID_2)),
+ snapshot.getAllSubIdsInGroup(TEST_PARCEL_UUID));
+ }
+}
diff --git a/tools/aapt2/util/Util.cpp b/tools/aapt2/util/Util.cpp
index 28330db..d7a8e6f 100644
--- a/tools/aapt2/util/Util.cpp
+++ b/tools/aapt2/util/Util.cpp
@@ -548,14 +548,14 @@
}
StringPiece16 GetString16(const android::ResStringPool& pool, size_t idx) {
- if (auto str = pool.stringAt(idx)) {
+ if (auto str = pool.stringAt(idx); str.ok()) {
return *str;
}
return StringPiece16();
}
std::string GetString(const android::ResStringPool& pool, size_t idx) {
- if (auto str = pool.string8At(idx)) {
+ if (auto str = pool.string8At(idx); str.ok()) {
return ModifiedUtf8ToUtf8(str->to_string());
}
return Utf16ToUtf8(GetString16(pool, idx));
diff --git a/tools/validatekeymaps/Main.cpp b/tools/validatekeymaps/Main.cpp
index 950473d..991b280 100644
--- a/tools/validatekeymaps/Main.cpp
+++ b/tools/validatekeymaps/Main.cpp
@@ -96,7 +96,7 @@
case FileType::KEY_LAYOUT: {
base::Result<std::shared_ptr<KeyLayoutMap>> ret = KeyLayoutMap::load(filename);
- if (!ret) {
+ if (!ret.ok()) {
error("Error %s parsing key layout file.\n\n", ret.error().message().c_str());
return false;
}
@@ -106,7 +106,7 @@
case FileType::KEY_CHARACTER_MAP: {
base::Result<std::shared_ptr<KeyCharacterMap>> ret =
KeyCharacterMap::load(filename, KeyCharacterMap::Format::ANY);
- if (!ret) {
+ if (!ret.ok()) {
error("Error %s parsing key character map file.\n\n",
ret.error().message().c_str());
return false;
diff --git a/wifi/Android.bp b/wifi/Android.bp
index c05f52c..07b2ea9 100644
--- a/wifi/Android.bp
+++ b/wifi/Android.bp
@@ -31,9 +31,6 @@
"java/**/*.java",
"java/**/*.aidl",
],
- exclude_srcs: [
- ":framework-wifi-non-updatable-sources"
- ],
path: "java",
visibility: ["//visibility:private"],
}
@@ -48,20 +45,6 @@
}
filegroup {
- name: "framework-wifi-non-updatable-sources",
- srcs: [
- // TODO(b/146011398) package android.net.wifi is now split amongst 2 jars: framework.jar and
- // framework-wifi.jar. This is not a good idea, should move WifiNetworkScoreCache
- // to a separate package.
- "java/android/net/wifi/SoftApConfToXmlMigrationUtil.java",
- "java/android/net/wifi/WifiNetworkScoreCache.java",
- "java/android/net/wifi/WifiMigration.java",
- "java/android/net/wifi/nl80211/*.java",
- ":libwificond_ipc_aidl",
- ],
-}
-
-filegroup {
name: "framework-wifi-annotations",
srcs: ["java/android/net/wifi/WifiAnnotations.java"],
}
@@ -69,6 +52,7 @@
// list of tests that are allowed to access @hide APIs from framework-wifi
test_access_hidden_api_whitelist = [
"//frameworks/base/wifi/tests",
+ "//frameworks/base/wifi/non-updatable/tests",
"//frameworks/opt/net/wifi/tests/wifitests:__subpackages__",
"//external/robolectric-shadows:__subpackages__",
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 06ebee4..23f47ef 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -147,6 +147,8 @@
void updateInterfaceIpState(String ifaceName, int mode);
+ boolean isDefaultCoexAlgorithmEnabled();
+
void setCoexUnsafeChannels(in List<CoexUnsafeChannel> unsafeChannels, int mandatoryRestrictions);
List<CoexUnsafeChannel> getCoexUnsafeChannels();
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 833f9b0..6496cc7 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -3225,6 +3225,19 @@
public @interface CoexRestriction {}
/**
+ * @return {@code true} if the default coex algorithm is enabled. {@code false} otherwise.
+ *
+ * @hide
+ */
+ public boolean isDefaultCoexAlgorithmEnabled() {
+ try {
+ return mService.isDefaultCoexAlgorithmEnabled();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Specify the set of {@link CoexUnsafeChannel} to propagate through the framework for
* Wi-Fi/Cellular coex channel avoidance if the default algorithm is disabled via overlay
* (i.e. config_wifiCoexDefaultAlgorithmEnabled = false). Otherwise do nothing.
diff --git a/wifi/non-updatable/java/Android.bp b/wifi/non-updatable/java/Android.bp
new file mode 100644
index 0000000..b35b4be
--- /dev/null
+++ b/wifi/non-updatable/java/Android.bp
@@ -0,0 +1,35 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// This directory contains framework Wifi APIs that are not part of the Wifi module (i.e. not
+// updatable), and are generally only called by the Wifi module.
+
+// necessary since we only want the `path` property to only refer to these files
+filegroup {
+ name: "framework-wifi-non-updatable-sources-internal",
+ srcs: ["src/**/*.java"],
+ path: "src",
+ visibility: ["//visibility:private"],
+}
+
+filegroup {
+ name: "framework-wifi-non-updatable-sources",
+ srcs: [
+ // TODO(b/146011398) package android.net.wifi is now split amongst 2 jars: framework.jar and
+ // framework-wifi.jar. This is not a good idea, should move WifiNetworkScoreCache
+ // to a separate package.
+ ":framework-wifi-non-updatable-sources-internal",
+ ":libwificond_ipc_aidl",
+ ],
+}
diff --git a/wifi/java/android/net/wifi/SoftApConfToXmlMigrationUtil.java b/wifi/non-updatable/java/src/android/net/wifi/SoftApConfToXmlMigrationUtil.java
similarity index 100%
rename from wifi/java/android/net/wifi/SoftApConfToXmlMigrationUtil.java
rename to wifi/non-updatable/java/src/android/net/wifi/SoftApConfToXmlMigrationUtil.java
diff --git a/wifi/java/android/net/wifi/WifiMigration.java b/wifi/non-updatable/java/src/android/net/wifi/WifiMigration.java
similarity index 98%
rename from wifi/java/android/net/wifi/WifiMigration.java
rename to wifi/non-updatable/java/src/android/net/wifi/WifiMigration.java
index 5792d27..4fabc0b 100755
--- a/wifi/java/android/net/wifi/WifiMigration.java
+++ b/wifi/non-updatable/java/src/android/net/wifi/WifiMigration.java
@@ -139,8 +139,8 @@
/**
* Load data from legacy shared wifi config store file.
* <p>
- * Expected AOSP format is available in the sample files under {@code /frameworks/base/wifi/
- * java/android/net/wifi/migration_samples}.
+ * Expected AOSP format is available in the sample files under {@code
+ * frameworks/base/wifi/non-updatable/migration_samples/}.
* </p>
* <p>
* Note:
@@ -218,8 +218,8 @@
/**
* Load data from legacy user wifi config store file.
* <p>
- * Expected AOSP format is available in the sample files under {@code /frameworks/base/wifi/
- * java/android/net/wifi/migration_samples}.
+ * Expected AOSP format is available in the sample files under {@code
+ * frameworks/base/wifi/non-updatable/migration_samples/}.
* </p>
* <p>
* Note:
diff --git a/wifi/java/android/net/wifi/WifiNetworkScoreCache.java b/wifi/non-updatable/java/src/android/net/wifi/WifiNetworkScoreCache.java
similarity index 98%
rename from wifi/java/android/net/wifi/WifiNetworkScoreCache.java
rename to wifi/non-updatable/java/src/android/net/wifi/WifiNetworkScoreCache.java
index 378549d..3903658 100755
--- a/wifi/java/android/net/wifi/WifiNetworkScoreCache.java
+++ b/wifi/non-updatable/java/src/android/net/wifi/WifiNetworkScoreCache.java
@@ -89,7 +89,7 @@
@Override public final void updateScores(List<ScoredNetwork> networks) {
if (networks == null || networks.isEmpty()) {
- return;
+ return;
}
if (DBG) {
Log.d(TAG, "updateScores list size=" + networks.size());
@@ -97,7 +97,7 @@
boolean changed = false;
- synchronized(mLock) {
+ synchronized (mLock) {
for (ScoredNetwork network : networks) {
String networkKey = buildNetworkKey(network);
if (networkKey == null) {
@@ -189,7 +189,7 @@
String key = buildNetworkKey(result);
if (key == null) return null;
- synchronized(mLock) {
+ synchronized (mLock) {
ScoredNetwork network = mCache.get(key);
return network;
}
diff --git a/wifi/java/android/net/wifi/nl80211/ChannelSettings.java b/wifi/non-updatable/java/src/android/net/wifi/nl80211/ChannelSettings.java
similarity index 100%
rename from wifi/java/android/net/wifi/nl80211/ChannelSettings.java
rename to wifi/non-updatable/java/src/android/net/wifi/nl80211/ChannelSettings.java
diff --git a/wifi/java/android/net/wifi/nl80211/DeviceWiphyCapabilities.java b/wifi/non-updatable/java/src/android/net/wifi/nl80211/DeviceWiphyCapabilities.java
similarity index 100%
rename from wifi/java/android/net/wifi/nl80211/DeviceWiphyCapabilities.java
rename to wifi/non-updatable/java/src/android/net/wifi/nl80211/DeviceWiphyCapabilities.java
diff --git a/wifi/java/android/net/wifi/nl80211/HiddenNetwork.java b/wifi/non-updatable/java/src/android/net/wifi/nl80211/HiddenNetwork.java
similarity index 100%
rename from wifi/java/android/net/wifi/nl80211/HiddenNetwork.java
rename to wifi/non-updatable/java/src/android/net/wifi/nl80211/HiddenNetwork.java
diff --git a/wifi/java/android/net/wifi/nl80211/NativeScanResult.java b/wifi/non-updatable/java/src/android/net/wifi/nl80211/NativeScanResult.java
similarity index 100%
rename from wifi/java/android/net/wifi/nl80211/NativeScanResult.java
rename to wifi/non-updatable/java/src/android/net/wifi/nl80211/NativeScanResult.java
diff --git a/wifi/java/android/net/wifi/nl80211/NativeWifiClient.java b/wifi/non-updatable/java/src/android/net/wifi/nl80211/NativeWifiClient.java
similarity index 100%
rename from wifi/java/android/net/wifi/nl80211/NativeWifiClient.java
rename to wifi/non-updatable/java/src/android/net/wifi/nl80211/NativeWifiClient.java
diff --git a/wifi/java/android/net/wifi/nl80211/PnoNetwork.java b/wifi/non-updatable/java/src/android/net/wifi/nl80211/PnoNetwork.java
similarity index 100%
rename from wifi/java/android/net/wifi/nl80211/PnoNetwork.java
rename to wifi/non-updatable/java/src/android/net/wifi/nl80211/PnoNetwork.java
diff --git a/wifi/java/android/net/wifi/nl80211/PnoSettings.java b/wifi/non-updatable/java/src/android/net/wifi/nl80211/PnoSettings.java
similarity index 100%
rename from wifi/java/android/net/wifi/nl80211/PnoSettings.java
rename to wifi/non-updatable/java/src/android/net/wifi/nl80211/PnoSettings.java
diff --git a/wifi/java/android/net/wifi/nl80211/RadioChainInfo.java b/wifi/non-updatable/java/src/android/net/wifi/nl80211/RadioChainInfo.java
similarity index 100%
rename from wifi/java/android/net/wifi/nl80211/RadioChainInfo.java
rename to wifi/non-updatable/java/src/android/net/wifi/nl80211/RadioChainInfo.java
diff --git a/wifi/java/android/net/wifi/nl80211/SingleScanSettings.java b/wifi/non-updatable/java/src/android/net/wifi/nl80211/SingleScanSettings.java
similarity index 100%
rename from wifi/java/android/net/wifi/nl80211/SingleScanSettings.java
rename to wifi/non-updatable/java/src/android/net/wifi/nl80211/SingleScanSettings.java
diff --git a/wifi/java/android/net/wifi/nl80211/WifiNl80211Manager.java b/wifi/non-updatable/java/src/android/net/wifi/nl80211/WifiNl80211Manager.java
similarity index 97%
rename from wifi/java/android/net/wifi/nl80211/WifiNl80211Manager.java
rename to wifi/non-updatable/java/src/android/net/wifi/nl80211/WifiNl80211Manager.java
index 91d25f9..db2eb99 100644
--- a/wifi/java/android/net/wifi/nl80211/WifiNl80211Manager.java
+++ b/wifi/non-updatable/java/src/android/net/wifi/nl80211/WifiNl80211Manager.java
@@ -588,7 +588,7 @@
public boolean setupInterfaceForClientMode(@NonNull String ifaceName,
@NonNull @CallbackExecutor Executor executor,
@NonNull ScanEventCallback scanCallback, @NonNull ScanEventCallback pnoScanCallback) {
- Log.d(TAG, "Setting up interface for client mode");
+ Log.d(TAG, "Setting up interface for client mode: " + ifaceName);
if (!retrieveWificondAndRegisterForDeath()) {
return false;
}
@@ -646,7 +646,7 @@
*/
public boolean tearDownClientInterface(@NonNull String ifaceName) {
if (getClientInterface(ifaceName) == null) {
- Log.e(TAG, "No valid wificond client interface handler");
+ Log.e(TAG, "No valid wificond client interface handler for iface=" + ifaceName);
return false;
}
try {
@@ -661,7 +661,7 @@
}
if (mWificond == null) {
- Log.e(TAG, "Reference to wifiCond is null");
+ Log.e(TAG, "tearDownClientInterface: mWificond binder is null! Did wificond die?");
return false;
}
@@ -691,7 +691,7 @@
* @return true on success.
*/
public boolean setupInterfaceForSoftApMode(@NonNull String ifaceName) {
- Log.d(TAG, "Setting up interface for soft ap mode");
+ Log.d(TAG, "Setting up interface for soft ap mode for iface=" + ifaceName);
if (!retrieveWificondAndRegisterForDeath()) {
return false;
}
@@ -725,12 +725,12 @@
*/
public boolean tearDownSoftApInterface(@NonNull String ifaceName) {
if (getApInterface(ifaceName) == null) {
- Log.e(TAG, "No valid wificond ap interface handler");
+ Log.e(TAG, "No valid wificond ap interface handler for iface=" + ifaceName);
return false;
}
if (mWificond == null) {
- Log.e(TAG, "Reference to wifiCond is null");
+ Log.e(TAG, "tearDownSoftApInterface: mWificond binder is null! Did wificond die?");
return false;
}
@@ -797,7 +797,7 @@
@Nullable public SignalPollResult signalPoll(@NonNull String ifaceName) {
IClientInterface iface = getClientInterface(ifaceName);
if (iface == null) {
- Log.e(TAG, "No valid wificond client interface handler");
+ Log.e(TAG, "No valid wificond client interface handler for iface=" + ifaceName);
return null;
}
@@ -828,7 +828,7 @@
@Nullable public TxPacketCounters getTxPacketCounters(@NonNull String ifaceName) {
IClientInterface iface = getClientInterface(ifaceName);
if (iface == null) {
- Log.e(TAG, "No valid wificond client interface handler");
+ Log.e(TAG, "No valid wificond client interface handler for iface=" + ifaceName);
return null;
}
@@ -871,7 +871,7 @@
@ScanResultType int scanType) {
IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
if (scannerImpl == null) {
- Log.e(TAG, "No valid wificond scanner interface handler");
+ Log.e(TAG, "No valid wificond scanner interface handler for iface=" + ifaceName);
return new ArrayList<>();
}
List<NativeScanResult> results = null;
@@ -936,7 +936,7 @@
@Nullable Set<Integer> freqs, @Nullable List<byte[]> hiddenNetworkSSIDs) {
IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
if (scannerImpl == null) {
- Log.e(TAG, "No valid wificond scanner interface handler");
+ Log.e(TAG, "No valid wificond scanner interface handler for iface=" + ifaceName);
return false;
}
SingleScanSettings settings = new SingleScanSettings();
@@ -1002,7 +1002,7 @@
@NonNull PnoScanRequestCallback callback) {
IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
if (scannerImpl == null) {
- Log.e(TAG, "No valid wificond scanner interface handler");
+ Log.e(TAG, "No valid wificond scanner interface handler for iface=" + ifaceName);
return false;
}
@@ -1040,7 +1040,7 @@
public boolean stopPnoScan(@NonNull String ifaceName) {
IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
if (scannerImpl == null) {
- Log.e(TAG, "No valid wificond scanner interface handler");
+ Log.e(TAG, "No valid wificond scanner interface handler for iface=" + ifaceName);
return false;
}
try {
@@ -1065,7 +1065,7 @@
public void abortScan(@NonNull String ifaceName) {
IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName);
if (scannerImpl == null) {
- Log.e(TAG, "No valid wificond scanner interface handler");
+ Log.e(TAG, "No valid wificond scanner interface handler for iface=" + ifaceName);
return;
}
try {
@@ -1091,7 +1091,7 @@
*/
public @NonNull int[] getChannelsMhzForBand(@WifiAnnotations.WifiBandBasic int band) {
if (mWificond == null) {
- Log.e(TAG, "No valid wificond scanner interface handler");
+ Log.e(TAG, "getChannelsMhzForBand: mWificond binder is null! Did wificond die?");
return new int[0];
}
int[] result = null;
@@ -1141,7 +1141,7 @@
*/
@Nullable public DeviceWiphyCapabilities getDeviceWiphyCapabilities(@NonNull String ifaceName) {
if (mWificond == null) {
- Log.e(TAG, "Can not query for device wiphy capabilities at this time");
+ Log.e(TAG, "getDeviceWiphyCapabilities: mWificond binder is null! Did wificond die?");
return null;
}
@@ -1176,7 +1176,7 @@
@NonNull SoftApCallback callback) {
IApInterface iface = getApInterface(ifaceName);
if (iface == null) {
- Log.e(TAG, "No valid ap interface handler");
+ Log.e(TAG, "No valid ap interface handler for iface=" + ifaceName);
return false;
}
@@ -1234,7 +1234,7 @@
// TODO (b/112029045) validate mcs
IClientInterface clientInterface = getClientInterface(ifaceName);
if (clientInterface == null) {
- Log.e(TAG, "No valid wificond client interface handler");
+ Log.e(TAG, "No valid wificond client interface handler for iface=" + ifaceName);
executor.execute(() -> callback.onFailure(SEND_MGMT_FRAME_ERROR_UNKNOWN));
return;
}
diff --git a/wifi/java/android/net/wifi/migration_samples/README.txt b/wifi/non-updatable/migration_samples/README.txt
similarity index 100%
rename from wifi/java/android/net/wifi/migration_samples/README.txt
rename to wifi/non-updatable/migration_samples/README.txt
diff --git a/wifi/java/android/net/wifi/migration_samples/Shared_WifiConfigStore.xml b/wifi/non-updatable/migration_samples/Shared_WifiConfigStore.xml
similarity index 100%
rename from wifi/java/android/net/wifi/migration_samples/Shared_WifiConfigStore.xml
rename to wifi/non-updatable/migration_samples/Shared_WifiConfigStore.xml
diff --git a/wifi/java/android/net/wifi/migration_samples/Shared_WifiConfigStoreSoftAp.xml b/wifi/non-updatable/migration_samples/Shared_WifiConfigStoreSoftAp.xml
similarity index 100%
rename from wifi/java/android/net/wifi/migration_samples/Shared_WifiConfigStoreSoftAp.xml
rename to wifi/non-updatable/migration_samples/Shared_WifiConfigStoreSoftAp.xml
diff --git a/wifi/java/android/net/wifi/migration_samples/User_WifiConfigStore.xml b/wifi/non-updatable/migration_samples/User_WifiConfigStore.xml
similarity index 100%
rename from wifi/java/android/net/wifi/migration_samples/User_WifiConfigStore.xml
rename to wifi/non-updatable/migration_samples/User_WifiConfigStore.xml
diff --git a/wifi/java/android/net/wifi/migration_samples/User_WifiConfigStoreNetworkSuggestions.xml b/wifi/non-updatable/migration_samples/User_WifiConfigStoreNetworkSuggestions.xml
similarity index 100%
rename from wifi/java/android/net/wifi/migration_samples/User_WifiConfigStoreNetworkSuggestions.xml
rename to wifi/non-updatable/migration_samples/User_WifiConfigStoreNetworkSuggestions.xml
diff --git a/wifi/non-updatable/tests/Android.bp b/wifi/non-updatable/tests/Android.bp
new file mode 100644
index 0000000..3f5cacf
--- /dev/null
+++ b/wifi/non-updatable/tests/Android.bp
@@ -0,0 +1,44 @@
+// 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.
+
+android_test {
+ name: "FrameworksWifiNonUpdatableApiTests",
+
+ defaults: ["framework-wifi-test-defaults"],
+
+ srcs: ["src/**/*.java"],
+
+ jacoco: {
+ include_filter: ["android.net.wifi.*"],
+ // TODO(b/147521214) need to exclude test classes
+ exclude_filter: [],
+ },
+
+ static_libs: [
+ "androidx.test.rules",
+ "frameworks-base-testutils",
+ "guava",
+ "mockito-target-minus-junit4",
+ "truth-prebuilt",
+ ],
+
+ libs: [
+ "android.test.runner",
+ "android.test.base",
+ ],
+
+ test_suites: [
+ "general-tests",
+ ],
+}
diff --git a/wifi/non-updatable/tests/AndroidManifest.xml b/wifi/non-updatable/tests/AndroidManifest.xml
new file mode 100644
index 0000000..18986fc
--- /dev/null
+++ b/wifi/non-updatable/tests/AndroidManifest.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.net.wifi.nonupdatable.test">
+
+ <application>
+ <uses-library android:name="android.test.runner"/>
+ <activity android:label="WifiTestDummyLabel"
+ android:name="WifiTestDummyName"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.net.wifi.nonupdatable.test"
+ android:label="Frameworks Wifi Non-updatable API Tests">
+ </instrumentation>
+
+</manifest>
diff --git a/media/tests/MediaTranscodingTest/AndroidTest.xml b/wifi/non-updatable/tests/AndroidTest.xml
similarity index 67%
rename from media/tests/MediaTranscodingTest/AndroidTest.xml
rename to wifi/non-updatable/tests/AndroidTest.xml
index c2167e8..4e8bb55 100644
--- a/media/tests/MediaTranscodingTest/AndroidTest.xml
+++ b/wifi/non-updatable/tests/AndroidTest.xml
@@ -13,14 +13,15 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<configuration description="Runs MediaTranscoding Tests">
- <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
- <option name="test-file-name" value="mediatranscodingtest.apk" />
+<configuration description="Runs Frameworks Wifi Non-updatable API Tests.">
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="test-file-name" value="FrameworksWifiNonUpdatableApiTests.apk" />
</target_preparer>
- <option name="test-tag" value="MediaTranscodingTest" />
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-tag" value="FrameworksWifiNonUpdatableApiTests" />
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
- <option name="package" value="com.android.mediatranscodingtest" />
+ <option name="package" value="android.net.wifi.nonupdatable.test" />
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
<option name="hidden-api-checks" value="false"/>
</test>
diff --git a/wifi/non-updatable/tests/README.md b/wifi/non-updatable/tests/README.md
new file mode 100644
index 0000000..ad535f4
--- /dev/null
+++ b/wifi/non-updatable/tests/README.md
@@ -0,0 +1,32 @@
+# Wifi Non-Updatable Framework Unit Tests
+This package contains unit tests for the non-updatable part (i.e. outside the Wifi module) of the
+Android Wifi framework APIs based on the
+[Android Testing Support Library](http://developer.android.com/tools/testing-support-library/index.html).
+The test cases are built using the [JUnit](http://junit.org/) and [Mockito](http://mockito.org/)
+libraries.
+
+## Running Tests
+The easiest way to run tests is simply run
+
+```
+atest android.net.wifi
+```
+
+To pick up changes in framework/base, you will need to:
+1. rebuild the framework library 'make -j32'
+2. sync over the updated library to the device 'adb sync'
+3. restart framework on the device 'adb shell stop' then 'adb shell start'
+
+To enable syncing data to the device for first time after clean reflash:
+1. adb disable-verity
+2. adb reboot
+3. adb remount
+
+## Adding Tests
+Tests can be added by adding classes to the src directory. JUnit4 style test cases can
+be written by simply annotating test methods with `org.junit.Test`.
+
+## Debugging Tests
+If you are trying to debug why tests are not doing what you expected, you can add android log
+statements and use logcat to view them. The beginning and end of every tests is automatically logged
+with the tag `TestRunner`.
diff --git a/wifi/tests/src/android/net/wifi/SoftApConfToXmlMigrationUtilTest.java b/wifi/non-updatable/tests/src/android/net/wifi/SoftApConfToXmlMigrationUtilTest.java
similarity index 100%
rename from wifi/tests/src/android/net/wifi/SoftApConfToXmlMigrationUtilTest.java
rename to wifi/non-updatable/tests/src/android/net/wifi/SoftApConfToXmlMigrationUtilTest.java
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkScoreCacheTest.java b/wifi/non-updatable/tests/src/android/net/wifi/WifiNetworkScoreCacheTest.java
similarity index 99%
rename from wifi/tests/src/android/net/wifi/WifiNetworkScoreCacheTest.java
rename to wifi/non-updatable/tests/src/android/net/wifi/WifiNetworkScoreCacheTest.java
index fdd11a3..c4967eb 100644
--- a/wifi/tests/src/android/net/wifi/WifiNetworkScoreCacheTest.java
+++ b/wifi/non-updatable/tests/src/android/net/wifi/WifiNetworkScoreCacheTest.java
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
package android.net.wifi;
diff --git a/wifi/tests/src/android/net/wifi/nl80211/DeviceWiphyCapabilitiesTest.java b/wifi/non-updatable/tests/src/android/net/wifi/nl80211/DeviceWiphyCapabilitiesTest.java
similarity index 100%
rename from wifi/tests/src/android/net/wifi/nl80211/DeviceWiphyCapabilitiesTest.java
rename to wifi/non-updatable/tests/src/android/net/wifi/nl80211/DeviceWiphyCapabilitiesTest.java
diff --git a/wifi/tests/src/android/net/wifi/nl80211/NativeScanResultTest.java b/wifi/non-updatable/tests/src/android/net/wifi/nl80211/NativeScanResultTest.java
similarity index 100%
rename from wifi/tests/src/android/net/wifi/nl80211/NativeScanResultTest.java
rename to wifi/non-updatable/tests/src/android/net/wifi/nl80211/NativeScanResultTest.java
diff --git a/wifi/tests/src/android/net/wifi/nl80211/PnoSettingsTest.java b/wifi/non-updatable/tests/src/android/net/wifi/nl80211/PnoSettingsTest.java
similarity index 100%
rename from wifi/tests/src/android/net/wifi/nl80211/PnoSettingsTest.java
rename to wifi/non-updatable/tests/src/android/net/wifi/nl80211/PnoSettingsTest.java
diff --git a/wifi/tests/src/android/net/wifi/nl80211/SingleScanSettingsTest.java b/wifi/non-updatable/tests/src/android/net/wifi/nl80211/SingleScanSettingsTest.java
similarity index 100%
rename from wifi/tests/src/android/net/wifi/nl80211/SingleScanSettingsTest.java
rename to wifi/non-updatable/tests/src/android/net/wifi/nl80211/SingleScanSettingsTest.java
diff --git a/wifi/tests/src/android/net/wifi/nl80211/WifiNl80211ManagerTest.java b/wifi/non-updatable/tests/src/android/net/wifi/nl80211/WifiNl80211ManagerTest.java
similarity index 100%
rename from wifi/tests/src/android/net/wifi/nl80211/WifiNl80211ManagerTest.java
rename to wifi/non-updatable/tests/src/android/net/wifi/nl80211/WifiNl80211ManagerTest.java
diff --git a/wifi/tests/Android.bp b/wifi/tests/Android.bp
index 7eba0a7..c0be244 100644
--- a/wifi/tests/Android.bp
+++ b/wifi/tests/Android.bp
@@ -39,6 +39,7 @@
"mockito-target-minus-junit4",
"modules-utils-build",
"net-tests-utils",
+ "net-utils-framework-common",
"truth-prebuilt",
],