diff options
1226 files changed, 21620 insertions, 19785 deletions
diff --git a/Android.bp b/Android.bp index 949373317097..598f4fcaf620 100644 --- a/Android.bp +++ b/Android.bp @@ -604,8 +604,9 @@ java_defaults { ], required: [ "framework-platform-compat-config", - // TODO: remove gps_debug and protolog.conf.json when the build system propagates "required" properly. + // TODO: remove gps_debug, cec_config.xml and protolog.conf.json when the build system propagates "required" properly. "gps_debug.conf", + "cec_config.xml", "icu4j-platform-compat-config", "libcore-platform-compat-config", "protolog.conf.json.gz", @@ -1334,8 +1335,6 @@ java_library { sdk_version: "module_current", min_sdk_version: "30", srcs: [ - "core/java/android/content/pm/BaseParceledListSlice.java", - "core/java/android/content/pm/ParceledListSlice.java", "core/java/android/os/HandlerExecutor.java", "core/java/com/android/internal/util/AsyncChannel.java", "core/java/com/android/internal/util/AsyncService.java", @@ -1354,12 +1353,6 @@ java_library { ], } -filegroup { - name: "framework-wifi-util-lib-aidls", - srcs: ["core/java/android/content/pm/ParceledListSlice.aidl"], - path: "core/java", -} - // utility classes statically linked into wifi-service filegroup { name: "framework-wifi-service-shared-srcs", diff --git a/ApiDocs.bp b/ApiDocs.bp index 7ed7ec526686..3d6bdbf19264 100644 --- a/ApiDocs.bp +++ b/ApiDocs.bp @@ -67,7 +67,7 @@ stubs_defaults { ":opt-net-voip-srcs", ":art.module.public.api{.public.stubs.source}", ":conscrypt.module.public.api{.public.stubs.source}", - ":android_icu4j_public_api_files", + ":i18n.module.public.api{.public.stubs.source}", "test-mock/src/**/*.java", "test-runner/src/**/*.java", ], diff --git a/BATTERY_STATS_OWNERS b/BATTERY_STATS_OWNERS new file mode 100644 index 000000000000..7728975fcec1 --- /dev/null +++ b/BATTERY_STATS_OWNERS @@ -0,0 +1,4 @@ +# OWNERS of BatteryStats related files +bookatz@google.com +dplotnikov@google.com +mwachens@google.com @@ -1,22 +1,29 @@ # This top-level list should remain narrowly defined as team leads; individual # teams are strongly encouraged to define narrower OWNERS files at deeper # levels within the source tree; see OWNERS.md for more details +akulian@google.com dsandler@android.com dsandler@google.com hackbod@android.com hackbod@google.com +jjaggi@google.com jsharkey@android.com jsharkey@google.com michaelwr@google.com nandana@google.com narayan@google.com ogunwale@google.com +roosa@google.com svetoslavganov@android.com svetoslavganov@google.com yamasani@google.com +# API changes are already covered by API-Review+1 (http://mdb/android-api-council) +# via https://android.git.corp.google.com/All-Projects/+/refs/meta/config/rules.pl. +per-file */api/*current.txt = * + # Support bulk translation updates -per-file */res*/values*/*.xml = byi@google.com +per-file */res*/values*/*.xml = byi@google.com, delphij@google.com per-file Android.bp = file:platform/build/soong:/OWNERS per-file Android.mk = file:platform/build/soong:/OWNERS diff --git a/OWNERS.md b/OWNERS.md index 6428c59fd793..601b5c641f21 100644 --- a/OWNERS.md +++ b/OWNERS.md @@ -1,3 +1,5 @@ +# Background + As general background, `OWNERS` files expedite code reviews by helping code authors quickly find relevant reviewers, and they also ensure that stakeholders are involved in code changes in their areas. @@ -27,8 +29,40 @@ main `services/core/` project: * `media/` * `wifi/` +# Design + Area maintainers are strongly encouraged to list people in a single authoritative `OWNERS` file in **exactly one** location. Then, other paths should reference that single authoritative `OWNERS` file using an include directive. This approach ensures that updates are applied consistently across the tree, reducing maintenance burden. + +# Examples + +The exact syntax of `OWNERS` files can be difficult to get correct, so here are +some common examples: + +``` +# Complete include of top-level owners from this repo +include /ZYGOTE_OWNERS +# Partial include of top-level owners from this repo +per-file ZygoteFile.java = file:/ZYGOTE_OWNERS +``` +``` +# Complete include of subdirectory owners from this repo +include /services/core/java/com/android/server/net/OWNERS +# Partial include of subdirectory owners from this repo +per-file NetworkFile.java = file:/services/core/java/com/android/server/net/OWNERS +``` +``` +# Complete include of top-level owners from another repo +include platform/libcore:/OWNERS +# Partial include of top-level owners from another repo +per-file LibcoreFile.java = file:platform/libcore:/OWNERS +``` +``` +# Complete include of subdirectory owners from another repo +include platform/frameworks/av:/camera/OWNERS +# Partial include of subdirectory owners from another repo +per-file CameraFile.java = file:platform/frameworks/av:/camera/OWNERS +``` diff --git a/StubLibraries.bp b/StubLibraries.bp index 380839e5c06b..12ee889387ec 100644 --- a/StubLibraries.bp +++ b/StubLibraries.bp @@ -48,7 +48,6 @@ stubs_defaults { ":opt-telephony-srcs", ":opt-net-voip-srcs", ":art.module.public.api{.public.stubs.source}", - ":android_icu4j_public_api_files", "**/package.html", ], sdk_version: "core_platform", @@ -251,6 +250,7 @@ java_library_static { "framework-statsd.stubs", "framework-tethering.stubs", "framework-wifi.stubs", + "i18n.module.public.api.stubs", "private-stub-annotations-jar", ], defaults: ["android_defaults_stubs_current"], @@ -270,6 +270,7 @@ java_library_static { "framework-statsd.stubs.system", "framework-tethering.stubs.system", "framework-wifi.stubs.system", + "i18n.module.public.api.stubs", "private-stub-annotations-jar", ], defaults: [ @@ -305,6 +306,7 @@ java_library_static { "framework-statsd.stubs.system", "framework-tethering.stubs.system", "framework-wifi.stubs.system", + "i18n.module.public.api.stubs", "private-stub-annotations-jar", ], defaults: [ diff --git a/apct-tests/perftests/blobstore/Android.bp b/apct-tests/perftests/blobstore/Android.bp index be5072ce3d9d..be700a2b021c 100644 --- a/apct-tests/perftests/blobstore/Android.bp +++ b/apct-tests/perftests/blobstore/Android.bp @@ -21,6 +21,7 @@ android_test { "androidx.annotation_annotation", "apct-perftests-utils", "ub-uiautomator", + "collector-device-lib-platform", ], platform_apis: true, test_suites: ["device-tests"], diff --git a/apct-tests/perftests/blobstore/AndroidTest.xml b/apct-tests/perftests/blobstore/AndroidTest.xml index 19456c6d81d7..58761d0e22f9 100644 --- a/apct-tests/perftests/blobstore/AndroidTest.xml +++ b/apct-tests/perftests/blobstore/AndroidTest.xml @@ -24,5 +24,22 @@ <test class="com.android.tradefed.testtype.AndroidJUnitTest" > <option name="package" value="com.android.perftests.blob" /> <option name="hidden-api-checks" value="false"/> + + <!-- TODO: Add PerfettoListener to automatically capture perfetto traces for each test--> + <!-- Listener related args for collecting the traces and waiting for the device + to stabilize. --> + <option name="device-listeners" + value="android.device.collectors.ProcLoadListener" /> + <!-- Guarantee that user defined RunListeners will be running before any of the default + listeners defined in this runner. --> + <option name="instrumentation-arg" key="newRunListenerMode" value="true" /> + + <!-- ProcLoadListener related arguments --> + <!-- Wait for device last minute threshold to reach 3 with 2 minute timeout before + starting the test run --> + <option name="instrumentation-arg" key="procload-collector:per_run" value="true" /> + <option name="instrumentation-arg" key="proc-loadavg-threshold" value="3" /> + <option name="instrumentation-arg" key="proc-loadavg-timeout" value="120000" /> + <option name="instrumentation-arg" key="proc-loadavg-interval" value="10000" /> </test> </configuration>
\ No newline at end of file diff --git a/apct-tests/perftests/packagemanager/Android.bp b/apct-tests/perftests/packagemanager/Android.bp index 17033e048c7d..c15b6418ce4d 100644 --- a/apct-tests/perftests/packagemanager/Android.bp +++ b/apct-tests/perftests/packagemanager/Android.bp @@ -10,6 +10,7 @@ android_test { "androidx.test.ext.junit", "androidx.annotation_annotation", "apct-perftests-utils", + "collector-device-lib-platform", ], libs: ["android.test.base"], @@ -18,4 +19,8 @@ android_test { test_suites: ["device-tests"], + data: [":perfetto_artifacts"], + + certificate: "platform", + } diff --git a/apct-tests/perftests/packagemanager/AndroidTest.xml b/apct-tests/perftests/packagemanager/AndroidTest.xml index c112d87d83e1..4903510fa502 100644 --- a/apct-tests/perftests/packagemanager/AndroidTest.xml +++ b/apct-tests/perftests/packagemanager/AndroidTest.xml @@ -15,74 +15,122 @@ ~ limitations under the License. --> <configuration description="Runs PackageManagerPerfTests metric instrumentation."> - <option name="test-suite-tag" value="apct" /> - <option name="test-suite-tag" value="apct-metric-instrumentation" /> + <option name="test-suite-tag" value="apct"/> + <option name="test-suite-tag" value="apct-metric-instrumentation"/> <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> - <option name="cleanup-apks" value="true" /> - <option name="test-file-name" value="PackageManagerPerfTests.apk" /> + <option name="cleanup-apks" value="true"/> + <option name="test-file-name" value="PackageManagerPerfTests.apk"/> </target_preparer> <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> - <option name="cleanup-apks" value="true" /> - <option name="force-queryable" value="false" /> - <option name="test-file-name" value="QueriesAll0.apk" /> - <option name="test-file-name" value="QueriesAll1.apk" /> - <option name="test-file-name" value="QueriesAll2.apk" /> - <option name="test-file-name" value="QueriesAll3.apk" /> - <option name="test-file-name" value="QueriesAll4.apk" /> - <option name="test-file-name" value="QueriesAll5.apk" /> - <option name="test-file-name" value="QueriesAll6.apk" /> - <option name="test-file-name" value="QueriesAll7.apk" /> - <option name="test-file-name" value="QueriesAll8.apk" /> - <option name="test-file-name" value="QueriesAll9.apk" /> - <option name="test-file-name" value="QueriesAll10.apk" /> - <option name="test-file-name" value="QueriesAll11.apk" /> - <option name="test-file-name" value="QueriesAll12.apk" /> - <option name="test-file-name" value="QueriesAll13.apk" /> - <option name="test-file-name" value="QueriesAll14.apk" /> - <option name="test-file-name" value="QueriesAll15.apk" /> - <option name="test-file-name" value="QueriesAll16.apk" /> - <option name="test-file-name" value="QueriesAll17.apk" /> - <option name="test-file-name" value="QueriesAll18.apk" /> - <option name="test-file-name" value="QueriesAll19.apk" /> - <option name="test-file-name" value="QueriesAll20.apk" /> - <option name="test-file-name" value="QueriesAll21.apk" /> - <option name="test-file-name" value="QueriesAll22.apk" /> - <option name="test-file-name" value="QueriesAll23.apk" /> - <option name="test-file-name" value="QueriesAll24.apk" /> - <option name="test-file-name" value="QueriesAll25.apk" /> - <option name="test-file-name" value="QueriesAll26.apk" /> - <option name="test-file-name" value="QueriesAll27.apk" /> - <option name="test-file-name" value="QueriesAll28.apk" /> - <option name="test-file-name" value="QueriesAll29.apk" /> - <option name="test-file-name" value="QueriesAll30.apk" /> - <option name="test-file-name" value="QueriesAll31.apk" /> - <option name="test-file-name" value="QueriesAll32.apk" /> - <option name="test-file-name" value="QueriesAll33.apk" /> - <option name="test-file-name" value="QueriesAll34.apk" /> - <option name="test-file-name" value="QueriesAll35.apk" /> - <option name="test-file-name" value="QueriesAll36.apk" /> - <option name="test-file-name" value="QueriesAll37.apk" /> - <option name="test-file-name" value="QueriesAll38.apk" /> - <option name="test-file-name" value="QueriesAll39.apk" /> - <option name="test-file-name" value="QueriesAll40.apk" /> - <option name="test-file-name" value="QueriesAll41.apk" /> - <option name="test-file-name" value="QueriesAll42.apk" /> - <option name="test-file-name" value="QueriesAll43.apk" /> - <option name="test-file-name" value="QueriesAll44.apk" /> - <option name="test-file-name" value="QueriesAll45.apk" /> - <option name="test-file-name" value="QueriesAll46.apk" /> - <option name="test-file-name" value="QueriesAll47.apk" /> - <option name="test-file-name" value="QueriesAll48.apk" /> - <option name="test-file-name" value="QueriesAll49.apk" /> + <option name="cleanup-apks" value="true"/> + <option name="force-queryable" value="false"/> + <option name="test-file-name" value="QueriesAll0.apk"/> + <option name="test-file-name" value="QueriesAll1.apk"/> + <option name="test-file-name" value="QueriesAll2.apk"/> + <option name="test-file-name" value="QueriesAll3.apk"/> + <option name="test-file-name" value="QueriesAll4.apk"/> + <option name="test-file-name" value="QueriesAll5.apk"/> + <option name="test-file-name" value="QueriesAll6.apk"/> + <option name="test-file-name" value="QueriesAll7.apk"/> + <option name="test-file-name" value="QueriesAll8.apk"/> + <option name="test-file-name" value="QueriesAll9.apk"/> + <option name="test-file-name" value="QueriesAll10.apk"/> + <option name="test-file-name" value="QueriesAll11.apk"/> + <option name="test-file-name" value="QueriesAll12.apk"/> + <option name="test-file-name" value="QueriesAll13.apk"/> + <option name="test-file-name" value="QueriesAll14.apk"/> + <option name="test-file-name" value="QueriesAll15.apk"/> + <option name="test-file-name" value="QueriesAll16.apk"/> + <option name="test-file-name" value="QueriesAll17.apk"/> + <option name="test-file-name" value="QueriesAll18.apk"/> + <option name="test-file-name" value="QueriesAll19.apk"/> + <option name="test-file-name" value="QueriesAll20.apk"/> + <option name="test-file-name" value="QueriesAll21.apk"/> + <option name="test-file-name" value="QueriesAll22.apk"/> + <option name="test-file-name" value="QueriesAll23.apk"/> + <option name="test-file-name" value="QueriesAll24.apk"/> + <option name="test-file-name" value="QueriesAll25.apk"/> + <option name="test-file-name" value="QueriesAll26.apk"/> + <option name="test-file-name" value="QueriesAll27.apk"/> + <option name="test-file-name" value="QueriesAll28.apk"/> + <option name="test-file-name" value="QueriesAll29.apk"/> + <option name="test-file-name" value="QueriesAll30.apk"/> + <option name="test-file-name" value="QueriesAll31.apk"/> + <option name="test-file-name" value="QueriesAll32.apk"/> + <option name="test-file-name" value="QueriesAll33.apk"/> + <option name="test-file-name" value="QueriesAll34.apk"/> + <option name="test-file-name" value="QueriesAll35.apk"/> + <option name="test-file-name" value="QueriesAll36.apk"/> + <option name="test-file-name" value="QueriesAll37.apk"/> + <option name="test-file-name" value="QueriesAll38.apk"/> + <option name="test-file-name" value="QueriesAll39.apk"/> + <option name="test-file-name" value="QueriesAll40.apk"/> + <option name="test-file-name" value="QueriesAll41.apk"/> + <option name="test-file-name" value="QueriesAll42.apk"/> + <option name="test-file-name" value="QueriesAll43.apk"/> + <option name="test-file-name" value="QueriesAll44.apk"/> + <option name="test-file-name" value="QueriesAll45.apk"/> + <option name="test-file-name" value="QueriesAll46.apk"/> + <option name="test-file-name" value="QueriesAll47.apk"/> + <option name="test-file-name" value="QueriesAll48.apk"/> + <option name="test-file-name" value="QueriesAll49.apk"/> </target_preparer> - <test class="com.android.tradefed.testtype.AndroidJUnitTest" > - <option name="package" value="com.android.perftests.packagemanager" /> + <test class="com.android.tradefed.testtype.AndroidJUnitTest"> + <option name="package" value="com.android.perftests.packagemanager"/> <option name="hidden-api-checks" value="false"/> </test> <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector"> - <option name="directory-keys" value="/data/local/PackageManagerPerfTests" /> - <option name="collect-on-run-ended-only" value="true" /> + <option name="directory-keys" value="/data/local/PackageManagerPerfTests"/> + <option name="collect-on-run-ended-only" value="true"/> </metrics_collector> + + <!-- Needed for pushing the trace config file --> + <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/> + <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"> + <option name="push-file" key="trace_config_detailed.textproto" + value="/data/misc/perfetto-traces/trace_config.textproto"/> + <!--Install the content provider automatically when we push some file in sdcard folder.--> + <!--Needed to avoid the installation during the test suite.--> + <option name="push-file" key="trace_config_detailed.textproto" + value="/sdcard/sample.textproto"/> + </target_preparer> + + <!-- Needed for pulling the collected trace config on to the host --> + <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector"> + <option name="pull-pattern-keys" value="perfetto_file_path"/> + </metrics_collector> + + <!-- Needed for storing the perfetto trace files in the sdcard/test_results --> + <option name="isolated-storage" value="false"/> + + <test class="com.android.tradefed.testtype.AndroidJUnitTest"> + <option name="package" value="com.android.perftests.packagemanager"/> + <option name="hidden-api-checks" value="false"/> + + <!-- Listener related args for collecting the traces and waiting for the device to + stabilize. --> + <option name="device-listeners" + value="android.device.collectors.ProcLoadListener,android.device.collectors.PerfettoListener"/> + <!-- Guarantee that user defined RunListeners will be running before any of the default + listeners defined in this runner. --> + <option name="instrumentation-arg" key="newRunListenerMode" value="true"/> + + <!-- ProcLoadListener related arguments --> + <!-- Wait for device last minute threshold to reach 3 with 2 minute timeout before starting + the test run --> + <option name="instrumentation-arg" key="procload-collector:per_run" value="true"/> + <option name="instrumentation-arg" key="proc-loadavg-threshold" value="3"/> + <option name="instrumentation-arg" key="proc-loadavg-timeout" value="120000"/> + <option name="instrumentation-arg" key="proc-loadavg-interval" value="10000"/> + + <!-- PerfettoListener related arguments --> + <option name="instrumentation-arg" key="perfetto_config_text_proto" value="true"/> + <option name="instrumentation-arg" key="perfetto_config_file" + value="trace_config.textproto"/> + + </test> + + </configuration> diff --git a/apex/appsearch/OWNERS b/apex/appsearch/OWNERS index ce0c212a9fe7..1703369271fa 100644 --- a/apex/appsearch/OWNERS +++ b/apex/appsearch/OWNERS @@ -1 +1,3 @@ +adorokhine@google.com sudheersai@google.com +yamasani@google.com diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java index b7cd4f5f8bce..59e7807deeef 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java +++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSession.java @@ -18,10 +18,10 @@ package android.app.appsearch; import android.annotation.CallbackExecutor; import android.annotation.NonNull; -import android.app.appsearch.exceptions.AppSearchException; import android.os.Bundle; import android.os.ParcelableException; import android.os.RemoteException; +import android.util.ArraySet; import java.util.ArrayList; import java.util.List; @@ -34,6 +34,8 @@ import java.util.function.Consumer; /** * Represents a connection to an AppSearch storage system where {@link GenericDocument}s can be * placed and queried. + * + * This class is thread safe. * @hide */ public final class AppSearchSession { @@ -79,7 +81,7 @@ public final class AppSearchSession { } /** - * Sets the schema will be used by documents provided to the {@link #putDocuments} method. + * Sets the schema that will be used by documents provided to the {@link #putDocuments} method. * * <p>The schema provided here is compared to the stored copy of the schema previously supplied * to {@link #setSchema}, if any, to determine how to treat existing documents. The following @@ -123,11 +125,19 @@ public final class AppSearchSession { * <p>It is a no-op to set the same schema as has been previously set; this is handled * efficiently. * + * <p>By default, documents are visible on platform surfaces. To opt out, call {@code + * SetSchemaRequest.Builder#setPlatformSurfaceable} with {@code surfaceable} as false. Any + * visibility settings apply only to the schemas that are included in the {@code request}. + * Visibility settings for a schema type do not apply or persist across + * {@link SetSchemaRequest}s. + * * @param request The schema update request. * @param executor Executor on which to invoke the callback. * @param callback Callback to receive errors resulting from setting the schema. If the * operation succeeds, the callback will be invoked with {@code null}. */ + // TODO(b/169883602): Change @code references to @link when setPlatformSurfaceable APIs are + // exposed. public void setSchema( @NonNull SetSchemaRequest request, @NonNull @CallbackExecutor Executor executor, @@ -156,6 +166,43 @@ public final class AppSearchSession { } /** + * Retrieves the schema most recently successfully provided to {@link #setSchema}. + * + * @param executor Executor on which to invoke the callback. + * @param callback Callback to receive the pending results of schema. + */ + public void getSchema( + @NonNull @CallbackExecutor Executor executor, + @NonNull Consumer<AppSearchResult<Set<AppSearchSchema>>> callback) { + Objects.requireNonNull(executor); + Objects.requireNonNull(callback); + try { + mService.getSchema( + mDatabaseName, + new IAppSearchResultCallback.Stub() { + public void onResult(AppSearchResult result) { + executor.execute(() -> { + if (result.isSuccess()) { + List<Bundle> schemaBundles = + (List<Bundle>) result.getResultValue(); + Set<AppSearchSchema> schemas = new ArraySet<>( + schemaBundles.size()); + for (int i = 0; i < schemaBundles.size(); i++) { + schemas.add(new AppSearchSchema(schemaBundles.get(i))); + } + callback.accept(AppSearchResult.newSuccessfulResult(schemas)); + } else { + callback.accept(result); + } + }); + } + }); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Indexes documents into AppSearch. * * <p>Each {@link GenericDocument}'s {@code schemaType} field must be set to the name of a @@ -167,9 +214,9 @@ public final class AppSearchSession { * of the returned {@link AppSearchBatchResult} are the URIs of the input * documents. The values are {@code null} if they were successfully indexed, * or a failed {@link AppSearchResult} otherwise. - * Or {@link BatchResultCallback#onSystemError} will be invoked with an - * {@link AppSearchException} if an error occurred in AppSearch initialization - * or a cause {@link Throwable} if other error occurred in AppSearch service. + * Or {@link BatchResultCallback#onSystemError} will be invoked with a + * {@link Throwable} if an unexpected internal error occurred in AppSearch + * service. */ public void putDocuments( @NonNull PutDocumentsRequest request, @@ -210,9 +257,9 @@ public final class AppSearchSession { * {@link AppSearchResult} otherwise. URIs that are not found will return a * failed {@link AppSearchResult} with a result code of * {@link AppSearchResult#RESULT_NOT_FOUND}. - * Or {@link BatchResultCallback#onSystemError} will be invoked with an - * {@link AppSearchException} if an error occurred in AppSearch initialization - * or a cause {@link Throwable} if other error occurred in AppSearch service. + * Or {@link BatchResultCallback#onSystemError} will be invoked with a + * {@link Throwable} if an unexpected internal error occurred in AppSearch + * service. */ public void getByUri( @NonNull GetByUriRequest request, @@ -338,9 +385,9 @@ public final class AppSearchSession { * are {@code null} on success, or a failed {@link AppSearchResult} otherwise. * URIs that are not found will return a failed {@link AppSearchResult} with a * result code of {@link AppSearchResult#RESULT_NOT_FOUND}. - * Or {@link BatchResultCallback#onSystemError} will be invoked with an - * {@link AppSearchException} if an error occurred in AppSearch initialization - * or a cause {@link Throwable} if other error occurred in AppSearch service. + * Or {@link BatchResultCallback#onSystemError} will be invoked with a + * {@link Throwable} if an unexpected internal error occurred in AppSearch + * service. */ public void removeByUri( @NonNull RemoveByUriRequest request, @@ -369,7 +416,7 @@ public final class AppSearchSession { /** * Removes {@link GenericDocument}s from the index by Query. Documents will be removed if they * match the {@code queryExpression} in given namespaces and schemaTypes which is set via - * {@link SearchSpec.Builder#addNamespace} and {@link SearchSpec.Builder#addSchema}. + * {@link SearchSpec.Builder#addNamespace} and {@link SearchSpec.Builder#addSchemaType}. * * <p> An empty {@code queryExpression} matches all documents. * @@ -377,10 +424,13 @@ public final class AppSearchSession { * the current database. * * @param queryExpression Query String to search. - * @param searchSpec Defines what and how to remove - * @param executor Executor on which to invoke the callback. - * @param callback Callback to receive errors resulting from removing the documents. If the - * operation succeeds, the callback will be invoked with {@code null}. + * @param searchSpec Spec containing schemaTypes, namespaces and query expression indicates + * how document will be removed. All specific about how to scoring, + * ordering, snippeting and resulting will be ignored. + * @param executor Executor on which to invoke the callback. + * @param callback Callback to receive errors resulting from removing the documents. If + * the operation succeeds, the callback will be invoked with + * {@code null}. */ public void removeByQuery(@NonNull String queryExpression, @NonNull SearchSpec searchSpec, diff --git a/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java b/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java index d2aa8eab4708..07938b704f11 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java +++ b/apex/appsearch/framework/java/android/app/appsearch/GlobalSearchSession.java @@ -115,7 +115,7 @@ public class GlobalSearchSession { * @return The search result of performing this operation. */ @NonNull - public SearchResults globalQuery( + public SearchResults query( @NonNull String queryExpression, @NonNull SearchSpec searchSpec, @NonNull @CallbackExecutor Executor executor) { diff --git a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl index 1d7cb87131c0..7883046f258e 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl +++ b/apex/appsearch/framework/java/android/app/appsearch/IAppSearchManager.aidl @@ -28,10 +28,10 @@ parcelable SearchResults; /** {@hide} */ interface IAppSearchManager { /** - * Sets the schema. + * Updates the AppSearch schema for this database. * - * @param databaseName The databaseName this document resides in. - * @param schemaBundles List of AppSearchSchema bundles. + * @param databaseName The name of the database where this schema lives. + * @param schemaBundles List of {@link AppSearchSchema} bundles. * @param schemasNotPlatformSurfaceable Schema types that should not be surfaced on platform * surfaces. * @param forceOverride Whether to apply the new schema even if it is incompatible. All @@ -46,6 +46,17 @@ interface IAppSearchManager { boolean forceOverride, in IAppSearchResultCallback callback); + + /** + * Retrieves the AppSearch schema for this database. + * + * @param databaseName The name of the database to retrieve. + * @param callback {@link IAppSearchResultCallback#onResult} will be called with an + * {@link AppSearchResult}<{@link List}<{@link Bundle}>>, where the value are + * AppSearchSchema bundle. + */ + void getSchema(in String databaseName, in IAppSearchResultCallback callback); + /** * Inserts documents into the index. * diff --git a/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java b/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java index 8548d209c787..7d3ea8bc132d 100644 --- a/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java +++ b/apex/appsearch/framework/java/android/app/appsearch/SearchResults.java @@ -77,7 +77,7 @@ public class SearchResults implements Closeable { * <p>Re-call this method to get next page of {@link SearchResult}, until it returns an * empty list. * - * <p>The page size is set by {@link SearchSpec.Builder#setNumPerPage}. + * <p>The page size is set by {@link SearchSpec.Builder#setResultCountPerPage}. * * @param callback Callback to receive the pending result of performing this operation. */ diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java index 551347c5c202..15128253b765 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java @@ -90,6 +90,32 @@ public class AppSearchManagerService extends SystemService { } @Override + public void getSchema( + @NonNull String databaseName, + @NonNull IAppSearchResultCallback callback) { + Preconditions.checkNotNull(databaseName); + Preconditions.checkNotNull(callback); + int callingUid = Binder.getCallingUidOrThrow(); + int callingUserId = UserHandle.getUserId(callingUid); + final long callingIdentity = Binder.clearCallingIdentity(); + try { + AppSearchImpl impl = ImplInstanceManager.getInstance(getContext(), callingUserId); + databaseName = rewriteDatabaseNameWithUid(databaseName, callingUid); + List<AppSearchSchema> schemas = impl.getSchema(databaseName); + List<Bundle> schemaBundles = new ArrayList<>(schemas.size()); + for (int i = 0; i < schemas.size(); i++) { + schemaBundles.add(schemas.get(i).getBundle()); + } + invokeCallbackOnResult(callback, + AppSearchResult.newSuccessfulResult(schemaBundles)); + } catch (Throwable t) { + invokeCallbackOnError(callback, t); + } finally { + Binder.restoreCallingIdentity(callingIdentity); + } + } + + @Override public void putDocuments( @NonNull String databaseName, @NonNull List<Bundle> documentBundles, diff --git a/apex/jobscheduler/OWNERS b/apex/jobscheduler/OWNERS index 0fe6cdffa5f6..d004eed2a0db 100644 --- a/apex/jobscheduler/OWNERS +++ b/apex/jobscheduler/OWNERS @@ -1,6 +1,6 @@ yamasani@google.com omakoto@google.com -ctate@google.com +ctate@android.com ctate@google.com kwekua@google.com suprabh@google.com
\ No newline at end of file diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java index 0b0923a67de6..dd1a0e2478dd 100644 --- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java +++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java @@ -1770,9 +1770,18 @@ public class AppStandbyController final int userId = getSendingUserId(); if (Intent.ACTION_PACKAGE_ADDED.equals(action) || Intent.ACTION_PACKAGE_CHANGED.equals(action)) { - clearCarrierPrivilegedApps(); - // ACTION_PACKAGE_ADDED is called even for system app downgrades. - evaluateSystemAppException(pkgName, userId); + final String[] cmpList = intent.getStringArrayExtra( + Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST); + // If this is PACKAGE_ADDED (cmpList == null), or if it's a whole-package + // enable/disable event (cmpList is just the package name itself), drop + // our carrier privileged app & system-app caches and let them refresh + if (cmpList == null + || (cmpList.length == 1 && pkgName.equals(cmpList[0]))) { + clearCarrierPrivilegedApps(); + evaluateSystemAppException(pkgName, userId); + } + // component-level enable/disable can affect bucketing, so we always + // reevaluate that for any PACKAGE_CHANGED mHandler.obtainMessage(MSG_CHECK_PACKAGE_IDLE_STATE, userId, -1, pkgName) .sendToTarget(); } diff --git a/api/Android.bp b/api/Android.bp index 5ee41b79b58c..9417030fc937 100644 --- a/api/Android.bp +++ b/api/Android.bp @@ -38,6 +38,7 @@ genrule { ":framework-statsd{.public.api.txt}", ":framework-tethering{.public.api.txt}", ":framework-wifi{.public.api.txt}", + ":i18n.module.public.api{.public.api.txt}", ":non-updatable-current.txt", ], out: ["current.txt"], @@ -50,7 +51,10 @@ genrule { dest: "current.txt", }, { - targets: ["sdk", "win_sdk"], + targets: [ + "sdk", + "win_sdk", + ], dir: "apistubs/android/public/api", dest: "android.txt", }, @@ -72,6 +76,7 @@ genrule { ":framework-statsd{.public.stubs.source}", ":framework-tethering{.public.stubs.source}", ":framework-wifi{.public.stubs.source}", + ":i18n.module.public.api{.public.stubs.source}", ], out: ["current.srcjar"], tools: ["merge_zips"], @@ -92,6 +97,7 @@ genrule { ":framework-statsd{.public.removed-api.txt}", ":framework-tethering{.public.removed-api.txt}", ":framework-wifi{.public.removed-api.txt}", + ":i18n.module.public.api{.public.removed-api.txt}", ":non-updatable-removed.txt", ], out: ["removed.txt"], @@ -130,7 +136,10 @@ genrule { dest: "system-current.txt", }, { - targets: ["sdk", "win_sdk"], + targets: [ + "sdk", + "win_sdk", + ], dir: "apistubs/android/system/api", dest: "android.txt", }, @@ -189,7 +198,10 @@ genrule { dest: "module-lib-current.txt", }, { - targets: ["sdk", "win_sdk"], + targets: [ + "sdk", + "win_sdk", + ], dir: "apistubs/android/module-lib/api", dest: "android.txt", }, diff --git a/core/api/current.txt b/core/api/current.txt index 423b523a1027..ab5b0e7e35a9 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -87,6 +87,7 @@ package android { field public static final String GET_PACKAGE_SIZE = "android.permission.GET_PACKAGE_SIZE"; field @Deprecated public static final String GET_TASKS = "android.permission.GET_TASKS"; field public static final String GLOBAL_SEARCH = "android.permission.GLOBAL_SEARCH"; + field public static final String HIDE_OVERLAY_WINDOWS = "android.permission.HIDE_OVERLAY_WINDOWS"; field public static final String INSTALL_LOCATION_PROVIDER = "android.permission.INSTALL_LOCATION_PROVIDER"; field public static final String INSTALL_PACKAGES = "android.permission.INSTALL_PACKAGES"; field public static final String INSTALL_SHORTCUT = "com.android.launcher.permission.INSTALL_SHORTCUT"; @@ -140,6 +141,7 @@ package android { field public static final String REQUEST_DELETE_PACKAGES = "android.permission.REQUEST_DELETE_PACKAGES"; field public static final String REQUEST_IGNORE_BATTERY_OPTIMIZATIONS = "android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"; field public static final String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES"; + field public static final String REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE = "android.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE"; field public static final String REQUEST_PASSWORD_COMPLEXITY = "android.permission.REQUEST_PASSWORD_COMPLEXITY"; field @Deprecated public static final String RESTART_PACKAGES = "android.permission.RESTART_PACKAGES"; field public static final String SEND_RESPOND_VIA_MESSAGE = "android.permission.SEND_RESPOND_VIA_MESSAGE"; @@ -6021,7 +6023,7 @@ package android.app { public class NotificationManager { method public String addAutomaticZenRule(android.app.AutomaticZenRule); - method public boolean areBubblesAllowed(); + method @Deprecated public boolean areBubblesAllowed(); method public boolean areNotificationsEnabled(); method public boolean areNotificationsPaused(); method public boolean canNotifyAsPackage(@NonNull String); @@ -6038,6 +6040,7 @@ package android.app { method public android.service.notification.StatusBarNotification[] getActiveNotifications(); method public android.app.AutomaticZenRule getAutomaticZenRule(String); method public java.util.Map<java.lang.String,android.app.AutomaticZenRule> getAutomaticZenRules(); + method public int getBubblePreference(); method @NonNull public android.app.NotificationManager.Policy getConsolidatedNotificationPolicy(); method public final int getCurrentInterruptionFilter(); method public int getImportance(); @@ -6072,6 +6075,9 @@ package android.app { field public static final int AUTOMATIC_RULE_STATUS_ENABLED = 1; // 0x1 field public static final int AUTOMATIC_RULE_STATUS_REMOVED = 3; // 0x3 field public static final int AUTOMATIC_RULE_STATUS_UNKNOWN = -1; // 0xffffffff + field public static final int BUBBLE_PREFERENCE_ALL = 1; // 0x1 + field public static final int BUBBLE_PREFERENCE_NONE = 0; // 0x0 + field public static final int BUBBLE_PREFERENCE_SELECTED = 2; // 0x2 field public static final String EXTRA_AUTOMATIC_RULE_ID = "android.app.extra.AUTOMATIC_RULE_ID"; field public static final String EXTRA_AUTOMATIC_ZEN_RULE_ID = "android.app.extra.AUTOMATIC_ZEN_RULE_ID"; field public static final String EXTRA_AUTOMATIC_ZEN_RULE_STATUS = "android.app.extra.AUTOMATIC_ZEN_RULE_STATUS"; @@ -6940,14 +6946,14 @@ package android.app.admin { method public long getPasswordExpirationTimeout(@Nullable android.content.ComponentName); method public int getPasswordHistoryLength(@Nullable android.content.ComponentName); method public int getPasswordMaximumLength(int); - method public int getPasswordMinimumLength(@Nullable android.content.ComponentName); - method public int getPasswordMinimumLetters(@Nullable android.content.ComponentName); - method public int getPasswordMinimumLowerCase(@Nullable android.content.ComponentName); - method public int getPasswordMinimumNonLetter(@Nullable android.content.ComponentName); - method public int getPasswordMinimumNumeric(@Nullable android.content.ComponentName); - method public int getPasswordMinimumSymbols(@Nullable android.content.ComponentName); - method public int getPasswordMinimumUpperCase(@Nullable android.content.ComponentName); - method public int getPasswordQuality(@Nullable android.content.ComponentName); + method @Deprecated public int getPasswordMinimumLength(@Nullable android.content.ComponentName); + method @Deprecated public int getPasswordMinimumLetters(@Nullable android.content.ComponentName); + method @Deprecated public int getPasswordMinimumLowerCase(@Nullable android.content.ComponentName); + method @Deprecated public int getPasswordMinimumNonLetter(@Nullable android.content.ComponentName); + method @Deprecated public int getPasswordMinimumNumeric(@Nullable android.content.ComponentName); + method @Deprecated public int getPasswordMinimumSymbols(@Nullable android.content.ComponentName); + method @Deprecated public int getPasswordMinimumUpperCase(@Nullable android.content.ComponentName); + method @Deprecated public int getPasswordQuality(@Nullable android.content.ComponentName); method @Nullable public android.app.admin.SystemUpdateInfo getPendingSystemUpdate(@NonNull android.content.ComponentName); method public int getPermissionGrantState(@Nullable android.content.ComponentName, @NonNull String, @NonNull String); method public int getPermissionPolicy(android.content.ComponentName); @@ -7071,14 +7077,14 @@ package android.app.admin { method @NonNull public String[] setPackagesSuspended(@NonNull android.content.ComponentName, @NonNull String[], boolean); method public void setPasswordExpirationTimeout(@NonNull android.content.ComponentName, long); method public void setPasswordHistoryLength(@NonNull android.content.ComponentName, int); - method public void setPasswordMinimumLength(@NonNull android.content.ComponentName, int); - method public void setPasswordMinimumLetters(@NonNull android.content.ComponentName, int); - method public void setPasswordMinimumLowerCase(@NonNull android.content.ComponentName, int); - method public void setPasswordMinimumNonLetter(@NonNull android.content.ComponentName, int); - method public void setPasswordMinimumNumeric(@NonNull android.content.ComponentName, int); - method public void setPasswordMinimumSymbols(@NonNull android.content.ComponentName, int); - method public void setPasswordMinimumUpperCase(@NonNull android.content.ComponentName, int); - method public void setPasswordQuality(@NonNull android.content.ComponentName, int); + method @Deprecated public void setPasswordMinimumLength(@NonNull android.content.ComponentName, int); + method @Deprecated public void setPasswordMinimumLetters(@NonNull android.content.ComponentName, int); + method @Deprecated public void setPasswordMinimumLowerCase(@NonNull android.content.ComponentName, int); + method @Deprecated public void setPasswordMinimumNonLetter(@NonNull android.content.ComponentName, int); + method @Deprecated public void setPasswordMinimumNumeric(@NonNull android.content.ComponentName, int); + method @Deprecated public void setPasswordMinimumSymbols(@NonNull android.content.ComponentName, int); + method @Deprecated public void setPasswordMinimumUpperCase(@NonNull android.content.ComponentName, int); + method @Deprecated public void setPasswordQuality(@NonNull android.content.ComponentName, int); method public boolean setPermissionGrantState(@NonNull android.content.ComponentName, @NonNull String, @NonNull String, int); method public void setPermissionPolicy(@NonNull android.content.ComponentName, int); method public boolean setPermittedAccessibilityServices(@NonNull android.content.ComponentName, java.util.List<java.lang.String>); @@ -9519,6 +9525,8 @@ package android.companion { method @NonNull public java.util.List<java.lang.String> getAssociations(); method public boolean hasNotificationAccess(android.content.ComponentName); method public void requestNotificationAccess(android.content.ComponentName); + method @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) public void startObservingDevicePresence(@NonNull String) throws android.companion.DeviceNotAssociatedException; + method @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) public void stopObservingDevicePresence(@NonNull String) throws android.companion.DeviceNotAssociatedException; field public static final String EXTRA_DEVICE = "android.companion.extra.DEVICE"; } @@ -9539,6 +9547,9 @@ package android.companion { public interface DeviceFilter<D extends android.os.Parcelable> extends android.os.Parcelable { } + public class DeviceNotAssociatedException extends java.lang.Exception { + } + public final class WifiDeviceFilter implements android.companion.DeviceFilter<android.net.wifi.ScanResult> { method public int describeContents(); method public void writeToParcel(@NonNull android.os.Parcel, int); @@ -12256,6 +12267,7 @@ package android.content.pm { field public static final String FEATURE_NFC_HOST_CARD_EMULATION_NFCF = "android.hardware.nfc.hcef"; field public static final String FEATURE_NFC_OFF_HOST_CARD_EMULATION_ESE = "android.hardware.nfc.ese"; field public static final String FEATURE_NFC_OFF_HOST_CARD_EMULATION_UICC = "android.hardware.nfc.uicc"; + field public static final String FEATURE_OPENGLES_DEQP_LEVEL = "android.software.opengles.deqp.level"; field public static final String FEATURE_OPENGLES_EXTENSION_PACK = "android.hardware.opengles.aep"; field public static final String FEATURE_PC = "android.hardware.type.pc"; field public static final String FEATURE_PICTURE_IN_PICTURE = "android.software.picture_in_picture"; @@ -15279,16 +15291,11 @@ package android.graphics { ctor public PaintFlagsDrawFilter(int, int); } - public final class ParcelableColorSpace extends android.graphics.ColorSpace implements android.os.Parcelable { + public final class ParcelableColorSpace implements android.os.Parcelable { ctor public ParcelableColorSpace(@NonNull android.graphics.ColorSpace); method public int describeContents(); - method @NonNull public float[] fromXyz(@NonNull float[]); method @NonNull public android.graphics.ColorSpace getColorSpace(); - method public float getMaxValue(int); - method public float getMinValue(int); method public static boolean isParcelable(@NonNull android.graphics.ColorSpace); - method public boolean isWideGamut(); - method @NonNull public float[] toXyz(@NonNull float[]); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.graphics.ParcelableColorSpace> CREATOR; } @@ -18524,4812 +18531,6 @@ package android.hardware.usb { } -package android.icu.lang { - - public final class UCharacter implements android.icu.lang.UCharacterEnums.ECharacterCategory android.icu.lang.UCharacterEnums.ECharacterDirection { - method public static int charCount(int); - method public static int codePointAt(CharSequence, int); - method public static int codePointAt(char[], int); - method public static int codePointAt(char[], int, int); - method public static int codePointBefore(CharSequence, int); - method public static int codePointBefore(char[], int); - method public static int codePointBefore(char[], int, int); - method public static int codePointCount(CharSequence, int, int); - method public static int codePointCount(char[], int, int); - method public static int digit(int, int); - method public static int digit(int); - method public static int foldCase(int, boolean); - method public static String foldCase(String, boolean); - method public static int foldCase(int, int); - method public static String foldCase(String, int); - method public static char forDigit(int, int); - method public static android.icu.util.VersionInfo getAge(int); - method public static int getBidiPairedBracket(int); - method public static int getCharFromExtendedName(String); - method public static int getCharFromName(String); - method public static int getCharFromNameAlias(String); - method public static int getCodePoint(char, char); - method public static int getCodePoint(char); - method public static int getCombiningClass(int); - method public static int getDirection(int); - method public static byte getDirectionality(int); - method public static String getExtendedName(int); - method public static android.icu.util.ValueIterator getExtendedNameIterator(); - method public static int getHanNumericValue(int); - method public static int getIntPropertyMaxValue(int); - method public static int getIntPropertyMinValue(int); - method public static int getIntPropertyValue(int, int); - method public static int getMirror(int); - method public static String getName(int); - method public static String getName(String, String); - method public static String getNameAlias(int); - method public static android.icu.util.ValueIterator getNameIterator(); - method public static int getNumericValue(int); - method public static int getPropertyEnum(CharSequence); - method public static String getPropertyName(int, int); - method public static int getPropertyValueEnum(int, CharSequence); - method public static String getPropertyValueName(int, int, int); - method public static int getType(int); - method public static android.icu.util.RangeValueIterator getTypeIterator(); - method public static double getUnicodeNumericValue(int); - method public static android.icu.util.VersionInfo getUnicodeVersion(); - method public static boolean hasBinaryProperty(int, int); - method public static boolean isBMP(int); - method public static boolean isBaseForm(int); - method public static boolean isDefined(int); - method public static boolean isDigit(int); - method public static boolean isHighSurrogate(char); - method public static boolean isISOControl(int); - method public static boolean isIdentifierIgnorable(int); - method public static boolean isJavaIdentifierPart(int); - method public static boolean isJavaIdentifierStart(int); - method public static boolean isLegal(int); - method public static boolean isLegal(String); - method public static boolean isLetter(int); - method public static boolean isLetterOrDigit(int); - method public static boolean isLowSurrogate(char); - method public static boolean isLowerCase(int); - method public static boolean isMirrored(int); - method public static boolean isPrintable(int); - method public static boolean isSpaceChar(int); - method public static boolean isSupplementary(int); - method public static boolean isSupplementaryCodePoint(int); - method public static boolean isSurrogatePair(char, char); - method public static boolean isTitleCase(int); - method public static boolean isUAlphabetic(int); - method public static boolean isULowercase(int); - method public static boolean isUUppercase(int); - method public static boolean isUWhiteSpace(int); - method public static boolean isUnicodeIdentifierPart(int); - method public static boolean isUnicodeIdentifierStart(int); - method public static boolean isUpperCase(int); - method public static boolean isValidCodePoint(int); - method public static boolean isWhitespace(int); - method public static int offsetByCodePoints(CharSequence, int, int); - method public static int offsetByCodePoints(char[], int, int, int, int); - method public static int toChars(int, char[], int); - method public static char[] toChars(int); - method public static int toCodePoint(char, char); - method public static int toLowerCase(int); - method public static String toLowerCase(String); - method public static String toLowerCase(java.util.Locale, String); - method public static String toLowerCase(android.icu.util.ULocale, String); - method public static String toString(int); - method public static int toTitleCase(int); - method public static String toTitleCase(String, android.icu.text.BreakIterator); - method public static String toTitleCase(java.util.Locale, String, android.icu.text.BreakIterator); - method public static String toTitleCase(android.icu.util.ULocale, String, android.icu.text.BreakIterator); - method public static String toTitleCase(android.icu.util.ULocale, String, android.icu.text.BreakIterator, int); - method public static String toTitleCase(java.util.Locale, String, android.icu.text.BreakIterator, int); - method public static int toUpperCase(int); - method public static String toUpperCase(String); - method public static String toUpperCase(java.util.Locale, String); - method public static String toUpperCase(android.icu.util.ULocale, String); - field public static final int FOLD_CASE_DEFAULT = 0; // 0x0 - field public static final int FOLD_CASE_EXCLUDE_SPECIAL_I = 1; // 0x1 - field public static final int MAX_CODE_POINT = 1114111; // 0x10ffff - field public static final char MAX_HIGH_SURROGATE = 56319; // 0xdbff '\udbff' - field public static final char MAX_LOW_SURROGATE = 57343; // 0xdfff '\udfff' - field public static final int MAX_RADIX = 36; // 0x24 - field public static final char MAX_SURROGATE = 57343; // 0xdfff '\udfff' - field public static final int MAX_VALUE = 1114111; // 0x10ffff - field public static final int MIN_CODE_POINT = 0; // 0x0 - field public static final char MIN_HIGH_SURROGATE = 55296; // 0xd800 '\ud800' - field public static final char MIN_LOW_SURROGATE = 56320; // 0xdc00 '\udc00' - field public static final int MIN_RADIX = 2; // 0x2 - field public static final int MIN_SUPPLEMENTARY_CODE_POINT = 65536; // 0x10000 - field public static final char MIN_SURROGATE = 55296; // 0xd800 '\ud800' - field public static final int MIN_VALUE = 0; // 0x0 - field public static final double NO_NUMERIC_VALUE = -1.23456789E8; - field public static final int REPLACEMENT_CHAR = 65533; // 0xfffd - field public static final int SUPPLEMENTARY_MIN_VALUE = 65536; // 0x10000 - field public static final int TITLECASE_NO_BREAK_ADJUSTMENT = 512; // 0x200 - field public static final int TITLECASE_NO_LOWERCASE = 256; // 0x100 - } - - public static interface UCharacter.BidiPairedBracketType { - field public static final int CLOSE = 2; // 0x2 - field public static final int NONE = 0; // 0x0 - field public static final int OPEN = 1; // 0x1 - } - - public static interface UCharacter.DecompositionType { - field public static final int CANONICAL = 1; // 0x1 - field public static final int CIRCLE = 3; // 0x3 - field public static final int COMPAT = 2; // 0x2 - field public static final int FINAL = 4; // 0x4 - field public static final int FONT = 5; // 0x5 - field public static final int FRACTION = 6; // 0x6 - field public static final int INITIAL = 7; // 0x7 - field public static final int ISOLATED = 8; // 0x8 - field public static final int MEDIAL = 9; // 0x9 - field public static final int NARROW = 10; // 0xa - field public static final int NOBREAK = 11; // 0xb - field public static final int NONE = 0; // 0x0 - field public static final int SMALL = 12; // 0xc - field public static final int SQUARE = 13; // 0xd - field public static final int SUB = 14; // 0xe - field public static final int SUPER = 15; // 0xf - field public static final int VERTICAL = 16; // 0x10 - field public static final int WIDE = 17; // 0x11 - } - - public static interface UCharacter.EastAsianWidth { - field public static final int AMBIGUOUS = 1; // 0x1 - field public static final int FULLWIDTH = 3; // 0x3 - field public static final int HALFWIDTH = 2; // 0x2 - field public static final int NARROW = 4; // 0x4 - field public static final int NEUTRAL = 0; // 0x0 - field public static final int WIDE = 5; // 0x5 - } - - public static interface UCharacter.GraphemeClusterBreak { - field public static final int CONTROL = 1; // 0x1 - field public static final int CR = 2; // 0x2 - field public static final int EXTEND = 3; // 0x3 - field public static final int E_BASE = 13; // 0xd - field public static final int E_BASE_GAZ = 14; // 0xe - field public static final int E_MODIFIER = 15; // 0xf - field public static final int GLUE_AFTER_ZWJ = 16; // 0x10 - field public static final int L = 4; // 0x4 - field public static final int LF = 5; // 0x5 - field public static final int LV = 6; // 0x6 - field public static final int LVT = 7; // 0x7 - field public static final int OTHER = 0; // 0x0 - field public static final int PREPEND = 11; // 0xb - field public static final int REGIONAL_INDICATOR = 12; // 0xc - field public static final int SPACING_MARK = 10; // 0xa - field public static final int T = 8; // 0x8 - field public static final int V = 9; // 0x9 - field public static final int ZWJ = 17; // 0x11 - } - - public static interface UCharacter.HangulSyllableType { - field public static final int LEADING_JAMO = 1; // 0x1 - field public static final int LVT_SYLLABLE = 5; // 0x5 - field public static final int LV_SYLLABLE = 4; // 0x4 - field public static final int NOT_APPLICABLE = 0; // 0x0 - field public static final int TRAILING_JAMO = 3; // 0x3 - field public static final int VOWEL_JAMO = 2; // 0x2 - } - - public static interface UCharacter.IndicPositionalCategory { - field public static final int BOTTOM = 1; // 0x1 - field public static final int BOTTOM_AND_LEFT = 2; // 0x2 - field public static final int BOTTOM_AND_RIGHT = 3; // 0x3 - field public static final int LEFT = 4; // 0x4 - field public static final int LEFT_AND_RIGHT = 5; // 0x5 - field public static final int NA = 0; // 0x0 - field public static final int OVERSTRUCK = 6; // 0x6 - field public static final int RIGHT = 7; // 0x7 - field public static final int TOP = 8; // 0x8 - field public static final int TOP_AND_BOTTOM = 9; // 0x9 - field public static final int TOP_AND_BOTTOM_AND_LEFT = 15; // 0xf - field public static final int TOP_AND_BOTTOM_AND_RIGHT = 10; // 0xa - field public static final int TOP_AND_LEFT = 11; // 0xb - field public static final int TOP_AND_LEFT_AND_RIGHT = 12; // 0xc - field public static final int TOP_AND_RIGHT = 13; // 0xd - field public static final int VISUAL_ORDER_LEFT = 14; // 0xe - } - - public static interface UCharacter.IndicSyllabicCategory { - field public static final int AVAGRAHA = 1; // 0x1 - field public static final int BINDU = 2; // 0x2 - field public static final int BRAHMI_JOINING_NUMBER = 3; // 0x3 - field public static final int CANTILLATION_MARK = 4; // 0x4 - field public static final int CONSONANT = 5; // 0x5 - field public static final int CONSONANT_DEAD = 6; // 0x6 - field public static final int CONSONANT_FINAL = 7; // 0x7 - field public static final int CONSONANT_HEAD_LETTER = 8; // 0x8 - field public static final int CONSONANT_INITIAL_POSTFIXED = 9; // 0x9 - field public static final int CONSONANT_KILLER = 10; // 0xa - field public static final int CONSONANT_MEDIAL = 11; // 0xb - field public static final int CONSONANT_PLACEHOLDER = 12; // 0xc - field public static final int CONSONANT_PRECEDING_REPHA = 13; // 0xd - field public static final int CONSONANT_PREFIXED = 14; // 0xe - field public static final int CONSONANT_SUBJOINED = 15; // 0xf - field public static final int CONSONANT_SUCCEEDING_REPHA = 16; // 0x10 - field public static final int CONSONANT_WITH_STACKER = 17; // 0x11 - field public static final int GEMINATION_MARK = 18; // 0x12 - field public static final int INVISIBLE_STACKER = 19; // 0x13 - field public static final int JOINER = 20; // 0x14 - field public static final int MODIFYING_LETTER = 21; // 0x15 - field public static final int NON_JOINER = 22; // 0x16 - field public static final int NUKTA = 23; // 0x17 - field public static final int NUMBER = 24; // 0x18 - field public static final int NUMBER_JOINER = 25; // 0x19 - field public static final int OTHER = 0; // 0x0 - field public static final int PURE_KILLER = 26; // 0x1a - field public static final int REGISTER_SHIFTER = 27; // 0x1b - field public static final int SYLLABLE_MODIFIER = 28; // 0x1c - field public static final int TONE_LETTER = 29; // 0x1d - field public static final int TONE_MARK = 30; // 0x1e - field public static final int VIRAMA = 31; // 0x1f - field public static final int VISARGA = 32; // 0x20 - field public static final int VOWEL = 33; // 0x21 - field public static final int VOWEL_DEPENDENT = 34; // 0x22 - field public static final int VOWEL_INDEPENDENT = 35; // 0x23 - } - - public static interface UCharacter.JoiningGroup { - field public static final int AFRICAN_FEH = 86; // 0x56 - field public static final int AFRICAN_NOON = 87; // 0x57 - field public static final int AFRICAN_QAF = 88; // 0x58 - field public static final int AIN = 1; // 0x1 - field public static final int ALAPH = 2; // 0x2 - field public static final int ALEF = 3; // 0x3 - field public static final int BEH = 4; // 0x4 - field public static final int BETH = 5; // 0x5 - field public static final int BURUSHASKI_YEH_BARREE = 54; // 0x36 - field public static final int DAL = 6; // 0x6 - field public static final int DALATH_RISH = 7; // 0x7 - field public static final int E = 8; // 0x8 - field public static final int FARSI_YEH = 55; // 0x37 - field public static final int FE = 51; // 0x33 - field public static final int FEH = 9; // 0x9 - field public static final int FINAL_SEMKATH = 10; // 0xa - field public static final int GAF = 11; // 0xb - field public static final int GAMAL = 12; // 0xc - field public static final int HAH = 13; // 0xd - field public static final int HAMZA_ON_HEH_GOAL = 14; // 0xe - field public static final int HANIFI_ROHINGYA_KINNA_YA = 100; // 0x64 - field public static final int HANIFI_ROHINGYA_PA = 101; // 0x65 - field public static final int HE = 15; // 0xf - field public static final int HEH = 16; // 0x10 - field public static final int HEH_GOAL = 17; // 0x11 - field public static final int HETH = 18; // 0x12 - field public static final int KAF = 19; // 0x13 - field public static final int KAPH = 20; // 0x14 - field public static final int KHAPH = 52; // 0x34 - field public static final int KNOTTED_HEH = 21; // 0x15 - field public static final int LAM = 22; // 0x16 - field public static final int LAMADH = 23; // 0x17 - field public static final int MALAYALAM_BHA = 89; // 0x59 - field public static final int MALAYALAM_JA = 90; // 0x5a - field public static final int MALAYALAM_LLA = 91; // 0x5b - field public static final int MALAYALAM_LLLA = 92; // 0x5c - field public static final int MALAYALAM_NGA = 93; // 0x5d - field public static final int MALAYALAM_NNA = 94; // 0x5e - field public static final int MALAYALAM_NNNA = 95; // 0x5f - field public static final int MALAYALAM_NYA = 96; // 0x60 - field public static final int MALAYALAM_RA = 97; // 0x61 - field public static final int MALAYALAM_SSA = 98; // 0x62 - field public static final int MALAYALAM_TTA = 99; // 0x63 - field public static final int MANICHAEAN_ALEPH = 58; // 0x3a - field public static final int MANICHAEAN_AYIN = 59; // 0x3b - field public static final int MANICHAEAN_BETH = 60; // 0x3c - field public static final int MANICHAEAN_DALETH = 61; // 0x3d - field public static final int MANICHAEAN_DHAMEDH = 62; // 0x3e - field public static final int MANICHAEAN_FIVE = 63; // 0x3f - field public static final int MANICHAEAN_GIMEL = 64; // 0x40 - field public static final int MANICHAEAN_HETH = 65; // 0x41 - field public static final int MANICHAEAN_HUNDRED = 66; // 0x42 - field public static final int MANICHAEAN_KAPH = 67; // 0x43 - field public static final int MANICHAEAN_LAMEDH = 68; // 0x44 - field public static final int MANICHAEAN_MEM = 69; // 0x45 - field public static final int MANICHAEAN_NUN = 70; // 0x46 - field public static final int MANICHAEAN_ONE = 71; // 0x47 - field public static final int MANICHAEAN_PE = 72; // 0x48 - field public static final int MANICHAEAN_QOPH = 73; // 0x49 - field public static final int MANICHAEAN_RESH = 74; // 0x4a - field public static final int MANICHAEAN_SADHE = 75; // 0x4b - field public static final int MANICHAEAN_SAMEKH = 76; // 0x4c - field public static final int MANICHAEAN_TAW = 77; // 0x4d - field public static final int MANICHAEAN_TEN = 78; // 0x4e - field public static final int MANICHAEAN_TETH = 79; // 0x4f - field public static final int MANICHAEAN_THAMEDH = 80; // 0x50 - field public static final int MANICHAEAN_TWENTY = 81; // 0x51 - field public static final int MANICHAEAN_WAW = 82; // 0x52 - field public static final int MANICHAEAN_YODH = 83; // 0x53 - field public static final int MANICHAEAN_ZAYIN = 84; // 0x54 - field public static final int MEEM = 24; // 0x18 - field public static final int MIM = 25; // 0x19 - field public static final int NOON = 26; // 0x1a - field public static final int NO_JOINING_GROUP = 0; // 0x0 - field public static final int NUN = 27; // 0x1b - field public static final int NYA = 56; // 0x38 - field public static final int PE = 28; // 0x1c - field public static final int QAF = 29; // 0x1d - field public static final int QAPH = 30; // 0x1e - field public static final int REH = 31; // 0x1f - field public static final int REVERSED_PE = 32; // 0x20 - field public static final int ROHINGYA_YEH = 57; // 0x39 - field public static final int SAD = 33; // 0x21 - field public static final int SADHE = 34; // 0x22 - field public static final int SEEN = 35; // 0x23 - field public static final int SEMKATH = 36; // 0x24 - field public static final int SHIN = 37; // 0x25 - field public static final int STRAIGHT_WAW = 85; // 0x55 - field public static final int SWASH_KAF = 38; // 0x26 - field public static final int SYRIAC_WAW = 39; // 0x27 - field public static final int TAH = 40; // 0x28 - field public static final int TAW = 41; // 0x29 - field public static final int TEH_MARBUTA = 42; // 0x2a - field public static final int TEH_MARBUTA_GOAL = 14; // 0xe - field public static final int TETH = 43; // 0x2b - field public static final int WAW = 44; // 0x2c - field public static final int YEH = 45; // 0x2d - field public static final int YEH_BARREE = 46; // 0x2e - field public static final int YEH_WITH_TAIL = 47; // 0x2f - field public static final int YUDH = 48; // 0x30 - field public static final int YUDH_HE = 49; // 0x31 - field public static final int ZAIN = 50; // 0x32 - field public static final int ZHAIN = 53; // 0x35 - } - - public static interface UCharacter.JoiningType { - field public static final int DUAL_JOINING = 2; // 0x2 - field public static final int JOIN_CAUSING = 1; // 0x1 - field public static final int LEFT_JOINING = 3; // 0x3 - field public static final int NON_JOINING = 0; // 0x0 - field public static final int RIGHT_JOINING = 4; // 0x4 - field public static final int TRANSPARENT = 5; // 0x5 - } - - public static interface UCharacter.LineBreak { - field public static final int ALPHABETIC = 2; // 0x2 - field public static final int AMBIGUOUS = 1; // 0x1 - field public static final int BREAK_AFTER = 4; // 0x4 - field public static final int BREAK_BEFORE = 5; // 0x5 - field public static final int BREAK_BOTH = 3; // 0x3 - field public static final int BREAK_SYMBOLS = 27; // 0x1b - field public static final int CARRIAGE_RETURN = 10; // 0xa - field public static final int CLOSE_PARENTHESIS = 36; // 0x24 - field public static final int CLOSE_PUNCTUATION = 8; // 0x8 - field public static final int COMBINING_MARK = 9; // 0x9 - field public static final int COMPLEX_CONTEXT = 24; // 0x18 - field public static final int CONDITIONAL_JAPANESE_STARTER = 37; // 0x25 - field public static final int CONTINGENT_BREAK = 7; // 0x7 - field public static final int EXCLAMATION = 11; // 0xb - field public static final int E_BASE = 40; // 0x28 - field public static final int E_MODIFIER = 41; // 0x29 - field public static final int GLUE = 12; // 0xc - field public static final int H2 = 31; // 0x1f - field public static final int H3 = 32; // 0x20 - field public static final int HEBREW_LETTER = 38; // 0x26 - field public static final int HYPHEN = 13; // 0xd - field public static final int IDEOGRAPHIC = 14; // 0xe - field public static final int INFIX_NUMERIC = 16; // 0x10 - field public static final int INSEPARABLE = 15; // 0xf - field public static final int INSEPERABLE = 15; // 0xf - field public static final int JL = 33; // 0x21 - field public static final int JT = 34; // 0x22 - field public static final int JV = 35; // 0x23 - field public static final int LINE_FEED = 17; // 0x11 - field public static final int MANDATORY_BREAK = 6; // 0x6 - field public static final int NEXT_LINE = 29; // 0x1d - field public static final int NONSTARTER = 18; // 0x12 - field public static final int NUMERIC = 19; // 0x13 - field public static final int OPEN_PUNCTUATION = 20; // 0x14 - field public static final int POSTFIX_NUMERIC = 21; // 0x15 - field public static final int PREFIX_NUMERIC = 22; // 0x16 - field public static final int QUOTATION = 23; // 0x17 - field public static final int REGIONAL_INDICATOR = 39; // 0x27 - field public static final int SPACE = 26; // 0x1a - field public static final int SURROGATE = 25; // 0x19 - field public static final int UNKNOWN = 0; // 0x0 - field public static final int WORD_JOINER = 30; // 0x1e - field public static final int ZWJ = 42; // 0x2a - field public static final int ZWSPACE = 28; // 0x1c - } - - public static interface UCharacter.NumericType { - field public static final int DECIMAL = 1; // 0x1 - field public static final int DIGIT = 2; // 0x2 - field public static final int NONE = 0; // 0x0 - field public static final int NUMERIC = 3; // 0x3 - } - - public static interface UCharacter.SentenceBreak { - field public static final int ATERM = 1; // 0x1 - field public static final int CLOSE = 2; // 0x2 - field public static final int CR = 11; // 0xb - field public static final int EXTEND = 12; // 0xc - field public static final int FORMAT = 3; // 0x3 - field public static final int LF = 13; // 0xd - field public static final int LOWER = 4; // 0x4 - field public static final int NUMERIC = 5; // 0x5 - field public static final int OLETTER = 6; // 0x6 - field public static final int OTHER = 0; // 0x0 - field public static final int SCONTINUE = 14; // 0xe - field public static final int SEP = 7; // 0x7 - field public static final int SP = 8; // 0x8 - field public static final int STERM = 9; // 0x9 - field public static final int UPPER = 10; // 0xa - } - - public static final class UCharacter.UnicodeBlock extends java.lang.Character.Subset { - method public static android.icu.lang.UCharacter.UnicodeBlock forName(String); - method public int getID(); - method public static android.icu.lang.UCharacter.UnicodeBlock getInstance(int); - method public static android.icu.lang.UCharacter.UnicodeBlock of(int); - field public static final android.icu.lang.UCharacter.UnicodeBlock ADLAM; - field public static final int ADLAM_ID = 263; // 0x107 - field public static final android.icu.lang.UCharacter.UnicodeBlock AEGEAN_NUMBERS; - field public static final int AEGEAN_NUMBERS_ID = 119; // 0x77 - field public static final android.icu.lang.UCharacter.UnicodeBlock AHOM; - field public static final int AHOM_ID = 253; // 0xfd - field public static final android.icu.lang.UCharacter.UnicodeBlock ALCHEMICAL_SYMBOLS; - field public static final int ALCHEMICAL_SYMBOLS_ID = 208; // 0xd0 - field public static final android.icu.lang.UCharacter.UnicodeBlock ALPHABETIC_PRESENTATION_FORMS; - field public static final int ALPHABETIC_PRESENTATION_FORMS_ID = 80; // 0x50 - field public static final android.icu.lang.UCharacter.UnicodeBlock ANATOLIAN_HIEROGLYPHS; - field public static final int ANATOLIAN_HIEROGLYPHS_ID = 254; // 0xfe - field public static final android.icu.lang.UCharacter.UnicodeBlock ANCIENT_GREEK_MUSICAL_NOTATION; - field public static final int ANCIENT_GREEK_MUSICAL_NOTATION_ID = 126; // 0x7e - field public static final android.icu.lang.UCharacter.UnicodeBlock ANCIENT_GREEK_NUMBERS; - field public static final int ANCIENT_GREEK_NUMBERS_ID = 127; // 0x7f - field public static final android.icu.lang.UCharacter.UnicodeBlock ANCIENT_SYMBOLS; - field public static final int ANCIENT_SYMBOLS_ID = 165; // 0xa5 - field public static final android.icu.lang.UCharacter.UnicodeBlock ARABIC; - field public static final android.icu.lang.UCharacter.UnicodeBlock ARABIC_EXTENDED_A; - field public static final int ARABIC_EXTENDED_A_ID = 210; // 0xd2 - field public static final int ARABIC_ID = 12; // 0xc - field public static final android.icu.lang.UCharacter.UnicodeBlock ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS; - field public static final int ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS_ID = 211; // 0xd3 - field public static final android.icu.lang.UCharacter.UnicodeBlock ARABIC_PRESENTATION_FORMS_A; - field public static final int ARABIC_PRESENTATION_FORMS_A_ID = 81; // 0x51 - field public static final android.icu.lang.UCharacter.UnicodeBlock ARABIC_PRESENTATION_FORMS_B; - field public static final int ARABIC_PRESENTATION_FORMS_B_ID = 85; // 0x55 - field public static final android.icu.lang.UCharacter.UnicodeBlock ARABIC_SUPPLEMENT; - field public static final int ARABIC_SUPPLEMENT_ID = 128; // 0x80 - field public static final android.icu.lang.UCharacter.UnicodeBlock ARMENIAN; - field public static final int ARMENIAN_ID = 10; // 0xa - field public static final android.icu.lang.UCharacter.UnicodeBlock ARROWS; - field public static final int ARROWS_ID = 46; // 0x2e - field public static final android.icu.lang.UCharacter.UnicodeBlock AVESTAN; - field public static final int AVESTAN_ID = 188; // 0xbc - field public static final android.icu.lang.UCharacter.UnicodeBlock BALINESE; - field public static final int BALINESE_ID = 147; // 0x93 - field public static final android.icu.lang.UCharacter.UnicodeBlock BAMUM; - field public static final int BAMUM_ID = 177; // 0xb1 - field public static final android.icu.lang.UCharacter.UnicodeBlock BAMUM_SUPPLEMENT; - field public static final int BAMUM_SUPPLEMENT_ID = 202; // 0xca - field public static final android.icu.lang.UCharacter.UnicodeBlock BASIC_LATIN; - field public static final int BASIC_LATIN_ID = 1; // 0x1 - field public static final android.icu.lang.UCharacter.UnicodeBlock BASSA_VAH; - field public static final int BASSA_VAH_ID = 221; // 0xdd - field public static final android.icu.lang.UCharacter.UnicodeBlock BATAK; - field public static final int BATAK_ID = 199; // 0xc7 - field public static final android.icu.lang.UCharacter.UnicodeBlock BENGALI; - field public static final int BENGALI_ID = 16; // 0x10 - field public static final android.icu.lang.UCharacter.UnicodeBlock BHAIKSUKI; - field public static final int BHAIKSUKI_ID = 264; // 0x108 - field public static final android.icu.lang.UCharacter.UnicodeBlock BLOCK_ELEMENTS; - field public static final int BLOCK_ELEMENTS_ID = 53; // 0x35 - field public static final android.icu.lang.UCharacter.UnicodeBlock BOPOMOFO; - field public static final android.icu.lang.UCharacter.UnicodeBlock BOPOMOFO_EXTENDED; - field public static final int BOPOMOFO_EXTENDED_ID = 67; // 0x43 - field public static final int BOPOMOFO_ID = 64; // 0x40 - field public static final android.icu.lang.UCharacter.UnicodeBlock BOX_DRAWING; - field public static final int BOX_DRAWING_ID = 52; // 0x34 - field public static final android.icu.lang.UCharacter.UnicodeBlock BRAHMI; - field public static final int BRAHMI_ID = 201; // 0xc9 - field public static final android.icu.lang.UCharacter.UnicodeBlock BRAILLE_PATTERNS; - field public static final int BRAILLE_PATTERNS_ID = 57; // 0x39 - field public static final android.icu.lang.UCharacter.UnicodeBlock BUGINESE; - field public static final int BUGINESE_ID = 129; // 0x81 - field public static final android.icu.lang.UCharacter.UnicodeBlock BUHID; - field public static final int BUHID_ID = 100; // 0x64 - field public static final android.icu.lang.UCharacter.UnicodeBlock BYZANTINE_MUSICAL_SYMBOLS; - field public static final int BYZANTINE_MUSICAL_SYMBOLS_ID = 91; // 0x5b - field public static final android.icu.lang.UCharacter.UnicodeBlock CARIAN; - field public static final int CARIAN_ID = 168; // 0xa8 - field public static final android.icu.lang.UCharacter.UnicodeBlock CAUCASIAN_ALBANIAN; - field public static final int CAUCASIAN_ALBANIAN_ID = 222; // 0xde - field public static final android.icu.lang.UCharacter.UnicodeBlock CHAKMA; - field public static final int CHAKMA_ID = 212; // 0xd4 - field public static final android.icu.lang.UCharacter.UnicodeBlock CHAM; - field public static final int CHAM_ID = 164; // 0xa4 - field public static final android.icu.lang.UCharacter.UnicodeBlock CHEROKEE; - field public static final int CHEROKEE_ID = 32; // 0x20 - field public static final android.icu.lang.UCharacter.UnicodeBlock CHEROKEE_SUPPLEMENT; - field public static final int CHEROKEE_SUPPLEMENT_ID = 255; // 0xff - field public static final android.icu.lang.UCharacter.UnicodeBlock CHESS_SYMBOLS; - field public static final int CHESS_SYMBOLS_ID = 281; // 0x119 - field public static final android.icu.lang.UCharacter.UnicodeBlock CHORASMIAN; - field public static final int CHORASMIAN_ID = 301; // 0x12d - field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_COMPATIBILITY; - field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_COMPATIBILITY_FORMS; - field public static final int CJK_COMPATIBILITY_FORMS_ID = 83; // 0x53 - field public static final int CJK_COMPATIBILITY_ID = 69; // 0x45 - field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS; - field public static final int CJK_COMPATIBILITY_IDEOGRAPHS_ID = 79; // 0x4f - field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT; - field public static final int CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT_ID = 95; // 0x5f - field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_RADICALS_SUPPLEMENT; - field public static final int CJK_RADICALS_SUPPLEMENT_ID = 58; // 0x3a - field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_STROKES; - field public static final int CJK_STROKES_ID = 130; // 0x82 - field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_SYMBOLS_AND_PUNCTUATION; - field public static final int CJK_SYMBOLS_AND_PUNCTUATION_ID = 61; // 0x3d - field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_UNIFIED_IDEOGRAPHS; - field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A; - field public static final int CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A_ID = 70; // 0x46 - field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B; - field public static final int CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B_ID = 94; // 0x5e - field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C; - field public static final int CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C_ID = 197; // 0xc5 - field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D; - field public static final int CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D_ID = 209; // 0xd1 - field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_E; - field public static final int CJK_UNIFIED_IDEOGRAPHS_EXTENSION_E_ID = 256; // 0x100 - field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_F; - field public static final int CJK_UNIFIED_IDEOGRAPHS_EXTENSION_F_ID = 274; // 0x112 - field public static final android.icu.lang.UCharacter.UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_G; - field public static final int CJK_UNIFIED_IDEOGRAPHS_EXTENSION_G_ID = 302; // 0x12e - field public static final int CJK_UNIFIED_IDEOGRAPHS_ID = 71; // 0x47 - field public static final android.icu.lang.UCharacter.UnicodeBlock COMBINING_DIACRITICAL_MARKS; - field public static final android.icu.lang.UCharacter.UnicodeBlock COMBINING_DIACRITICAL_MARKS_EXTENDED; - field public static final int COMBINING_DIACRITICAL_MARKS_EXTENDED_ID = 224; // 0xe0 - field public static final int COMBINING_DIACRITICAL_MARKS_ID = 7; // 0x7 - field public static final android.icu.lang.UCharacter.UnicodeBlock COMBINING_DIACRITICAL_MARKS_SUPPLEMENT; - field public static final int COMBINING_DIACRITICAL_MARKS_SUPPLEMENT_ID = 131; // 0x83 - field public static final android.icu.lang.UCharacter.UnicodeBlock COMBINING_HALF_MARKS; - field public static final int COMBINING_HALF_MARKS_ID = 82; // 0x52 - field public static final android.icu.lang.UCharacter.UnicodeBlock COMBINING_MARKS_FOR_SYMBOLS; - field public static final int COMBINING_MARKS_FOR_SYMBOLS_ID = 43; // 0x2b - field public static final android.icu.lang.UCharacter.UnicodeBlock COMMON_INDIC_NUMBER_FORMS; - field public static final int COMMON_INDIC_NUMBER_FORMS_ID = 178; // 0xb2 - field public static final android.icu.lang.UCharacter.UnicodeBlock CONTROL_PICTURES; - field public static final int CONTROL_PICTURES_ID = 49; // 0x31 - field public static final android.icu.lang.UCharacter.UnicodeBlock COPTIC; - field public static final android.icu.lang.UCharacter.UnicodeBlock COPTIC_EPACT_NUMBERS; - field public static final int COPTIC_EPACT_NUMBERS_ID = 223; // 0xdf - field public static final int COPTIC_ID = 132; // 0x84 - field public static final android.icu.lang.UCharacter.UnicodeBlock COUNTING_ROD_NUMERALS; - field public static final int COUNTING_ROD_NUMERALS_ID = 154; // 0x9a - field public static final android.icu.lang.UCharacter.UnicodeBlock CUNEIFORM; - field public static final int CUNEIFORM_ID = 152; // 0x98 - field public static final android.icu.lang.UCharacter.UnicodeBlock CUNEIFORM_NUMBERS_AND_PUNCTUATION; - field public static final int CUNEIFORM_NUMBERS_AND_PUNCTUATION_ID = 153; // 0x99 - field public static final android.icu.lang.UCharacter.UnicodeBlock CURRENCY_SYMBOLS; - field public static final int CURRENCY_SYMBOLS_ID = 42; // 0x2a - field public static final android.icu.lang.UCharacter.UnicodeBlock CYPRIOT_SYLLABARY; - field public static final int CYPRIOT_SYLLABARY_ID = 123; // 0x7b - field public static final android.icu.lang.UCharacter.UnicodeBlock CYRILLIC; - field public static final android.icu.lang.UCharacter.UnicodeBlock CYRILLIC_EXTENDED_A; - field public static final int CYRILLIC_EXTENDED_A_ID = 158; // 0x9e - field public static final android.icu.lang.UCharacter.UnicodeBlock CYRILLIC_EXTENDED_B; - field public static final int CYRILLIC_EXTENDED_B_ID = 160; // 0xa0 - field public static final android.icu.lang.UCharacter.UnicodeBlock CYRILLIC_EXTENDED_C; - field public static final int CYRILLIC_EXTENDED_C_ID = 265; // 0x109 - field public static final int CYRILLIC_ID = 9; // 0x9 - field public static final android.icu.lang.UCharacter.UnicodeBlock CYRILLIC_SUPPLEMENT; - field public static final android.icu.lang.UCharacter.UnicodeBlock CYRILLIC_SUPPLEMENTARY; - field public static final int CYRILLIC_SUPPLEMENTARY_ID = 97; // 0x61 - field public static final int CYRILLIC_SUPPLEMENT_ID = 97; // 0x61 - field public static final android.icu.lang.UCharacter.UnicodeBlock DESERET; - field public static final int DESERET_ID = 90; // 0x5a - field public static final android.icu.lang.UCharacter.UnicodeBlock DEVANAGARI; - field public static final android.icu.lang.UCharacter.UnicodeBlock DEVANAGARI_EXTENDED; - field public static final int DEVANAGARI_EXTENDED_ID = 179; // 0xb3 - field public static final int DEVANAGARI_ID = 15; // 0xf - field public static final android.icu.lang.UCharacter.UnicodeBlock DINGBATS; - field public static final int DINGBATS_ID = 56; // 0x38 - field public static final android.icu.lang.UCharacter.UnicodeBlock DIVES_AKURU; - field public static final int DIVES_AKURU_ID = 303; // 0x12f - field public static final android.icu.lang.UCharacter.UnicodeBlock DOGRA; - field public static final int DOGRA_ID = 282; // 0x11a - field public static final android.icu.lang.UCharacter.UnicodeBlock DOMINO_TILES; - field public static final int DOMINO_TILES_ID = 171; // 0xab - field public static final android.icu.lang.UCharacter.UnicodeBlock DUPLOYAN; - field public static final int DUPLOYAN_ID = 225; // 0xe1 - field public static final android.icu.lang.UCharacter.UnicodeBlock EARLY_DYNASTIC_CUNEIFORM; - field public static final int EARLY_DYNASTIC_CUNEIFORM_ID = 257; // 0x101 - field public static final android.icu.lang.UCharacter.UnicodeBlock EGYPTIAN_HIEROGLYPHS; - field public static final int EGYPTIAN_HIEROGLYPHS_ID = 194; // 0xc2 - field public static final android.icu.lang.UCharacter.UnicodeBlock EGYPTIAN_HIEROGLYPH_FORMAT_CONTROLS; - field public static final int EGYPTIAN_HIEROGLYPH_FORMAT_CONTROLS_ID = 292; // 0x124 - field public static final android.icu.lang.UCharacter.UnicodeBlock ELBASAN; - field public static final int ELBASAN_ID = 226; // 0xe2 - field public static final android.icu.lang.UCharacter.UnicodeBlock ELYMAIC; - field public static final int ELYMAIC_ID = 293; // 0x125 - field public static final android.icu.lang.UCharacter.UnicodeBlock EMOTICONS; - field public static final int EMOTICONS_ID = 206; // 0xce - field public static final android.icu.lang.UCharacter.UnicodeBlock ENCLOSED_ALPHANUMERICS; - field public static final int ENCLOSED_ALPHANUMERICS_ID = 51; // 0x33 - field public static final android.icu.lang.UCharacter.UnicodeBlock ENCLOSED_ALPHANUMERIC_SUPPLEMENT; - field public static final int ENCLOSED_ALPHANUMERIC_SUPPLEMENT_ID = 195; // 0xc3 - field public static final android.icu.lang.UCharacter.UnicodeBlock ENCLOSED_CJK_LETTERS_AND_MONTHS; - field public static final int ENCLOSED_CJK_LETTERS_AND_MONTHS_ID = 68; // 0x44 - field public static final android.icu.lang.UCharacter.UnicodeBlock ENCLOSED_IDEOGRAPHIC_SUPPLEMENT; - field public static final int ENCLOSED_IDEOGRAPHIC_SUPPLEMENT_ID = 196; // 0xc4 - field public static final android.icu.lang.UCharacter.UnicodeBlock ETHIOPIC; - field public static final android.icu.lang.UCharacter.UnicodeBlock ETHIOPIC_EXTENDED; - field public static final android.icu.lang.UCharacter.UnicodeBlock ETHIOPIC_EXTENDED_A; - field public static final int ETHIOPIC_EXTENDED_A_ID = 200; // 0xc8 - field public static final int ETHIOPIC_EXTENDED_ID = 133; // 0x85 - field public static final int ETHIOPIC_ID = 31; // 0x1f - field public static final android.icu.lang.UCharacter.UnicodeBlock ETHIOPIC_SUPPLEMENT; - field public static final int ETHIOPIC_SUPPLEMENT_ID = 134; // 0x86 - field public static final android.icu.lang.UCharacter.UnicodeBlock GENERAL_PUNCTUATION; - field public static final int GENERAL_PUNCTUATION_ID = 40; // 0x28 - field public static final android.icu.lang.UCharacter.UnicodeBlock GEOMETRIC_SHAPES; - field public static final android.icu.lang.UCharacter.UnicodeBlock GEOMETRIC_SHAPES_EXTENDED; - field public static final int GEOMETRIC_SHAPES_EXTENDED_ID = 227; // 0xe3 - field public static final int GEOMETRIC_SHAPES_ID = 54; // 0x36 - field public static final android.icu.lang.UCharacter.UnicodeBlock GEORGIAN; - field public static final android.icu.lang.UCharacter.UnicodeBlock GEORGIAN_EXTENDED; - field public static final int GEORGIAN_EXTENDED_ID = 283; // 0x11b - field public static final int GEORGIAN_ID = 29; // 0x1d - field public static final android.icu.lang.UCharacter.UnicodeBlock GEORGIAN_SUPPLEMENT; - field public static final int GEORGIAN_SUPPLEMENT_ID = 135; // 0x87 - field public static final android.icu.lang.UCharacter.UnicodeBlock GLAGOLITIC; - field public static final int GLAGOLITIC_ID = 136; // 0x88 - field public static final android.icu.lang.UCharacter.UnicodeBlock GLAGOLITIC_SUPPLEMENT; - field public static final int GLAGOLITIC_SUPPLEMENT_ID = 266; // 0x10a - field public static final android.icu.lang.UCharacter.UnicodeBlock GOTHIC; - field public static final int GOTHIC_ID = 89; // 0x59 - field public static final android.icu.lang.UCharacter.UnicodeBlock GRANTHA; - field public static final int GRANTHA_ID = 228; // 0xe4 - field public static final android.icu.lang.UCharacter.UnicodeBlock GREEK; - field public static final android.icu.lang.UCharacter.UnicodeBlock GREEK_EXTENDED; - field public static final int GREEK_EXTENDED_ID = 39; // 0x27 - field public static final int GREEK_ID = 8; // 0x8 - field public static final android.icu.lang.UCharacter.UnicodeBlock GUJARATI; - field public static final int GUJARATI_ID = 18; // 0x12 - field public static final android.icu.lang.UCharacter.UnicodeBlock GUNJALA_GONDI; - field public static final int GUNJALA_GONDI_ID = 284; // 0x11c - field public static final android.icu.lang.UCharacter.UnicodeBlock GURMUKHI; - field public static final int GURMUKHI_ID = 17; // 0x11 - field public static final android.icu.lang.UCharacter.UnicodeBlock HALFWIDTH_AND_FULLWIDTH_FORMS; - field public static final int HALFWIDTH_AND_FULLWIDTH_FORMS_ID = 87; // 0x57 - field public static final android.icu.lang.UCharacter.UnicodeBlock HANGUL_COMPATIBILITY_JAMO; - field public static final int HANGUL_COMPATIBILITY_JAMO_ID = 65; // 0x41 - field public static final android.icu.lang.UCharacter.UnicodeBlock HANGUL_JAMO; - field public static final android.icu.lang.UCharacter.UnicodeBlock HANGUL_JAMO_EXTENDED_A; - field public static final int HANGUL_JAMO_EXTENDED_A_ID = 180; // 0xb4 - field public static final android.icu.lang.UCharacter.UnicodeBlock HANGUL_JAMO_EXTENDED_B; - field public static final int HANGUL_JAMO_EXTENDED_B_ID = 185; // 0xb9 - field public static final int HANGUL_JAMO_ID = 30; // 0x1e - field public static final android.icu.lang.UCharacter.UnicodeBlock HANGUL_SYLLABLES; - field public static final int HANGUL_SYLLABLES_ID = 74; // 0x4a - field public static final android.icu.lang.UCharacter.UnicodeBlock HANIFI_ROHINGYA; - field public static final int HANIFI_ROHINGYA_ID = 285; // 0x11d - field public static final android.icu.lang.UCharacter.UnicodeBlock HANUNOO; - field public static final int HANUNOO_ID = 99; // 0x63 - field public static final android.icu.lang.UCharacter.UnicodeBlock HATRAN; - field public static final int HATRAN_ID = 258; // 0x102 - field public static final android.icu.lang.UCharacter.UnicodeBlock HEBREW; - field public static final int HEBREW_ID = 11; // 0xb - field public static final android.icu.lang.UCharacter.UnicodeBlock HIGH_PRIVATE_USE_SURROGATES; - field public static final int HIGH_PRIVATE_USE_SURROGATES_ID = 76; // 0x4c - field public static final android.icu.lang.UCharacter.UnicodeBlock HIGH_SURROGATES; - field public static final int HIGH_SURROGATES_ID = 75; // 0x4b - field public static final android.icu.lang.UCharacter.UnicodeBlock HIRAGANA; - field public static final int HIRAGANA_ID = 62; // 0x3e - field public static final android.icu.lang.UCharacter.UnicodeBlock IDEOGRAPHIC_DESCRIPTION_CHARACTERS; - field public static final int IDEOGRAPHIC_DESCRIPTION_CHARACTERS_ID = 60; // 0x3c - field public static final android.icu.lang.UCharacter.UnicodeBlock IDEOGRAPHIC_SYMBOLS_AND_PUNCTUATION; - field public static final int IDEOGRAPHIC_SYMBOLS_AND_PUNCTUATION_ID = 267; // 0x10b - field public static final android.icu.lang.UCharacter.UnicodeBlock IMPERIAL_ARAMAIC; - field public static final int IMPERIAL_ARAMAIC_ID = 186; // 0xba - field public static final android.icu.lang.UCharacter.UnicodeBlock INDIC_SIYAQ_NUMBERS; - field public static final int INDIC_SIYAQ_NUMBERS_ID = 286; // 0x11e - field public static final android.icu.lang.UCharacter.UnicodeBlock INSCRIPTIONAL_PAHLAVI; - field public static final int INSCRIPTIONAL_PAHLAVI_ID = 190; // 0xbe - field public static final android.icu.lang.UCharacter.UnicodeBlock INSCRIPTIONAL_PARTHIAN; - field public static final int INSCRIPTIONAL_PARTHIAN_ID = 189; // 0xbd - field public static final android.icu.lang.UCharacter.UnicodeBlock INVALID_CODE; - field public static final int INVALID_CODE_ID = -1; // 0xffffffff - field public static final android.icu.lang.UCharacter.UnicodeBlock IPA_EXTENSIONS; - field public static final int IPA_EXTENSIONS_ID = 5; // 0x5 - field public static final android.icu.lang.UCharacter.UnicodeBlock JAVANESE; - field public static final int JAVANESE_ID = 181; // 0xb5 - field public static final android.icu.lang.UCharacter.UnicodeBlock KAITHI; - field public static final int KAITHI_ID = 193; // 0xc1 - field public static final android.icu.lang.UCharacter.UnicodeBlock KANA_EXTENDED_A; - field public static final int KANA_EXTENDED_A_ID = 275; // 0x113 - field public static final android.icu.lang.UCharacter.UnicodeBlock KANA_SUPPLEMENT; - field public static final int KANA_SUPPLEMENT_ID = 203; // 0xcb - field public static final android.icu.lang.UCharacter.UnicodeBlock KANBUN; - field public static final int KANBUN_ID = 66; // 0x42 - field public static final android.icu.lang.UCharacter.UnicodeBlock KANGXI_RADICALS; - field public static final int KANGXI_RADICALS_ID = 59; // 0x3b - field public static final android.icu.lang.UCharacter.UnicodeBlock KANNADA; - field public static final int KANNADA_ID = 22; // 0x16 - field public static final android.icu.lang.UCharacter.UnicodeBlock KATAKANA; - field public static final int KATAKANA_ID = 63; // 0x3f - field public static final android.icu.lang.UCharacter.UnicodeBlock KATAKANA_PHONETIC_EXTENSIONS; - field public static final int KATAKANA_PHONETIC_EXTENSIONS_ID = 107; // 0x6b - field public static final android.icu.lang.UCharacter.UnicodeBlock KAYAH_LI; - field public static final int KAYAH_LI_ID = 162; // 0xa2 - field public static final android.icu.lang.UCharacter.UnicodeBlock KHAROSHTHI; - field public static final int KHAROSHTHI_ID = 137; // 0x89 - field public static final android.icu.lang.UCharacter.UnicodeBlock KHITAN_SMALL_SCRIPT; - field public static final int KHITAN_SMALL_SCRIPT_ID = 304; // 0x130 - field public static final android.icu.lang.UCharacter.UnicodeBlock KHMER; - field public static final int KHMER_ID = 36; // 0x24 - field public static final android.icu.lang.UCharacter.UnicodeBlock KHMER_SYMBOLS; - field public static final int KHMER_SYMBOLS_ID = 113; // 0x71 - field public static final android.icu.lang.UCharacter.UnicodeBlock KHOJKI; - field public static final int KHOJKI_ID = 229; // 0xe5 - field public static final android.icu.lang.UCharacter.UnicodeBlock KHUDAWADI; - field public static final int KHUDAWADI_ID = 230; // 0xe6 - field public static final android.icu.lang.UCharacter.UnicodeBlock LAO; - field public static final int LAO_ID = 26; // 0x1a - field public static final android.icu.lang.UCharacter.UnicodeBlock LATIN_1_SUPPLEMENT; - field public static final int LATIN_1_SUPPLEMENT_ID = 2; // 0x2 - field public static final android.icu.lang.UCharacter.UnicodeBlock LATIN_EXTENDED_A; - field public static final android.icu.lang.UCharacter.UnicodeBlock LATIN_EXTENDED_ADDITIONAL; - field public static final int LATIN_EXTENDED_ADDITIONAL_ID = 38; // 0x26 - field public static final int LATIN_EXTENDED_A_ID = 3; // 0x3 - field public static final android.icu.lang.UCharacter.UnicodeBlock LATIN_EXTENDED_B; - field public static final int LATIN_EXTENDED_B_ID = 4; // 0x4 - field public static final android.icu.lang.UCharacter.UnicodeBlock LATIN_EXTENDED_C; - field public static final int LATIN_EXTENDED_C_ID = 148; // 0x94 - field public static final android.icu.lang.UCharacter.UnicodeBlock LATIN_EXTENDED_D; - field public static final int LATIN_EXTENDED_D_ID = 149; // 0x95 - field public static final android.icu.lang.UCharacter.UnicodeBlock LATIN_EXTENDED_E; - field public static final int LATIN_EXTENDED_E_ID = 231; // 0xe7 - field public static final android.icu.lang.UCharacter.UnicodeBlock LEPCHA; - field public static final int LEPCHA_ID = 156; // 0x9c - field public static final android.icu.lang.UCharacter.UnicodeBlock LETTERLIKE_SYMBOLS; - field public static final int LETTERLIKE_SYMBOLS_ID = 44; // 0x2c - field public static final android.icu.lang.UCharacter.UnicodeBlock LIMBU; - field public static final int LIMBU_ID = 111; // 0x6f - field public static final android.icu.lang.UCharacter.UnicodeBlock LINEAR_A; - field public static final int LINEAR_A_ID = 232; // 0xe8 - field public static final android.icu.lang.UCharacter.UnicodeBlock LINEAR_B_IDEOGRAMS; - field public static final int LINEAR_B_IDEOGRAMS_ID = 118; // 0x76 - field public static final android.icu.lang.UCharacter.UnicodeBlock LINEAR_B_SYLLABARY; - field public static final int LINEAR_B_SYLLABARY_ID = 117; // 0x75 - field public static final android.icu.lang.UCharacter.UnicodeBlock LISU; - field public static final int LISU_ID = 176; // 0xb0 - field public static final android.icu.lang.UCharacter.UnicodeBlock LISU_SUPPLEMENT; - field public static final int LISU_SUPPLEMENT_ID = 305; // 0x131 - field public static final android.icu.lang.UCharacter.UnicodeBlock LOW_SURROGATES; - field public static final int LOW_SURROGATES_ID = 77; // 0x4d - field public static final android.icu.lang.UCharacter.UnicodeBlock LYCIAN; - field public static final int LYCIAN_ID = 167; // 0xa7 - field public static final android.icu.lang.UCharacter.UnicodeBlock LYDIAN; - field public static final int LYDIAN_ID = 169; // 0xa9 - field public static final android.icu.lang.UCharacter.UnicodeBlock MAHAJANI; - field public static final int MAHAJANI_ID = 233; // 0xe9 - field public static final android.icu.lang.UCharacter.UnicodeBlock MAHJONG_TILES; - field public static final int MAHJONG_TILES_ID = 170; // 0xaa - field public static final android.icu.lang.UCharacter.UnicodeBlock MAKASAR; - field public static final int MAKASAR_ID = 287; // 0x11f - field public static final android.icu.lang.UCharacter.UnicodeBlock MALAYALAM; - field public static final int MALAYALAM_ID = 23; // 0x17 - field public static final android.icu.lang.UCharacter.UnicodeBlock MANDAIC; - field public static final int MANDAIC_ID = 198; // 0xc6 - field public static final android.icu.lang.UCharacter.UnicodeBlock MANICHAEAN; - field public static final int MANICHAEAN_ID = 234; // 0xea - field public static final android.icu.lang.UCharacter.UnicodeBlock MARCHEN; - field public static final int MARCHEN_ID = 268; // 0x10c - field public static final android.icu.lang.UCharacter.UnicodeBlock MASARAM_GONDI; - field public static final int MASARAM_GONDI_ID = 276; // 0x114 - field public static final android.icu.lang.UCharacter.UnicodeBlock MATHEMATICAL_ALPHANUMERIC_SYMBOLS; - field public static final int MATHEMATICAL_ALPHANUMERIC_SYMBOLS_ID = 93; // 0x5d - field public static final android.icu.lang.UCharacter.UnicodeBlock MATHEMATICAL_OPERATORS; - field public static final int MATHEMATICAL_OPERATORS_ID = 47; // 0x2f - field public static final android.icu.lang.UCharacter.UnicodeBlock MAYAN_NUMERALS; - field public static final int MAYAN_NUMERALS_ID = 288; // 0x120 - field public static final android.icu.lang.UCharacter.UnicodeBlock MEDEFAIDRIN; - field public static final int MEDEFAIDRIN_ID = 289; // 0x121 - field public static final android.icu.lang.UCharacter.UnicodeBlock MEETEI_MAYEK; - field public static final android.icu.lang.UCharacter.UnicodeBlock MEETEI_MAYEK_EXTENSIONS; - field public static final int MEETEI_MAYEK_EXTENSIONS_ID = 213; // 0xd5 - field public static final int MEETEI_MAYEK_ID = 184; // 0xb8 - field public static final android.icu.lang.UCharacter.UnicodeBlock MENDE_KIKAKUI; - field public static final int MENDE_KIKAKUI_ID = 235; // 0xeb - field public static final android.icu.lang.UCharacter.UnicodeBlock MEROITIC_CURSIVE; - field public static final int MEROITIC_CURSIVE_ID = 214; // 0xd6 - field public static final android.icu.lang.UCharacter.UnicodeBlock MEROITIC_HIEROGLYPHS; - field public static final int MEROITIC_HIEROGLYPHS_ID = 215; // 0xd7 - field public static final android.icu.lang.UCharacter.UnicodeBlock MIAO; - field public static final int MIAO_ID = 216; // 0xd8 - field public static final android.icu.lang.UCharacter.UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A; - field public static final int MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A_ID = 102; // 0x66 - field public static final android.icu.lang.UCharacter.UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B; - field public static final int MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B_ID = 105; // 0x69 - field public static final android.icu.lang.UCharacter.UnicodeBlock MISCELLANEOUS_SYMBOLS; - field public static final android.icu.lang.UCharacter.UnicodeBlock MISCELLANEOUS_SYMBOLS_AND_ARROWS; - field public static final int MISCELLANEOUS_SYMBOLS_AND_ARROWS_ID = 115; // 0x73 - field public static final android.icu.lang.UCharacter.UnicodeBlock MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS; - field public static final int MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS_ID = 205; // 0xcd - field public static final int MISCELLANEOUS_SYMBOLS_ID = 55; // 0x37 - field public static final android.icu.lang.UCharacter.UnicodeBlock MISCELLANEOUS_TECHNICAL; - field public static final int MISCELLANEOUS_TECHNICAL_ID = 48; // 0x30 - field public static final android.icu.lang.UCharacter.UnicodeBlock MODI; - field public static final android.icu.lang.UCharacter.UnicodeBlock MODIFIER_TONE_LETTERS; - field public static final int MODIFIER_TONE_LETTERS_ID = 138; // 0x8a - field public static final int MODI_ID = 236; // 0xec - field public static final android.icu.lang.UCharacter.UnicodeBlock MONGOLIAN; - field public static final int MONGOLIAN_ID = 37; // 0x25 - field public static final android.icu.lang.UCharacter.UnicodeBlock MONGOLIAN_SUPPLEMENT; - field public static final int MONGOLIAN_SUPPLEMENT_ID = 269; // 0x10d - field public static final android.icu.lang.UCharacter.UnicodeBlock MRO; - field public static final int MRO_ID = 237; // 0xed - field public static final android.icu.lang.UCharacter.UnicodeBlock MULTANI; - field public static final int MULTANI_ID = 259; // 0x103 - field public static final android.icu.lang.UCharacter.UnicodeBlock MUSICAL_SYMBOLS; - field public static final int MUSICAL_SYMBOLS_ID = 92; // 0x5c - field public static final android.icu.lang.UCharacter.UnicodeBlock MYANMAR; - field public static final android.icu.lang.UCharacter.UnicodeBlock MYANMAR_EXTENDED_A; - field public static final int MYANMAR_EXTENDED_A_ID = 182; // 0xb6 - field public static final android.icu.lang.UCharacter.UnicodeBlock MYANMAR_EXTENDED_B; - field public static final int MYANMAR_EXTENDED_B_ID = 238; // 0xee - field public static final int MYANMAR_ID = 28; // 0x1c - field public static final android.icu.lang.UCharacter.UnicodeBlock NABATAEAN; - field public static final int NABATAEAN_ID = 239; // 0xef - field public static final android.icu.lang.UCharacter.UnicodeBlock NANDINAGARI; - field public static final int NANDINAGARI_ID = 294; // 0x126 - field public static final android.icu.lang.UCharacter.UnicodeBlock NEWA; - field public static final int NEWA_ID = 270; // 0x10e - field public static final android.icu.lang.UCharacter.UnicodeBlock NEW_TAI_LUE; - field public static final int NEW_TAI_LUE_ID = 139; // 0x8b - field public static final android.icu.lang.UCharacter.UnicodeBlock NKO; - field public static final int NKO_ID = 146; // 0x92 - field public static final android.icu.lang.UCharacter.UnicodeBlock NO_BLOCK; - field public static final android.icu.lang.UCharacter.UnicodeBlock NUMBER_FORMS; - field public static final int NUMBER_FORMS_ID = 45; // 0x2d - field public static final android.icu.lang.UCharacter.UnicodeBlock NUSHU; - field public static final int NUSHU_ID = 277; // 0x115 - field public static final android.icu.lang.UCharacter.UnicodeBlock NYIAKENG_PUACHUE_HMONG; - field public static final int NYIAKENG_PUACHUE_HMONG_ID = 295; // 0x127 - field public static final android.icu.lang.UCharacter.UnicodeBlock OGHAM; - field public static final int OGHAM_ID = 34; // 0x22 - field public static final android.icu.lang.UCharacter.UnicodeBlock OLD_HUNGARIAN; - field public static final int OLD_HUNGARIAN_ID = 260; // 0x104 - field public static final android.icu.lang.UCharacter.UnicodeBlock OLD_ITALIC; - field public static final int OLD_ITALIC_ID = 88; // 0x58 - field public static final android.icu.lang.UCharacter.UnicodeBlock OLD_NORTH_ARABIAN; - field public static final int OLD_NORTH_ARABIAN_ID = 240; // 0xf0 - field public static final android.icu.lang.UCharacter.UnicodeBlock OLD_PERMIC; - field public static final int OLD_PERMIC_ID = 241; // 0xf1 - field public static final android.icu.lang.UCharacter.UnicodeBlock OLD_PERSIAN; - field public static final int OLD_PERSIAN_ID = 140; // 0x8c - field public static final android.icu.lang.UCharacter.UnicodeBlock OLD_SOGDIAN; - field public static final int OLD_SOGDIAN_ID = 290; // 0x122 - field public static final android.icu.lang.UCharacter.UnicodeBlock OLD_SOUTH_ARABIAN; - field public static final int OLD_SOUTH_ARABIAN_ID = 187; // 0xbb - field public static final android.icu.lang.UCharacter.UnicodeBlock OLD_TURKIC; - field public static final int OLD_TURKIC_ID = 191; // 0xbf - field public static final android.icu.lang.UCharacter.UnicodeBlock OL_CHIKI; - field public static final int OL_CHIKI_ID = 157; // 0x9d - field public static final android.icu.lang.UCharacter.UnicodeBlock OPTICAL_CHARACTER_RECOGNITION; - field public static final int OPTICAL_CHARACTER_RECOGNITION_ID = 50; // 0x32 - field public static final android.icu.lang.UCharacter.UnicodeBlock ORIYA; - field public static final int ORIYA_ID = 19; // 0x13 - field public static final android.icu.lang.UCharacter.UnicodeBlock ORNAMENTAL_DINGBATS; - field public static final int ORNAMENTAL_DINGBATS_ID = 242; // 0xf2 - field public static final android.icu.lang.UCharacter.UnicodeBlock OSAGE; - field public static final int OSAGE_ID = 271; // 0x10f - field public static final android.icu.lang.UCharacter.UnicodeBlock OSMANYA; - field public static final int OSMANYA_ID = 122; // 0x7a - field public static final android.icu.lang.UCharacter.UnicodeBlock OTTOMAN_SIYAQ_NUMBERS; - field public static final int OTTOMAN_SIYAQ_NUMBERS_ID = 296; // 0x128 - field public static final android.icu.lang.UCharacter.UnicodeBlock PAHAWH_HMONG; - field public static final int PAHAWH_HMONG_ID = 243; // 0xf3 - field public static final android.icu.lang.UCharacter.UnicodeBlock PALMYRENE; - field public static final int PALMYRENE_ID = 244; // 0xf4 - field public static final android.icu.lang.UCharacter.UnicodeBlock PAU_CIN_HAU; - field public static final int PAU_CIN_HAU_ID = 245; // 0xf5 - field public static final android.icu.lang.UCharacter.UnicodeBlock PHAGS_PA; - field public static final int PHAGS_PA_ID = 150; // 0x96 - field public static final android.icu.lang.UCharacter.UnicodeBlock PHAISTOS_DISC; - field public static final int PHAISTOS_DISC_ID = 166; // 0xa6 - field public static final android.icu.lang.UCharacter.UnicodeBlock PHOENICIAN; - field public static final int PHOENICIAN_ID = 151; // 0x97 - field public static final android.icu.lang.UCharacter.UnicodeBlock PHONETIC_EXTENSIONS; - field public static final int PHONETIC_EXTENSIONS_ID = 114; // 0x72 - field public static final android.icu.lang.UCharacter.UnicodeBlock PHONETIC_EXTENSIONS_SUPPLEMENT; - field public static final int PHONETIC_EXTENSIONS_SUPPLEMENT_ID = 141; // 0x8d - field public static final android.icu.lang.UCharacter.UnicodeBlock PLAYING_CARDS; - field public static final int PLAYING_CARDS_ID = 204; // 0xcc - field public static final android.icu.lang.UCharacter.UnicodeBlock PRIVATE_USE; - field public static final android.icu.lang.UCharacter.UnicodeBlock PRIVATE_USE_AREA; - field public static final int PRIVATE_USE_AREA_ID = 78; // 0x4e - field public static final int PRIVATE_USE_ID = 78; // 0x4e - field public static final android.icu.lang.UCharacter.UnicodeBlock PSALTER_PAHLAVI; - field public static final int PSALTER_PAHLAVI_ID = 246; // 0xf6 - field public static final android.icu.lang.UCharacter.UnicodeBlock REJANG; - field public static final int REJANG_ID = 163; // 0xa3 - field public static final android.icu.lang.UCharacter.UnicodeBlock RUMI_NUMERAL_SYMBOLS; - field public static final int RUMI_NUMERAL_SYMBOLS_ID = 192; // 0xc0 - field public static final android.icu.lang.UCharacter.UnicodeBlock RUNIC; - field public static final int RUNIC_ID = 35; // 0x23 - field public static final android.icu.lang.UCharacter.UnicodeBlock SAMARITAN; - field public static final int SAMARITAN_ID = 172; // 0xac - field public static final android.icu.lang.UCharacter.UnicodeBlock SAURASHTRA; - field public static final int SAURASHTRA_ID = 161; // 0xa1 - field public static final android.icu.lang.UCharacter.UnicodeBlock SHARADA; - field public static final int SHARADA_ID = 217; // 0xd9 - field public static final android.icu.lang.UCharacter.UnicodeBlock SHAVIAN; - field public static final int SHAVIAN_ID = 121; // 0x79 - field public static final android.icu.lang.UCharacter.UnicodeBlock SHORTHAND_FORMAT_CONTROLS; - field public static final int SHORTHAND_FORMAT_CONTROLS_ID = 247; // 0xf7 - field public static final android.icu.lang.UCharacter.UnicodeBlock SIDDHAM; - field public static final int SIDDHAM_ID = 248; // 0xf8 - field public static final android.icu.lang.UCharacter.UnicodeBlock SINHALA; - field public static final android.icu.lang.UCharacter.UnicodeBlock SINHALA_ARCHAIC_NUMBERS; - field public static final int SINHALA_ARCHAIC_NUMBERS_ID = 249; // 0xf9 - field public static final int SINHALA_ID = 24; // 0x18 - field public static final android.icu.lang.UCharacter.UnicodeBlock SMALL_FORM_VARIANTS; - field public static final int SMALL_FORM_VARIANTS_ID = 84; // 0x54 - field public static final android.icu.lang.UCharacter.UnicodeBlock SMALL_KANA_EXTENSION; - field public static final int SMALL_KANA_EXTENSION_ID = 297; // 0x129 - field public static final android.icu.lang.UCharacter.UnicodeBlock SOGDIAN; - field public static final int SOGDIAN_ID = 291; // 0x123 - field public static final android.icu.lang.UCharacter.UnicodeBlock SORA_SOMPENG; - field public static final int SORA_SOMPENG_ID = 218; // 0xda - field public static final android.icu.lang.UCharacter.UnicodeBlock SOYOMBO; - field public static final int SOYOMBO_ID = 278; // 0x116 - field public static final android.icu.lang.UCharacter.UnicodeBlock SPACING_MODIFIER_LETTERS; - field public static final int SPACING_MODIFIER_LETTERS_ID = 6; // 0x6 - field public static final android.icu.lang.UCharacter.UnicodeBlock SPECIALS; - field public static final int SPECIALS_ID = 86; // 0x56 - field public static final android.icu.lang.UCharacter.UnicodeBlock SUNDANESE; - field public static final int SUNDANESE_ID = 155; // 0x9b - field public static final android.icu.lang.UCharacter.UnicodeBlock SUNDANESE_SUPPLEMENT; - field public static final int SUNDANESE_SUPPLEMENT_ID = 219; // 0xdb - field public static final android.icu.lang.UCharacter.UnicodeBlock SUPERSCRIPTS_AND_SUBSCRIPTS; - field public static final int SUPERSCRIPTS_AND_SUBSCRIPTS_ID = 41; // 0x29 - field public static final android.icu.lang.UCharacter.UnicodeBlock SUPPLEMENTAL_ARROWS_A; - field public static final int SUPPLEMENTAL_ARROWS_A_ID = 103; // 0x67 - field public static final android.icu.lang.UCharacter.UnicodeBlock SUPPLEMENTAL_ARROWS_B; - field public static final int SUPPLEMENTAL_ARROWS_B_ID = 104; // 0x68 - field public static final android.icu.lang.UCharacter.UnicodeBlock SUPPLEMENTAL_ARROWS_C; - field public static final int SUPPLEMENTAL_ARROWS_C_ID = 250; // 0xfa - field public static final android.icu.lang.UCharacter.UnicodeBlock SUPPLEMENTAL_MATHEMATICAL_OPERATORS; - field public static final int SUPPLEMENTAL_MATHEMATICAL_OPERATORS_ID = 106; // 0x6a - field public static final android.icu.lang.UCharacter.UnicodeBlock SUPPLEMENTAL_PUNCTUATION; - field public static final int SUPPLEMENTAL_PUNCTUATION_ID = 142; // 0x8e - field public static final android.icu.lang.UCharacter.UnicodeBlock SUPPLEMENTAL_SYMBOLS_AND_PICTOGRAPHS; - field public static final int SUPPLEMENTAL_SYMBOLS_AND_PICTOGRAPHS_ID = 261; // 0x105 - field public static final android.icu.lang.UCharacter.UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_A; - field public static final int SUPPLEMENTARY_PRIVATE_USE_AREA_A_ID = 109; // 0x6d - field public static final android.icu.lang.UCharacter.UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_B; - field public static final int SUPPLEMENTARY_PRIVATE_USE_AREA_B_ID = 110; // 0x6e - field public static final android.icu.lang.UCharacter.UnicodeBlock SUTTON_SIGNWRITING; - field public static final int SUTTON_SIGNWRITING_ID = 262; // 0x106 - field public static final android.icu.lang.UCharacter.UnicodeBlock SYLOTI_NAGRI; - field public static final int SYLOTI_NAGRI_ID = 143; // 0x8f - field public static final android.icu.lang.UCharacter.UnicodeBlock SYMBOLS_AND_PICTOGRAPHS_EXTENDED_A; - field public static final int SYMBOLS_AND_PICTOGRAPHS_EXTENDED_A_ID = 298; // 0x12a - field public static final android.icu.lang.UCharacter.UnicodeBlock SYMBOLS_FOR_LEGACY_COMPUTING; - field public static final int SYMBOLS_FOR_LEGACY_COMPUTING_ID = 306; // 0x132 - field public static final android.icu.lang.UCharacter.UnicodeBlock SYRIAC; - field public static final int SYRIAC_ID = 13; // 0xd - field public static final android.icu.lang.UCharacter.UnicodeBlock SYRIAC_SUPPLEMENT; - field public static final int SYRIAC_SUPPLEMENT_ID = 279; // 0x117 - field public static final android.icu.lang.UCharacter.UnicodeBlock TAGALOG; - field public static final int TAGALOG_ID = 98; // 0x62 - field public static final android.icu.lang.UCharacter.UnicodeBlock TAGBANWA; - field public static final int TAGBANWA_ID = 101; // 0x65 - field public static final android.icu.lang.UCharacter.UnicodeBlock TAGS; - field public static final int TAGS_ID = 96; // 0x60 - field public static final android.icu.lang.UCharacter.UnicodeBlock TAI_LE; - field public static final int TAI_LE_ID = 112; // 0x70 - field public static final android.icu.lang.UCharacter.UnicodeBlock TAI_THAM; - field public static final int TAI_THAM_ID = 174; // 0xae - field public static final android.icu.lang.UCharacter.UnicodeBlock TAI_VIET; - field public static final int TAI_VIET_ID = 183; // 0xb7 - field public static final android.icu.lang.UCharacter.UnicodeBlock TAI_XUAN_JING_SYMBOLS; - field public static final int TAI_XUAN_JING_SYMBOLS_ID = 124; // 0x7c - field public static final android.icu.lang.UCharacter.UnicodeBlock TAKRI; - field public static final int TAKRI_ID = 220; // 0xdc - field public static final android.icu.lang.UCharacter.UnicodeBlock TAMIL; - field public static final int TAMIL_ID = 20; // 0x14 - field public static final android.icu.lang.UCharacter.UnicodeBlock TAMIL_SUPPLEMENT; - field public static final int TAMIL_SUPPLEMENT_ID = 299; // 0x12b - field public static final android.icu.lang.UCharacter.UnicodeBlock TANGUT; - field public static final android.icu.lang.UCharacter.UnicodeBlock TANGUT_COMPONENTS; - field public static final int TANGUT_COMPONENTS_ID = 273; // 0x111 - field public static final int TANGUT_ID = 272; // 0x110 - field public static final android.icu.lang.UCharacter.UnicodeBlock TANGUT_SUPPLEMENT; - field public static final int TANGUT_SUPPLEMENT_ID = 307; // 0x133 - field public static final android.icu.lang.UCharacter.UnicodeBlock TELUGU; - field public static final int TELUGU_ID = 21; // 0x15 - field public static final android.icu.lang.UCharacter.UnicodeBlock THAANA; - field public static final int THAANA_ID = 14; // 0xe - field public static final android.icu.lang.UCharacter.UnicodeBlock THAI; - field public static final int THAI_ID = 25; // 0x19 - field public static final android.icu.lang.UCharacter.UnicodeBlock TIBETAN; - field public static final int TIBETAN_ID = 27; // 0x1b - field public static final android.icu.lang.UCharacter.UnicodeBlock TIFINAGH; - field public static final int TIFINAGH_ID = 144; // 0x90 - field public static final android.icu.lang.UCharacter.UnicodeBlock TIRHUTA; - field public static final int TIRHUTA_ID = 251; // 0xfb - field public static final android.icu.lang.UCharacter.UnicodeBlock TRANSPORT_AND_MAP_SYMBOLS; - field public static final int TRANSPORT_AND_MAP_SYMBOLS_ID = 207; // 0xcf - field public static final android.icu.lang.UCharacter.UnicodeBlock UGARITIC; - field public static final int UGARITIC_ID = 120; // 0x78 - field public static final android.icu.lang.UCharacter.UnicodeBlock UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS; - field public static final android.icu.lang.UCharacter.UnicodeBlock UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED; - field public static final int UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED_ID = 173; // 0xad - field public static final int UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_ID = 33; // 0x21 - field public static final android.icu.lang.UCharacter.UnicodeBlock VAI; - field public static final int VAI_ID = 159; // 0x9f - field public static final android.icu.lang.UCharacter.UnicodeBlock VARIATION_SELECTORS; - field public static final int VARIATION_SELECTORS_ID = 108; // 0x6c - field public static final android.icu.lang.UCharacter.UnicodeBlock VARIATION_SELECTORS_SUPPLEMENT; - field public static final int VARIATION_SELECTORS_SUPPLEMENT_ID = 125; // 0x7d - field public static final android.icu.lang.UCharacter.UnicodeBlock VEDIC_EXTENSIONS; - field public static final int VEDIC_EXTENSIONS_ID = 175; // 0xaf - field public static final android.icu.lang.UCharacter.UnicodeBlock VERTICAL_FORMS; - field public static final int VERTICAL_FORMS_ID = 145; // 0x91 - field public static final android.icu.lang.UCharacter.UnicodeBlock WANCHO; - field public static final int WANCHO_ID = 300; // 0x12c - field public static final android.icu.lang.UCharacter.UnicodeBlock WARANG_CITI; - field public static final int WARANG_CITI_ID = 252; // 0xfc - field public static final android.icu.lang.UCharacter.UnicodeBlock YEZIDI; - field public static final int YEZIDI_ID = 308; // 0x134 - field public static final android.icu.lang.UCharacter.UnicodeBlock YIJING_HEXAGRAM_SYMBOLS; - field public static final int YIJING_HEXAGRAM_SYMBOLS_ID = 116; // 0x74 - field public static final android.icu.lang.UCharacter.UnicodeBlock YI_RADICALS; - field public static final int YI_RADICALS_ID = 73; // 0x49 - field public static final android.icu.lang.UCharacter.UnicodeBlock YI_SYLLABLES; - field public static final int YI_SYLLABLES_ID = 72; // 0x48 - field public static final android.icu.lang.UCharacter.UnicodeBlock ZANABAZAR_SQUARE; - field public static final int ZANABAZAR_SQUARE_ID = 280; // 0x118 - } - - public static interface UCharacter.VerticalOrientation { - field public static final int ROTATED = 0; // 0x0 - field public static final int TRANSFORMED_ROTATED = 1; // 0x1 - field public static final int TRANSFORMED_UPRIGHT = 2; // 0x2 - field public static final int UPRIGHT = 3; // 0x3 - } - - public static interface UCharacter.WordBreak { - field public static final int ALETTER = 1; // 0x1 - field public static final int CR = 8; // 0x8 - field public static final int DOUBLE_QUOTE = 16; // 0x10 - field public static final int EXTEND = 9; // 0x9 - field public static final int EXTENDNUMLET = 7; // 0x7 - field public static final int E_BASE = 17; // 0x11 - field public static final int E_BASE_GAZ = 18; // 0x12 - field public static final int E_MODIFIER = 19; // 0x13 - field public static final int FORMAT = 2; // 0x2 - field public static final int GLUE_AFTER_ZWJ = 20; // 0x14 - field public static final int HEBREW_LETTER = 14; // 0xe - field public static final int KATAKANA = 3; // 0x3 - field public static final int LF = 10; // 0xa - field public static final int MIDLETTER = 4; // 0x4 - field public static final int MIDNUM = 5; // 0x5 - field public static final int MIDNUMLET = 11; // 0xb - field public static final int NEWLINE = 12; // 0xc - field public static final int NUMERIC = 6; // 0x6 - field public static final int OTHER = 0; // 0x0 - field public static final int REGIONAL_INDICATOR = 13; // 0xd - field public static final int SINGLE_QUOTE = 15; // 0xf - field public static final int WSEGSPACE = 22; // 0x16 - field public static final int ZWJ = 21; // 0x15 - } - - public final class UCharacterCategory implements android.icu.lang.UCharacterEnums.ECharacterCategory { - method public static String toString(int); - } - - public final class UCharacterDirection implements android.icu.lang.UCharacterEnums.ECharacterDirection { - method public static String toString(int); - } - - public class UCharacterEnums { - } - - public static interface UCharacterEnums.ECharacterCategory { - field public static final byte COMBINING_SPACING_MARK = 8; // 0x8 - field public static final byte CONNECTOR_PUNCTUATION = 22; // 0x16 - field public static final byte CONTROL = 15; // 0xf - field public static final byte CURRENCY_SYMBOL = 25; // 0x19 - field public static final byte DASH_PUNCTUATION = 19; // 0x13 - field public static final byte DECIMAL_DIGIT_NUMBER = 9; // 0x9 - field public static final byte ENCLOSING_MARK = 7; // 0x7 - field public static final byte END_PUNCTUATION = 21; // 0x15 - field public static final byte FINAL_PUNCTUATION = 29; // 0x1d - field public static final byte FINAL_QUOTE_PUNCTUATION = 29; // 0x1d - field public static final byte FORMAT = 16; // 0x10 - field public static final byte GENERAL_OTHER_TYPES = 0; // 0x0 - field public static final byte INITIAL_PUNCTUATION = 28; // 0x1c - field public static final byte INITIAL_QUOTE_PUNCTUATION = 28; // 0x1c - field public static final byte LETTER_NUMBER = 10; // 0xa - field public static final byte LINE_SEPARATOR = 13; // 0xd - field public static final byte LOWERCASE_LETTER = 2; // 0x2 - field public static final byte MATH_SYMBOL = 24; // 0x18 - field public static final byte MODIFIER_LETTER = 4; // 0x4 - field public static final byte MODIFIER_SYMBOL = 26; // 0x1a - field public static final byte NON_SPACING_MARK = 6; // 0x6 - field public static final byte OTHER_LETTER = 5; // 0x5 - field public static final byte OTHER_NUMBER = 11; // 0xb - field public static final byte OTHER_PUNCTUATION = 23; // 0x17 - field public static final byte OTHER_SYMBOL = 27; // 0x1b - field public static final byte PARAGRAPH_SEPARATOR = 14; // 0xe - field public static final byte PRIVATE_USE = 17; // 0x11 - field public static final byte SPACE_SEPARATOR = 12; // 0xc - field public static final byte START_PUNCTUATION = 20; // 0x14 - field public static final byte SURROGATE = 18; // 0x12 - field public static final byte TITLECASE_LETTER = 3; // 0x3 - field public static final byte UNASSIGNED = 0; // 0x0 - field public static final byte UPPERCASE_LETTER = 1; // 0x1 - } - - public static interface UCharacterEnums.ECharacterDirection { - field public static final int ARABIC_NUMBER = 5; // 0x5 - field public static final int BLOCK_SEPARATOR = 7; // 0x7 - field public static final int BOUNDARY_NEUTRAL = 18; // 0x12 - field public static final int COMMON_NUMBER_SEPARATOR = 6; // 0x6 - field public static final byte DIRECTIONALITY_ARABIC_NUMBER = 5; // 0x5 - field public static final byte DIRECTIONALITY_BOUNDARY_NEUTRAL = 18; // 0x12 - field public static final byte DIRECTIONALITY_COMMON_NUMBER_SEPARATOR = 6; // 0x6 - field public static final byte DIRECTIONALITY_EUROPEAN_NUMBER = 2; // 0x2 - field public static final byte DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR = 3; // 0x3 - field public static final byte DIRECTIONALITY_EUROPEAN_NUMBER_TERMINATOR = 4; // 0x4 - field public static final byte DIRECTIONALITY_LEFT_TO_RIGHT = 0; // 0x0 - field public static final byte DIRECTIONALITY_LEFT_TO_RIGHT_EMBEDDING = 11; // 0xb - field public static final byte DIRECTIONALITY_LEFT_TO_RIGHT_OVERRIDE = 12; // 0xc - field public static final byte DIRECTIONALITY_NONSPACING_MARK = 17; // 0x11 - field public static final byte DIRECTIONALITY_OTHER_NEUTRALS = 10; // 0xa - field public static final byte DIRECTIONALITY_PARAGRAPH_SEPARATOR = 7; // 0x7 - field public static final byte DIRECTIONALITY_POP_DIRECTIONAL_FORMAT = 16; // 0x10 - field public static final byte DIRECTIONALITY_RIGHT_TO_LEFT = 1; // 0x1 - field public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC = 13; // 0xd - field public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING = 14; // 0xe - field public static final byte DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE = 15; // 0xf - field public static final byte DIRECTIONALITY_SEGMENT_SEPARATOR = 8; // 0x8 - field public static final byte DIRECTIONALITY_UNDEFINED = -1; // 0xffffffff - field public static final byte DIRECTIONALITY_WHITESPACE = 9; // 0x9 - field public static final int DIR_NON_SPACING_MARK = 17; // 0x11 - field public static final int EUROPEAN_NUMBER = 2; // 0x2 - field public static final int EUROPEAN_NUMBER_SEPARATOR = 3; // 0x3 - field public static final int EUROPEAN_NUMBER_TERMINATOR = 4; // 0x4 - field public static final byte FIRST_STRONG_ISOLATE = 19; // 0x13 - field public static final int LEFT_TO_RIGHT = 0; // 0x0 - field public static final int LEFT_TO_RIGHT_EMBEDDING = 11; // 0xb - field public static final byte LEFT_TO_RIGHT_ISOLATE = 20; // 0x14 - field public static final int LEFT_TO_RIGHT_OVERRIDE = 12; // 0xc - field public static final int OTHER_NEUTRAL = 10; // 0xa - field public static final int POP_DIRECTIONAL_FORMAT = 16; // 0x10 - field public static final byte POP_DIRECTIONAL_ISOLATE = 22; // 0x16 - field public static final int RIGHT_TO_LEFT = 1; // 0x1 - field public static final int RIGHT_TO_LEFT_ARABIC = 13; // 0xd - field public static final int RIGHT_TO_LEFT_EMBEDDING = 14; // 0xe - field public static final byte RIGHT_TO_LEFT_ISOLATE = 21; // 0x15 - field public static final int RIGHT_TO_LEFT_OVERRIDE = 15; // 0xf - field public static final int SEGMENT_SEPARATOR = 8; // 0x8 - field public static final int WHITE_SPACE_NEUTRAL = 9; // 0x9 - } - - public interface UProperty { - field public static final int AGE = 16384; // 0x4000 - field public static final int ALPHABETIC = 0; // 0x0 - field public static final int ASCII_HEX_DIGIT = 1; // 0x1 - field public static final int BIDI_CLASS = 4096; // 0x1000 - field public static final int BIDI_CONTROL = 2; // 0x2 - field public static final int BIDI_MIRRORED = 3; // 0x3 - field public static final int BIDI_MIRRORING_GLYPH = 16385; // 0x4001 - field public static final int BIDI_PAIRED_BRACKET = 16397; // 0x400d - field public static final int BIDI_PAIRED_BRACKET_TYPE = 4117; // 0x1015 - field public static final int BINARY_START = 0; // 0x0 - field public static final int BLOCK = 4097; // 0x1001 - field public static final int CANONICAL_COMBINING_CLASS = 4098; // 0x1002 - field public static final int CASED = 49; // 0x31 - field public static final int CASE_FOLDING = 16386; // 0x4002 - field public static final int CASE_IGNORABLE = 50; // 0x32 - field public static final int CASE_SENSITIVE = 34; // 0x22 - field public static final int CHANGES_WHEN_CASEFOLDED = 54; // 0x36 - field public static final int CHANGES_WHEN_CASEMAPPED = 55; // 0x37 - field public static final int CHANGES_WHEN_LOWERCASED = 51; // 0x33 - field public static final int CHANGES_WHEN_NFKC_CASEFOLDED = 56; // 0x38 - field public static final int CHANGES_WHEN_TITLECASED = 53; // 0x35 - field public static final int CHANGES_WHEN_UPPERCASED = 52; // 0x34 - field public static final int DASH = 4; // 0x4 - field public static final int DECOMPOSITION_TYPE = 4099; // 0x1003 - field public static final int DEFAULT_IGNORABLE_CODE_POINT = 5; // 0x5 - field public static final int DEPRECATED = 6; // 0x6 - field public static final int DIACRITIC = 7; // 0x7 - field public static final int DOUBLE_START = 12288; // 0x3000 - field public static final int EAST_ASIAN_WIDTH = 4100; // 0x1004 - field public static final int EMOJI = 57; // 0x39 - field public static final int EMOJI_COMPONENT = 61; // 0x3d - field public static final int EMOJI_MODIFIER = 59; // 0x3b - field public static final int EMOJI_MODIFIER_BASE = 60; // 0x3c - field public static final int EMOJI_PRESENTATION = 58; // 0x3a - field public static final int EXTENDED_PICTOGRAPHIC = 64; // 0x40 - field public static final int EXTENDER = 8; // 0x8 - field public static final int FULL_COMPOSITION_EXCLUSION = 9; // 0x9 - field public static final int GENERAL_CATEGORY = 4101; // 0x1005 - field public static final int GENERAL_CATEGORY_MASK = 8192; // 0x2000 - field public static final int GRAPHEME_BASE = 10; // 0xa - field public static final int GRAPHEME_CLUSTER_BREAK = 4114; // 0x1012 - field public static final int GRAPHEME_EXTEND = 11; // 0xb - field public static final int GRAPHEME_LINK = 12; // 0xc - field public static final int HANGUL_SYLLABLE_TYPE = 4107; // 0x100b - field public static final int HEX_DIGIT = 13; // 0xd - field public static final int HYPHEN = 14; // 0xe - field public static final int IDEOGRAPHIC = 17; // 0x11 - field public static final int IDS_BINARY_OPERATOR = 18; // 0x12 - field public static final int IDS_TRINARY_OPERATOR = 19; // 0x13 - field public static final int ID_CONTINUE = 15; // 0xf - field public static final int ID_START = 16; // 0x10 - field public static final int INDIC_POSITIONAL_CATEGORY = 4118; // 0x1016 - field public static final int INDIC_SYLLABIC_CATEGORY = 4119; // 0x1017 - field public static final int INT_START = 4096; // 0x1000 - field public static final int JOINING_GROUP = 4102; // 0x1006 - field public static final int JOINING_TYPE = 4103; // 0x1007 - field public static final int JOIN_CONTROL = 20; // 0x14 - field public static final int LEAD_CANONICAL_COMBINING_CLASS = 4112; // 0x1010 - field public static final int LINE_BREAK = 4104; // 0x1008 - field public static final int LOGICAL_ORDER_EXCEPTION = 21; // 0x15 - field public static final int LOWERCASE = 22; // 0x16 - field public static final int LOWERCASE_MAPPING = 16388; // 0x4004 - field public static final int MASK_START = 8192; // 0x2000 - field public static final int MATH = 23; // 0x17 - field public static final int NAME = 16389; // 0x4005 - field public static final int NFC_INERT = 39; // 0x27 - field public static final int NFC_QUICK_CHECK = 4110; // 0x100e - field public static final int NFD_INERT = 37; // 0x25 - field public static final int NFD_QUICK_CHECK = 4108; // 0x100c - field public static final int NFKC_INERT = 40; // 0x28 - field public static final int NFKC_QUICK_CHECK = 4111; // 0x100f - field public static final int NFKD_INERT = 38; // 0x26 - field public static final int NFKD_QUICK_CHECK = 4109; // 0x100d - field public static final int NONCHARACTER_CODE_POINT = 24; // 0x18 - field public static final int NUMERIC_TYPE = 4105; // 0x1009 - field public static final int NUMERIC_VALUE = 12288; // 0x3000 - field public static final int OTHER_PROPERTY_START = 28672; // 0x7000 - field public static final int PATTERN_SYNTAX = 42; // 0x2a - field public static final int PATTERN_WHITE_SPACE = 43; // 0x2b - field public static final int POSIX_ALNUM = 44; // 0x2c - field public static final int POSIX_BLANK = 45; // 0x2d - field public static final int POSIX_GRAPH = 46; // 0x2e - field public static final int POSIX_PRINT = 47; // 0x2f - field public static final int POSIX_XDIGIT = 48; // 0x30 - field public static final int PREPENDED_CONCATENATION_MARK = 63; // 0x3f - field public static final int QUOTATION_MARK = 25; // 0x19 - field public static final int RADICAL = 26; // 0x1a - field public static final int REGIONAL_INDICATOR = 62; // 0x3e - field public static final int SCRIPT = 4106; // 0x100a - field public static final int SCRIPT_EXTENSIONS = 28672; // 0x7000 - field public static final int SEGMENT_STARTER = 41; // 0x29 - field public static final int SENTENCE_BREAK = 4115; // 0x1013 - field public static final int SIMPLE_CASE_FOLDING = 16390; // 0x4006 - field public static final int SIMPLE_LOWERCASE_MAPPING = 16391; // 0x4007 - field public static final int SIMPLE_TITLECASE_MAPPING = 16392; // 0x4008 - field public static final int SIMPLE_UPPERCASE_MAPPING = 16393; // 0x4009 - field public static final int SOFT_DOTTED = 27; // 0x1b - field public static final int STRING_START = 16384; // 0x4000 - field public static final int S_TERM = 35; // 0x23 - field public static final int TERMINAL_PUNCTUATION = 28; // 0x1c - field public static final int TITLECASE_MAPPING = 16394; // 0x400a - field public static final int TRAIL_CANONICAL_COMBINING_CLASS = 4113; // 0x1011 - field public static final int UNIFIED_IDEOGRAPH = 29; // 0x1d - field public static final int UPPERCASE = 30; // 0x1e - field public static final int UPPERCASE_MAPPING = 16396; // 0x400c - field public static final int VARIATION_SELECTOR = 36; // 0x24 - field public static final int VERTICAL_ORIENTATION = 4120; // 0x1018 - field public static final int WHITE_SPACE = 31; // 0x1f - field public static final int WORD_BREAK = 4116; // 0x1014 - field public static final int XID_CONTINUE = 32; // 0x20 - field public static final int XID_START = 33; // 0x21 - } - - public static interface UProperty.NameChoice { - field public static final int LONG = 1; // 0x1 - field public static final int SHORT = 0; // 0x0 - } - - public final class UScript { - method public static boolean breaksBetweenLetters(int); - method public static int[] getCode(java.util.Locale); - method public static int[] getCode(android.icu.util.ULocale); - method public static int[] getCode(String); - method public static int getCodeFromName(String); - method public static String getName(int); - method public static String getSampleString(int); - method public static int getScript(int); - method public static int getScriptExtensions(int, java.util.BitSet); - method public static String getShortName(int); - method public static android.icu.lang.UScript.ScriptUsage getUsage(int); - method public static boolean hasScript(int, int); - method public static boolean isCased(int); - method public static boolean isRightToLeft(int); - field public static final int ADLAM = 167; // 0xa7 - field public static final int AFAKA = 147; // 0x93 - field public static final int AHOM = 161; // 0xa1 - field public static final int ANATOLIAN_HIEROGLYPHS = 156; // 0x9c - field public static final int ARABIC = 2; // 0x2 - field public static final int ARMENIAN = 3; // 0x3 - field public static final int AVESTAN = 117; // 0x75 - field public static final int BALINESE = 62; // 0x3e - field public static final int BAMUM = 130; // 0x82 - field public static final int BASSA_VAH = 134; // 0x86 - field public static final int BATAK = 63; // 0x3f - field public static final int BENGALI = 4; // 0x4 - field public static final int BHAIKSUKI = 168; // 0xa8 - field public static final int BLISSYMBOLS = 64; // 0x40 - field public static final int BOOK_PAHLAVI = 124; // 0x7c - field public static final int BOPOMOFO = 5; // 0x5 - field public static final int BRAHMI = 65; // 0x41 - field public static final int BRAILLE = 46; // 0x2e - field public static final int BUGINESE = 55; // 0x37 - field public static final int BUHID = 44; // 0x2c - field public static final int CANADIAN_ABORIGINAL = 40; // 0x28 - field public static final int CARIAN = 104; // 0x68 - field public static final int CAUCASIAN_ALBANIAN = 159; // 0x9f - field public static final int CHAKMA = 118; // 0x76 - field public static final int CHAM = 66; // 0x42 - field public static final int CHEROKEE = 6; // 0x6 - field public static final int CHORASMIAN = 189; // 0xbd - field public static final int CIRTH = 67; // 0x43 - field public static final int COMMON = 0; // 0x0 - field public static final int COPTIC = 7; // 0x7 - field public static final int CUNEIFORM = 101; // 0x65 - field public static final int CYPRIOT = 47; // 0x2f - field public static final int CYRILLIC = 8; // 0x8 - field public static final int DEMOTIC_EGYPTIAN = 69; // 0x45 - field public static final int DESERET = 9; // 0x9 - field public static final int DEVANAGARI = 10; // 0xa - field public static final int DIVES_AKURU = 190; // 0xbe - field public static final int DOGRA = 178; // 0xb2 - field public static final int DUPLOYAN = 135; // 0x87 - field public static final int EASTERN_SYRIAC = 97; // 0x61 - field public static final int EGYPTIAN_HIEROGLYPHS = 71; // 0x47 - field public static final int ELBASAN = 136; // 0x88 - field public static final int ELYMAIC = 185; // 0xb9 - field public static final int ESTRANGELO_SYRIAC = 95; // 0x5f - field public static final int ETHIOPIC = 11; // 0xb - field public static final int GEORGIAN = 12; // 0xc - field public static final int GLAGOLITIC = 56; // 0x38 - field public static final int GOTHIC = 13; // 0xd - field public static final int GRANTHA = 137; // 0x89 - field public static final int GREEK = 14; // 0xe - field public static final int GUJARATI = 15; // 0xf - field public static final int GUNJALA_GONDI = 179; // 0xb3 - field public static final int GURMUKHI = 16; // 0x10 - field public static final int HAN = 17; // 0x11 - field public static final int HANGUL = 18; // 0x12 - field public static final int HANIFI_ROHINGYA = 182; // 0xb6 - field public static final int HANUNOO = 43; // 0x2b - field public static final int HAN_WITH_BOPOMOFO = 172; // 0xac - field public static final int HARAPPAN_INDUS = 77; // 0x4d - field public static final int HATRAN = 162; // 0xa2 - field public static final int HEBREW = 19; // 0x13 - field public static final int HIERATIC_EGYPTIAN = 70; // 0x46 - field public static final int HIRAGANA = 20; // 0x14 - field public static final int IMPERIAL_ARAMAIC = 116; // 0x74 - field public static final int INHERITED = 1; // 0x1 - field public static final int INSCRIPTIONAL_PAHLAVI = 122; // 0x7a - field public static final int INSCRIPTIONAL_PARTHIAN = 125; // 0x7d - field public static final int INVALID_CODE = -1; // 0xffffffff - field public static final int JAMO = 173; // 0xad - field public static final int JAPANESE = 105; // 0x69 - field public static final int JAVANESE = 78; // 0x4e - field public static final int JURCHEN = 148; // 0x94 - field public static final int KAITHI = 120; // 0x78 - field public static final int KANNADA = 21; // 0x15 - field public static final int KATAKANA = 22; // 0x16 - field public static final int KATAKANA_OR_HIRAGANA = 54; // 0x36 - field public static final int KAYAH_LI = 79; // 0x4f - field public static final int KHAROSHTHI = 57; // 0x39 - field public static final int KHITAN_SMALL_SCRIPT = 191; // 0xbf - field public static final int KHMER = 23; // 0x17 - field public static final int KHOJKI = 157; // 0x9d - field public static final int KHUDAWADI = 145; // 0x91 - field public static final int KHUTSURI = 72; // 0x48 - field public static final int KOREAN = 119; // 0x77 - field public static final int KPELLE = 138; // 0x8a - field public static final int LANNA = 106; // 0x6a - field public static final int LAO = 24; // 0x18 - field public static final int LATIN = 25; // 0x19 - field public static final int LATIN_FRAKTUR = 80; // 0x50 - field public static final int LATIN_GAELIC = 81; // 0x51 - field public static final int LEPCHA = 82; // 0x52 - field public static final int LIMBU = 48; // 0x30 - field public static final int LINEAR_A = 83; // 0x53 - field public static final int LINEAR_B = 49; // 0x31 - field public static final int LISU = 131; // 0x83 - field public static final int LOMA = 139; // 0x8b - field public static final int LYCIAN = 107; // 0x6b - field public static final int LYDIAN = 108; // 0x6c - field public static final int MAHAJANI = 160; // 0xa0 - field public static final int MAKASAR = 180; // 0xb4 - field public static final int MALAYALAM = 26; // 0x1a - field public static final int MANDAEAN = 84; // 0x54 - field public static final int MANDAIC = 84; // 0x54 - field public static final int MANICHAEAN = 121; // 0x79 - field public static final int MARCHEN = 169; // 0xa9 - field public static final int MASARAM_GONDI = 175; // 0xaf - field public static final int MATHEMATICAL_NOTATION = 128; // 0x80 - field public static final int MAYAN_HIEROGLYPHS = 85; // 0x55 - field public static final int MEDEFAIDRIN = 181; // 0xb5 - field public static final int MEITEI_MAYEK = 115; // 0x73 - field public static final int MENDE = 140; // 0x8c - field public static final int MEROITIC = 86; // 0x56 - field public static final int MEROITIC_CURSIVE = 141; // 0x8d - field public static final int MEROITIC_HIEROGLYPHS = 86; // 0x56 - field public static final int MIAO = 92; // 0x5c - field public static final int MODI = 163; // 0xa3 - field public static final int MONGOLIAN = 27; // 0x1b - field public static final int MOON = 114; // 0x72 - field public static final int MRO = 149; // 0x95 - field public static final int MULTANI = 164; // 0xa4 - field public static final int MYANMAR = 28; // 0x1c - field public static final int NABATAEAN = 143; // 0x8f - field public static final int NAKHI_GEBA = 132; // 0x84 - field public static final int NANDINAGARI = 187; // 0xbb - field public static final int NEWA = 170; // 0xaa - field public static final int NEW_TAI_LUE = 59; // 0x3b - field public static final int NKO = 87; // 0x57 - field public static final int NUSHU = 150; // 0x96 - field public static final int NYIAKENG_PUACHUE_HMONG = 186; // 0xba - field public static final int OGHAM = 29; // 0x1d - field public static final int OLD_CHURCH_SLAVONIC_CYRILLIC = 68; // 0x44 - field public static final int OLD_HUNGARIAN = 76; // 0x4c - field public static final int OLD_ITALIC = 30; // 0x1e - field public static final int OLD_NORTH_ARABIAN = 142; // 0x8e - field public static final int OLD_PERMIC = 89; // 0x59 - field public static final int OLD_PERSIAN = 61; // 0x3d - field public static final int OLD_SOGDIAN = 184; // 0xb8 - field public static final int OLD_SOUTH_ARABIAN = 133; // 0x85 - field public static final int OL_CHIKI = 109; // 0x6d - field public static final int ORIYA = 31; // 0x1f - field public static final int ORKHON = 88; // 0x58 - field public static final int OSAGE = 171; // 0xab - field public static final int OSMANYA = 50; // 0x32 - field public static final int PAHAWH_HMONG = 75; // 0x4b - field public static final int PALMYRENE = 144; // 0x90 - field public static final int PAU_CIN_HAU = 165; // 0xa5 - field public static final int PHAGS_PA = 90; // 0x5a - field public static final int PHOENICIAN = 91; // 0x5b - field public static final int PHONETIC_POLLARD = 92; // 0x5c - field public static final int PSALTER_PAHLAVI = 123; // 0x7b - field public static final int REJANG = 110; // 0x6e - field public static final int RONGORONGO = 93; // 0x5d - field public static final int RUNIC = 32; // 0x20 - field public static final int SAMARITAN = 126; // 0x7e - field public static final int SARATI = 94; // 0x5e - field public static final int SAURASHTRA = 111; // 0x6f - field public static final int SHARADA = 151; // 0x97 - field public static final int SHAVIAN = 51; // 0x33 - field public static final int SIDDHAM = 166; // 0xa6 - field public static final int SIGN_WRITING = 112; // 0x70 - field public static final int SIMPLIFIED_HAN = 73; // 0x49 - field public static final int SINDHI = 145; // 0x91 - field public static final int SINHALA = 33; // 0x21 - field public static final int SOGDIAN = 183; // 0xb7 - field public static final int SORA_SOMPENG = 152; // 0x98 - field public static final int SOYOMBO = 176; // 0xb0 - field public static final int SUNDANESE = 113; // 0x71 - field public static final int SYLOTI_NAGRI = 58; // 0x3a - field public static final int SYMBOLS = 129; // 0x81 - field public static final int SYMBOLS_EMOJI = 174; // 0xae - field public static final int SYRIAC = 34; // 0x22 - field public static final int TAGALOG = 42; // 0x2a - field public static final int TAGBANWA = 45; // 0x2d - field public static final int TAI_LE = 52; // 0x34 - field public static final int TAI_VIET = 127; // 0x7f - field public static final int TAKRI = 153; // 0x99 - field public static final int TAMIL = 35; // 0x23 - field public static final int TANGUT = 154; // 0x9a - field public static final int TELUGU = 36; // 0x24 - field public static final int TENGWAR = 98; // 0x62 - field public static final int THAANA = 37; // 0x25 - field public static final int THAI = 38; // 0x26 - field public static final int TIBETAN = 39; // 0x27 - field public static final int TIFINAGH = 60; // 0x3c - field public static final int TIRHUTA = 158; // 0x9e - field public static final int TRADITIONAL_HAN = 74; // 0x4a - field public static final int UCAS = 40; // 0x28 - field public static final int UGARITIC = 53; // 0x35 - field public static final int UNKNOWN = 103; // 0x67 - field public static final int UNWRITTEN_LANGUAGES = 102; // 0x66 - field public static final int VAI = 99; // 0x63 - field public static final int VISIBLE_SPEECH = 100; // 0x64 - field public static final int WANCHO = 188; // 0xbc - field public static final int WARANG_CITI = 146; // 0x92 - field public static final int WESTERN_SYRIAC = 96; // 0x60 - field public static final int WOLEAI = 155; // 0x9b - field public static final int YEZIDI = 192; // 0xc0 - field public static final int YI = 41; // 0x29 - field public static final int ZANABAZAR_SQUARE = 177; // 0xb1 - } - - public enum UScript.ScriptUsage { - enum_constant public static final android.icu.lang.UScript.ScriptUsage ASPIRATIONAL; - enum_constant public static final android.icu.lang.UScript.ScriptUsage EXCLUDED; - enum_constant public static final android.icu.lang.UScript.ScriptUsage LIMITED_USE; - enum_constant public static final android.icu.lang.UScript.ScriptUsage NOT_ENCODED; - enum_constant public static final android.icu.lang.UScript.ScriptUsage RECOMMENDED; - enum_constant public static final android.icu.lang.UScript.ScriptUsage UNKNOWN; - } - -} - -package android.icu.math { - - public class BigDecimal extends java.lang.Number implements java.lang.Comparable<android.icu.math.BigDecimal> java.io.Serializable { - ctor public BigDecimal(java.math.BigDecimal); - ctor public BigDecimal(java.math.BigInteger); - ctor public BigDecimal(java.math.BigInteger, int); - ctor public BigDecimal(char[]); - ctor public BigDecimal(char[], int, int); - ctor public BigDecimal(double); - ctor public BigDecimal(int); - ctor public BigDecimal(long); - ctor public BigDecimal(String); - method public android.icu.math.BigDecimal abs(); - method public android.icu.math.BigDecimal abs(android.icu.math.MathContext); - method public android.icu.math.BigDecimal add(android.icu.math.BigDecimal); - method public android.icu.math.BigDecimal add(android.icu.math.BigDecimal, android.icu.math.MathContext); - method public byte byteValueExact(); - method public int compareTo(android.icu.math.BigDecimal); - method public int compareTo(android.icu.math.BigDecimal, android.icu.math.MathContext); - method public android.icu.math.BigDecimal divide(android.icu.math.BigDecimal); - method public android.icu.math.BigDecimal divide(android.icu.math.BigDecimal, int); - method public android.icu.math.BigDecimal divide(android.icu.math.BigDecimal, int, int); - method public android.icu.math.BigDecimal divide(android.icu.math.BigDecimal, android.icu.math.MathContext); - method public android.icu.math.BigDecimal divideInteger(android.icu.math.BigDecimal); - method public android.icu.math.BigDecimal divideInteger(android.icu.math.BigDecimal, android.icu.math.MathContext); - method public double doubleValue(); - method public float floatValue(); - method public String format(int, int); - method public String format(int, int, int, int, int, int); - method public int intValue(); - method public int intValueExact(); - method public long longValue(); - method public long longValueExact(); - method public android.icu.math.BigDecimal max(android.icu.math.BigDecimal); - method public android.icu.math.BigDecimal max(android.icu.math.BigDecimal, android.icu.math.MathContext); - method public android.icu.math.BigDecimal min(android.icu.math.BigDecimal); - method public android.icu.math.BigDecimal min(android.icu.math.BigDecimal, android.icu.math.MathContext); - method public android.icu.math.BigDecimal movePointLeft(int); - method public android.icu.math.BigDecimal movePointRight(int); - method public android.icu.math.BigDecimal multiply(android.icu.math.BigDecimal); - method public android.icu.math.BigDecimal multiply(android.icu.math.BigDecimal, android.icu.math.MathContext); - method public android.icu.math.BigDecimal negate(); - method public android.icu.math.BigDecimal negate(android.icu.math.MathContext); - method public android.icu.math.BigDecimal plus(); - method public android.icu.math.BigDecimal plus(android.icu.math.MathContext); - method public android.icu.math.BigDecimal pow(android.icu.math.BigDecimal); - method public android.icu.math.BigDecimal pow(android.icu.math.BigDecimal, android.icu.math.MathContext); - method public android.icu.math.BigDecimal remainder(android.icu.math.BigDecimal); - method public android.icu.math.BigDecimal remainder(android.icu.math.BigDecimal, android.icu.math.MathContext); - method public int scale(); - method public android.icu.math.BigDecimal setScale(int); - method public android.icu.math.BigDecimal setScale(int, int); - method public short shortValueExact(); - method public int signum(); - method public android.icu.math.BigDecimal subtract(android.icu.math.BigDecimal); - method public android.icu.math.BigDecimal subtract(android.icu.math.BigDecimal, android.icu.math.MathContext); - method public java.math.BigDecimal toBigDecimal(); - method public java.math.BigInteger toBigInteger(); - method public java.math.BigInteger toBigIntegerExact(); - method public char[] toCharArray(); - method public java.math.BigInteger unscaledValue(); - method public static android.icu.math.BigDecimal valueOf(double); - method public static android.icu.math.BigDecimal valueOf(long); - method public static android.icu.math.BigDecimal valueOf(long, int); - field public static final android.icu.math.BigDecimal ONE; - field public static final int ROUND_CEILING = 2; // 0x2 - field public static final int ROUND_DOWN = 1; // 0x1 - field public static final int ROUND_FLOOR = 3; // 0x3 - field public static final int ROUND_HALF_DOWN = 5; // 0x5 - field public static final int ROUND_HALF_EVEN = 6; // 0x6 - field public static final int ROUND_HALF_UP = 4; // 0x4 - field public static final int ROUND_UNNECESSARY = 7; // 0x7 - field public static final int ROUND_UP = 0; // 0x0 - field public static final android.icu.math.BigDecimal TEN; - field public static final android.icu.math.BigDecimal ZERO; - } - - public final class MathContext implements java.io.Serializable { - ctor public MathContext(int); - ctor public MathContext(int, int); - ctor public MathContext(int, int, boolean); - ctor public MathContext(int, int, boolean, int); - method public int getDigits(); - method public int getForm(); - method public boolean getLostDigits(); - method public int getRoundingMode(); - field public static final android.icu.math.MathContext DEFAULT; - field public static final int ENGINEERING = 2; // 0x2 - field public static final int PLAIN = 0; // 0x0 - field public static final int ROUND_CEILING = 2; // 0x2 - field public static final int ROUND_DOWN = 1; // 0x1 - field public static final int ROUND_FLOOR = 3; // 0x3 - field public static final int ROUND_HALF_DOWN = 5; // 0x5 - field public static final int ROUND_HALF_EVEN = 6; // 0x6 - field public static final int ROUND_HALF_UP = 4; // 0x4 - field public static final int ROUND_UNNECESSARY = 7; // 0x7 - field public static final int ROUND_UP = 0; // 0x0 - field public static final int SCIENTIFIC = 1; // 0x1 - } - -} - -package android.icu.number { - - public class CompactNotation extends android.icu.number.Notation { - } - - public abstract class CurrencyPrecision extends android.icu.number.Precision { - method public android.icu.number.Precision withCurrency(android.icu.util.Currency); - } - - public class FormattedNumber implements java.lang.CharSequence { - method public char charAt(int); - method public int length(); - method public CharSequence subSequence(int, int); - method public java.math.BigDecimal toBigDecimal(); - method public java.text.AttributedCharacterIterator toCharacterIterator(); - } - - public class FormattedNumberRange implements java.lang.CharSequence { - method public char charAt(int); - method public java.math.BigDecimal getFirstBigDecimal(); - method public android.icu.number.NumberRangeFormatter.RangeIdentityResult getIdentityResult(); - method public java.math.BigDecimal getSecondBigDecimal(); - method public int length(); - method public CharSequence subSequence(int, int); - method public java.text.AttributedCharacterIterator toCharacterIterator(); - } - - public abstract class FractionPrecision extends android.icu.number.Precision { - method public android.icu.number.Precision withMaxDigits(int); - method public android.icu.number.Precision withMinDigits(int); - } - - public class IntegerWidth { - method public android.icu.number.IntegerWidth truncateAt(int); - method public static android.icu.number.IntegerWidth zeroFillTo(int); - } - - public class LocalizedNumberFormatter extends android.icu.number.NumberFormatterSettings<android.icu.number.LocalizedNumberFormatter> { - method public android.icu.number.FormattedNumber format(long); - method public android.icu.number.FormattedNumber format(double); - method public android.icu.number.FormattedNumber format(Number); - method public android.icu.number.FormattedNumber format(android.icu.util.Measure); - method public java.text.Format toFormat(); - } - - public class LocalizedNumberRangeFormatter extends android.icu.number.NumberRangeFormatterSettings<android.icu.number.LocalizedNumberRangeFormatter> { - method public android.icu.number.FormattedNumberRange formatRange(int, int); - method public android.icu.number.FormattedNumberRange formatRange(double, double); - method public android.icu.number.FormattedNumberRange formatRange(Number, Number); - } - - public class Notation { - method public static android.icu.number.CompactNotation compactLong(); - method public static android.icu.number.CompactNotation compactShort(); - method public static android.icu.number.ScientificNotation engineering(); - method public static android.icu.number.ScientificNotation scientific(); - method public static android.icu.number.SimpleNotation simple(); - } - - public final class NumberFormatter { - method public static android.icu.number.UnlocalizedNumberFormatter with(); - method public static android.icu.number.LocalizedNumberFormatter withLocale(java.util.Locale); - method public static android.icu.number.LocalizedNumberFormatter withLocale(android.icu.util.ULocale); - } - - public enum NumberFormatter.DecimalSeparatorDisplay { - enum_constant public static final android.icu.number.NumberFormatter.DecimalSeparatorDisplay ALWAYS; - enum_constant public static final android.icu.number.NumberFormatter.DecimalSeparatorDisplay AUTO; - } - - public enum NumberFormatter.GroupingStrategy { - enum_constant public static final android.icu.number.NumberFormatter.GroupingStrategy AUTO; - enum_constant public static final android.icu.number.NumberFormatter.GroupingStrategy MIN2; - enum_constant public static final android.icu.number.NumberFormatter.GroupingStrategy OFF; - enum_constant public static final android.icu.number.NumberFormatter.GroupingStrategy ON_ALIGNED; - enum_constant public static final android.icu.number.NumberFormatter.GroupingStrategy THOUSANDS; - } - - public enum NumberFormatter.SignDisplay { - enum_constant public static final android.icu.number.NumberFormatter.SignDisplay ACCOUNTING; - enum_constant public static final android.icu.number.NumberFormatter.SignDisplay ACCOUNTING_ALWAYS; - enum_constant public static final android.icu.number.NumberFormatter.SignDisplay ACCOUNTING_EXCEPT_ZERO; - enum_constant public static final android.icu.number.NumberFormatter.SignDisplay ALWAYS; - enum_constant public static final android.icu.number.NumberFormatter.SignDisplay AUTO; - enum_constant public static final android.icu.number.NumberFormatter.SignDisplay EXCEPT_ZERO; - enum_constant public static final android.icu.number.NumberFormatter.SignDisplay NEVER; - } - - public enum NumberFormatter.UnitWidth { - enum_constant public static final android.icu.number.NumberFormatter.UnitWidth FULL_NAME; - enum_constant public static final android.icu.number.NumberFormatter.UnitWidth HIDDEN; - enum_constant public static final android.icu.number.NumberFormatter.UnitWidth ISO_CODE; - enum_constant public static final android.icu.number.NumberFormatter.UnitWidth NARROW; - enum_constant public static final android.icu.number.NumberFormatter.UnitWidth SHORT; - } - - public abstract class NumberFormatterSettings<T extends android.icu.number.NumberFormatterSettings<?>> { - method public T decimal(android.icu.number.NumberFormatter.DecimalSeparatorDisplay); - method public T grouping(android.icu.number.NumberFormatter.GroupingStrategy); - method public T integerWidth(android.icu.number.IntegerWidth); - method public T notation(android.icu.number.Notation); - method public T perUnit(android.icu.util.MeasureUnit); - method public T precision(android.icu.number.Precision); - method public T roundingMode(java.math.RoundingMode); - method public T scale(android.icu.number.Scale); - method public T sign(android.icu.number.NumberFormatter.SignDisplay); - method public T symbols(android.icu.text.DecimalFormatSymbols); - method public T symbols(android.icu.text.NumberingSystem); - method public T unit(android.icu.util.MeasureUnit); - method public T unitWidth(android.icu.number.NumberFormatter.UnitWidth); - } - - public abstract class NumberRangeFormatter { - method public static android.icu.number.UnlocalizedNumberRangeFormatter with(); - method public static android.icu.number.LocalizedNumberRangeFormatter withLocale(java.util.Locale); - method public static android.icu.number.LocalizedNumberRangeFormatter withLocale(android.icu.util.ULocale); - } - - public enum NumberRangeFormatter.RangeCollapse { - enum_constant public static final android.icu.number.NumberRangeFormatter.RangeCollapse ALL; - enum_constant public static final android.icu.number.NumberRangeFormatter.RangeCollapse AUTO; - enum_constant public static final android.icu.number.NumberRangeFormatter.RangeCollapse NONE; - enum_constant public static final android.icu.number.NumberRangeFormatter.RangeCollapse UNIT; - } - - public enum NumberRangeFormatter.RangeIdentityFallback { - enum_constant public static final android.icu.number.NumberRangeFormatter.RangeIdentityFallback APPROXIMATELY; - enum_constant public static final android.icu.number.NumberRangeFormatter.RangeIdentityFallback APPROXIMATELY_OR_SINGLE_VALUE; - enum_constant public static final android.icu.number.NumberRangeFormatter.RangeIdentityFallback RANGE; - enum_constant public static final android.icu.number.NumberRangeFormatter.RangeIdentityFallback SINGLE_VALUE; - } - - public enum NumberRangeFormatter.RangeIdentityResult { - enum_constant public static final android.icu.number.NumberRangeFormatter.RangeIdentityResult EQUAL_AFTER_ROUNDING; - enum_constant public static final android.icu.number.NumberRangeFormatter.RangeIdentityResult EQUAL_BEFORE_ROUNDING; - enum_constant public static final android.icu.number.NumberRangeFormatter.RangeIdentityResult NOT_EQUAL; - } - - public abstract class NumberRangeFormatterSettings<T extends android.icu.number.NumberRangeFormatterSettings<?>> { - method public T collapse(android.icu.number.NumberRangeFormatter.RangeCollapse); - method public T identityFallback(android.icu.number.NumberRangeFormatter.RangeIdentityFallback); - method public T numberFormatterBoth(android.icu.number.UnlocalizedNumberFormatter); - method public T numberFormatterFirst(android.icu.number.UnlocalizedNumberFormatter); - method public T numberFormatterSecond(android.icu.number.UnlocalizedNumberFormatter); - } - - public abstract class Precision { - method public static android.icu.number.CurrencyPrecision currency(android.icu.util.Currency.CurrencyUsage); - method public static android.icu.number.FractionPrecision fixedFraction(int); - method public static android.icu.number.Precision fixedSignificantDigits(int); - method public static android.icu.number.Precision increment(java.math.BigDecimal); - method public static android.icu.number.FractionPrecision integer(); - method public static android.icu.number.FractionPrecision maxFraction(int); - method public static android.icu.number.Precision maxSignificantDigits(int); - method public static android.icu.number.FractionPrecision minFraction(int); - method public static android.icu.number.FractionPrecision minMaxFraction(int, int); - method public static android.icu.number.Precision minMaxSignificantDigits(int, int); - method public static android.icu.number.Precision minSignificantDigits(int); - method public static android.icu.number.Precision unlimited(); - } - - public class Scale { - method public static android.icu.number.Scale byBigDecimal(java.math.BigDecimal); - method public static android.icu.number.Scale byDouble(double); - method public static android.icu.number.Scale byDoubleAndPowerOfTen(double, int); - method public static android.icu.number.Scale none(); - method public static android.icu.number.Scale powerOfTen(int); - } - - public class ScientificNotation extends android.icu.number.Notation { - method public android.icu.number.ScientificNotation withExponentSignDisplay(android.icu.number.NumberFormatter.SignDisplay); - method public android.icu.number.ScientificNotation withMinExponentDigits(int); - } - - public class SimpleNotation extends android.icu.number.Notation { - } - - public class UnlocalizedNumberFormatter extends android.icu.number.NumberFormatterSettings<android.icu.number.UnlocalizedNumberFormatter> { - method public android.icu.number.LocalizedNumberFormatter locale(java.util.Locale); - method public android.icu.number.LocalizedNumberFormatter locale(android.icu.util.ULocale); - } - - public class UnlocalizedNumberRangeFormatter extends android.icu.number.NumberRangeFormatterSettings<android.icu.number.UnlocalizedNumberRangeFormatter> { - method public android.icu.number.LocalizedNumberRangeFormatter locale(java.util.Locale); - method public android.icu.number.LocalizedNumberRangeFormatter locale(android.icu.util.ULocale); - } - -} - -package android.icu.text { - - public final class AlphabeticIndex<V> implements java.lang.Iterable<android.icu.text.AlphabeticIndex.Bucket<V>> { - ctor public AlphabeticIndex(android.icu.util.ULocale); - ctor public AlphabeticIndex(java.util.Locale); - ctor public AlphabeticIndex(android.icu.text.RuleBasedCollator); - method public android.icu.text.AlphabeticIndex<V> addLabels(android.icu.text.UnicodeSet); - method public android.icu.text.AlphabeticIndex<V> addLabels(android.icu.util.ULocale...); - method public android.icu.text.AlphabeticIndex<V> addLabels(java.util.Locale...); - method public android.icu.text.AlphabeticIndex<V> addRecord(CharSequence, V); - method public android.icu.text.AlphabeticIndex.ImmutableIndex<V> buildImmutableIndex(); - method public android.icu.text.AlphabeticIndex<V> clearRecords(); - method public int getBucketCount(); - method public int getBucketIndex(CharSequence); - method public java.util.List<java.lang.String> getBucketLabels(); - method public android.icu.text.RuleBasedCollator getCollator(); - method public String getInflowLabel(); - method public int getMaxLabelCount(); - method public String getOverflowLabel(); - method public int getRecordCount(); - method public String getUnderflowLabel(); - method public java.util.Iterator<android.icu.text.AlphabeticIndex.Bucket<V>> iterator(); - method public android.icu.text.AlphabeticIndex<V> setInflowLabel(String); - method public android.icu.text.AlphabeticIndex<V> setMaxLabelCount(int); - method public android.icu.text.AlphabeticIndex<V> setOverflowLabel(String); - method public android.icu.text.AlphabeticIndex<V> setUnderflowLabel(String); - } - - public static class AlphabeticIndex.Bucket<V> implements java.lang.Iterable<android.icu.text.AlphabeticIndex.Record<V>> { - method public String getLabel(); - method public android.icu.text.AlphabeticIndex.Bucket.LabelType getLabelType(); - method public java.util.Iterator<android.icu.text.AlphabeticIndex.Record<V>> iterator(); - method public int size(); - } - - public enum AlphabeticIndex.Bucket.LabelType { - enum_constant public static final android.icu.text.AlphabeticIndex.Bucket.LabelType INFLOW; - enum_constant public static final android.icu.text.AlphabeticIndex.Bucket.LabelType NORMAL; - enum_constant public static final android.icu.text.AlphabeticIndex.Bucket.LabelType OVERFLOW; - enum_constant public static final android.icu.text.AlphabeticIndex.Bucket.LabelType UNDERFLOW; - } - - public static final class AlphabeticIndex.ImmutableIndex<V> implements java.lang.Iterable<android.icu.text.AlphabeticIndex.Bucket<V>> { - method public android.icu.text.AlphabeticIndex.Bucket<V> getBucket(int); - method public int getBucketCount(); - method public int getBucketIndex(CharSequence); - method public java.util.Iterator<android.icu.text.AlphabeticIndex.Bucket<V>> iterator(); - } - - public static class AlphabeticIndex.Record<V> { - method public V getData(); - method public CharSequence getName(); - } - - public class Bidi { - ctor public Bidi(); - ctor public Bidi(int, int); - ctor public Bidi(String, int); - ctor public Bidi(java.text.AttributedCharacterIterator); - ctor public Bidi(char[], int, byte[], int, int, int); - method public boolean baseIsLeftToRight(); - method public int countParagraphs(); - method public int countRuns(); - method public android.icu.text.Bidi createLineBidi(int, int); - method public static byte getBaseDirection(CharSequence); - method public int getBaseLevel(); - method public android.icu.text.BidiClassifier getCustomClassifier(); - method public int getCustomizedClass(int); - method public byte getDirection(); - method public int getLength(); - method public byte getLevelAt(int); - method public byte[] getLevels(); - method public int getLogicalIndex(int); - method public int[] getLogicalMap(); - method public android.icu.text.BidiRun getLogicalRun(int); - method public byte getParaLevel(); - method public android.icu.text.BidiRun getParagraph(int); - method public android.icu.text.BidiRun getParagraphByIndex(int); - method public int getParagraphIndex(int); - method public int getProcessedLength(); - method public int getReorderingMode(); - method public int getReorderingOptions(); - method public int getResultLength(); - method public int getRunCount(); - method public int getRunLevel(int); - method public int getRunLimit(int); - method public int getRunStart(int); - method public char[] getText(); - method public String getTextAsString(); - method public int getVisualIndex(int); - method public int[] getVisualMap(); - method public android.icu.text.BidiRun getVisualRun(int); - method public static int[] invertMap(int[]); - method public boolean isInverse(); - method public boolean isLeftToRight(); - method public boolean isMixed(); - method public boolean isOrderParagraphsLTR(); - method public boolean isRightToLeft(); - method public void orderParagraphsLTR(boolean); - method public static int[] reorderLogical(byte[]); - method public static int[] reorderVisual(byte[]); - method public static void reorderVisually(byte[], int, Object[], int, int); - method public static boolean requiresBidi(char[], int, int); - method public void setContext(String, String); - method public void setCustomClassifier(android.icu.text.BidiClassifier); - method public void setInverse(boolean); - method public android.icu.text.Bidi setLine(int, int); - method public void setPara(String, byte, byte[]); - method public void setPara(char[], byte, byte[]); - method public void setPara(java.text.AttributedCharacterIterator); - method public void setReorderingMode(int); - method public void setReorderingOptions(int); - method public String writeReordered(int); - method public static String writeReverse(String, int); - field public static final int DIRECTION_DEFAULT_LEFT_TO_RIGHT = 126; // 0x7e - field public static final int DIRECTION_DEFAULT_RIGHT_TO_LEFT = 127; // 0x7f - field public static final int DIRECTION_LEFT_TO_RIGHT = 0; // 0x0 - field public static final int DIRECTION_RIGHT_TO_LEFT = 1; // 0x1 - field public static final short DO_MIRRORING = 2; // 0x2 - field public static final short INSERT_LRM_FOR_NUMERIC = 4; // 0x4 - field public static final short KEEP_BASE_COMBINING = 1; // 0x1 - field public static final byte LEVEL_DEFAULT_LTR = 126; // 0x7e - field public static final byte LEVEL_DEFAULT_RTL = 127; // 0x7f - field public static final byte LEVEL_OVERRIDE = -128; // 0xffffff80 - field public static final byte LTR = 0; // 0x0 - field public static final int MAP_NOWHERE = -1; // 0xffffffff - field public static final byte MAX_EXPLICIT_LEVEL = 125; // 0x7d - field public static final byte MIXED = 2; // 0x2 - field public static final byte NEUTRAL = 3; // 0x3 - field public static final int OPTION_DEFAULT = 0; // 0x0 - field public static final int OPTION_INSERT_MARKS = 1; // 0x1 - field public static final int OPTION_REMOVE_CONTROLS = 2; // 0x2 - field public static final int OPTION_STREAMING = 4; // 0x4 - field public static final short OUTPUT_REVERSE = 16; // 0x10 - field public static final short REMOVE_BIDI_CONTROLS = 8; // 0x8 - field public static final short REORDER_DEFAULT = 0; // 0x0 - field public static final short REORDER_GROUP_NUMBERS_WITH_R = 2; // 0x2 - field public static final short REORDER_INVERSE_FOR_NUMBERS_SPECIAL = 6; // 0x6 - field public static final short REORDER_INVERSE_LIKE_DIRECT = 5; // 0x5 - field public static final short REORDER_INVERSE_NUMBERS_AS_L = 4; // 0x4 - field public static final short REORDER_NUMBERS_SPECIAL = 1; // 0x1 - field public static final short REORDER_RUNS_ONLY = 3; // 0x3 - field public static final byte RTL = 1; // 0x1 - } - - public class BidiClassifier { - ctor public BidiClassifier(Object); - method public int classify(int); - method public Object getContext(); - method public void setContext(Object); - } - - public class BidiRun { - method public byte getDirection(); - method public byte getEmbeddingLevel(); - method public int getLength(); - method public int getLimit(); - method public int getStart(); - method public boolean isEvenRun(); - method public boolean isOddRun(); - } - - public abstract class BreakIterator implements java.lang.Cloneable { - ctor protected BreakIterator(); - method public Object clone(); - method public abstract int current(); - method public abstract int first(); - method public abstract int following(int); - method public static java.util.Locale[] getAvailableLocales(); - method public static android.icu.text.BreakIterator getCharacterInstance(); - method public static android.icu.text.BreakIterator getCharacterInstance(java.util.Locale); - method public static android.icu.text.BreakIterator getCharacterInstance(android.icu.util.ULocale); - method public static android.icu.text.BreakIterator getLineInstance(); - method public static android.icu.text.BreakIterator getLineInstance(java.util.Locale); - method public static android.icu.text.BreakIterator getLineInstance(android.icu.util.ULocale); - method public int getRuleStatus(); - method public int getRuleStatusVec(int[]); - method public static android.icu.text.BreakIterator getSentenceInstance(); - method public static android.icu.text.BreakIterator getSentenceInstance(java.util.Locale); - method public static android.icu.text.BreakIterator getSentenceInstance(android.icu.util.ULocale); - method public abstract java.text.CharacterIterator getText(); - method @Deprecated public static android.icu.text.BreakIterator getTitleInstance(); - method @Deprecated public static android.icu.text.BreakIterator getTitleInstance(java.util.Locale); - method @Deprecated public static android.icu.text.BreakIterator getTitleInstance(android.icu.util.ULocale); - method public static android.icu.text.BreakIterator getWordInstance(); - method public static android.icu.text.BreakIterator getWordInstance(java.util.Locale); - method public static android.icu.text.BreakIterator getWordInstance(android.icu.util.ULocale); - method public boolean isBoundary(int); - method public abstract int last(); - method public abstract int next(int); - method public abstract int next(); - method public int preceding(int); - method public abstract int previous(); - method public void setText(String); - method public void setText(CharSequence); - method public abstract void setText(java.text.CharacterIterator); - field public static final int DONE = -1; // 0xffffffff - field public static final int KIND_CHARACTER = 0; // 0x0 - field public static final int KIND_LINE = 2; // 0x2 - field public static final int KIND_SENTENCE = 3; // 0x3 - field @Deprecated public static final int KIND_TITLE = 4; // 0x4 - field public static final int KIND_WORD = 1; // 0x1 - field public static final int WORD_IDEO = 400; // 0x190 - field public static final int WORD_IDEO_LIMIT = 500; // 0x1f4 - field public static final int WORD_KANA = 300; // 0x12c - field public static final int WORD_KANA_LIMIT = 400; // 0x190 - field public static final int WORD_LETTER = 200; // 0xc8 - field public static final int WORD_LETTER_LIMIT = 300; // 0x12c - field public static final int WORD_NONE = 0; // 0x0 - field public static final int WORD_NONE_LIMIT = 100; // 0x64 - field public static final int WORD_NUMBER = 100; // 0x64 - field public static final int WORD_NUMBER_LIMIT = 200; // 0xc8 - } - - public abstract class CaseMap { - method public static android.icu.text.CaseMap.Fold fold(); - method public abstract android.icu.text.CaseMap omitUnchangedText(); - method public static android.icu.text.CaseMap.Lower toLower(); - method public static android.icu.text.CaseMap.Title toTitle(); - method public static android.icu.text.CaseMap.Upper toUpper(); - } - - public static final class CaseMap.Fold extends android.icu.text.CaseMap { - method public String apply(CharSequence); - method public <A extends java.lang.Appendable> A apply(CharSequence, A, android.icu.text.Edits); - method public android.icu.text.CaseMap.Fold omitUnchangedText(); - method public android.icu.text.CaseMap.Fold turkic(); - } - - public static final class CaseMap.Lower extends android.icu.text.CaseMap { - method public String apply(java.util.Locale, CharSequence); - method public <A extends java.lang.Appendable> A apply(java.util.Locale, CharSequence, A, android.icu.text.Edits); - method public android.icu.text.CaseMap.Lower omitUnchangedText(); - } - - public static final class CaseMap.Title extends android.icu.text.CaseMap { - method public android.icu.text.CaseMap.Title adjustToCased(); - method public String apply(java.util.Locale, android.icu.text.BreakIterator, CharSequence); - method public <A extends java.lang.Appendable> A apply(java.util.Locale, android.icu.text.BreakIterator, CharSequence, A, android.icu.text.Edits); - method public android.icu.text.CaseMap.Title noBreakAdjustment(); - method public android.icu.text.CaseMap.Title noLowercase(); - method public android.icu.text.CaseMap.Title omitUnchangedText(); - method public android.icu.text.CaseMap.Title sentences(); - method public android.icu.text.CaseMap.Title wholeString(); - } - - public static final class CaseMap.Upper extends android.icu.text.CaseMap { - method public String apply(java.util.Locale, CharSequence); - method public <A extends java.lang.Appendable> A apply(java.util.Locale, CharSequence, A, android.icu.text.Edits); - method public android.icu.text.CaseMap.Upper omitUnchangedText(); - } - - public final class CollationElementIterator { - method public int getMaxExpansion(int); - method public int getOffset(); - method public int next(); - method public int previous(); - method public static int primaryOrder(int); - method public void reset(); - method public static int secondaryOrder(int); - method public void setOffset(int); - method public void setText(String); - method public void setText(android.icu.text.UCharacterIterator); - method public void setText(java.text.CharacterIterator); - method public static int tertiaryOrder(int); - field public static final int IGNORABLE = 0; // 0x0 - field public static final int NULLORDER = -1; // 0xffffffff - } - - public final class CollationKey implements java.lang.Comparable<android.icu.text.CollationKey> { - ctor public CollationKey(String, byte[]); - method public int compareTo(android.icu.text.CollationKey); - method public boolean equals(android.icu.text.CollationKey); - method public android.icu.text.CollationKey getBound(int, int); - method public String getSourceString(); - method public android.icu.text.CollationKey merge(android.icu.text.CollationKey); - method public byte[] toByteArray(); - } - - public static final class CollationKey.BoundMode { - field public static final int LOWER = 0; // 0x0 - field public static final int UPPER = 1; // 0x1 - field public static final int UPPER_LONG = 2; // 0x2 - } - - public abstract class Collator implements java.lang.Cloneable java.util.Comparator<java.lang.Object> android.icu.util.Freezable<android.icu.text.Collator> { - ctor protected Collator(); - method public Object clone() throws java.lang.CloneNotSupportedException; - method public android.icu.text.Collator cloneAsThawed(); - method public abstract int compare(String, String); - method public int compare(Object, Object); - method public boolean equals(String, String); - method public android.icu.text.Collator freeze(); - method public static java.util.Locale[] getAvailableLocales(); - method public static final android.icu.util.ULocale[] getAvailableULocales(); - method public abstract android.icu.text.CollationKey getCollationKey(String); - method public int getDecomposition(); - method public static String getDisplayName(java.util.Locale, java.util.Locale); - method public static String getDisplayName(android.icu.util.ULocale, android.icu.util.ULocale); - method public static String getDisplayName(java.util.Locale); - method public static String getDisplayName(android.icu.util.ULocale); - method public static int[] getEquivalentReorderCodes(int); - method public static final android.icu.util.ULocale getFunctionalEquivalent(String, android.icu.util.ULocale, boolean[]); - method public static final android.icu.util.ULocale getFunctionalEquivalent(String, android.icu.util.ULocale); - method public static final android.icu.text.Collator getInstance(); - method public static final android.icu.text.Collator getInstance(android.icu.util.ULocale); - method public static final android.icu.text.Collator getInstance(java.util.Locale); - method public static final String[] getKeywordValues(String); - method public static final String[] getKeywordValuesForLocale(String, android.icu.util.ULocale, boolean); - method public static final String[] getKeywords(); - method public int getMaxVariable(); - method public int[] getReorderCodes(); - method public int getStrength(); - method public android.icu.text.UnicodeSet getTailoredSet(); - method public abstract android.icu.util.VersionInfo getUCAVersion(); - method public abstract int getVariableTop(); - method public abstract android.icu.util.VersionInfo getVersion(); - method public boolean isFrozen(); - method public void setDecomposition(int); - method public android.icu.text.Collator setMaxVariable(int); - method public void setReorderCodes(int...); - method public void setStrength(int); - field public static final int CANONICAL_DECOMPOSITION = 17; // 0x11 - field public static final int FULL_DECOMPOSITION = 15; // 0xf - field public static final int IDENTICAL = 15; // 0xf - field public static final int NO_DECOMPOSITION = 16; // 0x10 - field public static final int PRIMARY = 0; // 0x0 - field public static final int QUATERNARY = 3; // 0x3 - field public static final int SECONDARY = 1; // 0x1 - field public static final int TERTIARY = 2; // 0x2 - } - - public static interface Collator.ReorderCodes { - field public static final int CURRENCY = 4099; // 0x1003 - field public static final int DEFAULT = -1; // 0xffffffff - field public static final int DIGIT = 4100; // 0x1004 - field public static final int FIRST = 4096; // 0x1000 - field public static final int NONE = 103; // 0x67 - field public static final int OTHERS = 103; // 0x67 - field public static final int PUNCTUATION = 4097; // 0x1001 - field public static final int SPACE = 4096; // 0x1000 - field public static final int SYMBOL = 4098; // 0x1002 - } - - public class CompactDecimalFormat extends android.icu.text.DecimalFormat { - method public static android.icu.text.CompactDecimalFormat getInstance(android.icu.util.ULocale, android.icu.text.CompactDecimalFormat.CompactStyle); - method public static android.icu.text.CompactDecimalFormat getInstance(java.util.Locale, android.icu.text.CompactDecimalFormat.CompactStyle); - } - - public enum CompactDecimalFormat.CompactStyle { - enum_constant public static final android.icu.text.CompactDecimalFormat.CompactStyle LONG; - enum_constant public static final android.icu.text.CompactDecimalFormat.CompactStyle SHORT; - } - - public class CurrencyPluralInfo implements java.lang.Cloneable java.io.Serializable { - ctor public CurrencyPluralInfo(); - ctor public CurrencyPluralInfo(java.util.Locale); - ctor public CurrencyPluralInfo(android.icu.util.ULocale); - method public Object clone(); - method public String getCurrencyPluralPattern(String); - method public static android.icu.text.CurrencyPluralInfo getInstance(); - method public static android.icu.text.CurrencyPluralInfo getInstance(java.util.Locale); - method public static android.icu.text.CurrencyPluralInfo getInstance(android.icu.util.ULocale); - method public android.icu.util.ULocale getLocale(); - method public android.icu.text.PluralRules getPluralRules(); - method public void setCurrencyPluralPattern(String, String); - method public void setLocale(android.icu.util.ULocale); - method public void setPluralRules(String); - } - - public abstract class DateFormat extends android.icu.text.UFormat { - ctor protected DateFormat(); - method public final StringBuffer format(Object, StringBuffer, java.text.FieldPosition); - method public abstract StringBuffer format(android.icu.util.Calendar, StringBuffer, java.text.FieldPosition); - method public StringBuffer format(java.util.Date, StringBuffer, java.text.FieldPosition); - method public final String format(java.util.Date); - method public static java.util.Locale[] getAvailableLocales(); - method public boolean getBooleanAttribute(android.icu.text.DateFormat.BooleanAttribute); - method public android.icu.util.Calendar getCalendar(); - method public android.icu.text.DisplayContext getContext(android.icu.text.DisplayContext.Type); - method public static final android.icu.text.DateFormat getDateInstance(); - method public static final android.icu.text.DateFormat getDateInstance(int); - method public static final android.icu.text.DateFormat getDateInstance(int, java.util.Locale); - method public static final android.icu.text.DateFormat getDateInstance(int, android.icu.util.ULocale); - method public static final android.icu.text.DateFormat getDateInstance(android.icu.util.Calendar, int, java.util.Locale); - method public static final android.icu.text.DateFormat getDateInstance(android.icu.util.Calendar, int, android.icu.util.ULocale); - method public static final android.icu.text.DateFormat getDateInstance(android.icu.util.Calendar, int); - method public static final android.icu.text.DateFormat getDateTimeInstance(); - method public static final android.icu.text.DateFormat getDateTimeInstance(int, int); - method public static final android.icu.text.DateFormat getDateTimeInstance(int, int, java.util.Locale); - method public static final android.icu.text.DateFormat getDateTimeInstance(int, int, android.icu.util.ULocale); - method public static final android.icu.text.DateFormat getDateTimeInstance(android.icu.util.Calendar, int, int, java.util.Locale); - method public static final android.icu.text.DateFormat getDateTimeInstance(android.icu.util.Calendar, int, int, android.icu.util.ULocale); - method public static final android.icu.text.DateFormat getDateTimeInstance(android.icu.util.Calendar, int, int); - method public static final android.icu.text.DateFormat getInstance(); - method public static final android.icu.text.DateFormat getInstance(android.icu.util.Calendar, java.util.Locale); - method public static final android.icu.text.DateFormat getInstance(android.icu.util.Calendar); - method public static final android.icu.text.DateFormat getInstanceForSkeleton(String); - method public static final android.icu.text.DateFormat getInstanceForSkeleton(String, java.util.Locale); - method public static final android.icu.text.DateFormat getInstanceForSkeleton(String, android.icu.util.ULocale); - method public static final android.icu.text.DateFormat getInstanceForSkeleton(android.icu.util.Calendar, String, java.util.Locale); - method public static final android.icu.text.DateFormat getInstanceForSkeleton(android.icu.util.Calendar, String, android.icu.util.ULocale); - method public android.icu.text.NumberFormat getNumberFormat(); - method public static final android.icu.text.DateFormat getPatternInstance(String); - method public static final android.icu.text.DateFormat getPatternInstance(String, java.util.Locale); - method public static final android.icu.text.DateFormat getPatternInstance(String, android.icu.util.ULocale); - method public static final android.icu.text.DateFormat getPatternInstance(android.icu.util.Calendar, String, java.util.Locale); - method public static final android.icu.text.DateFormat getPatternInstance(android.icu.util.Calendar, String, android.icu.util.ULocale); - method public static final android.icu.text.DateFormat getTimeInstance(); - method public static final android.icu.text.DateFormat getTimeInstance(int); - method public static final android.icu.text.DateFormat getTimeInstance(int, java.util.Locale); - method public static final android.icu.text.DateFormat getTimeInstance(int, android.icu.util.ULocale); - method public static final android.icu.text.DateFormat getTimeInstance(android.icu.util.Calendar, int, java.util.Locale); - method public static final android.icu.text.DateFormat getTimeInstance(android.icu.util.Calendar, int, android.icu.util.ULocale); - method public static final android.icu.text.DateFormat getTimeInstance(android.icu.util.Calendar, int); - method public android.icu.util.TimeZone getTimeZone(); - method public boolean isCalendarLenient(); - method public boolean isLenient(); - method public java.util.Date parse(String) throws java.text.ParseException; - method public abstract void parse(String, android.icu.util.Calendar, java.text.ParsePosition); - method public java.util.Date parse(String, java.text.ParsePosition); - method public Object parseObject(String, java.text.ParsePosition); - method public android.icu.text.DateFormat setBooleanAttribute(android.icu.text.DateFormat.BooleanAttribute, boolean); - method public void setCalendar(android.icu.util.Calendar); - method public void setCalendarLenient(boolean); - method public void setContext(android.icu.text.DisplayContext); - method public void setLenient(boolean); - method public void setNumberFormat(android.icu.text.NumberFormat); - method public void setTimeZone(android.icu.util.TimeZone); - field public static final String ABBR_GENERIC_TZ = "v"; - field public static final String ABBR_MONTH = "MMM"; - field public static final String ABBR_MONTH_DAY = "MMMd"; - field public static final String ABBR_MONTH_WEEKDAY_DAY = "MMMEd"; - field public static final String ABBR_QUARTER = "QQQ"; - field public static final String ABBR_SPECIFIC_TZ = "z"; - field public static final String ABBR_UTC_TZ = "ZZZZ"; - field public static final String ABBR_WEEKDAY = "E"; - field public static final int AM_PM_FIELD = 14; // 0xe - field public static final int AM_PM_MIDNIGHT_NOON_FIELD = 35; // 0x23 - field public static final int DATE_FIELD = 3; // 0x3 - field public static final String DAY = "d"; - field public static final int DAY_OF_WEEK_FIELD = 9; // 0x9 - field public static final int DAY_OF_WEEK_IN_MONTH_FIELD = 11; // 0xb - field public static final int DAY_OF_YEAR_FIELD = 10; // 0xa - field public static final int DEFAULT = 2; // 0x2 - field public static final int DOW_LOCAL_FIELD = 19; // 0x13 - field public static final int ERA_FIELD = 0; // 0x0 - field public static final int EXTENDED_YEAR_FIELD = 20; // 0x14 - field public static final int FLEXIBLE_DAY_PERIOD_FIELD = 36; // 0x24 - field public static final int FRACTIONAL_SECOND_FIELD = 8; // 0x8 - field public static final int FULL = 0; // 0x0 - field public static final String GENERIC_TZ = "vvvv"; - field public static final String HOUR = "j"; - field public static final int HOUR0_FIELD = 16; // 0x10 - field public static final int HOUR1_FIELD = 15; // 0xf - field public static final String HOUR24 = "H"; - field public static final String HOUR24_MINUTE = "Hm"; - field public static final String HOUR24_MINUTE_SECOND = "Hms"; - field public static final String HOUR_MINUTE = "jm"; - field public static final String HOUR_MINUTE_SECOND = "jms"; - field public static final int HOUR_OF_DAY0_FIELD = 5; // 0x5 - field public static final int HOUR_OF_DAY1_FIELD = 4; // 0x4 - field public static final int JULIAN_DAY_FIELD = 21; // 0x15 - field public static final String LOCATION_TZ = "VVVV"; - field public static final int LONG = 1; // 0x1 - field public static final int MEDIUM = 2; // 0x2 - field public static final int MILLISECONDS_IN_DAY_FIELD = 22; // 0x16 - field public static final int MILLISECOND_FIELD = 8; // 0x8 - field public static final String MINUTE = "m"; - field public static final int MINUTE_FIELD = 6; // 0x6 - field public static final String MINUTE_SECOND = "ms"; - field public static final String MONTH = "MMMM"; - field public static final String MONTH_DAY = "MMMMd"; - field public static final int MONTH_FIELD = 2; // 0x2 - field public static final String MONTH_WEEKDAY_DAY = "MMMMEEEEd"; - field public static final int NONE = -1; // 0xffffffff - field public static final String NUM_MONTH = "M"; - field public static final String NUM_MONTH_DAY = "Md"; - field public static final String NUM_MONTH_WEEKDAY_DAY = "MEd"; - field public static final String QUARTER = "QQQQ"; - field public static final int QUARTER_FIELD = 27; // 0x1b - field public static final int RELATIVE = 128; // 0x80 - field public static final int RELATIVE_DEFAULT = 130; // 0x82 - field public static final int RELATIVE_FULL = 128; // 0x80 - field public static final int RELATIVE_LONG = 129; // 0x81 - field public static final int RELATIVE_MEDIUM = 130; // 0x82 - field public static final int RELATIVE_SHORT = 131; // 0x83 - field public static final String SECOND = "s"; - field public static final int SECOND_FIELD = 7; // 0x7 - field public static final int SHORT = 3; // 0x3 - field public static final String SPECIFIC_TZ = "zzzz"; - field public static final int STANDALONE_DAY_FIELD = 25; // 0x19 - field public static final int STANDALONE_MONTH_FIELD = 26; // 0x1a - field public static final int STANDALONE_QUARTER_FIELD = 28; // 0x1c - field public static final int TIMEZONE_FIELD = 17; // 0x11 - field public static final int TIMEZONE_GENERIC_FIELD = 24; // 0x18 - field public static final int TIMEZONE_ISO_FIELD = 32; // 0x20 - field public static final int TIMEZONE_ISO_LOCAL_FIELD = 33; // 0x21 - field public static final int TIMEZONE_LOCALIZED_GMT_OFFSET_FIELD = 31; // 0x1f - field public static final int TIMEZONE_RFC_FIELD = 23; // 0x17 - field public static final int TIMEZONE_SPECIAL_FIELD = 29; // 0x1d - field public static final String WEEKDAY = "EEEE"; - field public static final int WEEK_OF_MONTH_FIELD = 13; // 0xd - field public static final int WEEK_OF_YEAR_FIELD = 12; // 0xc - field public static final String YEAR = "y"; - field public static final String YEAR_ABBR_MONTH = "yMMM"; - field public static final String YEAR_ABBR_MONTH_DAY = "yMMMd"; - field public static final String YEAR_ABBR_MONTH_WEEKDAY_DAY = "yMMMEd"; - field public static final String YEAR_ABBR_QUARTER = "yQQQ"; - field public static final int YEAR_FIELD = 1; // 0x1 - field public static final String YEAR_MONTH = "yMMMM"; - field public static final String YEAR_MONTH_DAY = "yMMMMd"; - field public static final String YEAR_MONTH_WEEKDAY_DAY = "yMMMMEEEEd"; - field public static final int YEAR_NAME_FIELD = 30; // 0x1e - field public static final String YEAR_NUM_MONTH = "yM"; - field public static final String YEAR_NUM_MONTH_DAY = "yMd"; - field public static final String YEAR_NUM_MONTH_WEEKDAY_DAY = "yMEd"; - field public static final String YEAR_QUARTER = "yQQQQ"; - field public static final int YEAR_WOY_FIELD = 18; // 0x12 - field protected android.icu.util.Calendar calendar; - field protected android.icu.text.NumberFormat numberFormat; - } - - public enum DateFormat.BooleanAttribute { - enum_constant public static final android.icu.text.DateFormat.BooleanAttribute PARSE_ALLOW_NUMERIC; - enum_constant public static final android.icu.text.DateFormat.BooleanAttribute PARSE_ALLOW_WHITESPACE; - enum_constant public static final android.icu.text.DateFormat.BooleanAttribute PARSE_MULTIPLE_PATTERNS_FOR_MATCH; - enum_constant public static final android.icu.text.DateFormat.BooleanAttribute PARSE_PARTIAL_LITERAL_MATCH; - } - - public static class DateFormat.Field extends java.text.Format.Field { - ctor protected DateFormat.Field(String, int); - method public int getCalendarField(); - method public static android.icu.text.DateFormat.Field ofCalendarField(int); - field public static final android.icu.text.DateFormat.Field AM_PM; - field public static final android.icu.text.DateFormat.Field AM_PM_MIDNIGHT_NOON; - field public static final android.icu.text.DateFormat.Field DAY_OF_MONTH; - field public static final android.icu.text.DateFormat.Field DAY_OF_WEEK; - field public static final android.icu.text.DateFormat.Field DAY_OF_WEEK_IN_MONTH; - field public static final android.icu.text.DateFormat.Field DAY_OF_YEAR; - field public static final android.icu.text.DateFormat.Field DOW_LOCAL; - field public static final android.icu.text.DateFormat.Field ERA; - field public static final android.icu.text.DateFormat.Field EXTENDED_YEAR; - field public static final android.icu.text.DateFormat.Field FLEXIBLE_DAY_PERIOD; - field public static final android.icu.text.DateFormat.Field HOUR0; - field public static final android.icu.text.DateFormat.Field HOUR1; - field public static final android.icu.text.DateFormat.Field HOUR_OF_DAY0; - field public static final android.icu.text.DateFormat.Field HOUR_OF_DAY1; - field public static final android.icu.text.DateFormat.Field JULIAN_DAY; - field public static final android.icu.text.DateFormat.Field MILLISECOND; - field public static final android.icu.text.DateFormat.Field MILLISECONDS_IN_DAY; - field public static final android.icu.text.DateFormat.Field MINUTE; - field public static final android.icu.text.DateFormat.Field MONTH; - field public static final android.icu.text.DateFormat.Field QUARTER; - field public static final android.icu.text.DateFormat.Field SECOND; - field public static final android.icu.text.DateFormat.Field TIME_ZONE; - field public static final android.icu.text.DateFormat.Field WEEK_OF_MONTH; - field public static final android.icu.text.DateFormat.Field WEEK_OF_YEAR; - field public static final android.icu.text.DateFormat.Field YEAR; - field public static final android.icu.text.DateFormat.Field YEAR_WOY; - } - - public class DateFormatSymbols implements java.lang.Cloneable java.io.Serializable { - ctor public DateFormatSymbols(); - ctor public DateFormatSymbols(java.util.Locale); - ctor public DateFormatSymbols(android.icu.util.ULocale); - ctor public DateFormatSymbols(android.icu.util.Calendar, java.util.Locale); - ctor public DateFormatSymbols(android.icu.util.Calendar, android.icu.util.ULocale); - ctor public DateFormatSymbols(Class<? extends android.icu.util.Calendar>, java.util.Locale); - ctor public DateFormatSymbols(Class<? extends android.icu.util.Calendar>, android.icu.util.ULocale); - ctor public DateFormatSymbols(java.util.ResourceBundle, java.util.Locale); - ctor public DateFormatSymbols(java.util.ResourceBundle, android.icu.util.ULocale); - method public Object clone(); - method public String[] getAmPmStrings(); - method public static java.util.Locale[] getAvailableLocales(); - method public String[] getEraNames(); - method public String[] getEras(); - method public static android.icu.text.DateFormatSymbols getInstance(); - method public static android.icu.text.DateFormatSymbols getInstance(java.util.Locale); - method public static android.icu.text.DateFormatSymbols getInstance(android.icu.util.ULocale); - method public String getLocalPatternChars(); - method public String[] getMonths(); - method public String[] getMonths(int, int); - method public String[] getQuarters(int, int); - method public String[] getShortMonths(); - method public String[] getShortWeekdays(); - method public String[] getWeekdays(); - method public String[] getWeekdays(int, int); - method public String[] getYearNames(int, int); - method public String[] getZodiacNames(int, int); - method public String[][] getZoneStrings(); - method protected void initializeData(android.icu.util.ULocale, String); - method public void setAmPmStrings(String[]); - method public void setEraNames(String[]); - method public void setEras(String[]); - method public void setLocalPatternChars(String); - method public void setMonths(String[]); - method public void setMonths(String[], int, int); - method public void setQuarters(String[], int, int); - method public void setShortMonths(String[]); - method public void setShortWeekdays(String[]); - method public void setWeekdays(String[], int, int); - method public void setWeekdays(String[]); - method public void setYearNames(String[], int, int); - method public void setZodiacNames(String[], int, int); - method public void setZoneStrings(String[][]); - field public static final int ABBREVIATED = 0; // 0x0 - field public static final int FORMAT = 0; // 0x0 - field public static final int NARROW = 2; // 0x2 - field public static final int SHORT = 3; // 0x3 - field public static final int STANDALONE = 1; // 0x1 - field public static final int WIDE = 1; // 0x1 - } - - public class DateIntervalFormat extends android.icu.text.UFormat { - method public final StringBuffer format(Object, StringBuffer, java.text.FieldPosition); - method public final StringBuffer format(android.icu.util.DateInterval, StringBuffer, java.text.FieldPosition); - method public final StringBuffer format(android.icu.util.Calendar, android.icu.util.Calendar, StringBuffer, java.text.FieldPosition); - method public android.icu.text.DateFormat getDateFormat(); - method public android.icu.text.DateIntervalInfo getDateIntervalInfo(); - method public static final android.icu.text.DateIntervalFormat getInstance(String); - method public static final android.icu.text.DateIntervalFormat getInstance(String, java.util.Locale); - method public static final android.icu.text.DateIntervalFormat getInstance(String, android.icu.util.ULocale); - method public static final android.icu.text.DateIntervalFormat getInstance(String, android.icu.text.DateIntervalInfo); - method public static final android.icu.text.DateIntervalFormat getInstance(String, java.util.Locale, android.icu.text.DateIntervalInfo); - method public static final android.icu.text.DateIntervalFormat getInstance(String, android.icu.util.ULocale, android.icu.text.DateIntervalInfo); - method public android.icu.util.TimeZone getTimeZone(); - method @Deprecated public Object parseObject(String, java.text.ParsePosition); - method public void setDateIntervalInfo(android.icu.text.DateIntervalInfo); - method public void setTimeZone(android.icu.util.TimeZone); - } - - public class DateIntervalInfo implements java.lang.Cloneable android.icu.util.Freezable<android.icu.text.DateIntervalInfo> java.io.Serializable { - ctor public DateIntervalInfo(android.icu.util.ULocale); - ctor public DateIntervalInfo(java.util.Locale); - method public Object clone(); - method public android.icu.text.DateIntervalInfo cloneAsThawed(); - method public android.icu.text.DateIntervalInfo freeze(); - method public boolean getDefaultOrder(); - method public String getFallbackIntervalPattern(); - method public android.icu.text.DateIntervalInfo.PatternInfo getIntervalPattern(String, int); - method public boolean isFrozen(); - method public void setFallbackIntervalPattern(String); - method public void setIntervalPattern(String, int, String); - } - - public static final class DateIntervalInfo.PatternInfo implements java.lang.Cloneable java.io.Serializable { - ctor public DateIntervalInfo.PatternInfo(String, String, boolean); - method public boolean firstDateInPtnIsLaterDate(); - method public String getFirstPart(); - method public String getSecondPart(); - } - - public class DateTimePatternGenerator implements java.lang.Cloneable android.icu.util.Freezable<android.icu.text.DateTimePatternGenerator> { - ctor protected DateTimePatternGenerator(); - method public android.icu.text.DateTimePatternGenerator addPattern(String, boolean, android.icu.text.DateTimePatternGenerator.PatternInfo); - method public Object clone(); - method public android.icu.text.DateTimePatternGenerator cloneAsThawed(); - method public android.icu.text.DateTimePatternGenerator freeze(); - method public String getAppendItemFormat(int); - method public String getAppendItemName(int); - method public String getBaseSkeleton(String); - method public java.util.Set<java.lang.String> getBaseSkeletons(java.util.Set<java.lang.String>); - method public String getBestPattern(String); - method public String getBestPattern(String, int); - method public String getDateTimeFormat(); - method public String getDecimal(); - method public static android.icu.text.DateTimePatternGenerator getEmptyInstance(); - method public String getFieldDisplayName(int, android.icu.text.DateTimePatternGenerator.DisplayWidth); - method public static android.icu.text.DateTimePatternGenerator getInstance(); - method public static android.icu.text.DateTimePatternGenerator getInstance(android.icu.util.ULocale); - method public static android.icu.text.DateTimePatternGenerator getInstance(java.util.Locale); - method public String getSkeleton(String); - method public java.util.Map<java.lang.String,java.lang.String> getSkeletons(java.util.Map<java.lang.String,java.lang.String>); - method public boolean isFrozen(); - method public String replaceFieldTypes(String, String); - method public String replaceFieldTypes(String, String, int); - method public void setAppendItemFormat(int, String); - method public void setAppendItemName(int, String); - method public void setDateTimeFormat(String); - method public void setDecimal(String); - field public static final int DAY = 7; // 0x7 - field public static final int DAYPERIOD = 10; // 0xa - field public static final int DAY_OF_WEEK_IN_MONTH = 9; // 0x9 - field public static final int DAY_OF_YEAR = 8; // 0x8 - field public static final int ERA = 0; // 0x0 - field public static final int FRACTIONAL_SECOND = 14; // 0xe - field public static final int HOUR = 11; // 0xb - field public static final int MATCH_ALL_FIELDS_LENGTH = 65535; // 0xffff - field public static final int MATCH_HOUR_FIELD_LENGTH = 2048; // 0x800 - field public static final int MATCH_NO_OPTIONS = 0; // 0x0 - field public static final int MINUTE = 12; // 0xc - field public static final int MONTH = 3; // 0x3 - field public static final int QUARTER = 2; // 0x2 - field public static final int SECOND = 13; // 0xd - field public static final int WEEKDAY = 6; // 0x6 - field public static final int WEEK_OF_MONTH = 5; // 0x5 - field public static final int WEEK_OF_YEAR = 4; // 0x4 - field public static final int YEAR = 1; // 0x1 - field public static final int ZONE = 15; // 0xf - } - - public enum DateTimePatternGenerator.DisplayWidth { - enum_constant public static final android.icu.text.DateTimePatternGenerator.DisplayWidth ABBREVIATED; - enum_constant public static final android.icu.text.DateTimePatternGenerator.DisplayWidth NARROW; - enum_constant public static final android.icu.text.DateTimePatternGenerator.DisplayWidth WIDE; - } - - public static final class DateTimePatternGenerator.PatternInfo { - ctor public DateTimePatternGenerator.PatternInfo(); - field public static final int BASE_CONFLICT = 1; // 0x1 - field public static final int CONFLICT = 2; // 0x2 - field public static final int OK = 0; // 0x0 - field public String conflictingPattern; - field public int status; - } - - public class DecimalFormat extends android.icu.text.NumberFormat { - ctor public DecimalFormat(); - ctor public DecimalFormat(String); - ctor public DecimalFormat(String, android.icu.text.DecimalFormatSymbols); - ctor public DecimalFormat(String, android.icu.text.DecimalFormatSymbols, android.icu.text.CurrencyPluralInfo, int); - method public void applyLocalizedPattern(String); - method public void applyPattern(String); - method public boolean areSignificantDigitsUsed(); - method public StringBuffer format(double, StringBuffer, java.text.FieldPosition); - method public StringBuffer format(long, StringBuffer, java.text.FieldPosition); - method public StringBuffer format(java.math.BigInteger, StringBuffer, java.text.FieldPosition); - method public StringBuffer format(java.math.BigDecimal, StringBuffer, java.text.FieldPosition); - method public StringBuffer format(android.icu.math.BigDecimal, StringBuffer, java.text.FieldPosition); - method public android.icu.text.CurrencyPluralInfo getCurrencyPluralInfo(); - method public android.icu.util.Currency.CurrencyUsage getCurrencyUsage(); - method public android.icu.text.DecimalFormatSymbols getDecimalFormatSymbols(); - method public int getFormatWidth(); - method public int getGroupingSize(); - method public java.math.MathContext getMathContext(); - method public android.icu.math.MathContext getMathContextICU(); - method public int getMaximumSignificantDigits(); - method public byte getMinimumExponentDigits(); - method public int getMinimumSignificantDigits(); - method public int getMultiplier(); - method public String getNegativePrefix(); - method public String getNegativeSuffix(); - method public char getPadCharacter(); - method public int getPadPosition(); - method @Deprecated public int getParseMaxDigits(); - method public String getPositivePrefix(); - method public String getPositiveSuffix(); - method public java.math.BigDecimal getRoundingIncrement(); - method public int getSecondaryGroupingSize(); - method public boolean isDecimalPatternMatchRequired(); - method public boolean isDecimalSeparatorAlwaysShown(); - method public boolean isExponentSignAlwaysShown(); - method public boolean isParseBigDecimal(); - method public boolean isScientificNotation(); - method public Number parse(String, java.text.ParsePosition); - method public void setCurrencyPluralInfo(android.icu.text.CurrencyPluralInfo); - method public void setCurrencyUsage(android.icu.util.Currency.CurrencyUsage); - method public void setDecimalFormatSymbols(android.icu.text.DecimalFormatSymbols); - method public void setDecimalPatternMatchRequired(boolean); - method public void setDecimalSeparatorAlwaysShown(boolean); - method public void setExponentSignAlwaysShown(boolean); - method public void setFormatWidth(int); - method public void setGroupingSize(int); - method public void setMathContext(java.math.MathContext); - method public void setMathContextICU(android.icu.math.MathContext); - method public void setMaximumSignificantDigits(int); - method public void setMinimumExponentDigits(byte); - method public void setMinimumSignificantDigits(int); - method public void setMultiplier(int); - method public void setNegativePrefix(String); - method public void setNegativeSuffix(String); - method public void setPadCharacter(char); - method public void setPadPosition(int); - method public void setParseBigDecimal(boolean); - method @Deprecated public void setParseMaxDigits(int); - method public void setPositivePrefix(String); - method public void setPositiveSuffix(String); - method public void setRoundingIncrement(java.math.BigDecimal); - method public void setRoundingIncrement(android.icu.math.BigDecimal); - method public void setRoundingIncrement(double); - method public void setScientificNotation(boolean); - method public void setSecondaryGroupingSize(int); - method public void setSignificantDigitsUsed(boolean); - method public String toLocalizedPattern(); - method public String toPattern(); - field public static final int PAD_AFTER_PREFIX = 1; // 0x1 - field public static final int PAD_AFTER_SUFFIX = 3; // 0x3 - field public static final int PAD_BEFORE_PREFIX = 0; // 0x0 - field public static final int PAD_BEFORE_SUFFIX = 2; // 0x2 - } - - public class DecimalFormatSymbols implements java.lang.Cloneable java.io.Serializable { - ctor public DecimalFormatSymbols(); - ctor public DecimalFormatSymbols(java.util.Locale); - ctor public DecimalFormatSymbols(android.icu.util.ULocale); - method public Object clone(); - method public static android.icu.text.DecimalFormatSymbols forNumberingSystem(java.util.Locale, android.icu.text.NumberingSystem); - method public static android.icu.text.DecimalFormatSymbols forNumberingSystem(android.icu.util.ULocale, android.icu.text.NumberingSystem); - method public static java.util.Locale[] getAvailableLocales(); - method public android.icu.util.Currency getCurrency(); - method public String getCurrencySymbol(); - method public char getDecimalSeparator(); - method public String getDecimalSeparatorString(); - method public char getDigit(); - method public String[] getDigitStrings(); - method public char[] getDigits(); - method public String getExponentMultiplicationSign(); - method public String getExponentSeparator(); - method public char getGroupingSeparator(); - method public String getGroupingSeparatorString(); - method public String getInfinity(); - method public static android.icu.text.DecimalFormatSymbols getInstance(); - method public static android.icu.text.DecimalFormatSymbols getInstance(java.util.Locale); - method public static android.icu.text.DecimalFormatSymbols getInstance(android.icu.util.ULocale); - method public String getInternationalCurrencySymbol(); - method public java.util.Locale getLocale(); - method public char getMinusSign(); - method public String getMinusSignString(); - method public char getMonetaryDecimalSeparator(); - method public String getMonetaryDecimalSeparatorString(); - method public char getMonetaryGroupingSeparator(); - method public String getMonetaryGroupingSeparatorString(); - method public String getNaN(); - method public char getPadEscape(); - method public String getPatternForCurrencySpacing(int, boolean); - method public char getPatternSeparator(); - method public char getPerMill(); - method public String getPerMillString(); - method public char getPercent(); - method public String getPercentString(); - method public char getPlusSign(); - method public String getPlusSignString(); - method public char getSignificantDigit(); - method public android.icu.util.ULocale getULocale(); - method public char getZeroDigit(); - method public void setCurrency(android.icu.util.Currency); - method public void setCurrencySymbol(String); - method public void setDecimalSeparator(char); - method public void setDecimalSeparatorString(String); - method public void setDigit(char); - method public void setDigitStrings(String[]); - method public void setExponentMultiplicationSign(String); - method public void setExponentSeparator(String); - method public void setGroupingSeparator(char); - method public void setGroupingSeparatorString(String); - method public void setInfinity(String); - method public void setInternationalCurrencySymbol(String); - method public void setMinusSign(char); - method public void setMinusSignString(String); - method public void setMonetaryDecimalSeparator(char); - method public void setMonetaryDecimalSeparatorString(String); - method public void setMonetaryGroupingSeparator(char); - method public void setMonetaryGroupingSeparatorString(String); - method public void setNaN(String); - method public void setPadEscape(char); - method public void setPatternForCurrencySpacing(int, boolean, String); - method public void setPatternSeparator(char); - method public void setPerMill(char); - method public void setPerMillString(String); - method public void setPercent(char); - method public void setPercentString(String); - method public void setPlusSign(char); - method public void setPlusSignString(String); - method public void setSignificantDigit(char); - method public void setZeroDigit(char); - field public static final int CURRENCY_SPC_CURRENCY_MATCH = 0; // 0x0 - field public static final int CURRENCY_SPC_INSERT = 2; // 0x2 - field public static final int CURRENCY_SPC_SURROUNDING_MATCH = 1; // 0x1 - } - - public enum DisplayContext { - method public android.icu.text.DisplayContext.Type type(); - method public int value(); - enum_constant public static final android.icu.text.DisplayContext CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE; - enum_constant public static final android.icu.text.DisplayContext CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE; - enum_constant public static final android.icu.text.DisplayContext CAPITALIZATION_FOR_STANDALONE; - enum_constant public static final android.icu.text.DisplayContext CAPITALIZATION_FOR_UI_LIST_OR_MENU; - enum_constant public static final android.icu.text.DisplayContext CAPITALIZATION_NONE; - enum_constant public static final android.icu.text.DisplayContext DIALECT_NAMES; - enum_constant public static final android.icu.text.DisplayContext LENGTH_FULL; - enum_constant public static final android.icu.text.DisplayContext LENGTH_SHORT; - enum_constant public static final android.icu.text.DisplayContext NO_SUBSTITUTE; - enum_constant public static final android.icu.text.DisplayContext STANDARD_NAMES; - enum_constant public static final android.icu.text.DisplayContext SUBSTITUTE; - } - - public enum DisplayContext.Type { - enum_constant public static final android.icu.text.DisplayContext.Type CAPITALIZATION; - enum_constant public static final android.icu.text.DisplayContext.Type DIALECT_HANDLING; - enum_constant public static final android.icu.text.DisplayContext.Type DISPLAY_LENGTH; - enum_constant public static final android.icu.text.DisplayContext.Type SUBSTITUTE_HANDLING; - } - - public final class Edits { - ctor public Edits(); - method public void addReplace(int, int); - method public void addUnchanged(int); - method public android.icu.text.Edits.Iterator getCoarseChangesIterator(); - method public android.icu.text.Edits.Iterator getCoarseIterator(); - method public android.icu.text.Edits.Iterator getFineChangesIterator(); - method public android.icu.text.Edits.Iterator getFineIterator(); - method public boolean hasChanges(); - method public int lengthDelta(); - method public android.icu.text.Edits mergeAndAppend(android.icu.text.Edits, android.icu.text.Edits); - method public int numberOfChanges(); - method public void reset(); - } - - public static final class Edits.Iterator { - method public int destinationIndex(); - method public int destinationIndexFromSourceIndex(int); - method public boolean findDestinationIndex(int); - method public boolean findSourceIndex(int); - method public boolean hasChange(); - method public int newLength(); - method public boolean next(); - method public int oldLength(); - method public int replacementIndex(); - method public int sourceIndex(); - method public int sourceIndexFromDestinationIndex(int); - } - - public abstract class IDNA { - method public static android.icu.text.IDNA getUTS46Instance(int); - method public abstract StringBuilder labelToASCII(CharSequence, StringBuilder, android.icu.text.IDNA.Info); - method public abstract StringBuilder labelToUnicode(CharSequence, StringBuilder, android.icu.text.IDNA.Info); - method public abstract StringBuilder nameToASCII(CharSequence, StringBuilder, android.icu.text.IDNA.Info); - method public abstract StringBuilder nameToUnicode(CharSequence, StringBuilder, android.icu.text.IDNA.Info); - field public static final int CHECK_BIDI = 4; // 0x4 - field public static final int CHECK_CONTEXTJ = 8; // 0x8 - field public static final int CHECK_CONTEXTO = 64; // 0x40 - field public static final int DEFAULT = 0; // 0x0 - field public static final int NONTRANSITIONAL_TO_ASCII = 16; // 0x10 - field public static final int NONTRANSITIONAL_TO_UNICODE = 32; // 0x20 - field public static final int USE_STD3_RULES = 2; // 0x2 - } - - public enum IDNA.Error { - enum_constant public static final android.icu.text.IDNA.Error BIDI; - enum_constant public static final android.icu.text.IDNA.Error CONTEXTJ; - enum_constant public static final android.icu.text.IDNA.Error CONTEXTO_DIGITS; - enum_constant public static final android.icu.text.IDNA.Error CONTEXTO_PUNCTUATION; - enum_constant public static final android.icu.text.IDNA.Error DISALLOWED; - enum_constant public static final android.icu.text.IDNA.Error DOMAIN_NAME_TOO_LONG; - enum_constant public static final android.icu.text.IDNA.Error EMPTY_LABEL; - enum_constant public static final android.icu.text.IDNA.Error HYPHEN_3_4; - enum_constant public static final android.icu.text.IDNA.Error INVALID_ACE_LABEL; - enum_constant public static final android.icu.text.IDNA.Error LABEL_HAS_DOT; - enum_constant public static final android.icu.text.IDNA.Error LABEL_TOO_LONG; - enum_constant public static final android.icu.text.IDNA.Error LEADING_COMBINING_MARK; - enum_constant public static final android.icu.text.IDNA.Error LEADING_HYPHEN; - enum_constant public static final android.icu.text.IDNA.Error PUNYCODE; - enum_constant public static final android.icu.text.IDNA.Error TRAILING_HYPHEN; - } - - public static final class IDNA.Info { - ctor public IDNA.Info(); - method public java.util.Set<android.icu.text.IDNA.Error> getErrors(); - method public boolean hasErrors(); - method public boolean isTransitionalDifferent(); - } - - public final class ListFormatter { - method public String format(java.lang.Object...); - method public String format(java.util.Collection<?>); - method public static android.icu.text.ListFormatter getInstance(android.icu.util.ULocale); - method public static android.icu.text.ListFormatter getInstance(java.util.Locale); - method public static android.icu.text.ListFormatter getInstance(); - method public String getPatternForNumItems(int); - } - - public abstract class LocaleDisplayNames { - method public abstract android.icu.text.DisplayContext getContext(android.icu.text.DisplayContext.Type); - method public abstract android.icu.text.LocaleDisplayNames.DialectHandling getDialectHandling(); - method public static android.icu.text.LocaleDisplayNames getInstance(android.icu.util.ULocale); - method public static android.icu.text.LocaleDisplayNames getInstance(java.util.Locale); - method public static android.icu.text.LocaleDisplayNames getInstance(android.icu.util.ULocale, android.icu.text.LocaleDisplayNames.DialectHandling); - method public static android.icu.text.LocaleDisplayNames getInstance(android.icu.util.ULocale, android.icu.text.DisplayContext...); - method public static android.icu.text.LocaleDisplayNames getInstance(java.util.Locale, android.icu.text.DisplayContext...); - method public abstract android.icu.util.ULocale getLocale(); - method public java.util.List<android.icu.text.LocaleDisplayNames.UiListItem> getUiList(java.util.Set<android.icu.util.ULocale>, boolean, java.util.Comparator<java.lang.Object>); - method public abstract java.util.List<android.icu.text.LocaleDisplayNames.UiListItem> getUiListCompareWholeItems(java.util.Set<android.icu.util.ULocale>, java.util.Comparator<android.icu.text.LocaleDisplayNames.UiListItem>); - method public abstract String keyDisplayName(String); - method public abstract String keyValueDisplayName(String, String); - method public abstract String languageDisplayName(String); - method public abstract String localeDisplayName(android.icu.util.ULocale); - method public abstract String localeDisplayName(java.util.Locale); - method public abstract String localeDisplayName(String); - method public abstract String regionDisplayName(String); - method public abstract String scriptDisplayName(String); - method public abstract String scriptDisplayName(int); - method public abstract String variantDisplayName(String); - } - - public enum LocaleDisplayNames.DialectHandling { - enum_constant public static final android.icu.text.LocaleDisplayNames.DialectHandling DIALECT_NAMES; - enum_constant public static final android.icu.text.LocaleDisplayNames.DialectHandling STANDARD_NAMES; - } - - public static class LocaleDisplayNames.UiListItem { - ctor public LocaleDisplayNames.UiListItem(android.icu.util.ULocale, android.icu.util.ULocale, String, String); - method public static java.util.Comparator<android.icu.text.LocaleDisplayNames.UiListItem> getComparator(java.util.Comparator<java.lang.Object>, boolean); - field public final android.icu.util.ULocale minimized; - field public final android.icu.util.ULocale modified; - field public final String nameInDisplayLocale; - field public final String nameInSelf; - } - - public class MeasureFormat extends android.icu.text.UFormat { - method public final boolean equals(Object); - method public StringBuffer format(Object, StringBuffer, java.text.FieldPosition); - method public StringBuilder formatMeasurePerUnit(android.icu.util.Measure, android.icu.util.MeasureUnit, StringBuilder, java.text.FieldPosition); - method public final String formatMeasures(android.icu.util.Measure...); - method public StringBuilder formatMeasures(StringBuilder, java.text.FieldPosition, android.icu.util.Measure...); - method public static android.icu.text.MeasureFormat getCurrencyFormat(android.icu.util.ULocale); - method public static android.icu.text.MeasureFormat getCurrencyFormat(java.util.Locale); - method public static android.icu.text.MeasureFormat getCurrencyFormat(); - method public static android.icu.text.MeasureFormat getInstance(android.icu.util.ULocale, android.icu.text.MeasureFormat.FormatWidth); - method public static android.icu.text.MeasureFormat getInstance(java.util.Locale, android.icu.text.MeasureFormat.FormatWidth); - method public static android.icu.text.MeasureFormat getInstance(android.icu.util.ULocale, android.icu.text.MeasureFormat.FormatWidth, android.icu.text.NumberFormat); - method public static android.icu.text.MeasureFormat getInstance(java.util.Locale, android.icu.text.MeasureFormat.FormatWidth, android.icu.text.NumberFormat); - method public final android.icu.util.ULocale getLocale(); - method public android.icu.text.NumberFormat getNumberFormat(); - method public String getUnitDisplayName(android.icu.util.MeasureUnit); - method public android.icu.text.MeasureFormat.FormatWidth getWidth(); - method public final int hashCode(); - method public android.icu.util.Measure parseObject(String, java.text.ParsePosition); - } - - public enum MeasureFormat.FormatWidth { - enum_constant public static final android.icu.text.MeasureFormat.FormatWidth NARROW; - enum_constant public static final android.icu.text.MeasureFormat.FormatWidth NUMERIC; - enum_constant public static final android.icu.text.MeasureFormat.FormatWidth SHORT; - enum_constant public static final android.icu.text.MeasureFormat.FormatWidth WIDE; - } - - public class MessageFormat extends android.icu.text.UFormat { - ctor public MessageFormat(String); - ctor public MessageFormat(String, java.util.Locale); - ctor public MessageFormat(String, android.icu.util.ULocale); - method public void applyPattern(String); - method public void applyPattern(String, android.icu.text.MessagePattern.ApostropheMode); - method public static String autoQuoteApostrophe(String); - method public final StringBuffer format(Object[], StringBuffer, java.text.FieldPosition); - method public final StringBuffer format(java.util.Map<java.lang.String,java.lang.Object>, StringBuffer, java.text.FieldPosition); - method public static String format(String, java.lang.Object...); - method public static String format(String, java.util.Map<java.lang.String,java.lang.Object>); - method public final StringBuffer format(Object, StringBuffer, java.text.FieldPosition); - method public android.icu.text.MessagePattern.ApostropheMode getApostropheMode(); - method public java.util.Set<java.lang.String> getArgumentNames(); - method public java.text.Format getFormatByArgumentName(String); - method public java.text.Format[] getFormats(); - method public java.text.Format[] getFormatsByArgumentIndex(); - method public java.util.Locale getLocale(); - method public android.icu.util.ULocale getULocale(); - method public Object[] parse(String, java.text.ParsePosition); - method public Object[] parse(String) throws java.text.ParseException; - method public Object parseObject(String, java.text.ParsePosition); - method public java.util.Map<java.lang.String,java.lang.Object> parseToMap(String, java.text.ParsePosition); - method public java.util.Map<java.lang.String,java.lang.Object> parseToMap(String) throws java.text.ParseException; - method public void setFormat(int, java.text.Format); - method public void setFormatByArgumentIndex(int, java.text.Format); - method public void setFormatByArgumentName(String, java.text.Format); - method public void setFormats(java.text.Format[]); - method public void setFormatsByArgumentIndex(java.text.Format[]); - method public void setFormatsByArgumentName(java.util.Map<java.lang.String,java.text.Format>); - method public void setLocale(java.util.Locale); - method public void setLocale(android.icu.util.ULocale); - method public String toPattern(); - method public boolean usesNamedArguments(); - } - - public static class MessageFormat.Field extends java.text.Format.Field { - ctor protected MessageFormat.Field(String); - field public static final android.icu.text.MessageFormat.Field ARGUMENT; - } - - public final class MessagePattern implements java.lang.Cloneable android.icu.util.Freezable<android.icu.text.MessagePattern> { - ctor public MessagePattern(); - ctor public MessagePattern(android.icu.text.MessagePattern.ApostropheMode); - ctor public MessagePattern(String); - method public String autoQuoteApostropheDeep(); - method public void clear(); - method public void clearPatternAndSetApostropheMode(android.icu.text.MessagePattern.ApostropheMode); - method public Object clone(); - method public android.icu.text.MessagePattern cloneAsThawed(); - method public int countParts(); - method public android.icu.text.MessagePattern freeze(); - method public android.icu.text.MessagePattern.ApostropheMode getApostropheMode(); - method public int getLimitPartIndex(int); - method public double getNumericValue(android.icu.text.MessagePattern.Part); - method public android.icu.text.MessagePattern.Part getPart(int); - method public android.icu.text.MessagePattern.Part.Type getPartType(int); - method public int getPatternIndex(int); - method public String getPatternString(); - method public double getPluralOffset(int); - method public String getSubstring(android.icu.text.MessagePattern.Part); - method public boolean hasNamedArguments(); - method public boolean hasNumberedArguments(); - method public boolean isFrozen(); - method public android.icu.text.MessagePattern parse(String); - method public android.icu.text.MessagePattern parseChoiceStyle(String); - method public android.icu.text.MessagePattern parsePluralStyle(String); - method public android.icu.text.MessagePattern parseSelectStyle(String); - method public boolean partSubstringMatches(android.icu.text.MessagePattern.Part, String); - method public static int validateArgumentName(String); - field public static final int ARG_NAME_NOT_NUMBER = -1; // 0xffffffff - field public static final int ARG_NAME_NOT_VALID = -2; // 0xfffffffe - field public static final double NO_NUMERIC_VALUE = -1.23456789E8; - } - - public enum MessagePattern.ApostropheMode { - enum_constant public static final android.icu.text.MessagePattern.ApostropheMode DOUBLE_OPTIONAL; - enum_constant public static final android.icu.text.MessagePattern.ApostropheMode DOUBLE_REQUIRED; - } - - public enum MessagePattern.ArgType { - method public boolean hasPluralStyle(); - enum_constant public static final android.icu.text.MessagePattern.ArgType CHOICE; - enum_constant public static final android.icu.text.MessagePattern.ArgType NONE; - enum_constant public static final android.icu.text.MessagePattern.ArgType PLURAL; - enum_constant public static final android.icu.text.MessagePattern.ArgType SELECT; - enum_constant public static final android.icu.text.MessagePattern.ArgType SELECTORDINAL; - enum_constant public static final android.icu.text.MessagePattern.ArgType SIMPLE; - } - - public static final class MessagePattern.Part { - method public android.icu.text.MessagePattern.ArgType getArgType(); - method public int getIndex(); - method public int getLength(); - method public int getLimit(); - method public android.icu.text.MessagePattern.Part.Type getType(); - method public int getValue(); - } - - public enum MessagePattern.Part.Type { - method public boolean hasNumericValue(); - enum_constant public static final android.icu.text.MessagePattern.Part.Type ARG_DOUBLE; - enum_constant public static final android.icu.text.MessagePattern.Part.Type ARG_INT; - enum_constant public static final android.icu.text.MessagePattern.Part.Type ARG_LIMIT; - enum_constant public static final android.icu.text.MessagePattern.Part.Type ARG_NAME; - enum_constant public static final android.icu.text.MessagePattern.Part.Type ARG_NUMBER; - enum_constant public static final android.icu.text.MessagePattern.Part.Type ARG_SELECTOR; - enum_constant public static final android.icu.text.MessagePattern.Part.Type ARG_START; - enum_constant public static final android.icu.text.MessagePattern.Part.Type ARG_STYLE; - enum_constant public static final android.icu.text.MessagePattern.Part.Type ARG_TYPE; - enum_constant public static final android.icu.text.MessagePattern.Part.Type INSERT_CHAR; - enum_constant public static final android.icu.text.MessagePattern.Part.Type MSG_LIMIT; - enum_constant public static final android.icu.text.MessagePattern.Part.Type MSG_START; - enum_constant public static final android.icu.text.MessagePattern.Part.Type REPLACE_NUMBER; - enum_constant public static final android.icu.text.MessagePattern.Part.Type SKIP_SYNTAX; - } - - public final class Normalizer implements java.lang.Cloneable { - method @Deprecated public Object clone(); - method public static int compare(char[], int, int, char[], int, int, int); - method public static int compare(String, String, int); - method public static int compare(char[], char[], int); - method public static int compare(int, int, int); - method public static int compare(int, String, int); - field public static final int COMPARE_CODE_POINT_ORDER = 32768; // 0x8000 - field public static final int COMPARE_IGNORE_CASE = 65536; // 0x10000 - field public static final int FOLD_CASE_DEFAULT = 0; // 0x0 - field public static final int FOLD_CASE_EXCLUDE_SPECIAL_I = 1; // 0x1 - field public static final int INPUT_IS_FCD = 131072; // 0x20000 - field public static final android.icu.text.Normalizer.QuickCheckResult MAYBE; - field public static final android.icu.text.Normalizer.QuickCheckResult NO; - field public static final android.icu.text.Normalizer.QuickCheckResult YES; - } - - public static final class Normalizer.QuickCheckResult { - } - - public abstract class Normalizer2 { - method public abstract StringBuilder append(StringBuilder, CharSequence); - method public int composePair(int, int); - method public int getCombiningClass(int); - method public abstract String getDecomposition(int); - method public static android.icu.text.Normalizer2 getInstance(java.io.InputStream, String, android.icu.text.Normalizer2.Mode); - method public static android.icu.text.Normalizer2 getNFCInstance(); - method public static android.icu.text.Normalizer2 getNFDInstance(); - method public static android.icu.text.Normalizer2 getNFKCCasefoldInstance(); - method public static android.icu.text.Normalizer2 getNFKCInstance(); - method public static android.icu.text.Normalizer2 getNFKDInstance(); - method public String getRawDecomposition(int); - method public abstract boolean hasBoundaryAfter(int); - method public abstract boolean hasBoundaryBefore(int); - method public abstract boolean isInert(int); - method public abstract boolean isNormalized(CharSequence); - method public String normalize(CharSequence); - method public abstract StringBuilder normalize(CharSequence, StringBuilder); - method public abstract Appendable normalize(CharSequence, Appendable); - method public abstract StringBuilder normalizeSecondAndAppend(StringBuilder, CharSequence); - method public abstract android.icu.text.Normalizer.QuickCheckResult quickCheck(CharSequence); - method public abstract int spanQuickCheckYes(CharSequence); - } - - public enum Normalizer2.Mode { - enum_constant public static final android.icu.text.Normalizer2.Mode COMPOSE; - enum_constant public static final android.icu.text.Normalizer2.Mode COMPOSE_CONTIGUOUS; - enum_constant public static final android.icu.text.Normalizer2.Mode DECOMPOSE; - enum_constant public static final android.icu.text.Normalizer2.Mode FCD; - } - - public abstract class NumberFormat extends android.icu.text.UFormat { - ctor public NumberFormat(); - method public StringBuffer format(Object, StringBuffer, java.text.FieldPosition); - method public final String format(double); - method public final String format(long); - method public final String format(java.math.BigInteger); - method public final String format(java.math.BigDecimal); - method public final String format(android.icu.math.BigDecimal); - method public final String format(android.icu.util.CurrencyAmount); - method public abstract StringBuffer format(double, StringBuffer, java.text.FieldPosition); - method public abstract StringBuffer format(long, StringBuffer, java.text.FieldPosition); - method public abstract StringBuffer format(java.math.BigInteger, StringBuffer, java.text.FieldPosition); - method public abstract StringBuffer format(java.math.BigDecimal, StringBuffer, java.text.FieldPosition); - method public abstract StringBuffer format(android.icu.math.BigDecimal, StringBuffer, java.text.FieldPosition); - method public StringBuffer format(android.icu.util.CurrencyAmount, StringBuffer, java.text.FieldPosition); - method public static java.util.Locale[] getAvailableLocales(); - method public android.icu.text.DisplayContext getContext(android.icu.text.DisplayContext.Type); - method public android.icu.util.Currency getCurrency(); - method public static final android.icu.text.NumberFormat getCurrencyInstance(); - method public static android.icu.text.NumberFormat getCurrencyInstance(java.util.Locale); - method public static android.icu.text.NumberFormat getCurrencyInstance(android.icu.util.ULocale); - method public static final android.icu.text.NumberFormat getInstance(); - method public static android.icu.text.NumberFormat getInstance(java.util.Locale); - method public static android.icu.text.NumberFormat getInstance(android.icu.util.ULocale); - method public static final android.icu.text.NumberFormat getInstance(int); - method public static android.icu.text.NumberFormat getInstance(java.util.Locale, int); - method public static android.icu.text.NumberFormat getInstance(android.icu.util.ULocale, int); - method public static final android.icu.text.NumberFormat getIntegerInstance(); - method public static android.icu.text.NumberFormat getIntegerInstance(java.util.Locale); - method public static android.icu.text.NumberFormat getIntegerInstance(android.icu.util.ULocale); - method public int getMaximumFractionDigits(); - method public int getMaximumIntegerDigits(); - method public int getMinimumFractionDigits(); - method public int getMinimumIntegerDigits(); - method public static final android.icu.text.NumberFormat getNumberInstance(); - method public static android.icu.text.NumberFormat getNumberInstance(java.util.Locale); - method public static android.icu.text.NumberFormat getNumberInstance(android.icu.util.ULocale); - method protected static String getPattern(android.icu.util.ULocale, int); - method public static final android.icu.text.NumberFormat getPercentInstance(); - method public static android.icu.text.NumberFormat getPercentInstance(java.util.Locale); - method public static android.icu.text.NumberFormat getPercentInstance(android.icu.util.ULocale); - method public int getRoundingMode(); - method public static final android.icu.text.NumberFormat getScientificInstance(); - method public static android.icu.text.NumberFormat getScientificInstance(java.util.Locale); - method public static android.icu.text.NumberFormat getScientificInstance(android.icu.util.ULocale); - method public boolean isGroupingUsed(); - method public boolean isParseIntegerOnly(); - method public boolean isParseStrict(); - method public abstract Number parse(String, java.text.ParsePosition); - method public Number parse(String) throws java.text.ParseException; - method public android.icu.util.CurrencyAmount parseCurrency(CharSequence, java.text.ParsePosition); - method public final Object parseObject(String, java.text.ParsePosition); - method public void setContext(android.icu.text.DisplayContext); - method public void setCurrency(android.icu.util.Currency); - method public void setGroupingUsed(boolean); - method public void setMaximumFractionDigits(int); - method public void setMaximumIntegerDigits(int); - method public void setMinimumFractionDigits(int); - method public void setMinimumIntegerDigits(int); - method public void setParseIntegerOnly(boolean); - method public void setParseStrict(boolean); - method public void setRoundingMode(int); - field public static final int ACCOUNTINGCURRENCYSTYLE = 7; // 0x7 - field public static final int CASHCURRENCYSTYLE = 8; // 0x8 - field public static final int CURRENCYSTYLE = 1; // 0x1 - field public static final int FRACTION_FIELD = 1; // 0x1 - field public static final int INTEGERSTYLE = 4; // 0x4 - field public static final int INTEGER_FIELD = 0; // 0x0 - field public static final int ISOCURRENCYSTYLE = 5; // 0x5 - field public static final int NUMBERSTYLE = 0; // 0x0 - field public static final int PERCENTSTYLE = 2; // 0x2 - field public static final int PLURALCURRENCYSTYLE = 6; // 0x6 - field public static final int SCIENTIFICSTYLE = 3; // 0x3 - field public static final int STANDARDCURRENCYSTYLE = 9; // 0x9 - } - - public static class NumberFormat.Field extends java.text.Format.Field { - ctor protected NumberFormat.Field(String); - field public static final android.icu.text.NumberFormat.Field CURRENCY; - field public static final android.icu.text.NumberFormat.Field DECIMAL_SEPARATOR; - field public static final android.icu.text.NumberFormat.Field EXPONENT; - field public static final android.icu.text.NumberFormat.Field EXPONENT_SIGN; - field public static final android.icu.text.NumberFormat.Field EXPONENT_SYMBOL; - field public static final android.icu.text.NumberFormat.Field FRACTION; - field public static final android.icu.text.NumberFormat.Field GROUPING_SEPARATOR; - field public static final android.icu.text.NumberFormat.Field INTEGER; - field public static final android.icu.text.NumberFormat.Field PERCENT; - field public static final android.icu.text.NumberFormat.Field PERMILLE; - field public static final android.icu.text.NumberFormat.Field SIGN; - } - - public class NumberingSystem { - ctor public NumberingSystem(); - method public static String[] getAvailableNames(); - method public String getDescription(); - method public static android.icu.text.NumberingSystem getInstance(int, boolean, String); - method public static android.icu.text.NumberingSystem getInstance(java.util.Locale); - method public static android.icu.text.NumberingSystem getInstance(android.icu.util.ULocale); - method public static android.icu.text.NumberingSystem getInstance(); - method public static android.icu.text.NumberingSystem getInstanceByName(String); - method public String getName(); - method public int getRadix(); - method public boolean isAlgorithmic(); - method public static boolean isValidDigitString(String); - field public static final android.icu.text.NumberingSystem LATIN; - } - - public class PluralFormat extends android.icu.text.UFormat { - ctor public PluralFormat(); - ctor public PluralFormat(android.icu.util.ULocale); - ctor public PluralFormat(java.util.Locale); - ctor public PluralFormat(android.icu.text.PluralRules); - ctor public PluralFormat(android.icu.util.ULocale, android.icu.text.PluralRules); - ctor public PluralFormat(java.util.Locale, android.icu.text.PluralRules); - ctor public PluralFormat(android.icu.util.ULocale, android.icu.text.PluralRules.PluralType); - ctor public PluralFormat(java.util.Locale, android.icu.text.PluralRules.PluralType); - ctor public PluralFormat(String); - ctor public PluralFormat(android.icu.util.ULocale, String); - ctor public PluralFormat(android.icu.text.PluralRules, String); - ctor public PluralFormat(android.icu.util.ULocale, android.icu.text.PluralRules, String); - ctor public PluralFormat(android.icu.util.ULocale, android.icu.text.PluralRules.PluralType, String); - method public void applyPattern(String); - method public boolean equals(android.icu.text.PluralFormat); - method public final String format(double); - method public StringBuffer format(Object, StringBuffer, java.text.FieldPosition); - method public Number parse(String, java.text.ParsePosition); - method public Object parseObject(String, java.text.ParsePosition); - method public void setNumberFormat(android.icu.text.NumberFormat); - method public String toPattern(); - } - - public class PluralRules implements java.io.Serializable { - method public static android.icu.text.PluralRules createRules(String); - method public boolean equals(android.icu.text.PluralRules); - method public static android.icu.text.PluralRules forLocale(android.icu.util.ULocale); - method public static android.icu.text.PluralRules forLocale(java.util.Locale); - method public static android.icu.text.PluralRules forLocale(android.icu.util.ULocale, android.icu.text.PluralRules.PluralType); - method public static android.icu.text.PluralRules forLocale(java.util.Locale, android.icu.text.PluralRules.PluralType); - method public java.util.Collection<java.lang.Double> getAllKeywordValues(String); - method public java.util.Set<java.lang.String> getKeywords(); - method public java.util.Collection<java.lang.Double> getSamples(String); - method public double getUniqueKeywordValue(String); - method public static android.icu.text.PluralRules parseDescription(String) throws java.text.ParseException; - method public String select(double); - field public static final android.icu.text.PluralRules DEFAULT; - field public static final String KEYWORD_FEW = "few"; - field public static final String KEYWORD_MANY = "many"; - field public static final String KEYWORD_ONE = "one"; - field public static final String KEYWORD_OTHER = "other"; - field public static final String KEYWORD_TWO = "two"; - field public static final String KEYWORD_ZERO = "zero"; - field public static final double NO_UNIQUE_VALUE = -0.00123456777; - } - - public enum PluralRules.PluralType { - enum_constant public static final android.icu.text.PluralRules.PluralType CARDINAL; - enum_constant public static final android.icu.text.PluralRules.PluralType ORDINAL; - } - - public final class RelativeDateTimeFormatter { - method public String combineDateAndTime(String, String); - method public String format(double, android.icu.text.RelativeDateTimeFormatter.Direction, android.icu.text.RelativeDateTimeFormatter.RelativeUnit); - method public String format(android.icu.text.RelativeDateTimeFormatter.Direction, android.icu.text.RelativeDateTimeFormatter.AbsoluteUnit); - method public String format(double, android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit); - method public String formatNumeric(double, android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit); - method public android.icu.text.DisplayContext getCapitalizationContext(); - method public android.icu.text.RelativeDateTimeFormatter.Style getFormatStyle(); - method public static android.icu.text.RelativeDateTimeFormatter getInstance(); - method public static android.icu.text.RelativeDateTimeFormatter getInstance(android.icu.util.ULocale); - method public static android.icu.text.RelativeDateTimeFormatter getInstance(java.util.Locale); - method public static android.icu.text.RelativeDateTimeFormatter getInstance(android.icu.util.ULocale, android.icu.text.NumberFormat); - method public static android.icu.text.RelativeDateTimeFormatter getInstance(android.icu.util.ULocale, android.icu.text.NumberFormat, android.icu.text.RelativeDateTimeFormatter.Style, android.icu.text.DisplayContext); - method public static android.icu.text.RelativeDateTimeFormatter getInstance(java.util.Locale, android.icu.text.NumberFormat); - method public android.icu.text.NumberFormat getNumberFormat(); - } - - public enum RelativeDateTimeFormatter.AbsoluteUnit { - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.AbsoluteUnit DAY; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.AbsoluteUnit FRIDAY; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.AbsoluteUnit MONDAY; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.AbsoluteUnit MONTH; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.AbsoluteUnit NOW; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.AbsoluteUnit SATURDAY; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.AbsoluteUnit SUNDAY; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.AbsoluteUnit THURSDAY; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.AbsoluteUnit TUESDAY; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.AbsoluteUnit WEDNESDAY; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.AbsoluteUnit WEEK; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.AbsoluteUnit YEAR; - } - - public enum RelativeDateTimeFormatter.Direction { - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.Direction LAST; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.Direction LAST_2; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.Direction NEXT; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.Direction NEXT_2; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.Direction PLAIN; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.Direction THIS; - } - - public enum RelativeDateTimeFormatter.RelativeDateTimeUnit { - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit DAY; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit FRIDAY; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit HOUR; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit MINUTE; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit MONDAY; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit MONTH; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit QUARTER; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit SATURDAY; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit SECOND; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit SUNDAY; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit THURSDAY; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit TUESDAY; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit WEDNESDAY; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit WEEK; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeDateTimeUnit YEAR; - } - - public enum RelativeDateTimeFormatter.RelativeUnit { - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeUnit DAYS; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeUnit HOURS; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeUnit MINUTES; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeUnit MONTHS; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeUnit SECONDS; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeUnit WEEKS; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.RelativeUnit YEARS; - } - - public enum RelativeDateTimeFormatter.Style { - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.Style LONG; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.Style NARROW; - enum_constant public static final android.icu.text.RelativeDateTimeFormatter.Style SHORT; - } - - public interface Replaceable { - method public int char32At(int); - method public char charAt(int); - method public void copy(int, int, int); - method public void getChars(int, int, char[], int); - method public boolean hasMetaData(); - method public int length(); - method public void replace(int, int, String); - method public void replace(int, int, char[], int, int); - } - - public final class RuleBasedCollator extends android.icu.text.Collator { - ctor public RuleBasedCollator(String) throws java.lang.Exception; - method public android.icu.text.RuleBasedCollator cloneAsThawed(); - method public int compare(String, String); - method public android.icu.text.CollationElementIterator getCollationElementIterator(String); - method public android.icu.text.CollationElementIterator getCollationElementIterator(java.text.CharacterIterator); - method public android.icu.text.CollationElementIterator getCollationElementIterator(android.icu.text.UCharacterIterator); - method public android.icu.text.CollationKey getCollationKey(String); - method public void getContractionsAndExpansions(android.icu.text.UnicodeSet, android.icu.text.UnicodeSet, boolean) throws java.lang.Exception; - method public boolean getNumericCollation(); - method public String getRules(); - method public String getRules(boolean); - method public android.icu.util.VersionInfo getUCAVersion(); - method public int getVariableTop(); - method public android.icu.util.VersionInfo getVersion(); - method public boolean isAlternateHandlingShifted(); - method public boolean isCaseLevel(); - method public boolean isFrenchCollation(); - method public boolean isLowerCaseFirst(); - method public boolean isUpperCaseFirst(); - method public void setAlternateHandlingDefault(); - method public void setAlternateHandlingShifted(boolean); - method public void setCaseFirstDefault(); - method public void setCaseLevel(boolean); - method public void setCaseLevelDefault(); - method public void setDecompositionDefault(); - method public void setFrenchCollation(boolean); - method public void setFrenchCollationDefault(); - method public void setLowerCaseFirst(boolean); - method public android.icu.text.RuleBasedCollator setMaxVariable(int); - method public void setNumericCollation(boolean); - method public void setNumericCollationDefault(); - method public void setStrengthDefault(); - method public void setUpperCaseFirst(boolean); - } - - public final class ScientificNumberFormatter { - method public String format(Object); - method public static android.icu.text.ScientificNumberFormatter getMarkupInstance(android.icu.util.ULocale, String, String); - method public static android.icu.text.ScientificNumberFormatter getMarkupInstance(android.icu.text.DecimalFormat, String, String); - method public static android.icu.text.ScientificNumberFormatter getSuperscriptInstance(android.icu.util.ULocale); - method public static android.icu.text.ScientificNumberFormatter getSuperscriptInstance(android.icu.text.DecimalFormat); - } - - public abstract class SearchIterator { - ctor protected SearchIterator(java.text.CharacterIterator, android.icu.text.BreakIterator); - method public final int first(); - method public final int following(int); - method public android.icu.text.BreakIterator getBreakIterator(); - method public android.icu.text.SearchIterator.ElementComparisonType getElementComparisonType(); - method public abstract int getIndex(); - method public int getMatchLength(); - method public int getMatchStart(); - method public String getMatchedText(); - method public java.text.CharacterIterator getTarget(); - method protected abstract int handleNext(int); - method protected abstract int handlePrevious(int); - method public boolean isOverlapping(); - method public final int last(); - method public int next(); - method public final int preceding(int); - method public int previous(); - method public void reset(); - method public void setBreakIterator(android.icu.text.BreakIterator); - method public void setElementComparisonType(android.icu.text.SearchIterator.ElementComparisonType); - method public void setIndex(int); - method protected void setMatchLength(int); - method public void setOverlapping(boolean); - method public void setTarget(java.text.CharacterIterator); - field public static final int DONE = -1; // 0xffffffff - field protected android.icu.text.BreakIterator breakIterator; - field protected int matchLength; - field protected java.text.CharacterIterator targetText; - } - - public enum SearchIterator.ElementComparisonType { - enum_constant public static final android.icu.text.SearchIterator.ElementComparisonType ANY_BASE_WEIGHT_IS_WILDCARD; - enum_constant public static final android.icu.text.SearchIterator.ElementComparisonType PATTERN_BASE_WEIGHT_IS_WILDCARD; - enum_constant public static final android.icu.text.SearchIterator.ElementComparisonType STANDARD_ELEMENT_COMPARISON; - } - - public class SelectFormat extends java.text.Format { - ctor public SelectFormat(String); - method public void applyPattern(String); - method public final String format(String); - method public StringBuffer format(Object, StringBuffer, java.text.FieldPosition); - method public Object parseObject(String, java.text.ParsePosition); - method public String toPattern(); - } - - public class SimpleDateFormat extends android.icu.text.DateFormat { - ctor public SimpleDateFormat(); - ctor public SimpleDateFormat(String); - ctor public SimpleDateFormat(String, java.util.Locale); - ctor public SimpleDateFormat(String, android.icu.util.ULocale); - ctor public SimpleDateFormat(String, String, android.icu.util.ULocale); - ctor public SimpleDateFormat(String, android.icu.text.DateFormatSymbols); - method public void applyLocalizedPattern(String); - method public void applyPattern(String); - method public StringBuffer format(android.icu.util.Calendar, StringBuffer, java.text.FieldPosition); - method public java.util.Date get2DigitYearStart(); - method public android.icu.text.DateFormatSymbols getDateFormatSymbols(); - method public android.icu.text.NumberFormat getNumberFormat(char); - method protected android.icu.text.DateFormatSymbols getSymbols(); - method public android.icu.text.TimeZoneFormat getTimeZoneFormat(); - method protected int matchQuarterString(String, int, int, String[], android.icu.util.Calendar); - method protected int matchString(String, int, int, String[], android.icu.util.Calendar); - method public void parse(String, android.icu.util.Calendar, java.text.ParsePosition); - method protected android.icu.text.DateFormat.Field patternCharToDateFormatField(char); - method public void set2DigitYearStart(java.util.Date); - method public void setDateFormatSymbols(android.icu.text.DateFormatSymbols); - method public void setNumberFormat(String, android.icu.text.NumberFormat); - method public void setTimeZoneFormat(android.icu.text.TimeZoneFormat); - method protected String subFormat(char, int, int, java.text.FieldPosition, android.icu.text.DateFormatSymbols, android.icu.util.Calendar) throws java.lang.IllegalArgumentException; - method protected int subParse(String, int, char, int, boolean, boolean, boolean[], android.icu.util.Calendar); - method public String toLocalizedPattern(); - method public String toPattern(); - method protected String zeroPaddingNumber(long, int, int); - } - - public class StringPrepParseException extends java.text.ParseException { - ctor public StringPrepParseException(String, int); - ctor public StringPrepParseException(String, int, String, int); - ctor public StringPrepParseException(String, int, String, int, int); - method public int getError(); - field public static final int ACE_PREFIX_ERROR = 6; // 0x6 - field public static final int BUFFER_OVERFLOW_ERROR = 9; // 0x9 - field public static final int CHECK_BIDI_ERROR = 4; // 0x4 - field public static final int DOMAIN_NAME_TOO_LONG_ERROR = 11; // 0xb - field public static final int ILLEGAL_CHAR_FOUND = 1; // 0x1 - field public static final int INVALID_CHAR_FOUND = 0; // 0x0 - field public static final int LABEL_TOO_LONG_ERROR = 8; // 0x8 - field public static final int PROHIBITED_ERROR = 2; // 0x2 - field public static final int STD3_ASCII_RULES_ERROR = 5; // 0x5 - field public static final int UNASSIGNED_ERROR = 3; // 0x3 - field public static final int VERIFICATION_ERROR = 7; // 0x7 - field public static final int ZERO_LENGTH_LABEL = 10; // 0xa - } - - public final class StringSearch extends android.icu.text.SearchIterator { - ctor public StringSearch(String, java.text.CharacterIterator, android.icu.text.RuleBasedCollator, android.icu.text.BreakIterator); - ctor public StringSearch(String, java.text.CharacterIterator, android.icu.text.RuleBasedCollator); - ctor public StringSearch(String, java.text.CharacterIterator, java.util.Locale); - ctor public StringSearch(String, java.text.CharacterIterator, android.icu.util.ULocale); - ctor public StringSearch(String, String); - method public android.icu.text.RuleBasedCollator getCollator(); - method public int getIndex(); - method public String getPattern(); - method protected int handleNext(int); - method protected int handlePrevious(int); - method public boolean isCanonical(); - method public void setCanonical(boolean); - method public void setCollator(android.icu.text.RuleBasedCollator); - method public void setPattern(String); - } - - public interface SymbolTable { - method public char[] lookup(String); - method public android.icu.text.UnicodeMatcher lookupMatcher(int); - method public String parseReference(String, java.text.ParsePosition, int); - field public static final char SYMBOL_REF = 36; // 0x0024 '$' - } - - public class TimeZoneFormat extends android.icu.text.UFormat implements android.icu.util.Freezable<android.icu.text.TimeZoneFormat> java.io.Serializable { - ctor protected TimeZoneFormat(android.icu.util.ULocale); - method public android.icu.text.TimeZoneFormat cloneAsThawed(); - method public final String format(android.icu.text.TimeZoneFormat.Style, android.icu.util.TimeZone, long); - method public String format(android.icu.text.TimeZoneFormat.Style, android.icu.util.TimeZone, long, android.icu.util.Output<android.icu.text.TimeZoneFormat.TimeType>); - method public StringBuffer format(Object, StringBuffer, java.text.FieldPosition); - method public final String formatOffsetISO8601Basic(int, boolean, boolean, boolean); - method public final String formatOffsetISO8601Extended(int, boolean, boolean, boolean); - method public String formatOffsetLocalizedGMT(int); - method public String formatOffsetShortLocalizedGMT(int); - method public android.icu.text.TimeZoneFormat freeze(); - method public java.util.EnumSet<android.icu.text.TimeZoneFormat.ParseOption> getDefaultParseOptions(); - method public String getGMTOffsetDigits(); - method public String getGMTOffsetPattern(android.icu.text.TimeZoneFormat.GMTOffsetPatternType); - method public String getGMTPattern(); - method public String getGMTZeroFormat(); - method public static android.icu.text.TimeZoneFormat getInstance(android.icu.util.ULocale); - method public static android.icu.text.TimeZoneFormat getInstance(java.util.Locale); - method public android.icu.text.TimeZoneNames getTimeZoneNames(); - method public boolean isFrozen(); - method public android.icu.util.TimeZone parse(android.icu.text.TimeZoneFormat.Style, String, java.text.ParsePosition, java.util.EnumSet<android.icu.text.TimeZoneFormat.ParseOption>, android.icu.util.Output<android.icu.text.TimeZoneFormat.TimeType>); - method public android.icu.util.TimeZone parse(android.icu.text.TimeZoneFormat.Style, String, java.text.ParsePosition, android.icu.util.Output<android.icu.text.TimeZoneFormat.TimeType>); - method public final android.icu.util.TimeZone parse(String, java.text.ParsePosition); - method public final android.icu.util.TimeZone parse(String) throws java.text.ParseException; - method public Object parseObject(String, java.text.ParsePosition); - method public final int parseOffsetISO8601(String, java.text.ParsePosition); - method public int parseOffsetLocalizedGMT(String, java.text.ParsePosition); - method public int parseOffsetShortLocalizedGMT(String, java.text.ParsePosition); - method public android.icu.text.TimeZoneFormat setDefaultParseOptions(java.util.EnumSet<android.icu.text.TimeZoneFormat.ParseOption>); - method public android.icu.text.TimeZoneFormat setGMTOffsetDigits(String); - method public android.icu.text.TimeZoneFormat setGMTOffsetPattern(android.icu.text.TimeZoneFormat.GMTOffsetPatternType, String); - method public android.icu.text.TimeZoneFormat setGMTPattern(String); - method public android.icu.text.TimeZoneFormat setGMTZeroFormat(String); - method public android.icu.text.TimeZoneFormat setTimeZoneNames(android.icu.text.TimeZoneNames); - } - - public enum TimeZoneFormat.GMTOffsetPatternType { - enum_constant public static final android.icu.text.TimeZoneFormat.GMTOffsetPatternType NEGATIVE_H; - enum_constant public static final android.icu.text.TimeZoneFormat.GMTOffsetPatternType NEGATIVE_HM; - enum_constant public static final android.icu.text.TimeZoneFormat.GMTOffsetPatternType NEGATIVE_HMS; - enum_constant public static final android.icu.text.TimeZoneFormat.GMTOffsetPatternType POSITIVE_H; - enum_constant public static final android.icu.text.TimeZoneFormat.GMTOffsetPatternType POSITIVE_HM; - enum_constant public static final android.icu.text.TimeZoneFormat.GMTOffsetPatternType POSITIVE_HMS; - } - - public enum TimeZoneFormat.ParseOption { - enum_constant public static final android.icu.text.TimeZoneFormat.ParseOption ALL_STYLES; - enum_constant public static final android.icu.text.TimeZoneFormat.ParseOption TZ_DATABASE_ABBREVIATIONS; - } - - public enum TimeZoneFormat.Style { - enum_constant public static final android.icu.text.TimeZoneFormat.Style EXEMPLAR_LOCATION; - enum_constant public static final android.icu.text.TimeZoneFormat.Style GENERIC_LOCATION; - enum_constant public static final android.icu.text.TimeZoneFormat.Style GENERIC_LONG; - enum_constant public static final android.icu.text.TimeZoneFormat.Style GENERIC_SHORT; - enum_constant public static final android.icu.text.TimeZoneFormat.Style ISO_BASIC_FIXED; - enum_constant public static final android.icu.text.TimeZoneFormat.Style ISO_BASIC_FULL; - enum_constant public static final android.icu.text.TimeZoneFormat.Style ISO_BASIC_LOCAL_FIXED; - enum_constant public static final android.icu.text.TimeZoneFormat.Style ISO_BASIC_LOCAL_FULL; - enum_constant public static final android.icu.text.TimeZoneFormat.Style ISO_BASIC_LOCAL_SHORT; - enum_constant public static final android.icu.text.TimeZoneFormat.Style ISO_BASIC_SHORT; - enum_constant public static final android.icu.text.TimeZoneFormat.Style ISO_EXTENDED_FIXED; - enum_constant public static final android.icu.text.TimeZoneFormat.Style ISO_EXTENDED_FULL; - enum_constant public static final android.icu.text.TimeZoneFormat.Style ISO_EXTENDED_LOCAL_FIXED; - enum_constant public static final android.icu.text.TimeZoneFormat.Style ISO_EXTENDED_LOCAL_FULL; - enum_constant public static final android.icu.text.TimeZoneFormat.Style LOCALIZED_GMT; - enum_constant public static final android.icu.text.TimeZoneFormat.Style LOCALIZED_GMT_SHORT; - enum_constant public static final android.icu.text.TimeZoneFormat.Style SPECIFIC_LONG; - enum_constant public static final android.icu.text.TimeZoneFormat.Style SPECIFIC_SHORT; - enum_constant public static final android.icu.text.TimeZoneFormat.Style ZONE_ID; - enum_constant public static final android.icu.text.TimeZoneFormat.Style ZONE_ID_SHORT; - } - - public enum TimeZoneFormat.TimeType { - enum_constant public static final android.icu.text.TimeZoneFormat.TimeType DAYLIGHT; - enum_constant public static final android.icu.text.TimeZoneFormat.TimeType STANDARD; - enum_constant public static final android.icu.text.TimeZoneFormat.TimeType UNKNOWN; - } - - public abstract class TimeZoneNames implements java.io.Serializable { - method public abstract java.util.Set<java.lang.String> getAvailableMetaZoneIDs(); - method public abstract java.util.Set<java.lang.String> getAvailableMetaZoneIDs(String); - method public final String getDisplayName(String, android.icu.text.TimeZoneNames.NameType, long); - method public String getExemplarLocationName(String); - method public static android.icu.text.TimeZoneNames getInstance(android.icu.util.ULocale); - method public static android.icu.text.TimeZoneNames getInstance(java.util.Locale); - method public abstract String getMetaZoneDisplayName(String, android.icu.text.TimeZoneNames.NameType); - method public abstract String getMetaZoneID(String, long); - method public abstract String getReferenceZoneID(String, String); - method public static android.icu.text.TimeZoneNames getTZDBInstance(android.icu.util.ULocale); - method public abstract String getTimeZoneDisplayName(String, android.icu.text.TimeZoneNames.NameType); - } - - public enum TimeZoneNames.NameType { - enum_constant public static final android.icu.text.TimeZoneNames.NameType EXEMPLAR_LOCATION; - enum_constant public static final android.icu.text.TimeZoneNames.NameType LONG_DAYLIGHT; - enum_constant public static final android.icu.text.TimeZoneNames.NameType LONG_GENERIC; - enum_constant public static final android.icu.text.TimeZoneNames.NameType LONG_STANDARD; - enum_constant public static final android.icu.text.TimeZoneNames.NameType SHORT_DAYLIGHT; - enum_constant public static final android.icu.text.TimeZoneNames.NameType SHORT_GENERIC; - enum_constant public static final android.icu.text.TimeZoneNames.NameType SHORT_STANDARD; - } - - public abstract class Transliterator { - method public static final android.icu.text.Transliterator createFromRules(String, String, int); - method public void filteredTransliterate(android.icu.text.Replaceable, android.icu.text.Transliterator.Position, boolean); - method public final void finishTransliteration(android.icu.text.Replaceable, android.icu.text.Transliterator.Position); - method public static final java.util.Enumeration<java.lang.String> getAvailableIDs(); - method public static final java.util.Enumeration<java.lang.String> getAvailableSources(); - method public static final java.util.Enumeration<java.lang.String> getAvailableTargets(String); - method public static final java.util.Enumeration<java.lang.String> getAvailableVariants(String, String); - method public static final String getDisplayName(String); - method public static String getDisplayName(String, java.util.Locale); - method public static String getDisplayName(String, android.icu.util.ULocale); - method public android.icu.text.Transliterator[] getElements(); - method public final android.icu.text.UnicodeFilter getFilter(); - method public final String getID(); - method public static final android.icu.text.Transliterator getInstance(String); - method public static android.icu.text.Transliterator getInstance(String, int); - method public final android.icu.text.Transliterator getInverse(); - method public final int getMaximumContextLength(); - method public final android.icu.text.UnicodeSet getSourceSet(); - method public android.icu.text.UnicodeSet getTargetSet(); - method public void setFilter(android.icu.text.UnicodeFilter); - method public String toRules(boolean); - method public final int transliterate(android.icu.text.Replaceable, int, int); - method public final void transliterate(android.icu.text.Replaceable); - method public final String transliterate(String); - method public final void transliterate(android.icu.text.Replaceable, android.icu.text.Transliterator.Position, String); - method public final void transliterate(android.icu.text.Replaceable, android.icu.text.Transliterator.Position, int); - method public final void transliterate(android.icu.text.Replaceable, android.icu.text.Transliterator.Position); - field public static final int FORWARD = 0; // 0x0 - field public static final int REVERSE = 1; // 0x1 - } - - public static class Transliterator.Position { - ctor public Transliterator.Position(); - ctor public Transliterator.Position(int, int, int); - ctor public Transliterator.Position(int, int, int, int); - ctor public Transliterator.Position(android.icu.text.Transliterator.Position); - method public void set(android.icu.text.Transliterator.Position); - method public final void validate(int); - field public int contextLimit; - field public int contextStart; - field public int limit; - field public int start; - } - - public abstract class UCharacterIterator implements java.lang.Cloneable { - ctor protected UCharacterIterator(); - method public Object clone() throws java.lang.CloneNotSupportedException; - method public abstract int current(); - method public int currentCodePoint(); - method public java.text.CharacterIterator getCharacterIterator(); - method public abstract int getIndex(); - method public static final android.icu.text.UCharacterIterator getInstance(android.icu.text.Replaceable); - method public static final android.icu.text.UCharacterIterator getInstance(String); - method public static final android.icu.text.UCharacterIterator getInstance(char[]); - method public static final android.icu.text.UCharacterIterator getInstance(char[], int, int); - method public static final android.icu.text.UCharacterIterator getInstance(StringBuffer); - method public static final android.icu.text.UCharacterIterator getInstance(java.text.CharacterIterator); - method public abstract int getLength(); - method public abstract int getText(char[], int); - method public final int getText(char[]); - method public String getText(); - method public int moveCodePointIndex(int); - method public int moveIndex(int); - method public abstract int next(); - method public int nextCodePoint(); - method public abstract int previous(); - method public int previousCodePoint(); - method public abstract void setIndex(int); - method public void setToLimit(); - method public void setToStart(); - field public static final int DONE = -1; // 0xffffffff - } - - public abstract class UFormat extends java.text.Format { - ctor public UFormat(); - } - - public abstract class UnicodeFilter implements android.icu.text.UnicodeMatcher { - method public abstract boolean contains(int); - method public int matches(android.icu.text.Replaceable, int[], int, boolean); - } - - public interface UnicodeMatcher { - method public void addMatchSetTo(android.icu.text.UnicodeSet); - method public int matches(android.icu.text.Replaceable, int[], int, boolean); - method public boolean matchesIndexValue(int); - method public String toPattern(boolean); - field public static final char ETHER = 65535; // 0xffff '\uffff' - field public static final int U_MATCH = 2; // 0x2 - field public static final int U_MISMATCH = 0; // 0x0 - field public static final int U_PARTIAL_MATCH = 1; // 0x1 - } - - public class UnicodeSet extends android.icu.text.UnicodeFilter implements java.lang.Comparable<android.icu.text.UnicodeSet> android.icu.util.Freezable<android.icu.text.UnicodeSet> java.lang.Iterable<java.lang.String> { - ctor public UnicodeSet(); - ctor public UnicodeSet(android.icu.text.UnicodeSet); - ctor public UnicodeSet(int, int); - ctor public UnicodeSet(int...); - ctor public UnicodeSet(String); - ctor public UnicodeSet(String, boolean); - ctor public UnicodeSet(String, int); - ctor public UnicodeSet(String, java.text.ParsePosition, android.icu.text.SymbolTable); - ctor public UnicodeSet(String, java.text.ParsePosition, android.icu.text.SymbolTable, int); - method public StringBuffer _generatePattern(StringBuffer, boolean); - method public StringBuffer _generatePattern(StringBuffer, boolean, boolean); - method public android.icu.text.UnicodeSet add(int, int); - method public final android.icu.text.UnicodeSet add(int); - method public final android.icu.text.UnicodeSet add(CharSequence); - method public android.icu.text.UnicodeSet add(Iterable<?>); - method public android.icu.text.UnicodeSet addAll(int, int); - method public final android.icu.text.UnicodeSet addAll(CharSequence); - method public android.icu.text.UnicodeSet addAll(android.icu.text.UnicodeSet); - method public android.icu.text.UnicodeSet addAll(Iterable<?>); - method public <T extends java.lang.CharSequence> android.icu.text.UnicodeSet addAll(T...); - method public <T extends java.util.Collection<java.lang.String>> T addAllTo(T); - method public void addMatchSetTo(android.icu.text.UnicodeSet); - method public android.icu.text.UnicodeSet applyIntPropertyValue(int, int); - method public final android.icu.text.UnicodeSet applyPattern(String); - method public android.icu.text.UnicodeSet applyPattern(String, boolean); - method public android.icu.text.UnicodeSet applyPattern(String, int); - method public android.icu.text.UnicodeSet applyPropertyAlias(String, String); - method public android.icu.text.UnicodeSet applyPropertyAlias(String, String, android.icu.text.SymbolTable); - method public int charAt(int); - method public android.icu.text.UnicodeSet clear(); - method public Object clone(); - method public android.icu.text.UnicodeSet cloneAsThawed(); - method public android.icu.text.UnicodeSet closeOver(int); - method public android.icu.text.UnicodeSet compact(); - method public int compareTo(android.icu.text.UnicodeSet); - method public int compareTo(android.icu.text.UnicodeSet, android.icu.text.UnicodeSet.ComparisonStyle); - method public int compareTo(Iterable<java.lang.String>); - method public android.icu.text.UnicodeSet complement(int, int); - method public final android.icu.text.UnicodeSet complement(int); - method public android.icu.text.UnicodeSet complement(); - method public final android.icu.text.UnicodeSet complement(CharSequence); - method public final android.icu.text.UnicodeSet complementAll(CharSequence); - method public android.icu.text.UnicodeSet complementAll(android.icu.text.UnicodeSet); - method public boolean contains(int); - method public boolean contains(int, int); - method public final boolean contains(CharSequence); - method public boolean containsAll(android.icu.text.UnicodeSet); - method public boolean containsAll(String); - method public <T extends java.lang.CharSequence> boolean containsAll(Iterable<T>); - method public boolean containsNone(int, int); - method public boolean containsNone(android.icu.text.UnicodeSet); - method public boolean containsNone(CharSequence); - method public <T extends java.lang.CharSequence> boolean containsNone(Iterable<T>); - method public final boolean containsSome(int, int); - method public final boolean containsSome(android.icu.text.UnicodeSet); - method public final boolean containsSome(CharSequence); - method public final <T extends java.lang.CharSequence> boolean containsSome(Iterable<T>); - method public android.icu.text.UnicodeSet freeze(); - method public static android.icu.text.UnicodeSet from(CharSequence); - method public static android.icu.text.UnicodeSet fromAll(CharSequence); - method public int getRangeCount(); - method public int getRangeEnd(int); - method public int getRangeStart(int); - method public int indexOf(int); - method public boolean isEmpty(); - method public boolean isFrozen(); - method public java.util.Iterator<java.lang.String> iterator(); - method public boolean matchesIndexValue(int); - method public Iterable<android.icu.text.UnicodeSet.EntryRange> ranges(); - method public android.icu.text.UnicodeSet remove(int, int); - method public final android.icu.text.UnicodeSet remove(int); - method public final android.icu.text.UnicodeSet remove(CharSequence); - method public final android.icu.text.UnicodeSet removeAll(CharSequence); - method public android.icu.text.UnicodeSet removeAll(android.icu.text.UnicodeSet); - method public <T extends java.lang.CharSequence> android.icu.text.UnicodeSet removeAll(Iterable<T>); - method public final android.icu.text.UnicodeSet removeAllStrings(); - method public android.icu.text.UnicodeSet retain(int, int); - method public final android.icu.text.UnicodeSet retain(int); - method public final android.icu.text.UnicodeSet retain(CharSequence); - method public final android.icu.text.UnicodeSet retainAll(CharSequence); - method public android.icu.text.UnicodeSet retainAll(android.icu.text.UnicodeSet); - method public <T extends java.lang.CharSequence> android.icu.text.UnicodeSet retainAll(Iterable<T>); - method public android.icu.text.UnicodeSet set(int, int); - method public android.icu.text.UnicodeSet set(android.icu.text.UnicodeSet); - method public int size(); - method public int span(CharSequence, android.icu.text.UnicodeSet.SpanCondition); - method public int span(CharSequence, int, android.icu.text.UnicodeSet.SpanCondition); - method public int spanBack(CharSequence, android.icu.text.UnicodeSet.SpanCondition); - method public int spanBack(CharSequence, int, android.icu.text.UnicodeSet.SpanCondition); - method public java.util.Collection<java.lang.String> strings(); - method public String toPattern(boolean); - field public static final int ADD_CASE_MAPPINGS = 4; // 0x4 - field public static final android.icu.text.UnicodeSet ALL_CODE_POINTS; - field public static final int CASE = 2; // 0x2 - field public static final int CASE_INSENSITIVE = 2; // 0x2 - field public static final android.icu.text.UnicodeSet EMPTY; - field public static final int IGNORE_SPACE = 1; // 0x1 - field public static final int MAX_VALUE = 1114111; // 0x10ffff - field public static final int MIN_VALUE = 0; // 0x0 - } - - public enum UnicodeSet.ComparisonStyle { - enum_constant public static final android.icu.text.UnicodeSet.ComparisonStyle LEXICOGRAPHIC; - enum_constant public static final android.icu.text.UnicodeSet.ComparisonStyle LONGER_FIRST; - enum_constant public static final android.icu.text.UnicodeSet.ComparisonStyle SHORTER_FIRST; - } - - public static class UnicodeSet.EntryRange { - field public int codepoint; - field public int codepointEnd; - } - - public enum UnicodeSet.SpanCondition { - enum_constant public static final android.icu.text.UnicodeSet.SpanCondition CONDITION_COUNT; - enum_constant public static final android.icu.text.UnicodeSet.SpanCondition CONTAINED; - enum_constant public static final android.icu.text.UnicodeSet.SpanCondition NOT_CONTAINED; - enum_constant public static final android.icu.text.UnicodeSet.SpanCondition SIMPLE; - } - - public class UnicodeSetIterator { - ctor public UnicodeSetIterator(android.icu.text.UnicodeSet); - ctor public UnicodeSetIterator(); - method public String getString(); - method public boolean next(); - method public boolean nextRange(); - method public void reset(android.icu.text.UnicodeSet); - method public void reset(); - field public static int IS_STRING; - field public int codepoint; - field public int codepointEnd; - field public String string; - } - - public class UnicodeSetSpanner { - ctor public UnicodeSetSpanner(android.icu.text.UnicodeSet); - method public int countIn(CharSequence); - method public int countIn(CharSequence, android.icu.text.UnicodeSetSpanner.CountMethod); - method public int countIn(CharSequence, android.icu.text.UnicodeSetSpanner.CountMethod, android.icu.text.UnicodeSet.SpanCondition); - method public String deleteFrom(CharSequence); - method public String deleteFrom(CharSequence, android.icu.text.UnicodeSet.SpanCondition); - method public android.icu.text.UnicodeSet getUnicodeSet(); - method public String replaceFrom(CharSequence, CharSequence); - method public String replaceFrom(CharSequence, CharSequence, android.icu.text.UnicodeSetSpanner.CountMethod); - method public String replaceFrom(CharSequence, CharSequence, android.icu.text.UnicodeSetSpanner.CountMethod, android.icu.text.UnicodeSet.SpanCondition); - method public CharSequence trim(CharSequence); - method public CharSequence trim(CharSequence, android.icu.text.UnicodeSetSpanner.TrimOption); - method public CharSequence trim(CharSequence, android.icu.text.UnicodeSetSpanner.TrimOption, android.icu.text.UnicodeSet.SpanCondition); - } - - public enum UnicodeSetSpanner.CountMethod { - enum_constant public static final android.icu.text.UnicodeSetSpanner.CountMethod MIN_ELEMENTS; - enum_constant public static final android.icu.text.UnicodeSetSpanner.CountMethod WHOLE_SPAN; - } - - public enum UnicodeSetSpanner.TrimOption { - enum_constant public static final android.icu.text.UnicodeSetSpanner.TrimOption BOTH; - enum_constant public static final android.icu.text.UnicodeSetSpanner.TrimOption LEADING; - enum_constant public static final android.icu.text.UnicodeSetSpanner.TrimOption TRAILING; - } - -} - -package android.icu.util { - - public class BuddhistCalendar extends android.icu.util.GregorianCalendar { - ctor public BuddhistCalendar(); - ctor public BuddhistCalendar(android.icu.util.TimeZone); - ctor public BuddhistCalendar(java.util.Locale); - ctor public BuddhistCalendar(android.icu.util.ULocale); - ctor public BuddhistCalendar(android.icu.util.TimeZone, java.util.Locale); - ctor public BuddhistCalendar(android.icu.util.TimeZone, android.icu.util.ULocale); - ctor public BuddhistCalendar(java.util.Date); - ctor public BuddhistCalendar(int, int, int); - ctor public BuddhistCalendar(int, int, int, int, int, int); - field public static final int BE = 0; // 0x0 - } - - public abstract class Calendar implements java.lang.Cloneable java.lang.Comparable<android.icu.util.Calendar> java.io.Serializable { - ctor protected Calendar(); - ctor protected Calendar(android.icu.util.TimeZone, java.util.Locale); - ctor protected Calendar(android.icu.util.TimeZone, android.icu.util.ULocale); - method public void add(int, int); - method public boolean after(Object); - method public boolean before(Object); - method public final void clear(); - method public final void clear(int); - method public Object clone(); - method public int compareTo(android.icu.util.Calendar); - method protected void complete(); - method protected void computeFields(); - method protected final void computeGregorianFields(int); - method protected int computeGregorianMonthStart(int, int); - method protected int computeJulianDay(); - method @Deprecated protected int computeMillisInDay(); - method protected void computeTime(); - method @Deprecated protected int computeZoneOffset(long, int); - method public int fieldDifference(java.util.Date, int); - method protected String fieldName(int); - method protected static final long floorDivide(long, long); - method protected static final int floorDivide(int, int); - method protected static final int floorDivide(int, int, int[]); - method protected static final int floorDivide(long, int, int[]); - method public final int get(int); - method public int getActualMaximum(int); - method public int getActualMinimum(int); - method public static java.util.Locale[] getAvailableLocales(); - method public android.icu.text.DateFormat getDateTimeFormat(int, int, java.util.Locale); - method public android.icu.text.DateFormat getDateTimeFormat(int, int, android.icu.util.ULocale); - method public String getDisplayName(java.util.Locale); - method public String getDisplayName(android.icu.util.ULocale); - method public final int getFieldCount(); - method protected int[][][] getFieldResolutionTable(); - method public int getFirstDayOfWeek(); - method public final int getGreatestMinimum(int); - method protected final int getGregorianDayOfMonth(); - method protected final int getGregorianDayOfYear(); - method protected final int getGregorianMonth(); - method protected final int getGregorianYear(); - method public static android.icu.util.Calendar getInstance(); - method public static android.icu.util.Calendar getInstance(android.icu.util.TimeZone); - method public static android.icu.util.Calendar getInstance(java.util.Locale); - method public static android.icu.util.Calendar getInstance(android.icu.util.ULocale); - method public static android.icu.util.Calendar getInstance(android.icu.util.TimeZone, java.util.Locale); - method public static android.icu.util.Calendar getInstance(android.icu.util.TimeZone, android.icu.util.ULocale); - method public static final String[] getKeywordValuesForLocale(String, android.icu.util.ULocale, boolean); - method public final int getLeastMaximum(int); - method protected int getLimit(int, int); - method public final int getMaximum(int); - method public int getMinimalDaysInFirstWeek(); - method public final int getMinimum(int); - method public int getRepeatedWallTimeOption(); - method public int getSkippedWallTimeOption(); - method protected final int getStamp(int); - method public final java.util.Date getTime(); - method public long getTimeInMillis(); - method public android.icu.util.TimeZone getTimeZone(); - method public String getType(); - method public android.icu.util.Calendar.WeekData getWeekData(); - method public static android.icu.util.Calendar.WeekData getWeekDataForRegion(String); - method protected static final int gregorianMonthLength(int, int); - method protected static final int gregorianPreviousMonthLength(int, int); - method protected void handleComputeFields(int); - method protected int handleComputeJulianDay(int); - method protected abstract int handleComputeMonthStart(int, int, boolean); - method protected int[] handleCreateFields(); - method protected android.icu.text.DateFormat handleGetDateFormat(String, java.util.Locale); - method protected android.icu.text.DateFormat handleGetDateFormat(String, String, java.util.Locale); - method protected android.icu.text.DateFormat handleGetDateFormat(String, android.icu.util.ULocale); - method protected abstract int handleGetExtendedYear(); - method protected abstract int handleGetLimit(int, int); - method protected int handleGetMonthLength(int, int); - method protected int handleGetYearLength(int); - method protected final int internalGet(int); - method protected final int internalGet(int, int); - method protected final long internalGetTimeInMillis(); - method protected final void internalSet(int, int); - method public boolean isEquivalentTo(android.icu.util.Calendar); - method protected static final boolean isGregorianLeapYear(int); - method public boolean isLenient(); - method public final boolean isSet(int); - method public boolean isWeekend(java.util.Date); - method public boolean isWeekend(); - method protected static final int julianDayToDayOfWeek(int); - method protected static final long julianDayToMillis(int); - method protected static final int millisToJulianDay(long); - method protected int newerField(int, int); - method protected int newestStamp(int, int, int); - method protected void pinField(int); - method protected void prepareGetActual(int, boolean); - method protected int resolveFields(int[][][]); - method public final void roll(int, boolean); - method public void roll(int, int); - method public final void set(int, int); - method public final void set(int, int, int); - method public final void set(int, int, int, int, int); - method public final void set(int, int, int, int, int, int); - method public void setFirstDayOfWeek(int); - method public void setLenient(boolean); - method public void setMinimalDaysInFirstWeek(int); - method public void setRepeatedWallTimeOption(int); - method public void setSkippedWallTimeOption(int); - method public final void setTime(java.util.Date); - method public void setTimeInMillis(long); - method public void setTimeZone(android.icu.util.TimeZone); - method public android.icu.util.Calendar setWeekData(android.icu.util.Calendar.WeekData); - method protected void validateField(int); - method protected final void validateField(int, int, int); - method protected void validateFields(); - method protected int weekNumber(int, int, int); - method protected final int weekNumber(int, int); - field public static final int AM = 0; // 0x0 - field public static final int AM_PM = 9; // 0x9 - field public static final int APRIL = 3; // 0x3 - field public static final int AUGUST = 7; // 0x7 - field @Deprecated protected static final int BASE_FIELD_COUNT = 23; // 0x17 - field public static final int DATE = 5; // 0x5 - field public static final int DAY_OF_MONTH = 5; // 0x5 - field public static final int DAY_OF_WEEK = 7; // 0x7 - field public static final int DAY_OF_WEEK_IN_MONTH = 8; // 0x8 - field public static final int DAY_OF_YEAR = 6; // 0x6 - field public static final int DECEMBER = 11; // 0xb - field public static final int DOW_LOCAL = 18; // 0x12 - field public static final int DST_OFFSET = 16; // 0x10 - field protected static final int EPOCH_JULIAN_DAY = 2440588; // 0x253d8c - field public static final int ERA = 0; // 0x0 - field public static final int EXTENDED_YEAR = 19; // 0x13 - field public static final int FEBRUARY = 1; // 0x1 - field public static final int FRIDAY = 6; // 0x6 - field protected static final int GREATEST_MINIMUM = 1; // 0x1 - field public static final int HOUR = 10; // 0xa - field public static final int HOUR_OF_DAY = 11; // 0xb - field protected static final int INTERNALLY_SET = 1; // 0x1 - field public static final int IS_LEAP_MONTH = 22; // 0x16 - field public static final int JANUARY = 0; // 0x0 - field protected static final int JAN_1_1_JULIAN_DAY = 1721426; // 0x1a4452 - field public static final int JULIAN_DAY = 20; // 0x14 - field public static final int JULY = 6; // 0x6 - field public static final int JUNE = 5; // 0x5 - field protected static final int LEAST_MAXIMUM = 2; // 0x2 - field public static final int MARCH = 2; // 0x2 - field protected static final int MAXIMUM = 3; // 0x3 - field protected static final java.util.Date MAX_DATE; - field @Deprecated protected static final int MAX_FIELD_COUNT = 32; // 0x20 - field protected static final int MAX_JULIAN = 2130706432; // 0x7f000000 - field protected static final long MAX_MILLIS = 183882168921600000L; // 0x28d47dbbf19b000L - field public static final int MAY = 4; // 0x4 - field public static final int MILLISECOND = 14; // 0xe - field public static final int MILLISECONDS_IN_DAY = 21; // 0x15 - field protected static final int MINIMUM = 0; // 0x0 - field protected static final int MINIMUM_USER_STAMP = 2; // 0x2 - field public static final int MINUTE = 12; // 0xc - field protected static final java.util.Date MIN_DATE; - field protected static final int MIN_JULIAN = -2130706432; // 0x81000000 - field protected static final long MIN_MILLIS = -184303902528000000L; // 0xfd713893bf19b000L - field public static final int MONDAY = 2; // 0x2 - field public static final int MONTH = 2; // 0x2 - field public static final int NOVEMBER = 10; // 0xa - field public static final int OCTOBER = 9; // 0x9 - field protected static final long ONE_DAY = 86400000L; // 0x5265c00L - field protected static final int ONE_HOUR = 3600000; // 0x36ee80 - field protected static final int ONE_MINUTE = 60000; // 0xea60 - field protected static final int ONE_SECOND = 1000; // 0x3e8 - field protected static final long ONE_WEEK = 604800000L; // 0x240c8400L - field public static final int PM = 1; // 0x1 - field protected static final int RESOLVE_REMAP = 32; // 0x20 - field public static final int SATURDAY = 7; // 0x7 - field public static final int SECOND = 13; // 0xd - field public static final int SEPTEMBER = 8; // 0x8 - field public static final int SUNDAY = 1; // 0x1 - field public static final int THURSDAY = 5; // 0x5 - field public static final int TUESDAY = 3; // 0x3 - field public static final int UNDECIMBER = 12; // 0xc - field protected static final int UNSET = 0; // 0x0 - field public static final int WALLTIME_FIRST = 1; // 0x1 - field public static final int WALLTIME_LAST = 0; // 0x0 - field public static final int WALLTIME_NEXT_VALID = 2; // 0x2 - field public static final int WEDNESDAY = 4; // 0x4 - field public static final int WEEK_OF_MONTH = 4; // 0x4 - field public static final int WEEK_OF_YEAR = 3; // 0x3 - field public static final int YEAR = 1; // 0x1 - field public static final int YEAR_WOY = 17; // 0x11 - field public static final int ZONE_OFFSET = 15; // 0xf - } - - public static final class Calendar.WeekData { - ctor public Calendar.WeekData(int, int, int, int, int, int); - field public final int firstDayOfWeek; - field public final int minimalDaysInFirstWeek; - field public final int weekendCease; - field public final int weekendCeaseMillis; - field public final int weekendOnset; - field public final int weekendOnsetMillis; - } - - public class ChineseCalendar extends android.icu.util.Calendar { - ctor public ChineseCalendar(); - ctor public ChineseCalendar(java.util.Date); - ctor public ChineseCalendar(int, int, int, int); - ctor public ChineseCalendar(int, int, int, int, int, int, int); - ctor public ChineseCalendar(int, int, int, int, int); - ctor public ChineseCalendar(int, int, int, int, int, int, int, int); - ctor public ChineseCalendar(java.util.Locale); - ctor public ChineseCalendar(android.icu.util.TimeZone); - ctor public ChineseCalendar(android.icu.util.TimeZone, java.util.Locale); - ctor public ChineseCalendar(android.icu.util.ULocale); - ctor public ChineseCalendar(android.icu.util.TimeZone, android.icu.util.ULocale); - method protected int handleComputeMonthStart(int, int, boolean); - method protected android.icu.text.DateFormat handleGetDateFormat(String, String, android.icu.util.ULocale); - method protected int handleGetExtendedYear(); - method protected int handleGetLimit(int, int); - } - - public final class CopticCalendar extends android.icu.util.Calendar { - ctor public CopticCalendar(); - ctor public CopticCalendar(android.icu.util.TimeZone); - ctor public CopticCalendar(java.util.Locale); - ctor public CopticCalendar(android.icu.util.ULocale); - ctor public CopticCalendar(android.icu.util.TimeZone, java.util.Locale); - ctor public CopticCalendar(android.icu.util.TimeZone, android.icu.util.ULocale); - ctor public CopticCalendar(int, int, int); - ctor public CopticCalendar(java.util.Date); - ctor public CopticCalendar(int, int, int, int, int, int); - method @Deprecated protected void handleComputeFields(int); - method protected int handleComputeMonthStart(int, int, boolean); - method @Deprecated protected int handleGetExtendedYear(); - method protected int handleGetLimit(int, int); - field public static final int AMSHIR = 5; // 0x5 - field public static final int BABA = 1; // 0x1 - field public static final int BARAMHAT = 6; // 0x6 - field public static final int BARAMOUDA = 7; // 0x7 - field public static final int BASHANS = 8; // 0x8 - field public static final int EPEP = 10; // 0xa - field public static final int HATOR = 2; // 0x2 - field public static final int KIAHK = 3; // 0x3 - field public static final int MESRA = 11; // 0xb - field public static final int NASIE = 12; // 0xc - field public static final int PAONA = 9; // 0x9 - field public static final int TOBA = 4; // 0x4 - field public static final int TOUT = 0; // 0x0 - } - - public class Currency extends android.icu.util.MeasureUnit { - ctor protected Currency(String); - method public static android.icu.util.Currency fromJavaCurrency(java.util.Currency); - method public static java.util.Set<android.icu.util.Currency> getAvailableCurrencies(); - method public static String[] getAvailableCurrencyCodes(android.icu.util.ULocale, java.util.Date); - method public static String[] getAvailableCurrencyCodes(java.util.Locale, java.util.Date); - method public static java.util.Locale[] getAvailableLocales(); - method public static android.icu.util.ULocale[] getAvailableULocales(); - method public String getCurrencyCode(); - method public int getDefaultFractionDigits(); - method public int getDefaultFractionDigits(android.icu.util.Currency.CurrencyUsage); - method public String getDisplayName(); - method public String getDisplayName(java.util.Locale); - method public static android.icu.util.Currency getInstance(java.util.Locale); - method public static android.icu.util.Currency getInstance(android.icu.util.ULocale); - method public static android.icu.util.Currency getInstance(String); - method public static final String[] getKeywordValuesForLocale(String, android.icu.util.ULocale, boolean); - method public String getName(java.util.Locale, int, boolean[]); - method public String getName(android.icu.util.ULocale, int, boolean[]); - method public String getName(java.util.Locale, int, String, boolean[]); - method public String getName(android.icu.util.ULocale, int, String, boolean[]); - method public int getNumericCode(); - method public double getRoundingIncrement(); - method public double getRoundingIncrement(android.icu.util.Currency.CurrencyUsage); - method public String getSymbol(); - method public String getSymbol(java.util.Locale); - method public String getSymbol(android.icu.util.ULocale); - method public static boolean isAvailable(String, java.util.Date, java.util.Date); - method public java.util.Currency toJavaCurrency(); - field public static final int LONG_NAME = 1; // 0x1 - field public static final int NARROW_SYMBOL_NAME = 3; // 0x3 - field public static final int PLURAL_LONG_NAME = 2; // 0x2 - field public static final int SYMBOL_NAME = 0; // 0x0 - } - - public enum Currency.CurrencyUsage { - enum_constant public static final android.icu.util.Currency.CurrencyUsage CASH; - enum_constant public static final android.icu.util.Currency.CurrencyUsage STANDARD; - } - - public class CurrencyAmount extends android.icu.util.Measure { - ctor public CurrencyAmount(Number, android.icu.util.Currency); - ctor public CurrencyAmount(double, android.icu.util.Currency); - ctor public CurrencyAmount(Number, java.util.Currency); - ctor public CurrencyAmount(double, java.util.Currency); - method public android.icu.util.Currency getCurrency(); - } - - public final class DateInterval implements java.io.Serializable { - ctor public DateInterval(long, long); - method public long getFromDate(); - method public long getToDate(); - } - - public final class EthiopicCalendar extends android.icu.util.Calendar { - ctor public EthiopicCalendar(); - ctor public EthiopicCalendar(android.icu.util.TimeZone); - ctor public EthiopicCalendar(java.util.Locale); - ctor public EthiopicCalendar(android.icu.util.ULocale); - ctor public EthiopicCalendar(android.icu.util.TimeZone, java.util.Locale); - ctor public EthiopicCalendar(android.icu.util.TimeZone, android.icu.util.ULocale); - ctor public EthiopicCalendar(int, int, int); - ctor public EthiopicCalendar(java.util.Date); - ctor public EthiopicCalendar(int, int, int, int, int, int); - method @Deprecated protected void handleComputeFields(int); - method protected int handleComputeMonthStart(int, int, boolean); - method @Deprecated protected int handleGetExtendedYear(); - method @Deprecated protected int handleGetLimit(int, int); - method public boolean isAmeteAlemEra(); - method public void setAmeteAlemEra(boolean); - field public static final int GENBOT = 8; // 0x8 - field public static final int HAMLE = 10; // 0xa - field public static final int HEDAR = 2; // 0x2 - field public static final int MEGABIT = 6; // 0x6 - field public static final int MESKEREM = 0; // 0x0 - field public static final int MIAZIA = 7; // 0x7 - field public static final int NEHASSE = 11; // 0xb - field public static final int PAGUMEN = 12; // 0xc - field public static final int SENE = 9; // 0x9 - field public static final int TAHSAS = 3; // 0x3 - field public static final int TEKEMT = 1; // 0x1 - field public static final int TER = 4; // 0x4 - field public static final int YEKATIT = 5; // 0x5 - } - - public interface Freezable<T> extends java.lang.Cloneable { - method public T cloneAsThawed(); - method public T freeze(); - method public boolean isFrozen(); - } - - public class GregorianCalendar extends android.icu.util.Calendar { - ctor public GregorianCalendar(); - ctor public GregorianCalendar(android.icu.util.TimeZone); - ctor public GregorianCalendar(java.util.Locale); - ctor public GregorianCalendar(android.icu.util.ULocale); - ctor public GregorianCalendar(android.icu.util.TimeZone, java.util.Locale); - ctor public GregorianCalendar(android.icu.util.TimeZone, android.icu.util.ULocale); - ctor public GregorianCalendar(int, int, int); - ctor public GregorianCalendar(int, int, int, int, int); - ctor public GregorianCalendar(int, int, int, int, int, int); - method public final java.util.Date getGregorianChange(); - method protected int handleComputeMonthStart(int, int, boolean); - method protected int handleGetExtendedYear(); - method protected int handleGetLimit(int, int); - method public boolean isLeapYear(int); - method public void setGregorianChange(java.util.Date); - field public static final int AD = 1; // 0x1 - field public static final int BC = 0; // 0x0 - field protected transient boolean invertGregorian; - field protected transient boolean isGregorian; - } - - public class HebrewCalendar extends android.icu.util.Calendar { - ctor public HebrewCalendar(); - ctor public HebrewCalendar(android.icu.util.TimeZone); - ctor public HebrewCalendar(java.util.Locale); - ctor public HebrewCalendar(android.icu.util.ULocale); - ctor public HebrewCalendar(android.icu.util.TimeZone, java.util.Locale); - ctor public HebrewCalendar(android.icu.util.TimeZone, android.icu.util.ULocale); - ctor public HebrewCalendar(int, int, int); - ctor public HebrewCalendar(java.util.Date); - ctor public HebrewCalendar(int, int, int, int, int, int); - method protected int handleComputeMonthStart(int, int, boolean); - method protected int handleGetExtendedYear(); - method protected int handleGetLimit(int, int); - method @Deprecated protected void validateField(int); - field public static final int ADAR = 6; // 0x6 - field public static final int ADAR_1 = 5; // 0x5 - field public static final int AV = 11; // 0xb - field public static final int ELUL = 12; // 0xc - field public static final int HESHVAN = 1; // 0x1 - field public static final int IYAR = 8; // 0x8 - field public static final int KISLEV = 2; // 0x2 - field public static final int NISAN = 7; // 0x7 - field public static final int SHEVAT = 4; // 0x4 - field public static final int SIVAN = 9; // 0x9 - field public static final int TAMUZ = 10; // 0xa - field public static final int TEVET = 3; // 0x3 - field public static final int TISHRI = 0; // 0x0 - } - - public class ICUUncheckedIOException extends java.lang.RuntimeException { - ctor public ICUUncheckedIOException(); - ctor public ICUUncheckedIOException(String); - ctor public ICUUncheckedIOException(Throwable); - ctor public ICUUncheckedIOException(String, Throwable); - } - - public class IllformedLocaleException extends java.lang.RuntimeException { - ctor public IllformedLocaleException(); - ctor public IllformedLocaleException(String); - ctor public IllformedLocaleException(String, int); - method public int getErrorIndex(); - } - - public class IndianCalendar extends android.icu.util.Calendar { - ctor public IndianCalendar(); - ctor public IndianCalendar(android.icu.util.TimeZone); - ctor public IndianCalendar(java.util.Locale); - ctor public IndianCalendar(android.icu.util.ULocale); - ctor public IndianCalendar(android.icu.util.TimeZone, java.util.Locale); - ctor public IndianCalendar(android.icu.util.TimeZone, android.icu.util.ULocale); - ctor public IndianCalendar(java.util.Date); - ctor public IndianCalendar(int, int, int); - ctor public IndianCalendar(int, int, int, int, int, int); - method protected int handleComputeMonthStart(int, int, boolean); - method protected int handleGetExtendedYear(); - method protected int handleGetLimit(int, int); - field public static final int AGRAHAYANA = 8; // 0x8 - field public static final int ASADHA = 3; // 0x3 - field public static final int ASVINA = 6; // 0x6 - field public static final int BHADRA = 5; // 0x5 - field public static final int CHAITRA = 0; // 0x0 - field public static final int IE = 0; // 0x0 - field public static final int JYAISTHA = 2; // 0x2 - field public static final int KARTIKA = 7; // 0x7 - field public static final int MAGHA = 10; // 0xa - field public static final int PAUSA = 9; // 0x9 - field public static final int PHALGUNA = 11; // 0xb - field public static final int SRAVANA = 4; // 0x4 - field public static final int VAISAKHA = 1; // 0x1 - } - - public class IslamicCalendar extends android.icu.util.Calendar { - ctor public IslamicCalendar(); - ctor public IslamicCalendar(android.icu.util.TimeZone); - ctor public IslamicCalendar(java.util.Locale); - ctor public IslamicCalendar(android.icu.util.ULocale); - ctor public IslamicCalendar(android.icu.util.TimeZone, java.util.Locale); - ctor public IslamicCalendar(android.icu.util.TimeZone, android.icu.util.ULocale); - ctor public IslamicCalendar(java.util.Date); - ctor public IslamicCalendar(int, int, int); - ctor public IslamicCalendar(int, int, int, int, int, int); - method public android.icu.util.IslamicCalendar.CalculationType getCalculationType(); - method protected int handleComputeMonthStart(int, int, boolean); - method protected int handleGetExtendedYear(); - method protected int handleGetLimit(int, int); - method public void setCalculationType(android.icu.util.IslamicCalendar.CalculationType); - field public static final int DHU_AL_HIJJAH = 11; // 0xb - field public static final int DHU_AL_QIDAH = 10; // 0xa - field public static final int JUMADA_1 = 4; // 0x4 - field public static final int JUMADA_2 = 5; // 0x5 - field public static final int MUHARRAM = 0; // 0x0 - field public static final int RABI_1 = 2; // 0x2 - field public static final int RABI_2 = 3; // 0x3 - field public static final int RAJAB = 6; // 0x6 - field public static final int RAMADAN = 8; // 0x8 - field public static final int SAFAR = 1; // 0x1 - field public static final int SHABAN = 7; // 0x7 - field public static final int SHAWWAL = 9; // 0x9 - } - - public enum IslamicCalendar.CalculationType { - enum_constant public static final android.icu.util.IslamicCalendar.CalculationType ISLAMIC; - enum_constant public static final android.icu.util.IslamicCalendar.CalculationType ISLAMIC_CIVIL; - enum_constant public static final android.icu.util.IslamicCalendar.CalculationType ISLAMIC_TBLA; - enum_constant public static final android.icu.util.IslamicCalendar.CalculationType ISLAMIC_UMALQURA; - } - - public class JapaneseCalendar extends android.icu.util.GregorianCalendar { - ctor public JapaneseCalendar(); - ctor public JapaneseCalendar(android.icu.util.TimeZone); - ctor public JapaneseCalendar(java.util.Locale); - ctor public JapaneseCalendar(android.icu.util.ULocale); - ctor public JapaneseCalendar(android.icu.util.TimeZone, java.util.Locale); - ctor public JapaneseCalendar(android.icu.util.TimeZone, android.icu.util.ULocale); - ctor public JapaneseCalendar(java.util.Date); - ctor public JapaneseCalendar(int, int, int, int); - ctor public JapaneseCalendar(int, int, int); - ctor public JapaneseCalendar(int, int, int, int, int, int); - field public static final int HEISEI; - field public static final int MEIJI; - field public static final int REIWA; - field public static final int SHOWA; - field public static final int TAISHO; - } - - public final class LocaleData { - method public static android.icu.util.VersionInfo getCLDRVersion(); - method public String getDelimiter(int); - method public static android.icu.util.LocaleData getInstance(android.icu.util.ULocale); - method public static android.icu.util.LocaleData getInstance(); - method public static android.icu.util.LocaleData.MeasurementSystem getMeasurementSystem(android.icu.util.ULocale); - method public boolean getNoSubstitute(); - method public static android.icu.util.LocaleData.PaperSize getPaperSize(android.icu.util.ULocale); - method public void setNoSubstitute(boolean); - field public static final int ALT_QUOTATION_END = 3; // 0x3 - field public static final int ALT_QUOTATION_START = 2; // 0x2 - field public static final int QUOTATION_END = 1; // 0x1 - field public static final int QUOTATION_START = 0; // 0x0 - } - - public static final class LocaleData.MeasurementSystem { - field public static final android.icu.util.LocaleData.MeasurementSystem SI; - field public static final android.icu.util.LocaleData.MeasurementSystem UK; - field public static final android.icu.util.LocaleData.MeasurementSystem US; - } - - public static final class LocaleData.PaperSize { - method public int getHeight(); - method public int getWidth(); - } - - public class Measure { - ctor public Measure(Number, android.icu.util.MeasureUnit); - method public Number getNumber(); - method public android.icu.util.MeasureUnit getUnit(); - } - - public class MeasureUnit implements java.io.Serializable { - method public static java.util.Set<android.icu.util.MeasureUnit> getAvailable(String); - method public static java.util.Set<android.icu.util.MeasureUnit> getAvailable(); - method public static java.util.Set<java.lang.String> getAvailableTypes(); - method public String getSubtype(); - method public String getType(); - field public static final android.icu.util.MeasureUnit ACRE; - field public static final android.icu.util.MeasureUnit ACRE_FOOT; - field public static final android.icu.util.MeasureUnit AMPERE; - field public static final android.icu.util.MeasureUnit ARC_MINUTE; - field public static final android.icu.util.MeasureUnit ARC_SECOND; - field public static final android.icu.util.MeasureUnit ASTRONOMICAL_UNIT; - field public static final android.icu.util.MeasureUnit ATMOSPHERE; - field public static final android.icu.util.MeasureUnit BIT; - field public static final android.icu.util.MeasureUnit BUSHEL; - field public static final android.icu.util.MeasureUnit BYTE; - field public static final android.icu.util.MeasureUnit CALORIE; - field public static final android.icu.util.MeasureUnit CARAT; - field public static final android.icu.util.MeasureUnit CELSIUS; - field public static final android.icu.util.MeasureUnit CENTILITER; - field public static final android.icu.util.MeasureUnit CENTIMETER; - field public static final android.icu.util.MeasureUnit CENTURY; - field public static final android.icu.util.MeasureUnit CUBIC_CENTIMETER; - field public static final android.icu.util.MeasureUnit CUBIC_FOOT; - field public static final android.icu.util.MeasureUnit CUBIC_INCH; - field public static final android.icu.util.MeasureUnit CUBIC_KILOMETER; - field public static final android.icu.util.MeasureUnit CUBIC_METER; - field public static final android.icu.util.MeasureUnit CUBIC_MILE; - field public static final android.icu.util.MeasureUnit CUBIC_YARD; - field public static final android.icu.util.MeasureUnit CUP; - field public static final android.icu.util.MeasureUnit CUP_METRIC; - field public static final android.icu.util.TimeUnit DAY; - field public static final android.icu.util.MeasureUnit DECILITER; - field public static final android.icu.util.MeasureUnit DECIMETER; - field public static final android.icu.util.MeasureUnit DEGREE; - field public static final android.icu.util.MeasureUnit FAHRENHEIT; - field public static final android.icu.util.MeasureUnit FATHOM; - field public static final android.icu.util.MeasureUnit FLUID_OUNCE; - field public static final android.icu.util.MeasureUnit FOODCALORIE; - field public static final android.icu.util.MeasureUnit FOOT; - field public static final android.icu.util.MeasureUnit FURLONG; - field public static final android.icu.util.MeasureUnit GALLON; - field public static final android.icu.util.MeasureUnit GALLON_IMPERIAL; - field public static final android.icu.util.MeasureUnit GENERIC_TEMPERATURE; - field public static final android.icu.util.MeasureUnit GIGABIT; - field public static final android.icu.util.MeasureUnit GIGABYTE; - field public static final android.icu.util.MeasureUnit GIGAHERTZ; - field public static final android.icu.util.MeasureUnit GIGAWATT; - field public static final android.icu.util.MeasureUnit GRAM; - field public static final android.icu.util.MeasureUnit G_FORCE; - field public static final android.icu.util.MeasureUnit HECTARE; - field public static final android.icu.util.MeasureUnit HECTOLITER; - field public static final android.icu.util.MeasureUnit HECTOPASCAL; - field public static final android.icu.util.MeasureUnit HERTZ; - field public static final android.icu.util.MeasureUnit HORSEPOWER; - field public static final android.icu.util.TimeUnit HOUR; - field public static final android.icu.util.MeasureUnit INCH; - field public static final android.icu.util.MeasureUnit INCH_HG; - field public static final android.icu.util.MeasureUnit JOULE; - field public static final android.icu.util.MeasureUnit KARAT; - field public static final android.icu.util.MeasureUnit KELVIN; - field public static final android.icu.util.MeasureUnit KILOBIT; - field public static final android.icu.util.MeasureUnit KILOBYTE; - field public static final android.icu.util.MeasureUnit KILOCALORIE; - field public static final android.icu.util.MeasureUnit KILOGRAM; - field public static final android.icu.util.MeasureUnit KILOHERTZ; - field public static final android.icu.util.MeasureUnit KILOJOULE; - field public static final android.icu.util.MeasureUnit KILOMETER; - field public static final android.icu.util.MeasureUnit KILOMETER_PER_HOUR; - field public static final android.icu.util.MeasureUnit KILOWATT; - field public static final android.icu.util.MeasureUnit KILOWATT_HOUR; - field public static final android.icu.util.MeasureUnit KNOT; - field public static final android.icu.util.MeasureUnit LIGHT_YEAR; - field public static final android.icu.util.MeasureUnit LITER; - field public static final android.icu.util.MeasureUnit LITER_PER_100KILOMETERS; - field public static final android.icu.util.MeasureUnit LITER_PER_KILOMETER; - field public static final android.icu.util.MeasureUnit LUX; - field public static final android.icu.util.MeasureUnit MEGABIT; - field public static final android.icu.util.MeasureUnit MEGABYTE; - field public static final android.icu.util.MeasureUnit MEGAHERTZ; - field public static final android.icu.util.MeasureUnit MEGALITER; - field public static final android.icu.util.MeasureUnit MEGAWATT; - field public static final android.icu.util.MeasureUnit METER; - field public static final android.icu.util.MeasureUnit METER_PER_SECOND; - field public static final android.icu.util.MeasureUnit METER_PER_SECOND_SQUARED; - field public static final android.icu.util.MeasureUnit METRIC_TON; - field public static final android.icu.util.MeasureUnit MICROGRAM; - field public static final android.icu.util.MeasureUnit MICROMETER; - field public static final android.icu.util.MeasureUnit MICROSECOND; - field public static final android.icu.util.MeasureUnit MILE; - field public static final android.icu.util.MeasureUnit MILE_PER_GALLON; - field public static final android.icu.util.MeasureUnit MILE_PER_GALLON_IMPERIAL; - field public static final android.icu.util.MeasureUnit MILE_PER_HOUR; - field public static final android.icu.util.MeasureUnit MILE_SCANDINAVIAN; - field public static final android.icu.util.MeasureUnit MILLIAMPERE; - field public static final android.icu.util.MeasureUnit MILLIBAR; - field public static final android.icu.util.MeasureUnit MILLIGRAM; - field public static final android.icu.util.MeasureUnit MILLIGRAM_PER_DECILITER; - field public static final android.icu.util.MeasureUnit MILLILITER; - field public static final android.icu.util.MeasureUnit MILLIMETER; - field public static final android.icu.util.MeasureUnit MILLIMETER_OF_MERCURY; - field public static final android.icu.util.MeasureUnit MILLIMOLE_PER_LITER; - field public static final android.icu.util.MeasureUnit MILLISECOND; - field public static final android.icu.util.MeasureUnit MILLIWATT; - field public static final android.icu.util.TimeUnit MINUTE; - field public static final android.icu.util.TimeUnit MONTH; - field public static final android.icu.util.MeasureUnit NANOMETER; - field public static final android.icu.util.MeasureUnit NANOSECOND; - field public static final android.icu.util.MeasureUnit NAUTICAL_MILE; - field public static final android.icu.util.MeasureUnit OHM; - field public static final android.icu.util.MeasureUnit OUNCE; - field public static final android.icu.util.MeasureUnit OUNCE_TROY; - field public static final android.icu.util.MeasureUnit PARSEC; - field public static final android.icu.util.MeasureUnit PART_PER_MILLION; - field public static final android.icu.util.MeasureUnit PERCENT; - field public static final android.icu.util.MeasureUnit PERMILLE; - field public static final android.icu.util.MeasureUnit PETABYTE; - field public static final android.icu.util.MeasureUnit PICOMETER; - field public static final android.icu.util.MeasureUnit PINT; - field public static final android.icu.util.MeasureUnit PINT_METRIC; - field public static final android.icu.util.MeasureUnit POINT; - field public static final android.icu.util.MeasureUnit POUND; - field public static final android.icu.util.MeasureUnit POUND_PER_SQUARE_INCH; - field public static final android.icu.util.MeasureUnit QUART; - field public static final android.icu.util.MeasureUnit RADIAN; - field public static final android.icu.util.MeasureUnit REVOLUTION_ANGLE; - field public static final android.icu.util.TimeUnit SECOND; - field public static final android.icu.util.MeasureUnit SQUARE_CENTIMETER; - field public static final android.icu.util.MeasureUnit SQUARE_FOOT; - field public static final android.icu.util.MeasureUnit SQUARE_INCH; - field public static final android.icu.util.MeasureUnit SQUARE_KILOMETER; - field public static final android.icu.util.MeasureUnit SQUARE_METER; - field public static final android.icu.util.MeasureUnit SQUARE_MILE; - field public static final android.icu.util.MeasureUnit SQUARE_YARD; - field public static final android.icu.util.MeasureUnit STONE; - field public static final android.icu.util.MeasureUnit TABLESPOON; - field public static final android.icu.util.MeasureUnit TEASPOON; - field public static final android.icu.util.MeasureUnit TERABIT; - field public static final android.icu.util.MeasureUnit TERABYTE; - field public static final android.icu.util.MeasureUnit TON; - field public static final android.icu.util.MeasureUnit VOLT; - field public static final android.icu.util.MeasureUnit WATT; - field public static final android.icu.util.TimeUnit WEEK; - field public static final android.icu.util.MeasureUnit YARD; - field public static final android.icu.util.TimeUnit YEAR; - } - - public class Output<T> { - ctor public Output(); - ctor public Output(T); - field public T value; - } - - public interface RangeValueIterator { - method public boolean next(android.icu.util.RangeValueIterator.Element); - method public void reset(); - } - - public static class RangeValueIterator.Element { - ctor public RangeValueIterator.Element(); - field public int limit; - field public int start; - field public int value; - } - - public class TaiwanCalendar extends android.icu.util.GregorianCalendar { - ctor public TaiwanCalendar(); - ctor public TaiwanCalendar(android.icu.util.TimeZone); - ctor public TaiwanCalendar(java.util.Locale); - ctor public TaiwanCalendar(android.icu.util.ULocale); - ctor public TaiwanCalendar(android.icu.util.TimeZone, java.util.Locale); - ctor public TaiwanCalendar(android.icu.util.TimeZone, android.icu.util.ULocale); - ctor public TaiwanCalendar(java.util.Date); - ctor public TaiwanCalendar(int, int, int); - ctor public TaiwanCalendar(int, int, int, int, int, int); - field public static final int BEFORE_MINGUO = 0; // 0x0 - field public static final int MINGUO = 1; // 0x1 - } - - public class TimeUnit extends android.icu.util.MeasureUnit { - method public static android.icu.util.TimeUnit[] values(); - } - - public abstract class TimeZone implements java.lang.Cloneable android.icu.util.Freezable<android.icu.util.TimeZone> java.io.Serializable { - ctor public TimeZone(); - method public Object clone(); - method public android.icu.util.TimeZone cloneAsThawed(); - method public static int countEquivalentIDs(String); - method public android.icu.util.TimeZone freeze(); - method public static java.util.Set<java.lang.String> getAvailableIDs(android.icu.util.TimeZone.SystemTimeZoneType, String, Integer); - method public static String[] getAvailableIDs(int); - method public static String[] getAvailableIDs(String); - method public static String[] getAvailableIDs(); - method public static String getCanonicalID(String); - method public static String getCanonicalID(String, boolean[]); - method public int getDSTSavings(); - method public static android.icu.util.TimeZone getDefault(); - method public final String getDisplayName(); - method public final String getDisplayName(java.util.Locale); - method public final String getDisplayName(android.icu.util.ULocale); - method public final String getDisplayName(boolean, int); - method public String getDisplayName(boolean, int, java.util.Locale); - method public String getDisplayName(boolean, int, android.icu.util.ULocale); - method public static String getEquivalentID(String, int); - method public static android.icu.util.TimeZone getFrozenTimeZone(String); - method public String getID(); - method public static String getIDForWindowsID(String, String); - method public abstract int getOffset(int, int, int, int, int, int); - method public int getOffset(long); - method public void getOffset(long, boolean, int[]); - method public abstract int getRawOffset(); - method public static String getRegion(String); - method public static String getTZDataVersion(); - method public static android.icu.util.TimeZone getTimeZone(String); - method public static android.icu.util.TimeZone getTimeZone(String, int); - method public static String getWindowsID(String); - method public boolean hasSameRules(android.icu.util.TimeZone); - method public abstract boolean inDaylightTime(java.util.Date); - method public boolean isFrozen(); - method public boolean observesDaylightTime(); - method public void setID(String); - method public abstract void setRawOffset(int); - method public abstract boolean useDaylightTime(); - field public static final int GENERIC_LOCATION = 7; // 0x7 - field public static final android.icu.util.TimeZone GMT_ZONE; - field public static final int LONG = 1; // 0x1 - field public static final int LONG_GENERIC = 3; // 0x3 - field public static final int LONG_GMT = 5; // 0x5 - field public static final int SHORT = 0; // 0x0 - field public static final int SHORT_COMMONLY_USED = 6; // 0x6 - field public static final int SHORT_GENERIC = 2; // 0x2 - field public static final int SHORT_GMT = 4; // 0x4 - field public static final int TIMEZONE_ICU = 0; // 0x0 - field public static final int TIMEZONE_JDK = 1; // 0x1 - field public static final android.icu.util.TimeZone UNKNOWN_ZONE; - field public static final String UNKNOWN_ZONE_ID = "Etc/Unknown"; - } - - public enum TimeZone.SystemTimeZoneType { - enum_constant public static final android.icu.util.TimeZone.SystemTimeZoneType ANY; - enum_constant public static final android.icu.util.TimeZone.SystemTimeZoneType CANONICAL; - enum_constant public static final android.icu.util.TimeZone.SystemTimeZoneType CANONICAL_LOCATION; - } - - public final class ULocale implements java.lang.Comparable<android.icu.util.ULocale> java.io.Serializable { - ctor public ULocale(String); - ctor public ULocale(String, String); - ctor public ULocale(String, String, String); - method public static android.icu.util.ULocale acceptLanguage(String, android.icu.util.ULocale[], boolean[]); - method public static android.icu.util.ULocale acceptLanguage(android.icu.util.ULocale[], android.icu.util.ULocale[], boolean[]); - method public static android.icu.util.ULocale acceptLanguage(String, boolean[]); - method public static android.icu.util.ULocale acceptLanguage(android.icu.util.ULocale[], boolean[]); - method public static android.icu.util.ULocale addLikelySubtags(android.icu.util.ULocale); - method public static String canonicalize(String); - method public Object clone(); - method public int compareTo(android.icu.util.ULocale); - method public static android.icu.util.ULocale createCanonical(String); - method public static android.icu.util.ULocale forLanguageTag(String); - method public static android.icu.util.ULocale forLocale(java.util.Locale); - method public static android.icu.util.ULocale[] getAvailableLocales(); - method public String getBaseName(); - method public static String getBaseName(String); - method public String getCharacterOrientation(); - method public String getCountry(); - method public static String getCountry(String); - method public static android.icu.util.ULocale getDefault(); - method public static android.icu.util.ULocale getDefault(android.icu.util.ULocale.Category); - method public String getDisplayCountry(); - method public String getDisplayCountry(android.icu.util.ULocale); - method public static String getDisplayCountry(String, String); - method public static String getDisplayCountry(String, android.icu.util.ULocale); - method public static String getDisplayKeyword(String); - method public static String getDisplayKeyword(String, String); - method public static String getDisplayKeyword(String, android.icu.util.ULocale); - method public String getDisplayKeywordValue(String); - method public String getDisplayKeywordValue(String, android.icu.util.ULocale); - method public static String getDisplayKeywordValue(String, String, String); - method public static String getDisplayKeywordValue(String, String, android.icu.util.ULocale); - method public String getDisplayLanguage(); - method public String getDisplayLanguage(android.icu.util.ULocale); - method public static String getDisplayLanguage(String, String); - method public static String getDisplayLanguage(String, android.icu.util.ULocale); - method public String getDisplayLanguageWithDialect(); - method public String getDisplayLanguageWithDialect(android.icu.util.ULocale); - method public static String getDisplayLanguageWithDialect(String, String); - method public static String getDisplayLanguageWithDialect(String, android.icu.util.ULocale); - method public String getDisplayName(); - method public String getDisplayName(android.icu.util.ULocale); - method public static String getDisplayName(String, String); - method public static String getDisplayName(String, android.icu.util.ULocale); - method public String getDisplayNameWithDialect(); - method public String getDisplayNameWithDialect(android.icu.util.ULocale); - method public static String getDisplayNameWithDialect(String, String); - method public static String getDisplayNameWithDialect(String, android.icu.util.ULocale); - method public String getDisplayScript(); - method public String getDisplayScript(android.icu.util.ULocale); - method public static String getDisplayScript(String, String); - method public static String getDisplayScript(String, android.icu.util.ULocale); - method public String getDisplayVariant(); - method public String getDisplayVariant(android.icu.util.ULocale); - method public static String getDisplayVariant(String, String); - method public static String getDisplayVariant(String, android.icu.util.ULocale); - method public String getExtension(char); - method public java.util.Set<java.lang.Character> getExtensionKeys(); - method public static String getFallback(String); - method public android.icu.util.ULocale getFallback(); - method public String getISO3Country(); - method public static String getISO3Country(String); - method public String getISO3Language(); - method public static String getISO3Language(String); - method public static String[] getISOCountries(); - method public static String[] getISOLanguages(); - method public String getKeywordValue(String); - method public static String getKeywordValue(String, String); - method public java.util.Iterator<java.lang.String> getKeywords(); - method public static java.util.Iterator<java.lang.String> getKeywords(String); - method public String getLanguage(); - method public static String getLanguage(String); - method public String getLineOrientation(); - method public String getName(); - method public static String getName(String); - method public String getScript(); - method public static String getScript(String); - method public java.util.Set<java.lang.String> getUnicodeLocaleAttributes(); - method public java.util.Set<java.lang.String> getUnicodeLocaleKeys(); - method public String getUnicodeLocaleType(String); - method public String getVariant(); - method public static String getVariant(String); - method public boolean isRightToLeft(); - method public static android.icu.util.ULocale minimizeSubtags(android.icu.util.ULocale); - method public android.icu.util.ULocale setKeywordValue(String, String); - method public static String setKeywordValue(String, String, String); - method public String toLanguageTag(); - method public static String toLegacyKey(String); - method public static String toLegacyType(String, String); - method public java.util.Locale toLocale(); - method public static String toUnicodeLocaleKey(String); - method public static String toUnicodeLocaleType(String, String); - field public static final android.icu.util.ULocale CANADA; - field public static final android.icu.util.ULocale CANADA_FRENCH; - field public static final android.icu.util.ULocale CHINA; - field public static final android.icu.util.ULocale CHINESE; - field public static final android.icu.util.ULocale ENGLISH; - field public static final android.icu.util.ULocale FRANCE; - field public static final android.icu.util.ULocale FRENCH; - field public static final android.icu.util.ULocale GERMAN; - field public static final android.icu.util.ULocale GERMANY; - field public static final android.icu.util.ULocale ITALIAN; - field public static final android.icu.util.ULocale ITALY; - field public static final android.icu.util.ULocale JAPAN; - field public static final android.icu.util.ULocale JAPANESE; - field public static final android.icu.util.ULocale KOREA; - field public static final android.icu.util.ULocale KOREAN; - field public static final android.icu.util.ULocale PRC; - field public static final char PRIVATE_USE_EXTENSION = 120; // 0x0078 'x' - field public static final android.icu.util.ULocale ROOT; - field public static final android.icu.util.ULocale SIMPLIFIED_CHINESE; - field public static final android.icu.util.ULocale TAIWAN; - field public static final android.icu.util.ULocale TRADITIONAL_CHINESE; - field public static final android.icu.util.ULocale UK; - field public static final char UNICODE_LOCALE_EXTENSION = 117; // 0x0075 'u' - field public static final android.icu.util.ULocale US; - } - - public static final class ULocale.Builder { - ctor public ULocale.Builder(); - method public android.icu.util.ULocale.Builder addUnicodeLocaleAttribute(String); - method public android.icu.util.ULocale build(); - method public android.icu.util.ULocale.Builder clear(); - method public android.icu.util.ULocale.Builder clearExtensions(); - method public android.icu.util.ULocale.Builder removeUnicodeLocaleAttribute(String); - method public android.icu.util.ULocale.Builder setExtension(char, String); - method public android.icu.util.ULocale.Builder setLanguage(String); - method public android.icu.util.ULocale.Builder setLanguageTag(String); - method public android.icu.util.ULocale.Builder setLocale(android.icu.util.ULocale); - method public android.icu.util.ULocale.Builder setRegion(String); - method public android.icu.util.ULocale.Builder setScript(String); - method public android.icu.util.ULocale.Builder setUnicodeLocaleKeyword(String, String); - method public android.icu.util.ULocale.Builder setVariant(String); - } - - public enum ULocale.Category { - enum_constant public static final android.icu.util.ULocale.Category DISPLAY; - enum_constant public static final android.icu.util.ULocale.Category FORMAT; - } - - public final class UniversalTimeScale { - method public static android.icu.math.BigDecimal bigDecimalFrom(double, int); - method public static android.icu.math.BigDecimal bigDecimalFrom(long, int); - method public static android.icu.math.BigDecimal bigDecimalFrom(android.icu.math.BigDecimal, int); - method public static long from(long, int); - method public static long getTimeScaleValue(int, int); - method public static android.icu.math.BigDecimal toBigDecimal(long, int); - method public static android.icu.math.BigDecimal toBigDecimal(android.icu.math.BigDecimal, int); - method public static long toLong(long, int); - field public static final int DB2_TIME = 8; // 0x8 - field public static final int DOTNET_DATE_TIME = 4; // 0x4 - field public static final int EPOCH_OFFSET_PLUS_1_VALUE = 6; // 0x6 - field public static final int EPOCH_OFFSET_VALUE = 1; // 0x1 - field public static final int EXCEL_TIME = 7; // 0x7 - field public static final int FROM_MAX_VALUE = 3; // 0x3 - field public static final int FROM_MIN_VALUE = 2; // 0x2 - field public static final int ICU4C_TIME = 2; // 0x2 - field public static final int JAVA_TIME = 0; // 0x0 - field public static final int MAC_OLD_TIME = 5; // 0x5 - field public static final int MAC_TIME = 6; // 0x6 - field @Deprecated public static final int MAX_SCALE = 10; // 0xa - field public static final int TO_MAX_VALUE = 5; // 0x5 - field public static final int TO_MIN_VALUE = 4; // 0x4 - field public static final int UNITS_VALUE = 0; // 0x0 - field public static final int UNIX_MICROSECONDS_TIME = 9; // 0x9 - field public static final int UNIX_TIME = 1; // 0x1 - field public static final int WINDOWS_FILE_TIME = 3; // 0x3 - } - - public interface ValueIterator { - method public boolean next(android.icu.util.ValueIterator.Element); - method public void reset(); - method public void setRange(int, int); - } - - public static final class ValueIterator.Element { - ctor public ValueIterator.Element(); - field public int integer; - field public Object value; - } - - public final class VersionInfo implements java.lang.Comparable<android.icu.util.VersionInfo> { - method public int compareTo(android.icu.util.VersionInfo); - method public static android.icu.util.VersionInfo getInstance(String); - method public static android.icu.util.VersionInfo getInstance(int, int, int, int); - method public static android.icu.util.VersionInfo getInstance(int, int, int); - method public static android.icu.util.VersionInfo getInstance(int, int); - method public static android.icu.util.VersionInfo getInstance(int); - method public int getMajor(); - method public int getMicro(); - method public int getMilli(); - method public int getMinor(); - field public static final android.icu.util.VersionInfo ICU_VERSION; - field public static final android.icu.util.VersionInfo UCOL_BUILDER_VERSION; - field public static final android.icu.util.VersionInfo UCOL_RUNTIME_VERSION; - field public static final android.icu.util.VersionInfo UNICODE_10_0; - field public static final android.icu.util.VersionInfo UNICODE_11_0; - field public static final android.icu.util.VersionInfo UNICODE_12_0; - field public static final android.icu.util.VersionInfo UNICODE_12_1; - field public static final android.icu.util.VersionInfo UNICODE_13_0; - field public static final android.icu.util.VersionInfo UNICODE_1_0; - field public static final android.icu.util.VersionInfo UNICODE_1_0_1; - field public static final android.icu.util.VersionInfo UNICODE_1_1_0; - field public static final android.icu.util.VersionInfo UNICODE_1_1_5; - field public static final android.icu.util.VersionInfo UNICODE_2_0; - field public static final android.icu.util.VersionInfo UNICODE_2_1_2; - field public static final android.icu.util.VersionInfo UNICODE_2_1_5; - field public static final android.icu.util.VersionInfo UNICODE_2_1_8; - field public static final android.icu.util.VersionInfo UNICODE_2_1_9; - field public static final android.icu.util.VersionInfo UNICODE_3_0; - field public static final android.icu.util.VersionInfo UNICODE_3_0_1; - field public static final android.icu.util.VersionInfo UNICODE_3_1_0; - field public static final android.icu.util.VersionInfo UNICODE_3_1_1; - field public static final android.icu.util.VersionInfo UNICODE_3_2; - field public static final android.icu.util.VersionInfo UNICODE_4_0; - field public static final android.icu.util.VersionInfo UNICODE_4_0_1; - field public static final android.icu.util.VersionInfo UNICODE_4_1; - field public static final android.icu.util.VersionInfo UNICODE_5_0; - field public static final android.icu.util.VersionInfo UNICODE_5_1; - field public static final android.icu.util.VersionInfo UNICODE_5_2; - field public static final android.icu.util.VersionInfo UNICODE_6_0; - field public static final android.icu.util.VersionInfo UNICODE_6_1; - field public static final android.icu.util.VersionInfo UNICODE_6_2; - field public static final android.icu.util.VersionInfo UNICODE_6_3; - field public static final android.icu.util.VersionInfo UNICODE_7_0; - field public static final android.icu.util.VersionInfo UNICODE_8_0; - field public static final android.icu.util.VersionInfo UNICODE_9_0; - } - -} - package android.inputmethodservice { public abstract class AbstractInputMethodService extends android.app.Service implements android.view.KeyEvent.Callback { @@ -24007,7 +19208,7 @@ package android.location { method public float getBearingAccuracyDegrees(); method public long getElapsedRealtimeNanos(); method public double getElapsedRealtimeUncertaintyNanos(); - method @Deprecated public android.os.Bundle getExtras(); + method public android.os.Bundle getExtras(); method public double getLatitude(); method public double getLongitude(); method public String getProvider(); @@ -24036,7 +19237,7 @@ package android.location { method public void setBearingAccuracyDegrees(float); method public void setElapsedRealtimeNanos(long); method public void setElapsedRealtimeUncertaintyNanos(double); - method @Deprecated public void setExtras(@Nullable android.os.Bundle); + method public void setExtras(@Nullable android.os.Bundle); method public void setLatitude(double); method public void setLongitude(double); method public void setProvider(String); @@ -24107,10 +19308,10 @@ package android.location { method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull android.location.LocationListener); method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull android.location.LocationListener, @Nullable android.os.Looper); method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener); - method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long, float, @NonNull android.location.Criteria, @NonNull android.location.LocationListener, @Nullable android.os.Looper); - method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long, float, @NonNull android.location.Criteria, @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(long, float, @NonNull android.location.Criteria, @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(long, float, @NonNull android.location.Criteria, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener); method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, long, float, @NonNull android.app.PendingIntent); - method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long, float, @NonNull android.location.Criteria, @NonNull android.app.PendingIntent); + method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long, float, @NonNull android.location.Criteria, @NonNull android.app.PendingIntent); method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, @NonNull android.location.LocationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener); method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@NonNull String, @NonNull android.location.LocationRequest, @NonNull android.app.PendingIntent); method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestSingleUpdate(@NonNull String, @NonNull android.location.LocationListener, @Nullable android.os.Looper); @@ -24128,6 +19329,7 @@ package android.location { field public static final String EXTRA_LOCATION_ENABLED = "android.location.extra.LOCATION_ENABLED"; field public static final String EXTRA_PROVIDER_ENABLED = "android.location.extra.PROVIDER_ENABLED"; field public static final String EXTRA_PROVIDER_NAME = "android.location.extra.PROVIDER_NAME"; + field public static final String FUSED_PROVIDER = "fused"; field public static final String GPS_PROVIDER = "gps"; field public static final String KEY_FLUSH_COMPLETE = "flushComplete"; field public static final String KEY_LOCATION_CHANGED = "location"; @@ -24309,6 +19511,7 @@ package android.media { public final class AudioDeviceInfo { method @NonNull public String getAddress(); + method @NonNull public java.util.List<android.media.AudioProfile> getAudioProfiles(); method @NonNull public int[] getChannelCounts(); method @NonNull public int[] getChannelIndexMasks(); method @NonNull public int[] getChannelMasks(); @@ -24474,6 +19677,7 @@ package android.media { method public java.util.List<android.media.MicrophoneInfo> getMicrophones() throws java.io.IOException; method public int getMode(); method public String getParameters(String); + method public static int getPlaybackOffloadSupport(@NonNull android.media.AudioFormat, @NonNull android.media.AudioAttributes); method public String getProperty(String); method public int getRingerMode(); method @Deprecated public int getRouting(int); @@ -24592,6 +19796,9 @@ package android.media { field public static final int MODE_NORMAL = 0; // 0x0 field public static final int MODE_RINGTONE = 1; // 0x1 field @Deprecated public static final int NUM_STREAMS = 5; // 0x5 + field public static final int PLAYBACK_OFFLOAD_GAPLESS_SUPPORTED = 2; // 0x2 + field public static final int PLAYBACK_OFFLOAD_NOT_SUPPORTED = 0; // 0x0 + field public static final int PLAYBACK_OFFLOAD_SUPPORTED = 1; // 0x1 field public static final String PROPERTY_OUTPUT_FRAMES_PER_BUFFER = "android.media.property.OUTPUT_FRAMES_PER_BUFFER"; field public static final String PROPERTY_OUTPUT_SAMPLE_RATE = "android.media.property.OUTPUT_SAMPLE_RATE"; field public static final String PROPERTY_SUPPORT_AUDIO_SOURCE_UNPROCESSED = "android.media.property.SUPPORT_AUDIO_SOURCE_UNPROCESSED"; @@ -24726,6 +19933,13 @@ package android.media { method @NonNull public android.media.AudioPresentation.Builder setProgramId(int); } + public class AudioProfile { + method @NonNull public int[] getChannelIndexMasks(); + method @NonNull public int[] getChannelMasks(); + method public int getFormat(); + method @NonNull public int[] getSampleRates(); + } + public class AudioRecord implements android.media.AudioRecordingMonitor android.media.AudioRouting android.media.MicrophoneDirection { ctor public AudioRecord(int, int, int, int, int) throws java.lang.IllegalArgumentException; method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler); @@ -28903,6 +24117,7 @@ package android.media.session { field public static final long ACTION_PREPARE_FROM_URI = 131072L; // 0x20000L field public static final long ACTION_REWIND = 8L; // 0x8L field public static final long ACTION_SEEK_TO = 256L; // 0x100L + field public static final long ACTION_SET_PLAYBACK_SPEED = 4194304L; // 0x400000L field public static final long ACTION_SET_RATING = 128L; // 0x80L field public static final long ACTION_SKIP_TO_NEXT = 32L; // 0x20L field public static final long ACTION_SKIP_TO_PREVIOUS = 16L; // 0x10L @@ -34716,6 +29931,7 @@ package android.os { field public static final String ID; field public static final String MANUFACTURER; field public static final String MODEL; + field @NonNull public static final String ODM_SKU; field public static final String PRODUCT; field @Deprecated public static final String RADIO; field @Deprecated public static final String SERIAL; @@ -45872,6 +41088,28 @@ package android.telephony { field public static final int IP_VERSION_MISMATCH = 2055; // 0x807 field public static final int IRAT_HANDOVER_FAILED = 2194; // 0x892 field public static final int IS707B_MAX_ACCESS_PROBES = 2089; // 0x829 + field public static final int IWLAN_AUTHORIZATION_REJECTED = 9003; // 0x232b + field public static final int IWLAN_DNS_RESOLUTION_NAME_FAILURE = 16388; // 0x4004 + field public static final int IWLAN_DNS_RESOLUTION_TIMEOUT = 16389; // 0x4005 + field public static final int IWLAN_IKEV2_AUTH_FAILURE = 16385; // 0x4001 + field public static final int IWLAN_IKEV2_CERT_INVALID = 16387; // 0x4003 + field public static final int IWLAN_IKEV2_CONFIG_FAILURE = 16384; // 0x4000 + field public static final int IWLAN_IKEV2_MSG_TIMEOUT = 16386; // 0x4002 + field public static final int IWLAN_ILLEGAL_ME = 9006; // 0x232e + field public static final int IWLAN_IMEI_NOT_ACCEPTED = 11005; // 0x2afd + field public static final int IWLAN_MAX_CONNECTION_REACHED = 8193; // 0x2001 + field public static final int IWLAN_NETWORK_FAILURE = 10500; // 0x2904 + field public static final int IWLAN_NON_3GPP_ACCESS_TO_EPC_NOT_ALLOWED = 9000; // 0x2328 + field public static final int IWLAN_NO_APN_SUBSCRIPTION = 9002; // 0x232a + field public static final int IWLAN_PDN_CONNECTION_REJECTION = 8192; // 0x2000 + field public static final int IWLAN_PLMN_NOT_ALLOWED = 11011; // 0x2b03 + field public static final int IWLAN_RAT_TYPE_NOT_ALLOWED = 11001; // 0x2af9 + field public static final int IWLAN_SEMANTIC_ERRORS_IN_PACKET_FILTERS = 8244; // 0x2034 + field public static final int IWLAN_SEMANTIC_ERROR_IN_THE_TFT_OPERATION = 8241; // 0x2031 + field public static final int IWLAN_SYNTACTICAL_ERRORS_IN_PACKET_FILTERS = 8245; // 0x2035 + field public static final int IWLAN_SYNTACTICAL_ERROR_IN_THE_TFT_OPERATION = 8242; // 0x2032 + field public static final int IWLAN_UNAUTHENTICATED_EMERGENCY_NOT_SUPPORTED = 11055; // 0x2b2f + field public static final int IWLAN_USER_UNKNOWN = 9001; // 0x2329 field public static final int LIMITED_TO_IPV4 = 2234; // 0x8ba field public static final int LIMITED_TO_IPV6 = 2235; // 0x8bb field public static final int LLC_SNDCP = 25; // 0x19 @@ -46981,6 +42219,7 @@ package android.telephony { method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public String getManualNetworkSelectionPlmn(); method @Nullable public String getManufacturerCode(); method @Nullable public String getManufacturerCode(int); + method public static long getMaximumCallComposerPictureSize(); method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getMeid(); method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getMeid(int); method public String getMmsUAProfUrl(); @@ -54221,6 +49460,7 @@ package android.view { method public void setFlags(int, int); method public void setFormat(int); method public void setGravity(int); + method @RequiresPermission(android.Manifest.permission.HIDE_OVERLAY_WINDOWS) public final void setHideOverlayWindows(boolean); method public void setIcon(@DrawableRes int); method public void setLayout(int, int); method public void setLocalFocus(boolean, boolean); diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt index d83c0adb3ae1..cbb3bea6327e 100644 --- a/core/api/module-lib-current.txt +++ b/core/api/module-lib-current.txt @@ -122,6 +122,20 @@ package android.media.session { } +package android.net { + + public final class TcpRepairWindow { + ctor public TcpRepairWindow(int, int, int, int, int, int); + field public final int maxWindow; + field public final int rcvWnd; + field public final int rcvWndScale; + field public final int rcvWup; + field public final int sndWl1; + field public final int sndWnd; + } + +} + package android.os { public class Binder implements android.os.IBinder { diff --git a/core/api/removed.txt b/core/api/removed.txt index f2dfb84eb8fe..990388a54c85 100644 --- a/core/api/removed.txt +++ b/core/api/removed.txt @@ -213,14 +213,6 @@ package android.hardware { } -package android.icu.util { - - public class JapaneseCalendar extends android.icu.util.GregorianCalendar { - field @Deprecated public static final int CURRENT_ERA; - } - -} - package android.location { public class Location implements android.os.Parcelable { diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 7ef2ccbd8a33..25890253ac7d 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -57,6 +57,7 @@ package android { field public static final String BRIGHTNESS_SLIDER_USAGE = "android.permission.BRIGHTNESS_SLIDER_USAGE"; field @Deprecated public static final String BROADCAST_NETWORK_PRIVILEGED = "android.permission.BROADCAST_NETWORK_PRIVILEGED"; field public static final String CAMERA_DISABLE_TRANSMIT_LED = "android.permission.CAMERA_DISABLE_TRANSMIT_LED"; + 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_TV_INPUT = "android.permission.CAPTURE_TV_INPUT"; @@ -93,7 +94,7 @@ package android { field public static final String HANDLE_CAR_MODE_CHANGES = "android.permission.HANDLE_CAR_MODE_CHANGES"; field public static final String HARDWARE_TEST = "android.permission.HARDWARE_TEST"; field public static final String HDMI_CEC = "android.permission.HDMI_CEC"; - field public static final String HIDE_NON_SYSTEM_OVERLAY_WINDOWS = "android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS"; + field @Deprecated public static final String HIDE_NON_SYSTEM_OVERLAY_WINDOWS = "android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS"; field public static final String INJECT_EVENTS = "android.permission.INJECT_EVENTS"; field public static final String INSTALL_DYNAMIC_SYSTEM = "android.permission.INSTALL_DYNAMIC_SYSTEM"; field public static final String INSTALL_GRANT_RUNTIME_PERMISSIONS = "android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS"; @@ -1343,6 +1344,7 @@ package android.app.role { public abstract class RoleControllerService extends android.app.Service { ctor public RoleControllerService(); + method @NonNull public android.app.role.RolePrivileges getRolePrivileges(@NonNull String); method @WorkerThread public abstract boolean onAddRoleHolder(@NonNull String, @NonNull String, int); method @Nullable public final android.os.IBinder onBind(@Nullable android.content.Intent); method @WorkerThread public abstract boolean onClearRoleHolders(@NonNull String, int); @@ -1369,6 +1371,18 @@ package android.app.role { field public static final int MANAGE_HOLDERS_FLAG_DONT_KILL_APP = 1; // 0x1 } + public final class RolePrivileges implements android.os.Parcelable { + ctor public RolePrivileges(@NonNull java.util.List<java.lang.String>, @NonNull java.util.List<java.lang.String>, @NonNull java.util.List<java.lang.String>, @NonNull java.util.List<java.lang.String>); + method public int describeContents(); + method @NonNull public java.util.List<java.lang.String> getAppOpPermissions(); + method @NonNull public java.util.List<java.lang.String> getAppOps(); + method @NonNull public java.util.List<java.lang.String> getCapabilities(); + method @NonNull public java.util.List<java.lang.String> getPermissions(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field public static final String CAPABILITY_NOTIFICATION_LISTENER = "android.app.role.capability.NOTIFICATION_LISTENER"; + field @NonNull public static final android.os.Parcelable.Creator<android.app.role.RolePrivileges> CREATOR; + } + } package android.app.time { @@ -2460,6 +2474,11 @@ package android.hardware.camera2 { field public static final int SESSION_OPERATION_MODE_VENDOR_START = 32768; // 0x8000 } + public abstract static class CameraManager.AvailabilityCallback { + method @RequiresPermission(android.Manifest.permission.CAMERA_OPEN_CLOSE_LISTENER) public void onCameraClosed(@NonNull String); + method @RequiresPermission(android.Manifest.permission.CAMERA_OPEN_CLOSE_LISTENER) public void onCameraOpened(@NonNull String, @NonNull String); + } + } package android.hardware.camera2.params { @@ -4167,7 +4186,6 @@ package android.location { method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setLocationEnabledForUser(boolean, @NonNull android.os.UserHandle); method @Deprecated @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean setProviderEnabledForUser(@NonNull String, boolean, @NonNull android.os.UserHandle); method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean unregisterGnssBatchedLocationCallback(@NonNull android.location.BatchedLocationCallback); - field public static final String FUSED_PROVIDER = "fused"; } public final class LocationRequest implements android.os.Parcelable { @@ -8383,6 +8401,18 @@ package android.printservice.recommendation { package android.provider { + public class CallLog { + method @RequiresPermission(android.Manifest.permission.WRITE_CALL_LOG) public static void storeCallComposerPictureAsUser(@NonNull android.content.Context, @Nullable android.os.UserHandle, @NonNull java.io.InputStream, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.net.Uri,android.provider.CallLog.CallComposerLoggingException>); + } + + public static class CallLog.CallComposerLoggingException extends java.lang.Throwable { + method public int getErrorCode(); + field public static final int ERROR_INPUT_CLOSED = 3; // 0x3 + field public static final int ERROR_REMOTE_END_CLOSED = 1; // 0x1 + field public static final int ERROR_STORAGE_FULL = 2; // 0x2 + field public static final int ERROR_UNKNOWN = 0; // 0x0 + } + @Deprecated public static final class ContactsContract.MetadataSync implements android.provider.BaseColumns android.provider.ContactsContract.MetadataSyncColumns { field @Deprecated public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/contact_metadata"; field @Deprecated public static final String CONTENT_TYPE = "vnd.android.cursor.dir/contact_metadata"; @@ -8449,6 +8479,7 @@ package android.provider { field public static final String NAMESPACE_INTELLIGENCE_ATTENTION = "intelligence_attention"; field public static final String NAMESPACE_MEDIA_NATIVE = "media_native"; field public static final String NAMESPACE_NETD_NATIVE = "netd_native"; + field public static final String NAMESPACE_OTA = "ota"; field public static final String NAMESPACE_PACKAGE_MANAGER_SERVICE = "package_manager_service"; field public static final String NAMESPACE_PERMISSIONS = "permissions"; field public static final String NAMESPACE_PRIVACY = "privacy"; @@ -11276,7 +11307,6 @@ package android.telephony.data { method @NonNull public android.telephony.data.ApnThrottleStatus.Builder setSlotIndex(int); method @NonNull public android.telephony.data.ApnThrottleStatus.Builder setThrottleExpiryTimeMillis(long); method @NonNull public android.telephony.data.ApnThrottleStatus.Builder setTransportType(int); - field public static final long NO_THROTTLE_EXPIRY_TIME = -1L; // 0xffffffffffffffffL } public final class DataCallResponse implements android.os.Parcelable { @@ -12312,6 +12342,7 @@ package android.telephony.ims { } public interface SipDelegateConnection { + method public void closeDialog(@NonNull String); method public void notifyMessageReceiveError(@NonNull String, int); method public void notifyMessageReceived(@NonNull String); method public void sendMessage(@NonNull android.telephony.ims.SipMessage, long); diff --git a/core/api/test-current.txt b/core/api/test-current.txt index d2941c3d1119..ffe2736fe8c5 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -94,6 +94,8 @@ package android.app { method public static void resumeAppSwitches() throws android.os.RemoteException; method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public void scheduleApplicationInfoChanged(java.util.List<java.lang.String>, int); method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public boolean updateMccMncConfiguration(@NonNull String, @NonNull String); + field public static final long DROP_CLOSE_SYSTEM_DIALOGS = 174664120L; // 0xa6929b8L + field public static final long LOCK_DOWN_CLOSE_SYSTEM_DIALOGS = 174664365L; // 0xa692aadL field public static final int PROCESS_CAPABILITY_ALL = 7; // 0x7 field public static final int PROCESS_CAPABILITY_ALL_EXPLICIT = 1; // 0x1 field public static final int PROCESS_CAPABILITY_ALL_IMPLICIT = 6; // 0x6 @@ -380,6 +382,7 @@ package android.app.admin { 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_REBOOT = 7; // 0x7 field public static final int OPERATION_REMOVE_USER = 6; // 0x6 field public static final int OPERATION_START_USER_IN_BACKGROUND = 3; // 0x3 field public static final int OPERATION_STOP_USER = 4; // 0x4 @@ -742,6 +745,11 @@ package android.hardware.camera2 { method public String[] getCameraIdListNoLazy() throws android.hardware.camera2.CameraAccessException; } + public abstract static class CameraManager.AvailabilityCallback { + method @RequiresPermission(android.Manifest.permission.CAMERA_OPEN_CLOSE_LISTENER) public void onCameraClosed(@NonNull String); + method @RequiresPermission(android.Manifest.permission.CAMERA_OPEN_CLOSE_LISTENER) public void onCameraOpened(@NonNull String, @NonNull String); + } + } package android.hardware.display { @@ -955,7 +963,6 @@ package android.location { method @NonNull public String[] getBackgroundThrottlingWhitelist(); method @NonNull public String[] getIgnoreSettingsWhitelist(); method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.READ_DEVICE_CONFIG) public java.util.List<java.lang.String> getProviderPackages(@NonNull String); - field public static final String FUSED_PROVIDER = "fused"; } } @@ -1003,6 +1010,8 @@ package android.media { field public static final int DEVICE_ROLE_DISABLED = 2; // 0x2 field public static final int DEVICE_ROLE_NONE = 0; // 0x0 field public static final int DEVICE_ROLE_PREFERRED = 1; // 0x1 + field public static final int OFFLOAD_GAPLESS_SUPPORTED = 2; // 0x2 + field public static final int OFFLOAD_SUPPORTED = 1; // 0x1 field public static final int STREAM_DEFAULT = -1; // 0xffffffff } diff --git a/core/java/android/accounts/ChooseAccountActivity.java b/core/java/android/accounts/ChooseAccountActivity.java index 4af22bfac92d..bc7f4d681e27 100644 --- a/core/java/android/accounts/ChooseAccountActivity.java +++ b/core/java/android/accounts/ChooseAccountActivity.java @@ -16,16 +16,12 @@ package android.accounts; import android.app.Activity; -import android.app.ActivityManager; -import android.app.ActivityTaskManager; import android.content.Context; import android.content.pm.PackageManager; import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.os.Bundle; -import android.os.IBinder; import android.os.Parcelable; -import android.os.RemoteException; import android.os.Process; import android.os.UserHandle; import android.util.Log; @@ -37,6 +33,7 @@ import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; + import com.android.internal.R; import java.util.HashMap; @@ -60,6 +57,9 @@ public class ChooseAccountActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + getWindow().addSystemFlags( + android.view.WindowManager.LayoutParams + .SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); mAccounts = getIntent().getParcelableArrayExtra(AccountManager.KEY_ACCOUNTS); mAccountManagerResponse = getIntent().getParcelableExtra(AccountManager.KEY_ACCOUNT_MANAGER_RESPONSE); @@ -71,15 +71,8 @@ public class ChooseAccountActivity extends Activity { return; } - try { - IBinder activityToken = getActivityToken(); - mCallingUid = ActivityTaskManager.getService().getLaunchedFromUid(activityToken); - mCallingPackage = ActivityTaskManager.getService().getLaunchedFromPackage( - activityToken); - } catch (RemoteException re) { - // Couldn't figure out caller details - Log.w(getClass().getSimpleName(), "Unable to get caller identity \n" + re); - } + mCallingUid = getLaunchedFromUid(); + mCallingPackage = getLaunchedFromPackage(); if (UserHandle.isSameApp(mCallingUid, Process.SYSTEM_UID) && getIntent().getStringExtra(AccountManager.KEY_ANDROID_PACKAGE_NAME) != null) { diff --git a/core/java/android/accounts/ChooseAccountTypeActivity.java b/core/java/android/accounts/ChooseAccountTypeActivity.java index e3352bc85668..63e005fbcfe7 100644 --- a/core/java/android/accounts/ChooseAccountTypeActivity.java +++ b/core/java/android/accounts/ChooseAccountTypeActivity.java @@ -31,6 +31,7 @@ import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; + import com.android.internal.R; import java.util.ArrayList; @@ -51,6 +52,9 @@ public class ChooseAccountTypeActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + getWindow().addSystemFlags( + android.view.WindowManager.LayoutParams + .SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "ChooseAccountTypeActivity.onCreate(savedInstanceState=" diff --git a/core/java/android/accounts/ChooseTypeAndAccountActivity.java b/core/java/android/accounts/ChooseTypeAndAccountActivity.java index 4b4ef002ae06..2be88ab60a1e 100644 --- a/core/java/android/accounts/ChooseTypeAndAccountActivity.java +++ b/core/java/android/accounts/ChooseTypeAndAccountActivity.java @@ -15,16 +15,10 @@ */ package android.accounts; -import android.app.ActivityTaskManager; -import com.google.android.collect.Sets; - import android.app.Activity; -import android.app.ActivityManager; import android.content.Intent; import android.os.Bundle; -import android.os.IBinder; import android.os.Parcelable; -import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; import android.text.TextUtils; @@ -39,6 +33,8 @@ import android.widget.TextView; import com.android.internal.R; +import com.google.android.collect.Sets; + import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; @@ -143,23 +139,17 @@ public class ChooseTypeAndAccountActivity extends Activity Log.v(TAG, "ChooseTypeAndAccountActivity.onCreate(savedInstanceState=" + savedInstanceState + ")"); } - - String message = null; - - try { - IBinder activityToken = getActivityToken(); - mCallingUid = ActivityTaskManager.getService().getLaunchedFromUid(activityToken); - mCallingPackage = ActivityTaskManager.getService().getLaunchedFromPackage( - activityToken); - if (mCallingUid != 0 && mCallingPackage != null) { - Bundle restrictions = UserManager.get(this) - .getUserRestrictions(new UserHandle(UserHandle.getUserId(mCallingUid))); - mDisallowAddAccounts = - restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false); - } - } catch (RemoteException re) { - // Couldn't figure out caller details - Log.w(getClass().getSimpleName(), "Unable to get caller identity \n" + re); + getWindow().addSystemFlags( + android.view.WindowManager.LayoutParams + .SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); + + mCallingUid = getLaunchedFromUid(); + mCallingPackage = getLaunchedFromPackage(); + if (mCallingUid != 0 && mCallingPackage != null) { + Bundle restrictions = UserManager.get(this) + .getUserRestrictions(new UserHandle(UserHandle.getUserId(mCallingUid))); + mDisallowAddAccounts = + restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false); } // save some items we use frequently diff --git a/core/java/android/accounts/GrantCredentialsPermissionActivity.java b/core/java/android/accounts/GrantCredentialsPermissionActivity.java index 5dc6e602e5d6..74dae0ecceb7 100644 --- a/core/java/android/accounts/GrantCredentialsPermissionActivity.java +++ b/core/java/android/accounts/GrantCredentialsPermissionActivity.java @@ -16,18 +16,14 @@ package android.accounts; import android.app.Activity; -import android.app.ActivityTaskManager; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.Resources; import android.os.Bundle; -import android.os.IBinder; import android.os.Process; -import android.os.RemoteException; import android.os.UserHandle; import android.text.TextUtils; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.widget.LinearLayout; @@ -85,13 +81,7 @@ public class GrantCredentialsPermissionActivity extends Activity implements View return; } - try { - IBinder activityToken = getActivityToken(); - mCallingUid = ActivityTaskManager.getService().getLaunchedFromUid(activityToken); - } catch (RemoteException re) { - // Couldn't figure out caller details - Log.w(getClass().getSimpleName(), "Unable to get caller identity \n" + re); - } + mCallingUid = getLaunchedFromUid(); if (!UserHandle.isSameApp(mCallingUid, Process.SYSTEM_UID) && mCallingUid != mUid) { setResult(Activity.RESULT_CANCELED); diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index f92768a28db1..294a363bc52f 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -6230,6 +6230,23 @@ public class Activity extends ContextThemeWrapper } /** + * Returns the uid who started this activity. + * @hide + */ + public int getLaunchedFromUid() { + return ActivityClient.getInstance().getLaunchedFromUid(getActivityToken()); + } + + /** + * Returns the package who started this activity. + * @hide + */ + @Nullable + public String getLaunchedFromPackage() { + return ActivityClient.getInstance().getLaunchedFromPackage(getActivityToken()); + } + + /** * Control whether this activity's main window is visible. This is intended * only for the special case of an activity that is not going to show a * UI itself, but can't just finish prior to onResume() because it needs @@ -7081,7 +7098,7 @@ public class Activity extends ContextThemeWrapper if (getWindow() != null && getWindow().peekDecorView() != null && getWindow().peekDecorView().getViewRootImpl() != null) { - getWindow().peekDecorView().getViewRootImpl().dump(prefix, fd, writer, args); + getWindow().peekDecorView().getViewRootImpl().dump(prefix, writer); } mHandler.getLooper().dump(new PrintWriterPrinter(writer), prefix); diff --git a/core/java/android/app/ActivityClient.java b/core/java/android/app/ActivityClient.java index 84ecd24b8c55..64d795c013c9 100644 --- a/core/java/android/app/ActivityClient.java +++ b/core/java/android/app/ActivityClient.java @@ -221,6 +221,22 @@ public class ActivityClient { } } + public int getLaunchedFromUid(IBinder token) { + try { + return getActivityClientController().getLaunchedFromUid(token); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + public String getLaunchedFromPackage(IBinder token) { + try { + return getActivityClientController().getLaunchedFromPackage(token); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + Bundle getActivityOptions(IBinder token) { try { return getActivityClientController().getActivityOptions(token); @@ -451,8 +467,20 @@ public class ActivityClient { return sInstance.get(); } + /** + * If system server has passed the controller interface, store it so the subsequent access can + * speed up. + */ + public static IActivityClientController setActivityClientController( + IActivityClientController activityClientController) { + // No lock because it is no harm to encounter race condition. The thread safe Singleton#get + // will take over that case. + return INTERFACE_SINGLETON.mKnownInstance = activityClientController; + } + private static IActivityClientController getActivityClientController() { - return sActivityClientController.get(); + final IActivityClientController controller = INTERFACE_SINGLETON.mKnownInstance; + return controller != null ? controller : INTERFACE_SINGLETON.get(); } private static final Singleton<ActivityClient> sInstance = new Singleton<ActivityClient>() { @@ -462,8 +490,17 @@ public class ActivityClient { } }; - private static final Singleton<IActivityClientController> sActivityClientController = - new Singleton<IActivityClientController>() { + private static final ActivityClientControllerSingleton INTERFACE_SINGLETON = + new ActivityClientControllerSingleton(); + + private static class ActivityClientControllerSingleton + extends Singleton<IActivityClientController> { + /** + * A quick look up to reduce potential extra binder transactions. E.g. getting activity + * task manager from service manager and controller from activity task manager. + */ + IActivityClientController mKnownInstance; + @Override protected IActivityClientController create() { try { @@ -472,5 +509,5 @@ public class ActivityClient { throw e.rethrowFromSystemServer(); } } - }; + } } diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 38a22d8ade94..a5d88ef4c8af 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -31,6 +31,8 @@ import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; +import android.compat.annotation.ChangeId; +import android.compat.annotation.Disabled; import android.compat.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Context; @@ -91,9 +93,6 @@ import com.android.internal.util.MemInfoReader; import com.android.internal.util.Preconditions; import com.android.server.LocalServices; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlSerializer; - import java.io.FileDescriptor; import java.io.FileOutputStream; import java.io.IOException; @@ -870,6 +869,39 @@ public class ActivityManager { private static final boolean DEVELOPMENT_FORCE_LOW_RAM = SystemProperties.getBoolean("debug.force_low_ram", false); + /** + * Intent {@link Intent#ACTION_CLOSE_SYSTEM_DIALOGS} is too powerful to be unrestricted. We + * restrict its usage for a few legitimate use-cases only, regardless of targetSdk. For the + * other use-cases we drop the intent with a log message. + * + * Note that this is the lighter version of {@link ActivityManager + * #LOCK_DOWN_CLOSE_SYSTEM_DIALOGS} which is not gated on targetSdk in order to eliminate the + * abuse vector. + * + * @hide + */ + @TestApi + @ChangeId + @Disabled + public static final long DROP_CLOSE_SYSTEM_DIALOGS = 174664120L; + + /** + * Intent {@link Intent#ACTION_CLOSE_SYSTEM_DIALOGS} is too powerful to be unrestricted. So, + * apps targeting {@link Build.VERSION_CODES#S} or higher will crash if they try to send such + * intent and don't have permission {@code android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS}. + * + * Note that this is the more restrict version of {@link ActivityManager + * #DROP_CLOSE_SYSTEM_DIALOGS} that expects the app to stop sending aforementioned intent once + * it bumps its targetSdk to {@link Build.VERSION_CODES#S} or higher. + * + * @hide + */ + @TestApi + @ChangeId + @Disabled + // @EnabledSince(targetSdkVersion = VERSION_CODES.S) + public static final long LOCK_DOWN_CLOSE_SYSTEM_DIALOGS = 174664365L; + /** @hide */ public int getFrontActivityScreenCompatMode() { try { @@ -4167,10 +4199,8 @@ public class ActivityManager { "android.permission.INTERACT_ACROSS_USERS_FULL" }) public static int getCurrentUser() { - UserInfo ui; try { - ui = getService().getCurrentUser(); - return ui != null ? ui.id : 0; + return getService().getCurrentUserId(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index ed6dea815e4c..6d564a3ce61c 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -6681,8 +6681,7 @@ public final class ActivityThread extends ClientTransactionHandler { private InstrumentationInfo prepareInstrumentation(AppBindData data) { final InstrumentationInfo ii; try { - ii = new ApplicationPackageManager( - null, getPackageManager(), getPermissionManager()) + ii = new ApplicationPackageManager(null, getPackageManager()) .getInstrumentationInfo(data.instrumentationName, 0); } catch (PackageManager.NameNotFoundException e) { throw new RuntimeException( diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index f60f569be892..20953c6f6637 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -1169,9 +1169,18 @@ public class AppOpsManager { public static final int OP_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER = AppProtoEnums.APP_OP_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER; + /** + * App output audio is being recorded + * + * @hide + */ + // TODO: Add as AppProtoEnums + public static final int OP_RECORD_AUDIO_OUTPUT = 106; + + /** @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public static final int _NUM_OP = 106; + public static final int _NUM_OP = 107; /** Access to coarse location information. */ public static final String OPSTR_COARSE_LOCATION = "android:coarse_location"; @@ -1537,6 +1546,12 @@ public class AppOpsManager { @TestApi public static final String OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER = "android:use_icc_auth_with_device_identifier"; + /** + * App output audio is being recorded + * + * @hide + */ + public static final String OPSTR_RECORD_AUDIO_OUTPUT = "android:record_audio_output"; /** {@link #sAppOpsToNote} not initialized yet for this op */ private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0; @@ -1735,6 +1750,7 @@ public class AppOpsManager { OP_MANAGE_ONGOING_CALLS, // MANAGE_ONGOING_CALLS OP_MANAGE_CREDENTIALS, // MANAGE_CREDENTIALS OP_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER + OP_RECORD_AUDIO_OUTPUT, // RECORD_AUDIO_OUTPUT }; /** @@ -1847,6 +1863,7 @@ public class AppOpsManager { OPSTR_MANAGE_ONGOING_CALLS, OPSTR_MANAGE_CREDENTIALS, OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER, + OPSTR_RECORD_AUDIO_OUTPUT, }; /** @@ -1960,6 +1977,7 @@ public class AppOpsManager { "MANAGE_ONGOING_CALLS", "MANAGE_CREDENTIALS", "USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER", + "RECORD_AUDIO_OUTPUT", }; /** @@ -2074,6 +2092,7 @@ public class AppOpsManager { Manifest.permission.MANAGE_ONGOING_CALLS, null, // no permission for OP_MANAGE_CREDENTIALS Manifest.permission.USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER, + null, // no permission for OP_RECORD_AUDIO_OUTPUT }; /** @@ -2188,6 +2207,7 @@ public class AppOpsManager { null, // MANAGE_ONGOING_CALLS null, // MANAGE_CREDENTIALS null, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER + null, // RECORD_AUDIO_OUTPUT }; /** @@ -2301,6 +2321,7 @@ public class AppOpsManager { null, // MANAGE_ONGOING_CALLS null, // MANAGE_CREDENTIALS null, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER + null, // RECORD_AUDIO_OUTPUT }; /** @@ -2413,6 +2434,7 @@ public class AppOpsManager { AppOpsManager.MODE_DEFAULT, // MANAGE_ONGOING_CALLS AppOpsManager.MODE_DEFAULT, // MANAGE_CREDENTIALS AppOpsManager.MODE_DEFAULT, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER + AppOpsManager.MODE_ALLOWED, // RECORD_AUDIO_OUTPUT }; /** @@ -2529,6 +2551,7 @@ public class AppOpsManager { true, // MANAGE_ONGOING_CALLS false, // MANAGE_CREDENTIALS true, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER + false, // RECORD_AUDIO_OUTPUT }; /** @@ -6511,9 +6534,10 @@ public class AppOpsManager { * @param code The op code. * @param uid The UID performing the operation. * @param packageName The package performing the operation. + * @param flags The flags of this op * @param result The result of the note. */ - void onOpNoted(int code, int uid, String packageName, int result); + void onOpNoted(int code, int uid, String packageName, @OpFlags int flags, @Mode int result); } /** @@ -6550,9 +6574,10 @@ public class AppOpsManager { * @param op The op code. * @param uid The UID performing the operation. * @param packageName The package performing the operation. + * @param flags The flags of this op * @param result The result of the start. */ - void onOpStarted(int op, int uid, String packageName, int result); + void onOpStarted(int op, int uid, String packageName, @OpFlags int flags, @Mode int result); } AppOpsManager(Context context, IAppOpsService service) { @@ -7135,8 +7160,8 @@ public class AppOpsManager { } cb = new IAppOpsStartedCallback.Stub() { @Override - public void opStarted(int op, int uid, String packageName, int mode) { - callback.onOpStarted(op, uid, packageName, mode); + public void opStarted(int op, int uid, String packageName, int flags, int mode) { + callback.onOpStarted(op, uid, packageName, flags, mode); } }; mStartedWatchers.put(callback, cb); @@ -7202,8 +7227,8 @@ public class AppOpsManager { } cb = new IAppOpsNotedCallback.Stub() { @Override - public void opNoted(int op, int uid, String packageName, int mode) { - callback.onOpNoted(op, uid, packageName, mode); + public void opNoted(int op, int uid, String packageName, int flags, int mode) { + callback.onOpNoted(op, uid, packageName, flags, mode); } }; mNotedWatchers.put(callback, cb); diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 3642d318e820..186d1fede5e0 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -59,8 +59,6 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageInstaller; import android.content.pm.PackageItemInfo; import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.content.pm.PackageManager.Property; import android.content.pm.ParceledListSlice; import android.content.pm.PermissionGroupInfo; import android.content.pm.PermissionInfo; @@ -95,8 +93,6 @@ import android.os.UserHandle; import android.os.UserManager; import android.os.storage.StorageManager; import android.os.storage.VolumeInfo; -import android.permission.IOnPermissionsChangeListener; -import android.permission.IPermissionManager; import android.permission.PermissionManager; import android.provider.Settings; import android.system.ErrnoException; @@ -106,7 +102,6 @@ import android.system.StructStat; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; -import android.util.DebugUtils; import android.util.LauncherIcons; import android.util.Log; @@ -129,7 +124,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.Set; @@ -137,14 +131,6 @@ import java.util.Set; public class ApplicationPackageManager extends PackageManager { private static final String TAG = "ApplicationPackageManager"; private static final boolean DEBUG_ICONS = false; - /** - * Note: Changing this won't do anything on it's own - you should also change the filtering in - * {@link #shouldTraceGrant} - * - * @hide - */ - public static final boolean DEBUG_TRACE_GRANTS = false; - public static final boolean DEBUG_TRACE_PERMISSION_UPDATES = false; private static final int DEFAULT_EPHEMERAL_COOKIE_MAX_SIZE_BYTES = 16384; // 16KB @@ -171,6 +157,8 @@ public class ApplicationPackageManager extends PackageManager { @GuardedBy("mLock") private UserManager mUserManager; @GuardedBy("mLock") + private PermissionManager mPermissionManager; + @GuardedBy("mLock") private PackageInstaller mInstaller; @GuardedBy("mLock") private ArtManager mArtManager; @@ -190,6 +178,15 @@ public class ApplicationPackageManager extends PackageManager { } } + private PermissionManager getPermissionManager() { + synchronized (mLock) { + if (mPermissionManager == null) { + mPermissionManager = mContext.getSystemService(PermissionManager.class); + } + return mPermissionManager; + } + } + @Override public int getUserId() { return mContext.getUserId(); @@ -355,66 +352,41 @@ public class ApplicationPackageManager extends PackageManager { @Override @SuppressWarnings("unchecked") public List<PermissionGroupInfo> getAllPermissionGroups(int flags) { - try { - final ParceledListSlice<PermissionGroupInfo> parceledList = - mPermissionManager.getAllPermissionGroups(flags); - if (parceledList == null) { - return Collections.emptyList(); - } - return parceledList.getList(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + return getPermissionManager().getAllPermissionGroups(flags); } @Override public PermissionGroupInfo getPermissionGroupInfo(String groupName, int flags) throws NameNotFoundException { - try { - final PermissionGroupInfo pgi = - mPermissionManager.getPermissionGroupInfo(groupName, flags); - if (pgi != null) { - return pgi; - } - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); + final PermissionGroupInfo permissionGroupInfo = getPermissionManager() + .getPermissionGroupInfo(groupName, flags); + if (permissionGroupInfo == null) { + throw new NameNotFoundException(groupName); } - throw new NameNotFoundException(groupName); + return permissionGroupInfo; } @Override public PermissionInfo getPermissionInfo(String permName, int flags) throws NameNotFoundException { - try { - final String packageName = mContext.getOpPackageName(); - final PermissionInfo pi = - mPermissionManager.getPermissionInfo(permName, packageName, flags); - if (pi != null) { - return pi; - } - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); + final PermissionInfo permissionInfo = getPermissionManager().getPermissionInfo(permName, + flags); + if (permissionInfo == null) { + throw new NameNotFoundException(permName); } - throw new NameNotFoundException(permName); + return permissionInfo; } @Override @SuppressWarnings("unchecked") public List<PermissionInfo> queryPermissionsByGroup(String groupName, int flags) throws NameNotFoundException { - try { - final ParceledListSlice<PermissionInfo> parceledList = - mPermissionManager.queryPermissionsByGroup(groupName, flags); - if (parceledList != null) { - final List<PermissionInfo> pi = parceledList.getList(); - if (pi != null) { - return pi; - } - } - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); + final List<PermissionInfo> permissionInfos = getPermissionManager().queryPermissionsByGroup( + groupName, flags); + if (permissionInfos == null) { + throw new NameNotFoundException(groupName); } - throw new NameNotFoundException(groupName); + return permissionInfos; } @Override @@ -724,11 +696,7 @@ public class ApplicationPackageManager extends PackageManager { @Override public boolean isPermissionRevokedByPolicy(String permName, String pkgName) { - try { - return mPermissionManager.isPermissionRevokedByPolicy(permName, pkgName, getUserId()); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + return getPermissionManager().isPermissionRevokedByPolicy(pkgName, permName); } /** @@ -750,50 +718,23 @@ public class ApplicationPackageManager extends PackageManager { @Override public boolean addPermission(PermissionInfo info) { - try { - return mPermissionManager.addPermission(info, false); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + return getPermissionManager().addPermission(info, false); } @Override public boolean addPermissionAsync(PermissionInfo info) { - try { - return mPermissionManager.addPermission(info, true); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + return getPermissionManager().addPermission(info, true); } @Override public void removePermission(String name) { - try { - mPermissionManager.removePermission(name); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + getPermissionManager().removePermission(name); } @Override public void grantRuntimePermission(String packageName, String permissionName, UserHandle user) { - if (DEBUG_TRACE_GRANTS - && shouldTraceGrant(packageName, permissionName, user.getIdentifier())) { - Log.i(TAG, "App " + mContext.getPackageName() + " is granting " + packageName + " " - + permissionName + " for user " + user.getIdentifier(), new RuntimeException()); - } - try { - mPM.grantRuntimePermission(packageName, permissionName, user.getIdentifier()); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** @hide */ - public static boolean shouldTraceGrant(String packageName, String permissionName, int userId) { - // To be modified when debugging - return false; + getPermissionManager().grantRuntimePermission(packageName, permissionName, user); } @Override @@ -804,124 +745,55 @@ public class ApplicationPackageManager extends PackageManager { @Override public void revokeRuntimePermission(String packageName, String permName, UserHandle user, String reason) { - if (DEBUG_TRACE_PERMISSION_UPDATES - && shouldTraceGrant(packageName, permName, user.getIdentifier())) { - Log.i(TAG, "App " + mContext.getPackageName() + " is revoking " + packageName + " " - + permName + " for user " + user.getIdentifier() + " with reason " + reason, - new RuntimeException()); - } - try { - mPermissionManager - .revokeRuntimePermission(packageName, permName, user.getIdentifier(), reason); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + getPermissionManager().revokeRuntimePermission(packageName, permName, user, reason); } @Override public int getPermissionFlags(String permName, String packageName, UserHandle user) { - try { - return mPermissionManager - .getPermissionFlags(permName, packageName, user.getIdentifier()); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + return getPermissionManager().getPermissionFlags(packageName, permName, user); } @Override public void updatePermissionFlags(String permName, String packageName, int flagMask, int flagValues, UserHandle user) { - if (DEBUG_TRACE_PERMISSION_UPDATES - && shouldTraceGrant(packageName, permName, user.getIdentifier())) { - Log.i(TAG, "App " + mContext.getPackageName() + " is updating flags for " - + packageName + " " - + permName + " for user " + user.getIdentifier() + ": " - + DebugUtils.flagsToString(PackageManager.class, "FLAG_PERMISSION_", flagMask) - + " := " + DebugUtils.flagsToString( - PackageManager.class, "FLAG_PERMISSION_", flagValues), - new RuntimeException()); - } - try { - final boolean checkAdjustPolicyFlagPermission = - mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.Q; - mPermissionManager.updatePermissionFlags(permName, packageName, flagMask, - flagValues, checkAdjustPolicyFlagPermission, user.getIdentifier()); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + getPermissionManager().updatePermissionFlags(packageName, permName, flagMask, flagValues, + user); } @Override public @NonNull Set<String> getWhitelistedRestrictedPermissions( @NonNull String packageName, @PermissionWhitelistFlags int flags) { - try { - final int userId = getUserId(); - final List<String> whitelist = mPermissionManager - .getWhitelistedRestrictedPermissions(packageName, flags, userId); - if (whitelist != null) { - return new ArraySet<>(whitelist); - } - return Collections.emptySet(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + return getPermissionManager().getAllowlistedRestrictedPermissions(packageName, flags); } @Override public boolean addWhitelistedRestrictedPermission(@NonNull String packageName, @NonNull String permName, @PermissionWhitelistFlags int flags) { - try { - final int userId = getUserId(); - return mPermissionManager - .addWhitelistedRestrictedPermission(packageName, permName, flags, userId); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + return getPermissionManager().addAllowlistedRestrictedPermission(packageName, permName, + flags); } @Override - public boolean setAutoRevokeWhitelisted( - @NonNull String packageName, boolean whitelisted) { - try { - final int userId = getUserId(); - return mPermissionManager.setAutoRevokeWhitelisted(packageName, whitelisted, userId); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + public boolean setAutoRevokeWhitelisted(@NonNull String packageName, boolean whitelisted) { + return getPermissionManager().setAutoRevokeExempted(packageName, whitelisted); } @Override public boolean isAutoRevokeWhitelisted(@NonNull String packageName) { - try { - final int userId = getUserId(); - return mPermissionManager.isAutoRevokeWhitelisted(packageName, userId); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + return getPermissionManager().isAutoRevokeExempted(packageName); } @Override public boolean removeWhitelistedRestrictedPermission(@NonNull String packageName, @NonNull String permName, @PermissionWhitelistFlags int flags) { - try { - final int userId = getUserId(); - return mPermissionManager - .removeWhitelistedRestrictedPermission(packageName, permName, flags, userId); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + return getPermissionManager().removeAllowlistedRestrictedPermission(packageName, permName, + flags); } @Override @UnsupportedAppUsage public boolean shouldShowRequestPermissionRationale(String permName) { - try { - final String packageName = mContext.getPackageName(); - return mPermissionManager - .shouldShowRequestPermissionRationale(permName, packageName, getUserId()); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + return getPermissionManager().shouldShowRequestPermissionRationale(permName); } @Override @@ -1880,34 +1752,12 @@ public class ApplicationPackageManager extends PackageManager { @Override public void addOnPermissionsChangeListener(OnPermissionsChangedListener listener) { - synchronized (mPermissionListeners) { - if (mPermissionListeners.get(listener) != null) { - return; - } - OnPermissionsChangeListenerDelegate delegate = - new OnPermissionsChangeListenerDelegate(listener, Looper.getMainLooper()); - try { - mPermissionManager.addOnPermissionsChangeListener(delegate); - mPermissionListeners.put(listener, delegate); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } + getPermissionManager().addOnPermissionsChangeListener(listener); } @Override public void removeOnPermissionsChangeListener(OnPermissionsChangedListener listener) { - synchronized (mPermissionListeners) { - IOnPermissionsChangeListener delegate = mPermissionListeners.get(listener); - if (delegate != null) { - try { - mPermissionManager.removeOnPermissionsChangeListener(delegate); - mPermissionListeners.remove(listener); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - } + getPermissionManager().removeOnPermissionsChangeListener(listener); } @UnsupportedAppUsage @@ -1918,11 +1768,9 @@ public class ApplicationPackageManager extends PackageManager { } } - protected ApplicationPackageManager(ContextImpl context, IPackageManager pm, - IPermissionManager permissionManager) { + protected ApplicationPackageManager(ContextImpl context, IPackageManager pm) { mContext = context; mPM = pm; - mPermissionManager = permissionManager; } /** @@ -3234,7 +3082,6 @@ public class ApplicationPackageManager extends PackageManager { private final ContextImpl mContext; @UnsupportedAppUsage private final IPackageManager mPM; - private final IPermissionManager mPermissionManager; /** Assume locked until we hear otherwise */ private volatile boolean mUserUnlocked = false; @@ -3245,41 +3092,6 @@ public class ApplicationPackageManager extends PackageManager { private static ArrayMap<ResourceName, WeakReference<CharSequence>> sStringCache = new ArrayMap<ResourceName, WeakReference<CharSequence>>(); - private final Map<OnPermissionsChangedListener, IOnPermissionsChangeListener> - mPermissionListeners = new ArrayMap<>(); - - public class OnPermissionsChangeListenerDelegate extends IOnPermissionsChangeListener.Stub - implements Handler.Callback{ - private static final int MSG_PERMISSIONS_CHANGED = 1; - - private final OnPermissionsChangedListener mListener; - private final Handler mHandler; - - - public OnPermissionsChangeListenerDelegate(OnPermissionsChangedListener listener, - Looper looper) { - mListener = listener; - mHandler = new Handler(looper, this); - } - - @Override - public void onPermissionsChanged(int uid) { - mHandler.obtainMessage(MSG_PERMISSIONS_CHANGED, uid, 0).sendToTarget(); - } - - @Override - public boolean handleMessage(Message msg) { - switch (msg.what) { - case MSG_PERMISSIONS_CHANGED: { - final int uid = msg.arg1; - mListener.onPermissionsChanged(uid); - return true; - } - } - return false; - } - } - @Override public boolean canRequestPackageInstalls() { try { diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 2fec9f79717a..124cf71edc9c 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -72,7 +72,6 @@ import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; import android.os.storage.StorageManager; -import android.permission.IPermissionManager; import android.permission.PermissionManager; import android.system.ErrnoException; import android.system.Os; @@ -370,10 +369,9 @@ class ContextImpl extends Context { } final IPackageManager pm = ActivityThread.getPackageManager(); - final IPermissionManager permissionManager = ActivityThread.getPermissionManager(); - if (pm != null && permissionManager != null) { + if (pm != null) { // Doesn't matter if we make more than one instance. - return (mPackageManager = new ApplicationPackageManager(this, pm, permissionManager)); + return (mPackageManager = new ApplicationPackageManager(this, pm)); } return null; diff --git a/core/java/android/app/IActivityClientController.aidl b/core/java/android/app/IActivityClientController.aidl index f9449f241545..e1e0a8a534a8 100644 --- a/core/java/android/app/IActivityClientController.aidl +++ b/core/java/android/app/IActivityClientController.aidl @@ -58,6 +58,8 @@ interface IActivityClientController { int getTaskForActivity(in IBinder token, in boolean onlyRoot); ComponentName getCallingActivity(in IBinder token); String getCallingPackage(in IBinder token); + int getLaunchedFromUid(in IBinder token); + String getLaunchedFromPackage(in IBinder token); Bundle getActivityOptions(in IBinder token); void setRequestedOrientation(in IBinder token, int requestedOrientation); diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index 86625d340a14..c564d285fbc2 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -363,6 +363,7 @@ interface IActivityManager { boolean killProcessesBelowForeground(in String reason); @UnsupportedAppUsage UserInfo getCurrentUser(); + int getCurrentUserId(); // This is not public because you need to be very careful in how you // manage your activity to make sure it is always the uid you expect. @UnsupportedAppUsage diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl index 4b2557389382..fabce459afcc 100644 --- a/core/java/android/app/IActivityTaskManager.aidl +++ b/core/java/android/app/IActivityTaskManager.aidl @@ -159,8 +159,6 @@ interface IActivityTaskManager { int userId); boolean isTopActivityImmersive(); ActivityManager.TaskDescription getTaskDescription(int taskId); - int getLaunchedFromUid(in IBinder activityToken); - String getLaunchedFromPackage(in IBinder activityToken); void reportAssistContextExtras(in IBinder assistToken, in Bundle extras, in AssistStructure structure, in AssistContent content, in Uri referrer); @@ -257,8 +255,6 @@ interface IActivityTaskManager { * etc. */ void keyguardGoingAway(int flags); - ComponentName getActivityClassForToken(in IBinder token); - String getPackageForToken(in IBinder token); void suppressResizeConfigChanges(boolean suppress); boolean moveTopActivityToPinnedRootTask(int rootTaskId, in Rect bounds); diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 82f61a4c615a..c528588b72b0 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -5163,16 +5163,10 @@ public class Notification implements Parcelable bindHeaderChronometerAndTime(contentView, p, hasTextToLeft); bindProfileBadge(contentView, p); bindAlertedIcon(contentView, p); - bindFeedbackIcon(contentView, p); bindExpandButton(contentView, p); mN.mUsesStandardHeader = true; } - private void bindFeedbackIcon(RemoteViews contentView, StandardTemplateParams p) { - int color = getNeutralColor(p); - contentView.setDrawableTint(R.id.feedback, false, color, PorterDuff.Mode.SRC_ATOP); - } - private void bindExpandButton(RemoteViews contentView, StandardTemplateParams p) { int color = isColorized(p) ? getPrimaryTextColor(p) : getSecondaryTextColor(p); contentView.setDrawableTint(R.id.expand_button, false, color, diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index da7a29f8ac10..58f382dc2c6c 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -34,6 +34,7 @@ import android.content.pm.ParceledListSlice; import android.content.pm.ShortcutInfo; import android.graphics.drawable.Icon; import android.net.Uri; +import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.Handler; @@ -532,15 +533,23 @@ public class NotificationManager { public static final int IMPORTANCE_MAX = 5; /** - * @hide + * Indicates that the no bubbles are allowed from the app. If the app sends bubbles, only the + * notification will appear. The notification will have an affordance allowing the user to + * bubble it. If the user selects this affordance, that notification is approved to bubble + * and the apps' bubble preference will be upgraded to {@link #BUBBLE_PREFERENCE_SELECTED}. */ public static final int BUBBLE_PREFERENCE_NONE = 0; + /** - * @hide + * Indicates that all bubbles are allowed from the app. If the app sends bubbles, the bubble + * will appear along with the notification. */ public static final int BUBBLE_PREFERENCE_ALL = 1; + /** - * @hide + * Indicates that only notifications selected by the user will appear as bubbles. If + * the app sends bubbles that haven't been selected, only the notification appear. If the + * bubble has been approved by the user, it will appear along with the notification. */ public static final int BUBBLE_PREFERENCE_SELECTED = 2; @@ -1323,10 +1332,12 @@ public class NotificationManager { * notification shade, floating over other apps' content. * * <p>This value will be ignored for notifications that are posted to channels that do not - * allow bubbles ({@link NotificationChannel#canBubble()}. + * allow bubbles ({@link NotificationChannel#canBubble()}). * * @see Notification#getBubbleMetadata() + * @deprecated use {@link #getBubblePreference()} instead. */ + @Deprecated public boolean areBubblesAllowed() { INotificationManager service = getService(); try { @@ -1337,6 +1348,34 @@ public class NotificationManager { } /** + * Gets the bubble preference for the app. This preference only applies to notifications that + * have been properly configured to bubble. + * + * <p> + * If {@link #BUBBLE_PREFERENCE_ALL}, then any bubble notification will appear as a bubble, as + * long as the user hasn't excluded it ({@link NotificationChannel#canBubble()}). + * + * <p> + * If {@link #BUBBLE_PREFERENCE_SELECTED}, then any bubble notification will appear as a bubble, + * as long as the user has selected it. + * + * <p> + * If {@link #BUBBLE_PREFERENCE_NONE}, then no notification may appear as a bubble from the app. + * + * @see Notification#getBubbleMetadata() + * @return the users' bubble preference for the app. + */ + public int getBubblePreference() { + INotificationManager service = getService(); + try { + return service.getBubblePreferenceForPackage(mContext.getPackageName(), + Binder.getCallingUid()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Silences the current notification sound, if ones currently playing. * <p> * It is intended to handle use-cases such as silencing a ringing call diff --git a/core/java/android/app/OWNERS b/core/java/android/app/OWNERS index 633d093435ee..06ad9c99c301 100644 --- a/core/java/android/app/OWNERS +++ b/core/java/android/app/OWNERS @@ -1 +1,34 @@ + +# Remain no owner because multiple modules may touch this file. +per-file ContextImpl.java = * + +# ActivityThread +per-file ActivityThread.java = file:/services/core/java/com/android/server/am/OWNERS +per-file ActivityThread.java = file:/services/core/java/com/android/server/wm/OWNERS + +# Alarm +per-file *Alarm* = file:/apex/jobscheduler/OWNERS + +# AppOps +per-file *AppOp* = file:/core/java/android/permission/OWNERS + +# Notification +per-file *Notification* = file:/packages/SystemUI/OWNERS + +# ResourcesManager +per-file ResourcesManager = rtmitchell@google.com, toddke@google.com + +# Wallpaper +per-file *Wallpaper* = file:/core/java/android/service/wallpaper/OWNERS + +# WindowManager +per-file *Activity* = file:/services/core/java/com/android/server/wm/OWNERS +per-file ClientTransactionHandler.java = file:/services/core/java/com/android/server/wm/OWNERS +per-file Fragment.java = file:/services/core/java/com/android/server/wm/OWNERS +per-file *Task* = file:/services/core/java/com/android/server/wm/OWNERS +per-file Window* = file:/services/core/java/com/android/server/wm/OWNERS + +# TODO(b/174932174): determine the ownership of KeyguardManager.java + +# Zygote per-file *Zygote* = file:/ZYGOTE_OWNERS diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 392d6fbe53d6..5326bf37fad2 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -63,7 +63,6 @@ import android.content.pm.CrossProfileApps; import android.content.pm.DataLoaderManager; import android.content.pm.ICrossProfileApps; import android.content.pm.IDataLoaderManager; -import android.content.pm.IPackageManager; import android.content.pm.IShortcutService; import android.content.pm.LauncherApps; import android.content.pm.PackageManager; @@ -118,7 +117,6 @@ import android.media.tv.tunerresourcemanager.ITunerResourceManager; import android.media.tv.tunerresourcemanager.TunerResourceManager; import android.net.ConnectivityDiagnosticsManager; import android.net.ConnectivityManager; -import android.net.ConnectivityThread; import android.net.EthernetManager; import android.net.IConnectivityManager; import android.net.IEthernetManager; @@ -176,6 +174,7 @@ import android.os.image.IDynamicSystemService; import android.os.incremental.IIncrementalService; import android.os.incremental.IncrementalManager; import android.os.storage.StorageManager; +import android.permission.LegacyPermissionManager; import android.permission.PermissionControllerManager; import android.permission.PermissionManager; import android.print.IPrintManager; @@ -781,8 +780,7 @@ public final class SystemServiceRegistry { public LowpanManager createService(ContextImpl ctx) throws ServiceNotFoundException { IBinder b = ServiceManager.getServiceOrThrow(Context.LOWPAN_SERVICE); ILowpanManager service = ILowpanManager.Stub.asInterface(b); - return new LowpanManager(ctx.getOuterContext(), service, - ConnectivityThread.getInstanceLooper()); + return new LowpanManager(ctx.getOuterContext(), service); }}); registerService(Context.ETHERNET_SERVICE, EthernetManager.class, @@ -1264,8 +1262,15 @@ public final class SystemServiceRegistry { @Override public PermissionManager createService(ContextImpl ctx) throws ServiceNotFoundException { - IPackageManager packageManager = AppGlobals.getPackageManager(); - return new PermissionManager(ctx.getOuterContext(), packageManager); + return new PermissionManager(ctx.getOuterContext()); + }}); + + registerService(Context.LEGACY_PERMISSION_SERVICE, LegacyPermissionManager.class, + new CachedServiceFetcher<LegacyPermissionManager>() { + @Override + public LegacyPermissionManager createService(ContextImpl ctx) + throws ServiceNotFoundException { + return new LegacyPermissionManager(); }}); registerService(Context.PERMISSION_CONTROLLER_SERVICE, PermissionControllerManager.class, diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java index fe382a33a8c5..2da5e001a3e4 100644 --- a/core/java/android/app/TaskInfo.java +++ b/core/java/android/app/TaskInfo.java @@ -27,7 +27,6 @@ import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.graphics.Point; -import android.graphics.Rect; import android.os.Build; import android.os.IBinder; import android.os.Parcel; @@ -187,22 +186,6 @@ public class TaskInfo { public boolean isResizeable; /** - * Activity bounds if this task or its top activity is presented in letterbox mode and - * {@code null} otherwise. - * @hide - */ - @Nullable - public Rect letterboxActivityBounds; - - /** - * Activity insets if this task or its top activity is presented in letterbox mode and - * {@code null} otherwise. - * @hide - */ - @Nullable - public Rect letterboxActivityInsets; - - /** * Relative position of the task's top left corner in the parent container. * @hide */ @@ -223,12 +206,6 @@ public class TaskInfo { public int parentTaskId; /** - * Parent bounds. - * @hide - */ - public Rect parentBounds; - - /** * Whether this task is focused. * @hide */ @@ -320,7 +297,6 @@ public class TaskInfo { return topActivityType == that.topActivityType && isResizeable == that.isResizeable && Objects.equals(positionInParent, that.positionInParent) - && equalsLetterboxParams(that) && Objects.equals(pictureInPictureParams, that.pictureInPictureParams) && getWindowingMode() == that.getWindowingMode() && Objects.equals(taskDescription, that.taskDescription) @@ -328,18 +304,6 @@ public class TaskInfo { && isVisible == that.isVisible; } - private boolean equalsLetterboxParams(TaskInfo that) { - return Objects.equals(letterboxActivityBounds, that.letterboxActivityBounds) - && Objects.equals( - getConfiguration().windowConfiguration.getBounds(), - that.getConfiguration().windowConfiguration.getBounds()) - && Objects.equals( - getConfiguration().windowConfiguration.getMaxBounds(), - that.getConfiguration().windowConfiguration.getMaxBounds()) - && Objects.equals(parentBounds, that.parentBounds) - && Objects.equals(letterboxActivityInsets, that.letterboxActivityInsets); - } - /** * Reads the TaskInfo from a parcel. */ @@ -368,13 +332,10 @@ public class TaskInfo { topActivityInfo = source.readTypedObject(ActivityInfo.CREATOR); isResizeable = source.readBoolean(); source.readBinderList(launchCookies); - letterboxActivityBounds = source.readTypedObject(Rect.CREATOR); positionInParent = source.readTypedObject(Point.CREATOR); parentTaskId = source.readInt(); - parentBounds = source.readTypedObject(Rect.CREATOR); isFocused = source.readBoolean(); isVisible = source.readBoolean(); - letterboxActivityInsets = source.readTypedObject(Rect.CREATOR); } /** @@ -406,13 +367,10 @@ public class TaskInfo { dest.writeTypedObject(topActivityInfo, flags); dest.writeBoolean(isResizeable); dest.writeBinderList(launchCookies); - dest.writeTypedObject(letterboxActivityBounds, flags); dest.writeTypedObject(positionInParent, flags); dest.writeInt(parentTaskId); - dest.writeTypedObject(parentBounds, flags); dest.writeBoolean(isFocused); dest.writeBoolean(isVisible); - dest.writeTypedObject(letterboxActivityInsets, flags); } @Override @@ -433,13 +391,10 @@ public class TaskInfo { + " pictureInPictureParams=" + pictureInPictureParams + " topActivityInfo=" + topActivityInfo + " launchCookies=" + launchCookies - + " letterboxActivityBounds=" + letterboxActivityBounds + " positionInParent=" + positionInParent + " parentTaskId=" + parentTaskId - + " parentBounds=" + parentBounds + " isFocused=" + isFocused + " isVisible=" + isVisible - + " letterboxActivityInsets=" + letterboxActivityInsets + "}"; } } diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 251252ed4800..94084b851ae0 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -2610,6 +2610,9 @@ public class DevicePolicyManager { /** @hide */ @TestApi public static final int OPERATION_REMOVE_USER = 6; + /** @hide */ + @TestApi + public static final int OPERATION_REBOOT = 7; private static final String PREFIX_OPERATION = "OPERATION_"; @@ -2620,7 +2623,8 @@ public class DevicePolicyManager { OPERATION_START_USER_IN_BACKGROUND, OPERATION_STOP_USER, OPERATION_CREATE_AND_MANAGE_USER, - OPERATION_REMOVE_USER + OPERATION_REMOVE_USER, + OPERATION_REBOOT }) @Retention(RetentionPolicy.SOURCE) public static @interface DevicePolicyOperation { @@ -2915,22 +2919,36 @@ public class DevicePolicyManager { * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has * not, a security exception will be thrown. * <p> - * This method can be called on the {@link DevicePolicyManager} instance returned by + * Apps targeting {@link android.os.Build.VERSION_CODES#R} and below can call this method on the + * {@link DevicePolicyManager} instance returned by * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent - * profile. + * profile. Apps targeting {@link android.os.Build.VERSION_CODES#S} and above will get a + * {@code IllegalArgumentException} when calling this method on the parent + * {@link DevicePolicyManager} instance. * * <p><strong>Note:</strong> Specifying password requirements using this method clears the * password complexity requirements set using {@link #setRequiredPasswordComplexity(int)}. * + * @deprecated Prefer using {@link #setRequiredPasswordComplexity(int)}, to require a password + * that satisfies a complexity level defined by the platform, rather than specifying custom + * password requirement. + * Setting custom, overly-complicated password requirements leads to passwords that are hard + * for users to remember and may not provide any security benefits given as Android uses + * hardware-backed throttling to thwart online and offline brute-forcing of the device's + * screen lock. * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param quality The new desired quality. One of {@link #PASSWORD_QUALITY_UNSPECIFIED}, * {@link #PASSWORD_QUALITY_BIOMETRIC_WEAK}, * {@link #PASSWORD_QUALITY_SOMETHING}, {@link #PASSWORD_QUALITY_NUMERIC}, * {@link #PASSWORD_QUALITY_NUMERIC_COMPLEX}, {@link #PASSWORD_QUALITY_ALPHABETIC}, * {@link #PASSWORD_QUALITY_ALPHANUMERIC} or {@link #PASSWORD_QUALITY_COMPLEX}. - * @throws SecurityException if {@code admin} is not an active administrator or if {@code admin} - * does not use {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} + * @throws SecurityException if {@code admin} is not an active administrator, if {@code admin} + * does not use {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} or if the + * calling app is targeting {@link android.os.Build.VERSION_CODES#S} and above, + * and is calling the method the {@link DevicePolicyManager} instance returned by + * {@link #getParentProfileInstance(ComponentName)}. */ + @Deprecated public void setPasswordQuality(@NonNull ComponentName admin, int quality) { if (mService != null) { try { @@ -2953,9 +2971,12 @@ public class DevicePolicyManager { * <p>Note: on devices not supporting {@link PackageManager#FEATURE_SECURE_LOCK_SCREEN} feature, * the password is always treated as empty. * + * @deprecated see {@link #setPasswordQuality(ComponentName, int)} for details. + * * @param admin The name of the admin component to check, or {@code null} to aggregate * all admins. */ + @Deprecated public int getPasswordQuality(@Nullable ComponentName admin) { return getPasswordQuality(admin, myUserId()); } @@ -2995,10 +3016,14 @@ public class DevicePolicyManager { * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has * not, a security exception will be thrown. * <p> - * This method can be called on the {@link DevicePolicyManager} instance returned by + * + * Apps targeting {@link android.os.Build.VERSION_CODES#R} and below can call this method on the + * {@link DevicePolicyManager} instance returned by * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent * profile. * + * @deprecated see {@link #setPasswordQuality(ComponentName, int)} for details. + * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param length The new desired minimum password length. A value of 0 means there is no * restriction. @@ -3008,6 +3033,7 @@ public class DevicePolicyManager { * {@link android.os.Build.VERSION_CODES#R} and above and didn't set a sufficient password * quality requirement prior to calling this method. */ + @Deprecated public void setPasswordMinimumLength(@NonNull ComponentName admin, int length) { if (mService != null) { try { @@ -3030,9 +3056,12 @@ public class DevicePolicyManager { * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve * restrictions on the parent profile. * + * @deprecated see {@link #setPasswordQuality(ComponentName, int)} for details. + * * @param admin The name of the admin component to check, or {@code null} to aggregate * all admins. */ + @Deprecated public int getPasswordMinimumLength(@Nullable ComponentName admin) { return getPasswordMinimumLength(admin, myUserId()); } @@ -3070,10 +3099,14 @@ public class DevicePolicyManager { * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has * not, a security exception will be thrown. * <p> - * This method can be called on the {@link DevicePolicyManager} instance returned by + * + * Apps targeting {@link android.os.Build.VERSION_CODES#R} and below can call this method on the + * {@link DevicePolicyManager} instance returned by * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent * profile. * + * @deprecated see {@link #setPasswordQuality(ComponentName, int)} for details. + * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param length The new desired minimum number of upper case letters required in the password. * A value of 0 means there is no restriction. @@ -3083,6 +3116,7 @@ public class DevicePolicyManager { * {@link android.os.Build.VERSION_CODES#R} and above and didn't set a sufficient password * quality requirement prior to calling this method. */ + @Deprecated public void setPasswordMinimumUpperCase(@NonNull ComponentName admin, int length) { if (mService != null) { try { @@ -3110,11 +3144,14 @@ public class DevicePolicyManager { * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve * restrictions on the parent profile. * + * @deprecated see {@link #setPasswordQuality(ComponentName, int)} for details. + * * @param admin The name of the admin component to check, or {@code null} to * aggregate all admins. * @return The minimum number of upper case letters required in the * password. */ + @Deprecated public int getPasswordMinimumUpperCase(@Nullable ComponentName admin) { return getPasswordMinimumUpperCase(admin, myUserId()); } @@ -3152,10 +3189,14 @@ public class DevicePolicyManager { * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has * not, a security exception will be thrown. * <p> - * This method can be called on the {@link DevicePolicyManager} instance returned by + * + * Apps targeting {@link android.os.Build.VERSION_CODES#R} and below can call this method on the + * {@link DevicePolicyManager} instance returned by * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent * profile. * + * @deprecated see {@link #setPasswordQuality(ComponentName, int)} for details. + * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param length The new desired minimum number of lower case letters required in the password. * A value of 0 means there is no restriction. @@ -3165,6 +3206,7 @@ public class DevicePolicyManager { * {@link android.os.Build.VERSION_CODES#R} and above and didn't set a sufficient password * quality requirement prior to calling this method. */ + @Deprecated public void setPasswordMinimumLowerCase(@NonNull ComponentName admin, int length) { if (mService != null) { try { @@ -3192,11 +3234,14 @@ public class DevicePolicyManager { * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve * restrictions on the parent profile. * + * @deprecated see {@link #setPasswordQuality(ComponentName, int)} for details. + * * @param admin The name of the admin component to check, or {@code null} to * aggregate all admins. * @return The minimum number of lower case letters required in the * password. */ + @Deprecated public int getPasswordMinimumLowerCase(@Nullable ComponentName admin) { return getPasswordMinimumLowerCase(admin, myUserId()); } @@ -3234,10 +3279,14 @@ public class DevicePolicyManager { * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has * not, a security exception will be thrown. * <p> - * This method can be called on the {@link DevicePolicyManager} instance returned by + * + * Apps targeting {@link android.os.Build.VERSION_CODES#R} and below can call this method on the + * {@link DevicePolicyManager} instance returned by * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent * profile. * + * @deprecated see {@link #setPasswordQuality(ComponentName, int)} for details. + * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param length The new desired minimum number of letters required in the password. A value of * 0 means there is no restriction. @@ -3247,6 +3296,7 @@ public class DevicePolicyManager { * {@link android.os.Build.VERSION_CODES#R} and above and didn't set a sufficient password * quality requirement prior to calling this method. */ + @Deprecated public void setPasswordMinimumLetters(@NonNull ComponentName admin, int length) { if (mService != null) { try { @@ -3274,10 +3324,13 @@ public class DevicePolicyManager { * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve * restrictions on the parent profile. * + * @deprecated see {@link #setPasswordQuality(ComponentName, int)} for details. + * * @param admin The name of the admin component to check, or {@code null} to * aggregate all admins. * @return The minimum number of letters required in the password. */ + @Deprecated public int getPasswordMinimumLetters(@Nullable ComponentName admin) { return getPasswordMinimumLetters(admin, myUserId()); } @@ -3315,10 +3368,14 @@ public class DevicePolicyManager { * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has * not, a security exception will be thrown. * <p> - * This method can be called on the {@link DevicePolicyManager} instance returned by + * + * Apps targeting {@link android.os.Build.VERSION_CODES#R} and below can call this method on the + * {@link DevicePolicyManager} instance returned by * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent * profile. * + * @deprecated see {@link #setPasswordQuality(ComponentName, int)} for details. + * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param length The new desired minimum number of numerical digits required in the password. A * value of 0 means there is no restriction. @@ -3328,6 +3385,7 @@ public class DevicePolicyManager { * {@link android.os.Build.VERSION_CODES#R} and above and didn't set a sufficient password * quality requirement prior to calling this method. */ + @Deprecated public void setPasswordMinimumNumeric(@NonNull ComponentName admin, int length) { if (mService != null) { try { @@ -3355,10 +3413,13 @@ public class DevicePolicyManager { * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve * restrictions on the parent profile. * + * @deprecated see {@link #setPasswordQuality(ComponentName, int)} for details. + * * @param admin The name of the admin component to check, or {@code null} to * aggregate all admins. * @return The minimum number of numerical digits required in the password. */ + @Deprecated public int getPasswordMinimumNumeric(@Nullable ComponentName admin) { return getPasswordMinimumNumeric(admin, myUserId()); } @@ -3396,10 +3457,14 @@ public class DevicePolicyManager { * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has * not, a security exception will be thrown. * <p> - * This method can be called on the {@link DevicePolicyManager} instance returned by + * + * Apps targeting {@link android.os.Build.VERSION_CODES#R} and below can call this method on the + * {@link DevicePolicyManager} instance returned by * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent * profile. * + * @deprecated see {@link #setPasswordQuality(ComponentName, int)} for details. + * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param length The new desired minimum number of symbols required in the password. A value of * 0 means there is no restriction. @@ -3409,6 +3474,7 @@ public class DevicePolicyManager { * {@link android.os.Build.VERSION_CODES#R} and above and didn't set a sufficient password * quality requirement prior to calling this method. */ + @Deprecated public void setPasswordMinimumSymbols(@NonNull ComponentName admin, int length) { if (mService != null) { try { @@ -3435,10 +3501,13 @@ public class DevicePolicyManager { * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve * restrictions on the parent profile. * + * @deprecated see {@link #setPasswordQuality(ComponentName, int)} for details. + * * @param admin The name of the admin component to check, or {@code null} to * aggregate all admins. * @return The minimum number of symbols required in the password. */ + @Deprecated public int getPasswordMinimumSymbols(@Nullable ComponentName admin) { return getPasswordMinimumSymbols(admin, myUserId()); } @@ -3476,10 +3545,14 @@ public class DevicePolicyManager { * {@link DeviceAdminInfo#USES_POLICY_LIMIT_PASSWORD} to be able to call this method; if it has * not, a security exception will be thrown. * <p> - * This method can be called on the {@link DevicePolicyManager} instance returned by + * + * Apps targeting {@link android.os.Build.VERSION_CODES#R} and below can call this method on the + * {@link DevicePolicyManager} instance returned by * {@link #getParentProfileInstance(ComponentName)} in order to set restrictions on the parent * profile. * + * @deprecated see {@link #setPasswordQuality(ComponentName, int)} for details. + * * @param admin Which {@link DeviceAdminReceiver} this request is associated with. * @param length The new desired minimum number of letters required in the password. A value of * 0 means there is no restriction. @@ -3489,6 +3562,7 @@ public class DevicePolicyManager { * {@link android.os.Build.VERSION_CODES#R} and above and didn't set a sufficient password * quality requirement prior to calling this method. */ + @Deprecated public void setPasswordMinimumNonLetter(@NonNull ComponentName admin, int length) { if (mService != null) { try { @@ -3516,10 +3590,13 @@ public class DevicePolicyManager { * returned by {@link #getParentProfileInstance(ComponentName)} in order to retrieve * restrictions on the parent profile. * + * @deprecated see {@link #setPasswordQuality(ComponentName, int)} for details. + * * @param admin The name of the admin component to check, or {@code null} to * aggregate all admins. * @return The minimum number of letters required in the password. */ + @Deprecated public int getPasswordMinimumNonLetter(@Nullable ComponentName admin) { return getPasswordMinimumNonLetter(admin, myUserId()); } diff --git a/core/java/android/app/admin/OWNERS b/core/java/android/app/admin/OWNERS index 64a1d27d4cf7..8462cbe7497b 100644 --- a/core/java/android/app/admin/OWNERS +++ b/core/java/android/app/admin/OWNERS @@ -1,4 +1,11 @@ # Bug component: 142675 -yamasani@google.com +# Android Enterprise team rubinxu@google.com +sandness@google.com +eranm@google.com +alexkershaw@google.com +pgrafov@google.com + +# Emeritus +yamasani@google.com diff --git a/core/java/android/app/role/IRoleController.aidl b/core/java/android/app/role/IRoleController.aidl index 8a43d7fa9036..fbf79a485dd5 100644 --- a/core/java/android/app/role/IRoleController.aidl +++ b/core/java/android/app/role/IRoleController.aidl @@ -16,7 +16,9 @@ package android.app.role; +import android.app.role.RolePrivileges; import android.os.RemoteCallback; +import com.android.internal.infra.AndroidFuture; /** * @hide @@ -40,4 +42,6 @@ oneway interface IRoleController { in RemoteCallback callback); void isRoleVisible(in String roleName, in RemoteCallback callback); + + void getRolePrivileges(in String roleName, in AndroidFuture<RolePrivileges> callback); } diff --git a/core/java/android/app/role/RoleControllerService.java b/core/java/android/app/role/RoleControllerService.java index d92c95691eea..4c6aa8d2a4e0 100644 --- a/core/java/android/app/role/RoleControllerService.java +++ b/core/java/android/app/role/RoleControllerService.java @@ -16,6 +16,8 @@ package android.app.role; +import static java.util.Collections.emptyList; + import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; @@ -32,6 +34,7 @@ import android.os.Process; import android.os.RemoteCallback; import android.os.UserHandle; +import com.android.internal.infra.AndroidFuture; import com.android.internal.util.Preconditions; import com.android.internal.util.function.pooled.PooledLambda; @@ -177,6 +180,20 @@ public abstract class RoleControllerService extends Service { boolean visible = onIsRoleVisible(roleName); callback.sendResult(visible ? Bundle.EMPTY : null); } + + @Override + public void getRolePrivileges(String roleName, AndroidFuture<RolePrivileges> callback) { + enforceCallingPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, null); + + Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); + Objects.requireNonNull(callback, "callback cannot be null"); + + try { + callback.complete(RoleControllerService.this.getRolePrivileges(roleName)); + } catch (Throwable t) { + callback.completeExceptionally(t); + } + } }; } @@ -302,4 +319,14 @@ public abstract class RoleControllerService extends Service { * @return whether the role should be visible to user */ public abstract boolean onIsRoleVisible(@NonNull String roleName); + + /** + * Queries the {@link RolePrivileges privileges} that the given role grants. + * + * @param roleName name of the role to quey for + * @return the {@link RolePrivileges} for the role + */ + public @NonNull RolePrivileges getRolePrivileges(@NonNull String roleName) { + return new RolePrivileges(emptyList(), emptyList(), emptyList(), emptyList()); + } } diff --git a/core/java/android/app/role/RolePrivileges.aidl b/core/java/android/app/role/RolePrivileges.aidl new file mode 100644 index 000000000000..1561ad499d0a --- /dev/null +++ b/core/java/android/app/role/RolePrivileges.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.app.role; + +parcelable RolePrivileges; diff --git a/core/java/android/app/role/RolePrivileges.java b/core/java/android/app/role/RolePrivileges.java new file mode 100644 index 000000000000..5fc0b0a086af --- /dev/null +++ b/core/java/android/app/role/RolePrivileges.java @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package android.app.role; + +import android.annotation.NonNull; +import android.annotation.SystemApi; +import android.os.Parcelable; + +import com.android.internal.util.DataClass; + +import java.util.List; + +/** + * Describes a set of privileges granted by a {@link RoleManager role} + * + * @hide + */ +@SystemApi +@DataClass +public final class RolePrivileges implements Parcelable { + + /** + * An identifier of a role holder app being granted the + * {@link android.service.notification.NotificationListenerService Notification Access} + * privilege. + */ + public static final String CAPABILITY_NOTIFICATION_LISTENER = + "android.app.role.capability.NOTIFICATION_LISTENER"; + + /** + * Permissions granted to the role holder(s). + */ + private @NonNull List<String> mPermissions; + /** + * Appop permissions granted to the role holder(s). + */ + private @NonNull List<String> mAppOpPermissions; + /** + * Appops granted to the role holder(s). + */ + private @NonNull List<String> mAppOps; + /** + * Special access granted to the role holder(s). + * + * @see #CAPABILITY_NOTIFICATION_LISTENER + */ + private @NonNull List<String> mCapabilities; + + + + // Code below generated by codegen v1.0.22. + // + // DO NOT MODIFY! + // CHECKSTYLE:OFF Generated code + // + // To regenerate run: + // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/app/role/RolePrivileges.java + // + // To exclude the generated code from IntelliJ auto-formatting enable (one-time): + // Settings > Editor > Code Style > Formatter Control + //@formatter:off + + + /** + * Creates a new RolePrivileges. + * + * @param permissions + * Permissions granted to the role holder(s). + * @param appOpPermissions + * Appop permissions granted to the role holder(s). + * @param appOps + * Appops granted to the role holder(s). + * @param capabilities + * Special access granted to the role holder(s). + */ + @DataClass.Generated.Member + public RolePrivileges( + @NonNull List<String> permissions, + @NonNull List<String> appOpPermissions, + @NonNull List<String> appOps, + @NonNull List<String> capabilities) { + this.mPermissions = permissions; + com.android.internal.util.AnnotationValidations.validate( + NonNull.class, null, mPermissions); + this.mAppOpPermissions = appOpPermissions; + com.android.internal.util.AnnotationValidations.validate( + NonNull.class, null, mAppOpPermissions); + this.mAppOps = appOps; + com.android.internal.util.AnnotationValidations.validate( + NonNull.class, null, mAppOps); + this.mCapabilities = capabilities; + com.android.internal.util.AnnotationValidations.validate( + NonNull.class, null, mCapabilities); + + // onConstructed(); // You can define this method to get a callback + } + + /** + * Permissions granted to the role holder(s). + */ + @DataClass.Generated.Member + public @NonNull List<String> getPermissions() { + return mPermissions; + } + + /** + * Appop permissions granted to the role holder(s). + */ + @DataClass.Generated.Member + public @NonNull List<String> getAppOpPermissions() { + return mAppOpPermissions; + } + + /** + * Appops granted to the role holder(s). + */ + @DataClass.Generated.Member + public @NonNull List<String> getAppOps() { + return mAppOps; + } + + /** + * Special access granted to the role holder(s). + * + * @see #CAPABILITY_NOTIFICATION_LISTENER + */ + @DataClass.Generated.Member + public @NonNull List<String> getCapabilities() { + return mCapabilities; + } + + @Override + @DataClass.Generated.Member + public void writeToParcel(@NonNull android.os.Parcel dest, int flags) { + // You can override field parcelling by defining methods like: + // void parcelFieldName(Parcel dest, int flags) { ... } + + dest.writeStringList(mPermissions); + dest.writeStringList(mAppOpPermissions); + dest.writeStringList(mAppOps); + dest.writeStringList(mCapabilities); + } + + @Override + @DataClass.Generated.Member + public int describeContents() { return 0; } + + /** @hide */ + @SuppressWarnings({"unchecked", "RedundantCast"}) + @DataClass.Generated.Member + /* package-private */ RolePrivileges(@NonNull android.os.Parcel in) { + // You can override field unparcelling by defining methods like: + // static FieldType unparcelFieldName(Parcel in) { ... } + + List<String> permissions = new java.util.ArrayList<>(); + in.readStringList(permissions); + List<String> appOpPermissions = new java.util.ArrayList<>(); + in.readStringList(appOpPermissions); + List<String> appOps = new java.util.ArrayList<>(); + in.readStringList(appOps); + List<String> capabilities = new java.util.ArrayList<>(); + in.readStringList(capabilities); + + this.mPermissions = permissions; + com.android.internal.util.AnnotationValidations.validate( + NonNull.class, null, mPermissions); + this.mAppOpPermissions = appOpPermissions; + com.android.internal.util.AnnotationValidations.validate( + NonNull.class, null, mAppOpPermissions); + this.mAppOps = appOps; + com.android.internal.util.AnnotationValidations.validate( + NonNull.class, null, mAppOps); + this.mCapabilities = capabilities; + com.android.internal.util.AnnotationValidations.validate( + NonNull.class, null, mCapabilities); + + // onConstructed(); // You can define this method to get a callback + } + + @DataClass.Generated.Member + public static final @NonNull Parcelable.Creator<RolePrivileges> CREATOR + = new Parcelable.Creator<RolePrivileges>() { + @Override + public RolePrivileges[] newArray(int size) { + return new RolePrivileges[size]; + } + + @Override + public RolePrivileges createFromParcel(@NonNull android.os.Parcel in) { + return new RolePrivileges(in); + } + }; + + @DataClass.Generated( + time = 1607546429137L, + codegenVersion = "1.0.22", + sourceFile = "frameworks/base/core/java/android/app/role/RolePrivileges.java", + inputSignatures = "public static final java.lang.String CAPABILITY_NOTIFICATION_LISTENER\nprivate @android.annotation.NonNull java.util.List<java.lang.String> mPermissions\nprivate @android.annotation.NonNull java.util.List<java.lang.String> mAppOpPermissions\nprivate @android.annotation.NonNull java.util.List<java.lang.String> mAppOps\nprivate @android.annotation.NonNull java.util.List<java.lang.String> mCapabilities\nclass RolePrivileges extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass") + @Deprecated + private void __metadata() {} + + + //@formatter:on + // End of generated code + +} diff --git a/core/java/android/app/servertransaction/LaunchActivityItem.java b/core/java/android/app/servertransaction/LaunchActivityItem.java index 7f08bfbef289..3758cb49e2d0 100644 --- a/core/java/android/app/servertransaction/LaunchActivityItem.java +++ b/core/java/android/app/servertransaction/LaunchActivityItem.java @@ -20,8 +20,10 @@ import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.ActivityClient; import android.app.ActivityThread.ActivityClientRecord; import android.app.ClientTransactionHandler; +import android.app.IActivityClientController; import android.app.ProfilerInfo; import android.app.ResultInfo; import android.compat.annotation.UnsupportedAppUsage; @@ -67,6 +69,11 @@ public class LaunchActivityItem extends ClientTransactionItem { private boolean mIsForward; private ProfilerInfo mProfilerInfo; private IBinder mAssistToken; + /** + * It is only non-null if the process is the first time to launch activity. It is only an + * optimization for quick look up of the interface so the field is ignored for comparison. + */ + private IActivityClientController mActivityClientController; private FixedRotationAdjustments mFixedRotationAdjustments; @Override @@ -74,6 +81,9 @@ public class LaunchActivityItem extends ClientTransactionItem { client.countLaunchingActivities(1); client.updateProcessState(mProcState, false); client.updatePendingConfiguration(mCurConfig); + if (mActivityClientController != null) { + ActivityClient.setActivityClientController(mActivityClientController); + } } @Override @@ -105,14 +115,16 @@ public class LaunchActivityItem extends ClientTransactionItem { String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state, PersistableBundle persistentState, List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, boolean isForward, ProfilerInfo profilerInfo, - IBinder assistToken, FixedRotationAdjustments fixedRotationAdjustments) { + IBinder assistToken, IActivityClientController activityClientController, + FixedRotationAdjustments fixedRotationAdjustments) { LaunchActivityItem instance = ObjectPool.obtain(LaunchActivityItem.class); if (instance == null) { instance = new LaunchActivityItem(); } setValues(instance, intent, ident, info, curConfig, overrideConfig, compatInfo, referrer, voiceInteractor, procState, state, persistentState, pendingResults, - pendingNewIntents, isForward, profilerInfo, assistToken, fixedRotationAdjustments); + pendingNewIntents, isForward, profilerInfo, assistToken, activityClientController, + fixedRotationAdjustments); return instance; } @@ -120,7 +132,7 @@ public class LaunchActivityItem extends ClientTransactionItem { @Override public void recycle() { setValues(this, null, 0, null, null, null, null, null, null, 0, null, null, null, null, - false, null, null, null); + false, null, null, null, null); ObjectPool.recycle(this); } @@ -146,6 +158,7 @@ public class LaunchActivityItem extends ClientTransactionItem { dest.writeBoolean(mIsForward); dest.writeTypedObject(mProfilerInfo, flags); dest.writeStrongBinder(mAssistToken); + dest.writeStrongInterface(mActivityClientController); dest.writeTypedObject(mFixedRotationAdjustments, flags); } @@ -162,6 +175,7 @@ public class LaunchActivityItem extends ClientTransactionItem { in.createTypedArrayList(ReferrerIntent.CREATOR), in.readBoolean(), in.readTypedObject(ProfilerInfo.CREATOR), in.readStrongBinder(), + IActivityClientController.Stub.asInterface(in.readStrongBinder()), in.readTypedObject(FixedRotationAdjustments.CREATOR)); } @@ -266,6 +280,7 @@ public class LaunchActivityItem extends ClientTransactionItem { int procState, Bundle state, PersistableBundle persistentState, List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents, boolean isForward, ProfilerInfo profilerInfo, IBinder assistToken, + IActivityClientController activityClientController, FixedRotationAdjustments fixedRotationAdjustments) { instance.mIntent = intent; instance.mIdent = ident; @@ -283,6 +298,7 @@ public class LaunchActivityItem extends ClientTransactionItem { instance.mIsForward = isForward; instance.mProfilerInfo = profilerInfo; instance.mAssistToken = assistToken; + instance.mActivityClientController = activityClientController; instance.mFixedRotationAdjustments = fixedRotationAdjustments; } } diff --git a/core/java/android/app/time/OWNERS b/core/java/android/app/time/OWNERS new file mode 100644 index 000000000000..8f8089717e3b --- /dev/null +++ b/core/java/android/app/time/OWNERS @@ -0,0 +1,3 @@ +# Bug component: 847766 +mingaleev@google.com +include /core/java/android/app/timedetector/OWNERS diff --git a/core/java/android/app/timedetector/GnssTimeSuggestion.aidl b/core/java/android/app/timedetector/GnssTimeSuggestion.aidl new file mode 100644 index 000000000000..81475ec8156d --- /dev/null +++ b/core/java/android/app/timedetector/GnssTimeSuggestion.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.app.timedetector; + +parcelable GnssTimeSuggestion; diff --git a/core/java/android/app/timedetector/GnssTimeSuggestion.java b/core/java/android/app/timedetector/GnssTimeSuggestion.java new file mode 100644 index 000000000000..6478a2dd2aa9 --- /dev/null +++ b/core/java/android/app/timedetector/GnssTimeSuggestion.java @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app.timedetector; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.TimestampedValue; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +/** + * A time signal from a GNSS source. + * + * <p>{@code utcTime} is the suggested time. The {@code utcTime.value} is the number of milliseconds + * elapsed since 1/1/1970 00:00:00 UTC. The {@code utcTime.referenceTimeMillis} is the value of the + * elapsed realtime clock when the {@code utcTime.value} was established. + * Note that the elapsed realtime clock is considered accurate but it is volatile, so time + * suggestions cannot be persisted across device resets. + * + * <p>{@code debugInfo} contains debugging metadata associated with the suggestion. This is used to + * record why the suggestion exists and how it was entered. This information exists only to aid in + * debugging and therefore is used by {@link #toString()}, but it is not for use in detection + * logic and is not considered in {@link #hashCode()} or {@link #equals(Object)}. + * + * @hide + */ +public final class GnssTimeSuggestion implements Parcelable { + + public static final @NonNull Creator<GnssTimeSuggestion> CREATOR = + new Creator<GnssTimeSuggestion>() { + public GnssTimeSuggestion createFromParcel(Parcel in) { + return GnssTimeSuggestion.createFromParcel(in); + } + + public GnssTimeSuggestion[] newArray(int size) { + return new GnssTimeSuggestion[size]; + } + }; + + @NonNull private final TimestampedValue<Long> mUtcTime; + @Nullable private ArrayList<String> mDebugInfo; + + public GnssTimeSuggestion(@NonNull TimestampedValue<Long> utcTime) { + mUtcTime = Objects.requireNonNull(utcTime); + Objects.requireNonNull(utcTime.getValue()); + } + + private static GnssTimeSuggestion createFromParcel(Parcel in) { + TimestampedValue<Long> utcTime = in.readParcelable(null /* classLoader */); + GnssTimeSuggestion suggestion = new GnssTimeSuggestion(utcTime); + @SuppressWarnings("unchecked") + ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */); + suggestion.mDebugInfo = debugInfo; + return suggestion; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeParcelable(mUtcTime, 0); + dest.writeList(mDebugInfo); + } + + @NonNull + public TimestampedValue<Long> getUtcTime() { + return mUtcTime; + } + + @NonNull + public List<String> getDebugInfo() { + return mDebugInfo == null + ? Collections.emptyList() : Collections.unmodifiableList(mDebugInfo); + } + + /** + * Associates information with the instance that can be useful for debugging / logging. The + * information is present in {@link #toString()} but is not considered for + * {@link #equals(Object)} and {@link #hashCode()}. + */ + public void addDebugInfo(String... debugInfos) { + if (mDebugInfo == null) { + mDebugInfo = new ArrayList<>(); + } + mDebugInfo.addAll(Arrays.asList(debugInfos)); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + GnssTimeSuggestion that = (GnssTimeSuggestion) o; + return Objects.equals(mUtcTime, that.mUtcTime); + } + + @Override + public int hashCode() { + return Objects.hash(mUtcTime); + } + + @Override + public String toString() { + return "GnssTimeSuggestion{" + + "mUtcTime=" + mUtcTime + + ", mDebugInfo=" + mDebugInfo + + '}'; + } +} diff --git a/core/java/android/app/timedetector/ITimeDetectorService.aidl b/core/java/android/app/timedetector/ITimeDetectorService.aidl index 7bea5d7d60b1..87e72332274e 100644 --- a/core/java/android/app/timedetector/ITimeDetectorService.aidl +++ b/core/java/android/app/timedetector/ITimeDetectorService.aidl @@ -16,6 +16,7 @@ package android.app.timedetector; +import android.app.timedetector.GnssTimeSuggestion; import android.app.timedetector.ManualTimeSuggestion; import android.app.timedetector.NetworkTimeSuggestion; import android.app.timedetector.TelephonyTimeSuggestion; @@ -34,6 +35,7 @@ import android.app.timedetector.TelephonyTimeSuggestion; * {@hide} */ interface ITimeDetectorService { + void suggestGnssTime(in GnssTimeSuggestion timeSuggestion); boolean suggestManualTime(in ManualTimeSuggestion timeSuggestion); void suggestNetworkTime(in NetworkTimeSuggestion timeSuggestion); void suggestTelephonyTime(in TelephonyTimeSuggestion timeSuggestion); diff --git a/core/java/android/app/timedetector/OWNERS b/core/java/android/app/timedetector/OWNERS index 8c113246b5d4..941eed8de631 100644 --- a/core/java/android/app/timedetector/OWNERS +++ b/core/java/android/app/timedetector/OWNERS @@ -1,4 +1,4 @@ # Bug component: 847766 - +mingaleev@google.com narayan@google.com nfuller@google.com diff --git a/core/java/android/app/timedetector/TimeDetector.java b/core/java/android/app/timedetector/TimeDetector.java index 162e18215cae..52016b65688b 100644 --- a/core/java/android/app/timedetector/TimeDetector.java +++ b/core/java/android/app/timedetector/TimeDetector.java @@ -71,4 +71,12 @@ public interface TimeDetector { */ @RequiresPermission(android.Manifest.permission.SET_TIME) void suggestNetworkTime(NetworkTimeSuggestion timeSuggestion); + + /** + * Suggests the time according to a gnss time source. + * + * @hide + */ + @RequiresPermission(android.Manifest.permission.SET_TIME) + void suggestGnssTime(GnssTimeSuggestion timeSuggestion); } diff --git a/core/java/android/app/timedetector/TimeDetectorImpl.java b/core/java/android/app/timedetector/TimeDetectorImpl.java index ac02c8930982..b0aa3c8d4575 100644 --- a/core/java/android/app/timedetector/TimeDetectorImpl.java +++ b/core/java/android/app/timedetector/TimeDetectorImpl.java @@ -74,4 +74,16 @@ public final class TimeDetectorImpl implements TimeDetector { throw e.rethrowFromSystemServer(); } } + + @Override + public void suggestGnssTime(GnssTimeSuggestion timeSuggestion) { + if (DEBUG) { + Log.d(TAG, "suggestGnssTime called: " + timeSuggestion); + } + try { + mITimeDetectorService.suggestGnssTime(timeSuggestion); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } } diff --git a/core/java/android/app/timezone/OWNERS b/core/java/android/app/timezone/OWNERS index 8c113246b5d4..8f8089717e3b 100644 --- a/core/java/android/app/timezone/OWNERS +++ b/core/java/android/app/timezone/OWNERS @@ -1,4 +1,3 @@ # Bug component: 847766 - -narayan@google.com -nfuller@google.com +mingaleev@google.com +include /core/java/android/app/timedetector/OWNERS diff --git a/core/java/android/app/timezonedetector/OWNERS b/core/java/android/app/timezonedetector/OWNERS new file mode 100644 index 000000000000..8f8089717e3b --- /dev/null +++ b/core/java/android/app/timezonedetector/OWNERS @@ -0,0 +1,3 @@ +# Bug component: 847766 +mingaleev@google.com +include /core/java/android/app/timedetector/OWNERS diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java index c3c270e52eb6..59646f106db5 100644 --- a/core/java/android/companion/CompanionDeviceManager.java +++ b/core/java/android/companion/CompanionDeviceManager.java @@ -34,6 +34,7 @@ import android.os.Handler; import android.os.RemoteException; import android.os.UserHandle; import android.service.notification.NotificationListenerService; +import android.util.ExceptionUtils; import android.util.Log; import java.util.Collections; @@ -321,6 +322,77 @@ public final class CompanionDeviceManager { } } + /** + * Register to receive callbacks whenever the associated device comes in and out of range. + * + * The provided device must be {@link #associate associated} with the calling app before + * calling this method. + * + * Caller must implement a single {@link CompanionDeviceService} which will be bound to and + * receive callbacks to {@link CompanionDeviceService#onDeviceAppeared} and + * {@link CompanionDeviceService#onDeviceDisappeared}. + * The app doesn't need to remain running in order to receive its callbacks. + * + * Calling app must declare uses-permission + * {@link android.Manifest.permission#REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE}. + * + * Calling app must check for feature presence of + * {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP} before calling this API. + * + * @param deviceAddress a previously-associated companion device's address + * + * @throws DeviceNotAssociatedException if the given device was not previously associated + * with this app. + */ + @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) + public void startObservingDevicePresence(@NonNull String deviceAddress) + throws DeviceNotAssociatedException { + if (!checkFeaturePresent()) { + return; + } + Objects.requireNonNull(deviceAddress, "address cannot be null"); + try { + mService.registerDevicePresenceListenerService( + mContext.getPackageName(), deviceAddress); + } catch (RemoteException e) { + ExceptionUtils.propagateIfInstanceOf(e.getCause(), DeviceNotAssociatedException.class); + throw e.rethrowFromSystemServer(); + } + } + + /** + * Unregister for receiving callbacks whenever the associated device comes in and out of range. + * + * The provided device must be {@link #associate associated} with the calling app before + * calling this method. + * + * Calling app must declare uses-permission + * {@link android.Manifest.permission#REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE}. + * + * Calling app must check for feature presence of + * {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP} before calling this API. + * + * @param deviceAddress a previously-associated companion device's address + * + * @throws DeviceNotAssociatedException if the given device was not previously associated + * with this app. + */ + @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) + public void stopObservingDevicePresence(@NonNull String deviceAddress) + throws DeviceNotAssociatedException { + if (!checkFeaturePresent()) { + return; + } + Objects.requireNonNull(deviceAddress, "address cannot be null"); + try { + mService.unregisterDevicePresenceListenerService( + mContext.getPackageName(), deviceAddress); + } catch (RemoteException e) { + ExceptionUtils.propagateIfInstanceOf(e.getCause(), DeviceNotAssociatedException.class); + throw e.rethrowFromSystemServer(); + } + } + private boolean checkFeaturePresent() { boolean featurePresent = mService != null; if (!featurePresent && DEBUG) { diff --git a/core/java/android/companion/DeviceNotAssociatedException.java b/core/java/android/companion/DeviceNotAssociatedException.java new file mode 100644 index 000000000000..bebb6c9ff7eb --- /dev/null +++ b/core/java/android/companion/DeviceNotAssociatedException.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package android.companion; + +import android.annotation.Nullable; + +/** + * An exception for a case when a given device was not + * {@link CompanionDeviceManager#associate associated} to the calling app. + */ +public class DeviceNotAssociatedException extends Exception { + /** @hide */ + public DeviceNotAssociatedException(@Nullable String deviceName) { + super("Device not associated with the current app: " + deviceName); + } +} diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl index bcb9be80e6a4..527d8df94ea0 100644 --- a/core/java/android/companion/ICompanionDeviceManager.aidl +++ b/core/java/android/companion/ICompanionDeviceManager.aidl @@ -45,4 +45,8 @@ interface ICompanionDeviceManager { boolean isDeviceAssociatedForWifiConnection(in String packageName, in String macAddress, int userId); + + void registerDevicePresenceListenerService(in String packageName, in String deviceAddress); + + void unregisterDevicePresenceListenerService(in String packageName, in String deviceAddress); } diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index d920fb3e97e6..f3e1a87ea271 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -4564,6 +4564,15 @@ public abstract class Context { public static final String PERMISSION_SERVICE = "permission"; /** + * Official published name of the legacy (internal) permission service. + * + * @see #getSystemService(String) + * @hide + */ + //@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public static final String LEGACY_PERMISSION_SERVICE = "legacy_permission"; + + /** * Official published name of the (internal) permission controller service. * * @see #getSystemService(String) diff --git a/core/java/android/content/OWNERS b/core/java/android/content/OWNERS new file mode 100644 index 000000000000..c1e7e41972ba --- /dev/null +++ b/core/java/android/content/OWNERS @@ -0,0 +1,3 @@ +# Remain no owner because multiple modules may touch this file. +per-file Context.java = * +per-file ContextWrapper.java = * diff --git a/core/java/android/content/pm/OWNERS b/core/java/android/content/pm/OWNERS index 3a590dac7c0b..24872e8c3c1d 100644 --- a/core/java/android/content/pm/OWNERS +++ b/core/java/android/content/pm/OWNERS @@ -5,3 +5,4 @@ toddke@google.com patb@google.com per-file PackageParser.java = chiuwinson@google.com +per-file *Shortcut* = omakoto@google.com, yamasani@google.com, sunnygoyal@google.com, mett@google.com, pinyaoting@google.com diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index cf3f7069c63f..bd270997ead0 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -2682,6 +2682,23 @@ public abstract class PackageManager { /** * Feature for {@link #getSystemAvailableFeatures} and + * {@link #hasSystemFeature(String, int)}: If this feature is supported, the feature version + * specifies a date such that the device is known to pass the OpenGLES dEQP test suite + * associated with that date. The date is encoded as follows: + * <ul> + * <li>Year in bits 31-16</li> + * <li>Month in bits 15-8</li> + * <li>Day in bits 7-0</li> + * </ul> + * <p> + * Example: 2021-03-01 is encoded as 0x07E50301, and would indicate that the device passes the + * OpenGL ES dEQP test suite version that was current on 2021-03-01. + */ + @SdkConstant(SdkConstantType.FEATURE) + public static final String FEATURE_OPENGLES_DEQP_LEVEL = "android.software.opengles.deqp.level"; + + /** + * Feature for {@link #getSystemAvailableFeatures} and * {@link #hasSystemFeature}: The device includes broadcast radio tuner. * @hide */ @@ -4438,6 +4455,7 @@ public abstract class PackageManager { * @throws NameNotFoundException if a package with the given name cannot be * found on the system. */ + //@Deprecated public abstract PermissionInfo getPermissionInfo(@NonNull String permName, @PermissionInfoFlags int flags) throws NameNotFoundException; @@ -4450,9 +4468,10 @@ public abstract class PackageManager { * @param flags Additional option flags to modify the data returned. * @return Returns a list of {@link PermissionInfo} containing information * about all of the permissions in the given group. - * @throws NameNotFoundException if a package with the given name cannot be + * @throws NameNotFoundException if a group with the given name cannot be * found on the system. */ + //@Deprecated @NonNull public abstract List<PermissionInfo> queryPermissionsByGroup(@NonNull String permissionGroup, @PermissionInfoFlags int flags) throws NameNotFoundException; @@ -4481,7 +4500,7 @@ public abstract class PackageManager { * Retrieve all of the information we know about a particular group of * permissions. * - * @param permName The fully qualified name (i.e. + * @param groupName The fully qualified name (i.e. * com.google.permission_group.APPS) of the permission you are * interested in. * @param flags Additional option flags to modify the data returned. @@ -4490,8 +4509,9 @@ public abstract class PackageManager { * @throws NameNotFoundException if a package with the given name cannot be * found on the system. */ + //@Deprecated @NonNull - public abstract PermissionGroupInfo getPermissionGroupInfo(@NonNull String permName, + public abstract PermissionGroupInfo getPermissionGroupInfo(@NonNull String groupName, @PermissionGroupInfoFlags int flags) throws NameNotFoundException; /** @@ -4501,6 +4521,7 @@ public abstract class PackageManager { * @return Returns a list of {@link PermissionGroupInfo} containing * information about all of the known permission groups. */ + //@Deprecated @NonNull public abstract List<PermissionGroupInfo> getAllPermissionGroups( @PermissionGroupInfoFlags int flags); @@ -4757,6 +4778,7 @@ public abstract class PackageManager { * @return Whether the permission is restricted by policy. */ @CheckResult + //@Deprecated public abstract boolean isPermissionRevokedByPolicy(@NonNull String permName, @NonNull String packageName); @@ -4805,6 +4827,7 @@ public abstract class PackageManager { * * @see #removePermission(String) */ + //@Deprecated public abstract boolean addPermission(@NonNull PermissionInfo info); /** @@ -4814,6 +4837,7 @@ public abstract class PackageManager { * expense of no guarantee the added permission will be retained if * the device is rebooted before it is written. */ + //@Deprecated public abstract boolean addPermissionAsync(@NonNull PermissionInfo info); /** @@ -4829,6 +4853,7 @@ public abstract class PackageManager { * * @see #addPermission(PermissionInfo) */ + //@Deprecated public abstract void removePermission(@NonNull String permName); /** @@ -4881,6 +4906,7 @@ public abstract class PackageManager { * * @hide */ + //@Deprecated @SuppressWarnings("HiddenAbstractMethod") @SystemApi @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) @@ -4908,6 +4934,7 @@ public abstract class PackageManager { * * @hide */ + //@Deprecated @SuppressWarnings("HiddenAbstractMethod") @SystemApi @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS) @@ -4936,6 +4963,7 @@ public abstract class PackageManager { * * @hide */ + //@Deprecated @SystemApi @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS) public void revokeRuntimePermission(@NonNull String packageName, @@ -4953,6 +4981,7 @@ public abstract class PackageManager { * * @hide */ + //@Deprecated @SuppressWarnings("HiddenAbstractMethod") @SystemApi @RequiresPermission(anyOf = { @@ -4976,6 +5005,7 @@ public abstract class PackageManager { * * @hide */ + //@Deprecated @SuppressWarnings("HiddenAbstractMethod") @SystemApi @RequiresPermission(anyOf = { @@ -5040,6 +5070,7 @@ public abstract class PackageManager { * * @throws SecurityException if you try to access a whitelist that you have no access to. */ + //@Deprecated @RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS, conditional = true) public @NonNull Set<String> getWhitelistedRestrictedPermissions( @@ -5106,6 +5137,7 @@ public abstract class PackageManager { * * @throws SecurityException if you try to modify a whitelist that you have no access to. */ + //@Deprecated @RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS, conditional = true) public boolean addWhitelistedRestrictedPermission(@NonNull String packageName, @@ -5175,6 +5207,7 @@ public abstract class PackageManager { * * @throws SecurityException if you try to modify a whitelist that you have no access to. */ + //@Deprecated @RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS, conditional = true) public boolean removeWhitelistedRestrictedPermission(@NonNull String packageName, @@ -5207,6 +5240,7 @@ public abstract class PackageManager { * * @throws SecurityException if you you have no access to modify this. */ + //@Deprecated @RequiresPermission(value = Manifest.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS, conditional = true) public boolean setAutoRevokeWhitelisted(@NonNull String packageName, boolean whitelisted) { @@ -5234,6 +5268,7 @@ public abstract class PackageManager { * * @throws SecurityException if you you have no access to this. */ + //@Deprecated @RequiresPermission(value = Manifest.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS, conditional = true) public boolean isAutoRevokeWhitelisted(@NonNull String packageName) { @@ -5252,6 +5287,7 @@ public abstract class PackageManager { * * @hide */ + //@Deprecated @SuppressWarnings("HiddenAbstractMethod") @UnsupportedAppUsage public abstract boolean shouldShowRequestPermissionRationale(@NonNull String permName); @@ -7554,6 +7590,7 @@ public abstract class PackageManager { * * @hide */ + //@Deprecated @SuppressWarnings("HiddenAbstractMethod") @SystemApi @RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS) @@ -7567,6 +7604,7 @@ public abstract class PackageManager { * * @hide */ + //@Deprecated @SuppressWarnings("HiddenAbstractMethod") @SystemApi @RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS) diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 4dfbd75a9d67..45f072adf801 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -53,7 +53,6 @@ import android.compat.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Intent; import android.content.IntentFilter; -import android.content.pm.permission.SplitPermissionInfoParcelable; import android.content.pm.split.DefaultSplitAssetLoader; import android.content.pm.split.SplitAssetDependencyLoader; import android.content.pm.split.SplitAssetLoader; @@ -74,6 +73,7 @@ import android.os.SystemProperties; import android.os.Trace; import android.os.UserHandle; import android.os.storage.StorageManager; +import android.permission.PermissionManager; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; @@ -2394,17 +2394,13 @@ public class PackageParser { Slog.i(TAG, newPermsMsg.toString()); } - List<SplitPermissionInfoParcelable> splitPermissions; - - try { - splitPermissions = ActivityThread.getPermissionManager().getSplitPermissions(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + final List<PermissionManager.SplitPermissionInfo> splitPermissions = + ActivityThread.currentApplication().getSystemService(PermissionManager.class) + .getSplitPermissions(); final int listSize = splitPermissions.size(); for (int is = 0; is < listSize; is++) { - final SplitPermissionInfoParcelable spi = splitPermissions.get(is); + final PermissionManager.SplitPermissionInfo spi = splitPermissions.get(is); if (pkg.applicationInfo.targetSdkVersion >= spi.getTargetSdk() || !pkg.requestedPermissions.contains(spi.getSplitPermission())) { continue; diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java index eae7d452ff74..561a9e31b4b0 100644 --- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java +++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java @@ -71,7 +71,6 @@ import android.content.pm.parsing.result.ParseInput; import android.content.pm.parsing.result.ParseInput.DeferredError; import android.content.pm.parsing.result.ParseResult; import android.content.pm.parsing.result.ParseTypeImpl; -import android.content.pm.permission.SplitPermissionInfoParcelable; import android.content.pm.split.DefaultSplitAssetLoader; import android.content.pm.split.SplitAssetDependencyLoader; import android.content.pm.split.SplitAssetLoader; @@ -85,9 +84,9 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.FileUtils; -import android.os.RemoteException; import android.os.Trace; import android.os.ext.SdkExtensions; +import android.permission.PermissionManager; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; @@ -2664,17 +2663,13 @@ public class ParsingPackageUtils { } private static void convertSplitPermissions(ParsingPackage pkg) { - List<SplitPermissionInfoParcelable> splitPermissions; - - try { - splitPermissions = ActivityThread.getPermissionManager().getSplitPermissions(); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + final List<PermissionManager.SplitPermissionInfo> splitPermissions = + ActivityThread.currentApplication().getSystemService(PermissionManager.class) + .getSplitPermissions(); final int listSize = splitPermissions.size(); for (int is = 0; is < listSize; is++) { - final SplitPermissionInfoParcelable spi = splitPermissions.get(is); + final PermissionManager.SplitPermissionInfo spi = splitPermissions.get(is); List<String> requestedPermissions = pkg.getRequestedPermissions(); if (pkg.getTargetSdkVersion() >= spi.getTargetSdk() || !requestedPermissions.contains(spi.getSplitPermission())) { diff --git a/core/java/android/database/OWNERS b/core/java/android/database/OWNERS index 1734cfcad360..7e19942ba332 100644 --- a/core/java/android/database/OWNERS +++ b/core/java/android/database/OWNERS @@ -1,3 +1,3 @@ omakoto@google.com -jsharkey@google.com +jsharkey@android.com yamasani@google.com diff --git a/core/java/android/hardware/ISensorPrivacyManager.aidl b/core/java/android/hardware/ISensorPrivacyManager.aidl index 1ba7b989a764..4e368d0610b3 100644 --- a/core/java/android/hardware/ISensorPrivacyManager.aidl +++ b/core/java/android/hardware/ISensorPrivacyManager.aidl @@ -32,4 +32,12 @@ interface ISensorPrivacyManager { void setSensorPrivacy(boolean enable); // =============== End of transactions used on native side as well ============================ + + // TODO(evanseverson) add to native interface + boolean isIndividualSensorPrivacyEnabled(int sensor); + + // TODO(evanseverson) add to native interface + void setIndividualSensorPrivacy(int sensor, boolean enable); + + // TODO(evanseverson) listeners }
\ No newline at end of file diff --git a/core/java/android/hardware/OWNERS b/core/java/android/hardware/OWNERS index 47dbf2d960e3..3295042b0b35 100644 --- a/core/java/android/hardware/OWNERS +++ b/core/java/android/hardware/OWNERS @@ -1,2 +1,5 @@ # Camera per-file *Camera*=cychen@google.com,epeev@google.com,etalvala@google.com,shuzhenwang@google.com,yinchiayeh@google.com,zhijunhe@google.com,jchowdhary@google.com + +# Sensor Privacy +per-file *SensorPrivacy* = file:platform/frameworks/native:/libs/sensorprivacy/OWNERS diff --git a/core/java/android/hardware/SensorPrivacyManager.java b/core/java/android/hardware/SensorPrivacyManager.java index 274202f7c190..c647239d9049 100644 --- a/core/java/android/hardware/SensorPrivacyManager.java +++ b/core/java/android/hardware/SensorPrivacyManager.java @@ -16,6 +16,7 @@ package android.hardware; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.RequiresPermission; import android.annotation.SystemService; @@ -23,10 +24,14 @@ import android.content.Context; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; +import android.service.SensorPrivacyIndividualEnabledSensorProto; import android.util.ArrayMap; import com.android.internal.annotations.GuardedBy; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * This class provides access to the sensor privacy services; sensor privacy allows the * user to disable access to all sensors on the device. This class provides methods to query the @@ -38,6 +43,25 @@ import com.android.internal.annotations.GuardedBy; @SystemService(Context.SENSOR_PRIVACY_SERVICE) public final class SensorPrivacyManager { + /** Microphone */ + public static final int INDIVIDUAL_SENSOR_MICROPHONE = + SensorPrivacyIndividualEnabledSensorProto.MICROPHONE; + + /** Camera */ + public static final int INDIVIDUAL_SENSOR_CAMERA = + SensorPrivacyIndividualEnabledSensorProto.CAMERA; + + /** + * Individual sensors not listed in {@link Sensor} + * @hide + */ + @IntDef(prefix = "INDIVIDUAL_SENSOR_", value = { + INDIVIDUAL_SENSOR_MICROPHONE, + INDIVIDUAL_SENSOR_CAMERA + }) + @Retention(RetentionPolicy.SOURCE) + public @interface IndividualSensor {} + /** * A class implementing this interface can register with the {@link * android.hardware.SensorPrivacyManager} to receive notification when the sensor privacy @@ -168,4 +192,31 @@ public final class SensorPrivacyManager { throw e.rethrowFromSystemServer(); } } + + /** + * Returns whether sensor privacy is currently enabled for a specific sensor. + * + * @return true if sensor privacy is currently enabled, false otherwise. + */ + public boolean isIndividualSensorPrivacyEnabled(@IndividualSensor int sensor) { + try { + return mService.isIndividualSensorPrivacyEnabled(sensor); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Sets sensor privacy to the specified state for an individual sensor. + * + * @param enable the state to which sensor privacy should be set. + */ + @RequiresPermission(android.Manifest.permission.MANAGE_SENSOR_PRIVACY) + public void setIndividualSensorPrivacy(@IndividualSensor int sensor, boolean enable) { + try { + mService.setIndividualSensorPrivacy(sensor, enable); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } } diff --git a/core/java/android/hardware/camera2/CameraCaptureSession.java b/core/java/android/hardware/camera2/CameraCaptureSession.java index e8581595ad91..bd4746369811 100644 --- a/core/java/android/hardware/camera2/CameraCaptureSession.java +++ b/core/java/android/hardware/camera2/CameraCaptureSession.java @@ -964,12 +964,20 @@ public abstract class CameraCaptureSession implements AutoCloseable { * <p>Closing a session frees up the target output Surfaces of the session for reuse with either * a new session, or to other APIs that can draw to Surfaces.</p> * - * <p>Note that creating a new capture session with {@link CameraDevice#createCaptureSession} + * <p>Note that for common usage scenarios like creating a new session or closing the camera + * device, it is faster to call respective APIs directly (see below for more details) without + * calling into this method. This API is only useful when application wants to uncofigure the + * camera but keep the device open for later use.</p> + * + * <p>Creating a new capture session with {@link CameraDevice#createCaptureSession} * will close any existing capture session automatically, and call the older session listener's * {@link StateCallback#onClosed} callback. Using {@link CameraDevice#createCaptureSession} * directly without closing is the recommended approach for quickly switching to a new session, * since unchanged target outputs can be reused more efficiently.</p> * + * <p>Closing the device with {@link CameraDevice#close} directly without calling this API is + * also recommended for quickly closing the camera.</p> + * * <p>Once a session is closed, all methods on it will throw an IllegalStateException, and any * repeating requests or bursts are stopped (as if {@link #stopRepeating()} was called). * However, any in-progress capture requests submitted to the session will be completed as diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java index 8469f5f981ed..cdfdc1fdb2c3 100644 --- a/core/java/android/hardware/camera2/CameraManager.java +++ b/core/java/android/hardware/camera2/CameraManager.java @@ -20,6 +20,7 @@ import android.annotation.CallbackExecutor; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; +import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; import android.content.Context; @@ -850,13 +851,17 @@ public final class CameraManager { * A camera device has been opened by an application. * * <p>The default implementation of this method does nothing.</p> - * - * @param cameraId The unique identifier of the new camera. + * android.Manifest.permission.CAMERA_OPEN_CLOSE_LISTENER is required to receive this + * callback + * @param cameraId The unique identifier of the camera opened. * @param packageId The package Id of the application opening the camera. * * @see #onCameraClosed + * @hide */ - /** @hide */ + @SystemApi + @TestApi + @RequiresPermission(android.Manifest.permission.CAMERA_OPEN_CLOSE_LISTENER) public void onCameraOpened(@NonNull String cameraId, @NonNull String packageId) { // default empty implementation } @@ -865,10 +870,14 @@ public final class CameraManager { * A previously-opened camera has been closed. * * <p>The default implementation of this method does nothing.</p> - * + * android.Manifest.permission.CAMERA_OPEN_CLOSE_LISTENER is required to receive this + * callback. * @param cameraId The unique identifier of the closed camera. + * @hide */ - /** @hide */ + @SystemApi + @TestApi + @RequiresPermission(android.Manifest.permission.CAMERA_OPEN_CLOSE_LISTENER) public void onCameraClosed(@NonNull String cameraId) { // default empty implementation } diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java index 7afba1a214b8..41cc12f3b2e3 100644 --- a/core/java/android/hardware/camera2/CameraMetadata.java +++ b/core/java/android/hardware/camera2/CameraMetadata.java @@ -2856,10 +2856,10 @@ public abstract class CameraMetadata<TKey> { * respective color channel provided in * {@link CaptureRequest#SENSOR_TEST_PATTERN_DATA android.sensor.testPatternData}.</p> * <p>For example:</p> - * <pre><code>android.testPatternData = [0, 0xFFFFFFFF, 0xFFFFFFFF, 0] + * <pre><code>android.control.testPatternData = [0, 0xFFFFFFFF, 0xFFFFFFFF, 0] * </code></pre> * <p>All green pixels are 100% green. All red/blue pixels are black.</p> - * <pre><code>android.testPatternData = [0xFFFFFFFF, 0, 0xFFFFFFFF, 0] + * <pre><code>android.control.testPatternData = [0xFFFFFFFF, 0, 0xFFFFFFFF, 0] * </code></pre> * <p>All red pixels are 100% red. Only the odd green pixels * are 100% green. All blue pixels are 100% black.</p> diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java index 19f4cd6e991a..5cc7bf8cefed 100644 --- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java +++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java @@ -1719,37 +1719,25 @@ public class CameraMetadataNative implements Parcelable { private static native long nativeAllocateCopy(long ptr) throws NullPointerException; - @FastNative private static synchronized native void nativeWriteToParcel(Parcel dest, long ptr); - @FastNative private static synchronized native void nativeReadFromParcel(Parcel source, long ptr); - @FastNative private static synchronized native void nativeSwap(long ptr, long otherPtr) throws NullPointerException; - @FastNative private static synchronized native void nativeClose(long ptr); - @FastNative private static synchronized native boolean nativeIsEmpty(long ptr); - @FastNative private static synchronized native int nativeGetEntryCount(long ptr); - @FastNative private static synchronized native long nativeGetBufferSize(long ptr); @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - @FastNative private static synchronized native byte[] nativeReadValues(int tag, long ptr); - @FastNative private static synchronized native void nativeWriteValues(int tag, byte[] src, long ptr); private static synchronized native void nativeDump(long ptr) throws IOException; // dump to LOGD - @FastNative private static synchronized native ArrayList nativeGetAllVendorKeys(long ptr, Class keyClass); @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - @FastNative private static synchronized native int nativeGetTagFromKeyLocal(long ptr, String keyName) throws IllegalArgumentException; @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - @FastNative private static synchronized native int nativeGetTypeFromTagLocal(long ptr, int tag) throws IllegalArgumentException; @FastNative diff --git a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java index c6007f1184f5..a8cafef844f1 100644 --- a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java +++ b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java @@ -19,6 +19,7 @@ package android.hardware.hdmi; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.hardware.hdmi.HdmiControlManager.HdmiCecVersion; import android.os.Parcel; import android.os.Parcelable; @@ -107,6 +108,8 @@ public class HdmiDeviceInfo implements Parcelable { // CEC only parameters. private final int mLogicalAddress; private final int mDeviceType; + @HdmiCecVersion + private final int mHdmiCecVersion; private final int mVendorId; private final String mDisplayName; private final int mDevicePowerStatus; @@ -133,8 +136,9 @@ public class HdmiDeviceInfo implements Parcelable { int vendorId = source.readInt(); int powerStatus = source.readInt(); String displayName = source.readString(); + int cecVersion = source.readInt(); return new HdmiDeviceInfo(logicalAddress, physicalAddress, portId, - deviceType, vendorId, displayName, powerStatus); + deviceType, vendorId, displayName, powerStatus, cecVersion); case HDMI_DEVICE_TYPE_MHL: int deviceId = source.readInt(); int adopterId = source.readInt(); @@ -167,7 +171,7 @@ public class HdmiDeviceInfo implements Parcelable { * @hide */ public HdmiDeviceInfo(int logicalAddress, int physicalAddress, int portId, int deviceType, - int vendorId, String displayName, int powerStatus) { + int vendorId, String displayName, int powerStatus, int hdmiCecVersion) { mHdmiDeviceType = HDMI_DEVICE_TYPE_CEC; mPhysicalAddress = physicalAddress; mPortId = portId; @@ -175,6 +179,7 @@ public class HdmiDeviceInfo implements Parcelable { mId = idForCecDevice(logicalAddress); mLogicalAddress = logicalAddress; mDeviceType = deviceType; + mHdmiCecVersion = hdmiCecVersion; mVendorId = vendorId; mDevicePowerStatus = powerStatus; mDisplayName = displayName; @@ -192,12 +197,31 @@ public class HdmiDeviceInfo implements Parcelable { * @param deviceType type of device * @param vendorId vendor id of device. Used for vendor specific command. * @param displayName name of device + * @param powerStatus device power status + * @hide + */ + public HdmiDeviceInfo(int logicalAddress, int physicalAddress, int portId, int deviceType, + int vendorId, String displayName, int powerStatus) { + this(logicalAddress, physicalAddress, portId, deviceType, + vendorId, displayName, powerStatus, HdmiControlManager.HDMI_CEC_VERSION_1_4_b); + } + + /** + * Constructor. Used to initialize the instance for CEC device. + * + * @param logicalAddress logical address of HDMI-CEC device + * @param physicalAddress physical address of HDMI-CEC device + * @param portId HDMI port ID (1 for HDMI1) + * @param deviceType type of device + * @param vendorId vendor id of device. Used for vendor specific command. + * @param displayName name of device * @hide */ public HdmiDeviceInfo(int logicalAddress, int physicalAddress, int portId, int deviceType, int vendorId, String displayName) { this(logicalAddress, physicalAddress, portId, deviceType, - vendorId, displayName, HdmiControlManager.POWER_STATUS_UNKNOWN); + vendorId, displayName, HdmiControlManager.POWER_STATUS_UNKNOWN, + HdmiControlManager.HDMI_CEC_VERSION_1_4_b); } /** @@ -215,6 +239,7 @@ public class HdmiDeviceInfo implements Parcelable { mId = idForHardware(portId); mLogicalAddress = -1; mDeviceType = DEVICE_RESERVED; + mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_b; mVendorId = 0; mDevicePowerStatus = HdmiControlManager.POWER_STATUS_UNKNOWN; mDisplayName = "HDMI" + portId; @@ -240,6 +265,7 @@ public class HdmiDeviceInfo implements Parcelable { mId = idForMhlDevice(portId); mLogicalAddress = -1; mDeviceType = DEVICE_RESERVED; + mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_b; mVendorId = 0; mDevicePowerStatus = HdmiControlManager.POWER_STATUS_UNKNOWN; mDisplayName = "Mobile"; @@ -261,6 +287,7 @@ public class HdmiDeviceInfo implements Parcelable { mLogicalAddress = -1; mDeviceType = DEVICE_INACTIVE; + mHdmiCecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_b; mPortId = PORT_INVALID; mDevicePowerStatus = HdmiControlManager.POWER_STATUS_UNKNOWN; mDisplayName = "Inactive"; @@ -339,6 +366,16 @@ public class HdmiDeviceInfo implements Parcelable { } /** + * Returns the CEC version the device supports. + * + * @hide + */ + @HdmiCecVersion + public int getCecVersion() { + return mHdmiCecVersion; + } + + /** * Returns device's power status. It should be one of the following values. * <ul> * <li>{@link HdmiControlManager#POWER_STATUS_ON} @@ -448,6 +485,7 @@ public class HdmiDeviceInfo implements Parcelable { dest.writeInt(mVendorId); dest.writeInt(mDevicePowerStatus); dest.writeString(mDisplayName); + dest.writeInt(mHdmiCecVersion); break; case HDMI_DEVICE_TYPE_MHL: dest.writeInt(mDeviceId); @@ -470,6 +508,7 @@ public class HdmiDeviceInfo implements Parcelable { s.append("logical_address: ").append(String.format("0x%02X", mLogicalAddress)); s.append(" "); s.append("device_type: ").append(mDeviceType).append(" "); + s.append("cec_version: ").append(mHdmiCecVersion).append(" "); s.append("vendor_id: ").append(mVendorId).append(" "); s.append("display_name: ").append(mDisplayName).append(" "); s.append("power_status: ").append(mDevicePowerStatus).append(" "); @@ -507,6 +546,7 @@ public class HdmiDeviceInfo implements Parcelable { && mPortId == other.mPortId && mLogicalAddress == other.mLogicalAddress && mDeviceType == other.mDeviceType + && mHdmiCecVersion == other.mHdmiCecVersion && mVendorId == other.mVendorId && mDevicePowerStatus == other.mDevicePowerStatus && mDisplayName.equals(other.mDisplayName) @@ -522,6 +562,7 @@ public class HdmiDeviceInfo implements Parcelable { mPortId, mLogicalAddress, mDeviceType, + mHdmiCecVersion, mVendorId, mDevicePowerStatus, mDisplayName, diff --git a/core/java/android/hardware/hdmi/HdmiPortInfo.java b/core/java/android/hardware/hdmi/HdmiPortInfo.java index e4b311a64c31..625a6a53d9ce 100644 --- a/core/java/android/hardware/hdmi/HdmiPortInfo.java +++ b/core/java/android/hardware/hdmi/HdmiPortInfo.java @@ -192,6 +192,7 @@ public final class HdmiPortInfo implements Parcelable { @Override public int hashCode() { - return mId; + return java.util.Objects.hash( + mId, mType, mAddress, mCecSupported, mArcSupported, mMhlSupported); } } diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java index 0676ad4e2322..6780167fa63e 100644 --- a/core/java/android/net/NetworkAgent.java +++ b/core/java/android/net/NetworkAgent.java @@ -51,7 +51,7 @@ import java.util.concurrent.atomic.AtomicBoolean; * An agent manages the life cycle of a network. A network starts its * life cycle when {@link register} is called on NetworkAgent. The network * is then connecting. When full L3 connectivity has been established, - * the agent shoud call {@link markConnected} to inform the system that + * the agent should call {@link markConnected} to inform the system that * this network is ready to use. When the network disconnects its life * ends and the agent should call {@link unregister}, at which point the * system will clean up and free resources. @@ -94,12 +94,6 @@ public abstract class NetworkAgent { @Nullable private volatile Network mNetwork; - // Whether this NetworkAgent is using the legacy (never unhidden) API. The difference is - // that the legacy API uses NetworkInfo to convey the state, while the current API is - // exposing methods to manage it and generate it internally instead. - // TODO : remove this as soon as all agents have been converted. - private final boolean mIsLegacy; - private final Handler mHandler; private volatile AsyncChannel mAsyncChannel; private final String LOG_TAG; @@ -110,8 +104,6 @@ public abstract class NetworkAgent { private static final long BW_REFRESH_MIN_WIN_MS = 500; private boolean mBandwidthUpdateScheduled = false; private AtomicBoolean mBandwidthUpdatePending = new AtomicBoolean(false); - // Not used by legacy agents. Non-legacy agents use this to convert the NetworkAgent system API - // into the internal API of ConnectivityService. @NonNull private NetworkInfo mNetworkInfo; @NonNull @@ -337,35 +329,6 @@ public abstract class NetworkAgent { */ public static final int CMD_REMOVE_KEEPALIVE_PACKET_FILTER = BASE + 17; - /** @hide TODO: remove and replace usage with the public constructor. */ - public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, - NetworkCapabilities nc, LinkProperties lp, int score) { - this(looper, context, logTag, ni, nc, lp, score, null, NetworkProvider.ID_NONE); - // Register done by the constructor called in the previous line - } - - /** @hide TODO: remove and replace usage with the public constructor. */ - public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, - NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config) { - this(looper, context, logTag, ni, nc, lp, score, config, NetworkProvider.ID_NONE); - // Register done by the constructor called in the previous line - } - - /** @hide TODO: remove and replace usage with the public constructor. */ - public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, - NetworkCapabilities nc, LinkProperties lp, int score, int providerId) { - this(looper, context, logTag, ni, nc, lp, score, null, providerId); - // Register done by the constructor called in the previous line - } - - /** @hide TODO: remove and replace usage with the public constructor. */ - public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni, - NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config, - int providerId) { - this(looper, context, logTag, nc, lp, score, config, providerId, ni, true /* legacy */); - register(); - } - private static NetworkInfo getLegacyNetworkInfo(final NetworkAgentConfig config) { // The subtype can be changed with (TODO) setLegacySubtype, but it starts // with 0 (TelephonyManager.NETWORK_TYPE_UNKNOWN) and an empty description. @@ -393,7 +356,7 @@ public abstract class NetworkAgent { @NonNull NetworkAgentConfig config, @Nullable NetworkProvider provider) { this(looper, context, logTag, nc, lp, score, config, provider == null ? NetworkProvider.ID_NONE : provider.getProviderId(), - getLegacyNetworkInfo(config), false /* legacy */); + getLegacyNetworkInfo(config)); } private static class InitialConfiguration { @@ -418,11 +381,9 @@ public abstract class NetworkAgent { private NetworkAgent(@NonNull Looper looper, @NonNull Context context, @NonNull String logTag, @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, int score, - @NonNull NetworkAgentConfig config, int providerId, @NonNull NetworkInfo ni, - boolean legacy) { + @NonNull NetworkAgentConfig config, int providerId, @NonNull NetworkInfo ni) { mHandler = new NetworkAgentHandler(looper); LOG_TAG = logTag; - mIsLegacy = legacy; mNetworkInfo = new NetworkInfo(ni); this.providerId = providerId; if (ni == null || nc == null || lp == null) { @@ -696,11 +657,6 @@ public abstract class NetworkAgent { * Call {@link #unregister} to disconnect. */ public void markConnected() { - if (mIsLegacy) { - throw new UnsupportedOperationException( - "Legacy agents can't call markConnected."); - } - // |reason| cannot be used by the non-legacy agents mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null /* reason */, mNetworkInfo.getExtraInfo()); queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo); @@ -713,9 +669,6 @@ public abstract class NetworkAgent { * the network is torn down and this agent can no longer be used. */ public void unregister() { - if (mIsLegacy) { - throw new UnsupportedOperationException("Legacy agents can't call unregister."); - } // When unregistering an agent nobody should use the extrainfo (or reason) any more. mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null /* reason */, null /* extraInfo */); @@ -735,9 +688,6 @@ public abstract class NetworkAgent { */ @Deprecated public void setLegacySubtype(final int legacySubtype, @NonNull final String legacySubtypeName) { - if (mIsLegacy) { - throw new UnsupportedOperationException("Legacy agents can't call setLegacySubtype."); - } mNetworkInfo.setSubtype(legacySubtype, legacySubtypeName); queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo); } @@ -760,9 +710,6 @@ public abstract class NetworkAgent { */ @Deprecated public void setLegacyExtraInfo(@Nullable final String extraInfo) { - if (mIsLegacy) { - throw new UnsupportedOperationException("Legacy agents can't call setLegacyExtraInfo."); - } mNetworkInfo.setExtraInfo(extraInfo); queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, mNetworkInfo); } @@ -773,9 +720,6 @@ public abstract class NetworkAgent { */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) public final void sendNetworkInfo(NetworkInfo networkInfo) { - if (!mIsLegacy) { - throw new UnsupportedOperationException("Only legacy agents can call sendNetworkInfo."); - } queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, new NetworkInfo(networkInfo)); } diff --git a/core/java/android/net/OWNERS b/core/java/android/net/OWNERS index 2f8f685af40b..4ea8a54828b3 100644 --- a/core/java/android/net/OWNERS +++ b/core/java/android/net/OWNERS @@ -1,11 +1,5 @@ set noparent -codewiz@google.com -jchalard@google.com -jsharkey@google.com -junyulai@google.com -lorenzo@google.com -reminv@google.com -satk@google.com +include platform/frameworks/base:/services/core/java/com/android/server/net/OWNERS per-file SSL*, Uri*, Url* = prb@google.com, dauletz@google.com, narayan@google.com, ngeoffray@google.com diff --git a/core/java/android/net/TcpRepairWindow.java b/core/java/android/net/TcpRepairWindow.java index 86034f0a76ed..f062fa9034ea 100644 --- a/core/java/android/net/TcpRepairWindow.java +++ b/core/java/android/net/TcpRepairWindow.java @@ -16,12 +16,15 @@ package android.net; +import android.annotation.SystemApi; + /** * Corresponds to C's {@code struct tcp_repair_window} from * include/uapi/linux/tcp.h * * @hide */ +@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public final class TcpRepairWindow { public final int sndWl1; public final int sndWnd; diff --git a/core/java/android/os/BatteryConsumer.java b/core/java/android/os/BatteryConsumer.java index d00c3c361722..3956ef949ad5 100644 --- a/core/java/android/os/BatteryConsumer.java +++ b/core/java/android/os/BatteryConsumer.java @@ -42,13 +42,37 @@ public abstract class BatteryConsumer { public static @interface PowerComponent { } - public static final int POWER_COMPONENT_CPU = 0; + public static final int POWER_COMPONENT_USAGE = 0; + public static final int POWER_COMPONENT_CPU = 1; - public static final int POWER_COMPONENT_COUNT = 1; + public static final int POWER_COMPONENT_COUNT = 2; public static final int FIRST_CUSTOM_POWER_COMPONENT_ID = 1000; public static final int LAST_CUSTOM_POWER_COMPONENT_ID = 9999; + /** + * 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_CPU, + TIME_COMPONENT_CPU_FOREGROUND, + }) + @Retention(RetentionPolicy.SOURCE) + public static @interface TimeComponent { + } + + public static final int TIME_COMPONENT_USAGE = 0; + public static final int TIME_COMPONENT_CPU = 1; + public static final int TIME_COMPONENT_CPU_FOREGROUND = 2; + + public static final int TIME_COMPONENT_COUNT = 3; + + public static final int FIRST_CUSTOM_TIME_COMPONENT_ID = 1000; + public static final int LAST_CUSTOM_TIME_COMPONENT_ID = 9999; + private final PowerComponents mPowerComponents; protected BatteryConsumer(@NonNull PowerComponents powerComponents) { @@ -83,7 +107,106 @@ public abstract class BatteryConsumer { return mPowerComponents.getConsumedPowerForCustomComponent(componentId); } + /** + * Returns the amount of time since BatteryStats reset 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}. + * @return Amount of time in milliseconds. + */ + public long getUsageDurationMillis(@TimeComponent int componentId) { + return mPowerComponents.getUsageDurationMillis(componentId); + } + + /** + * Returns the amount of usage time attributed to the specified custom component + * since BatteryStats reset. + * + * @param componentId The ID of the custom power component. + * @return Amount of time in milliseconds. + */ + public long getUsageDurationForCustomComponentMillis(int componentId) { + return mPowerComponents.getUsageDurationForCustomComponentMillis(componentId); + } + protected void writeToParcel(Parcel dest, int flags) { mPowerComponents.writeToParcel(dest, flags); } + + protected abstract static class BaseBuilder<T extends BaseBuilder<?>> { + final PowerComponents.Builder mPowerComponentsBuilder; + + public BaseBuilder(int customPowerComponentCount, int customTimeComponentCount) { + mPowerComponentsBuilder = new PowerComponents.Builder(customPowerComponentCount, + customTimeComponentCount); + } + + /** + * Sets the amount of drain attributed to the specified drain type, e.g. CPU, WiFi etc. + * + * @param componentId The ID of the power component, e.g. + * {@link BatteryConsumer#POWER_COMPONENT_CPU}. + * @param componentPower Amount of consumed power in mAh. + */ + @SuppressWarnings("unchecked") + @NonNull + public T setConsumedPower(@PowerComponent int componentId, double componentPower) { + mPowerComponentsBuilder.setConsumedPower(componentId, componentPower); + return (T) this; + } + + /** + * Sets the amount of drain attributed to the specified custom drain type. + * + * @param componentId The ID of the custom power component. + * @param componentPower Amount of consumed power in mAh. + */ + @SuppressWarnings("unchecked") + @NonNull + public T setConsumedPowerForCustomComponent(int componentId, double componentPower) { + mPowerComponentsBuilder.setConsumedPowerForCustomComponent(componentId, componentPower); + return (T) this; + } + + /** + * Sets the total amount of power consumed since BatteryStats reset, mAh. + */ + @SuppressWarnings("unchecked") + @NonNull + public T setConsumedPower(double consumedPower) { + mPowerComponentsBuilder.setTotalPowerConsumed(consumedPower); + return (T) this; + } + + /** + * Sets the amount of time used by the specified component, e.g. CPU, WiFi etc. + * + * @param componentId The ID of the time component, e.g. + * {@link UidBatteryConsumer#TIME_COMPONENT_CPU}. + * @param componentUsageTimeMillis Amount of time in microseconds. + */ + @SuppressWarnings("unchecked") + @NonNull + public T setUsageDurationMillis(@UidBatteryConsumer.TimeComponent int componentId, + long componentUsageTimeMillis) { + mPowerComponentsBuilder.setUsageDurationMillis(componentId, componentUsageTimeMillis); + return (T) this; + } + + /** + * Sets the amount of time used by the specified custom component. + * + * @param componentId The ID of the custom power component. + * @param componentUsageTimeMillis Amount of time in microseconds. + */ + @SuppressWarnings("unchecked") + @NonNull + public T setUsageDurationForCustomComponentMillis(int componentId, + long componentUsageTimeMillis) { + mPowerComponentsBuilder.setUsageDurationForCustomComponentMillis(componentId, + componentUsageTimeMillis); + return (T) this; + } + } } diff --git a/core/java/android/os/BatteryUsageStats.java b/core/java/android/os/BatteryUsageStats.java index 3f036cdcfa72..af8e8de85d9f 100644 --- a/core/java/android/os/BatteryUsageStats.java +++ b/core/java/android/os/BatteryUsageStats.java @@ -18,6 +18,7 @@ package android.os; import android.annotation.NonNull; import android.annotation.SuppressLint; +import android.util.SparseArray; import java.util.ArrayList; import java.util.List; @@ -31,11 +32,21 @@ public final class BatteryUsageStats implements Parcelable { private final double mConsumedPower; private final int mDischargePercentage; private final ArrayList<UidBatteryConsumer> mUidBatteryConsumers; + private final ArrayList<SystemBatteryConsumer> mSystemBatteryConsumers; private BatteryUsageStats(@NonNull Builder builder) { mConsumedPower = builder.mConsumedPower; mDischargePercentage = builder.mDischargePercentage; - mUidBatteryConsumers = builder.mUidBatteryConsumers; + int uidBatteryConsumerCount = builder.mUidBatteryConsumerBuilders.size(); + mUidBatteryConsumers = new ArrayList<>(uidBatteryConsumerCount); + for (int i = 0; i < uidBatteryConsumerCount; i++) { + mUidBatteryConsumers.add(builder.mUidBatteryConsumerBuilders.valueAt(i).build()); + } + int systemBatteryConsumerCount = builder.mSystemBatteryConsumerBuilders.size(); + mSystemBatteryConsumers = new ArrayList<>(systemBatteryConsumerCount); + for (int i = 0; i < systemBatteryConsumerCount; i++) { + mSystemBatteryConsumers.add(builder.mSystemBatteryConsumerBuilders.valueAt(i).build()); + } } /** @@ -59,6 +70,11 @@ public final class BatteryUsageStats implements Parcelable { return mUidBatteryConsumers; } + @NonNull + public List<SystemBatteryConsumer> getSystemBatteryConsumers() { + return mSystemBatteryConsumers; + } + @Override public int describeContents() { return 0; @@ -67,6 +83,8 @@ public final class BatteryUsageStats implements Parcelable { private BatteryUsageStats(@NonNull Parcel source) { mUidBatteryConsumers = new ArrayList<>(); source.readParcelableList(mUidBatteryConsumers, getClass().getClassLoader()); + mSystemBatteryConsumers = new ArrayList<>(); + source.readParcelableList(mSystemBatteryConsumers, getClass().getClassLoader()); mConsumedPower = source.readDouble(); mDischargePercentage = source.readInt(); } @@ -74,6 +92,7 @@ public final class BatteryUsageStats implements Parcelable { @Override public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeParcelableList(mUidBatteryConsumers, flags); + dest.writeParcelableList(mSystemBatteryConsumers, flags); dest.writeDouble(mConsumedPower); dest.writeInt(mDischargePercentage); } @@ -93,9 +112,19 @@ public final class BatteryUsageStats implements Parcelable { * Builder for BatteryUsageStats. */ public static final class Builder { + private final int mCustomPowerComponentCount; + private final int mCustomTimeComponentCount; private double mConsumedPower; private int mDischargePercentage; - private final ArrayList<UidBatteryConsumer> mUidBatteryConsumers = new ArrayList<>(); + private final SparseArray<UidBatteryConsumer.Builder> mUidBatteryConsumerBuilders = + new SparseArray<>(); + private final SparseArray<SystemBatteryConsumer.Builder> mSystemBatteryConsumerBuilders = + new SparseArray<>(); + + public Builder(int customPowerComponentCount, int customTimeComponentCount) { + mCustomPowerComponentCount = customPowerComponentCount; + mCustomTimeComponentCount = customTimeComponentCount; + } /** * Constructs a read-only object using the Builder values. @@ -108,6 +137,7 @@ public final class BatteryUsageStats implements Parcelable { /** * Sets the battery discharge amount since BatteryStats reset as percentage of the full * charge. + * */ @SuppressLint("PercentageInt") // See b/174188159 @NonNull @@ -126,13 +156,41 @@ public final class BatteryUsageStats implements Parcelable { } /** - * Adds a UidBatteryConsumer, which represents battery attribution data for an - * individual UID. + * Creates or returns a exiting UidBatteryConsumer, which represents battery attribution + * data for an individual UID. */ @NonNull - public Builder addUidBatteryConsumer(@NonNull UidBatteryConsumer uidBatteryConsumer) { - mUidBatteryConsumers.add(uidBatteryConsumer); - return this; + public UidBatteryConsumer.Builder getOrCreateUidBatteryConsumerBuilder( + @NonNull BatteryStats.Uid batteryStatsUid) { + int uid = batteryStatsUid.getUid(); + UidBatteryConsumer.Builder builder = mUidBatteryConsumerBuilders.get(uid); + if (builder == null) { + builder = new UidBatteryConsumer.Builder(mCustomPowerComponentCount, + mCustomTimeComponentCount, batteryStatsUid); + mUidBatteryConsumerBuilders.put(uid, builder); + } + return builder; + } + + /** + * Creates or returns a exiting UidBatteryConsumer, which represents battery attribution + * data for an individual UID. + */ + @NonNull + public SystemBatteryConsumer.Builder getOrCreateSystemBatteryConsumerBuilder( + @SystemBatteryConsumer.DrainType int drainType) { + SystemBatteryConsumer.Builder builder = mSystemBatteryConsumerBuilders.get(drainType); + if (builder == null) { + builder = new SystemBatteryConsumer.Builder(mCustomPowerComponentCount, + mCustomTimeComponentCount, drainType); + mSystemBatteryConsumerBuilders.put(drainType, builder); + } + return builder; + } + + @NonNull + public SparseArray<UidBatteryConsumer.Builder> getUidBatteryConsumerBuilders() { + return mUidBatteryConsumerBuilders; } } } diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index bd18150da201..8148c457ec99 100755 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -107,12 +107,24 @@ public class Build { public static final String HARDWARE = getString("ro.hardware"); /** - * The hardware variant (SKU), if available. + * The SKU of the hardware (from the kernel command line). The SKU is reported by the bootloader + * to configure system software features. */ @NonNull public static final String SKU = getString("ro.boot.hardware.sku"); /** + * The SKU of the device as set by the original design manufacturer (ODM). This is a + * runtime-initialized property set during startup to configure device services. + * + * <p>The ODM SKU may have multiple variants for the same system SKU in case a manufacturer + * produces variants of the same design. For example, the same build may be released with + * variations in physical keyboard and/or display hardware, each with a different ODM SKU. + */ + @NonNull + public static final String ODM_SKU = getString("ro.boot.product.hardware.sku"); + + /** * Whether this build was for an emulator device. * @hide */ diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java index 379d6e6f5dfe..92fe98ca1044 100644 --- a/core/java/android/os/FileUtils.java +++ b/core/java/android/os/FileUtils.java @@ -1436,9 +1436,7 @@ public final class FileUtils { public static FileDescriptor convertToModernFd(FileDescriptor fd) { try { Context context = AppGlobals.getInitialApplication(); - // TODO(b/169327180): Consider device config. - if (!SystemProperties.getBoolean("persist.sys.fuse.transcode_enabled", false) - || !SystemProperties.getBoolean("persist.sys.fuse.transcode_optimize", true) + if (!SystemProperties.getBoolean("sys.fuse.transcode_enabled", false) || UserHandle.getAppId(Process.myUid()) == getMediaProviderAppId(context)) { // If transcode is enabled we optimize by default, unless explicitly disabled. // Never convert modern fd for MediaProvider, because this requires diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index e1d900528f07..25d84bab89e2 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -321,16 +321,6 @@ interface INetworkManagementService void setFirewallChainEnabled(int chain, boolean enable); /** - * Set all packets from users in ranges to go through VPN specified by netId. - */ - void addVpnUidRanges(int netId, in UidRange[] ranges); - - /** - * Clears the special VPN rules for users in ranges and VPN specified by netId. - */ - void removeVpnUidRanges(int netId, in UidRange[] ranges); - - /** * Start listening for mobile activity state changes. */ void registerNetworkActivityListener(INetworkActivityListener listener); @@ -361,7 +351,5 @@ interface INetworkManagementService void removeInterfaceFromLocalNetwork(String iface); int removeRoutesFromLocalNetwork(in List<RouteInfo> routes); - void setAllowOnlyVpnForUids(boolean enable, in UidRange[] uidRanges); - boolean isNetworkRestricted(int uid); } diff --git a/core/java/android/os/IVibratorManagerService.aidl b/core/java/android/os/IVibratorManagerService.aidl index 08d201977c49..804dc102c3f6 100644 --- a/core/java/android/os/IVibratorManagerService.aidl +++ b/core/java/android/os/IVibratorManagerService.aidl @@ -18,10 +18,14 @@ package android.os; import android.os.CombinedVibrationEffect; import android.os.VibrationAttributes; +import android.os.VibratorInfo; /** {@hide} */ interface IVibratorManagerService { int[] getVibratorIds(); + VibratorInfo getVibratorInfo(int vibratorId); + boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, + in CombinedVibrationEffect effect, in VibrationAttributes attributes); void vibrate(int uid, String opPkg, in CombinedVibrationEffect effect, in VibrationAttributes attributes, String reason, IBinder token); void cancelVibrate(IBinder token); diff --git a/core/java/android/os/IVibratorService.aidl b/core/java/android/os/IVibratorService.aidl index 615ae6593330..1cd48dcf797b 100644 --- a/core/java/android/os/IVibratorService.aidl +++ b/core/java/android/os/IVibratorService.aidl @@ -18,6 +18,7 @@ package android.os; import android.os.VibrationEffect; import android.os.VibrationAttributes; +import android.os.VibratorInfo; import android.os.IVibratorStateListener; /** {@hide} */ @@ -25,13 +26,10 @@ interface IVibratorService { boolean hasVibrator(); boolean isVibrating(); + VibratorInfo getVibratorInfo(); boolean registerVibratorStateListener(in IVibratorStateListener listener); boolean unregisterVibratorStateListener(in IVibratorStateListener listener); boolean hasAmplitudeControl(); - int[] areEffectsSupported(in int[] effectIds); - boolean[] arePrimitivesSupported(in int[] primitiveIds); - boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, in VibrationEffect effect, - in VibrationAttributes attributes); void vibrate(int uid, String opPkg, in VibrationEffect effect, in VibrationAttributes attributes, String reason, IBinder token); void cancelVibrate(IBinder token); diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS index d392d7170f2f..49451d9d0910 100644 --- a/core/java/android/os/OWNERS +++ b/core/java/android/os/OWNERS @@ -16,7 +16,19 @@ per-file IPowerManager.aidl = michaelwr@google.com, santoscordon@google.com per-file PowerManager.java = michaelwr@google.com, santoscordon@google.com per-file PowerManagerInternal.java = michaelwr@google.com, santoscordon@google.com +# BatteryStats +per-file *BatteryConsumer* = file:/BATTERY_STATS_OWNERS +per-file BatteryManager* = file:/BATTERY_STATS_OWNERS +per-file BatteryStats* = file:/BATTERY_STATS_OWNERS +per-file BatteryUsageStats* = file:/BATTERY_STATS_OWNERS +per-file PowerComponents.java = file:/BATTERY_STATS_OWNERS per-file GraphicsEnvironment.java = chrisforbes@google.com, cnorthrop@google.com, lpy@google.com, timvp@google.com, zzyiwei@google.com +per-file *Network* = file:/services/core/java/com/android/server/net/OWNERS +per-file *Power* = file:/services/core/java/com/android/server/power/OWNERS +per-file *Telephony* = file:/telephony/OWNERS per-file *Zygote* = file:/ZYGOTE_OWNERS + +# RecoverySystem +per-file *Recovery* = file:/services/core/java/com/android/server/recoverysystem/OWNERS diff --git a/core/java/android/os/PowerComponents.java b/core/java/android/os/PowerComponents.java index 42ba1ff60e5a..c18fff64ba62 100644 --- a/core/java/android/os/PowerComponents.java +++ b/core/java/android/os/PowerComponents.java @@ -29,21 +29,25 @@ class PowerComponents { private final double mTotalPowerConsumed; private final double[] mPowerComponents; + private final long[] mTimeComponents; PowerComponents(@NonNull Builder builder) { mTotalPowerConsumed = builder.mTotalPowerConsumed; mPowerComponents = builder.mPowerComponents; + mTimeComponents = builder.mTimeComponents; } PowerComponents(@NonNull Parcel source) { mTotalPowerConsumed = source.readDouble(); mPowerComponents = source.createDoubleArray(); + mTimeComponents = source.createLongArray(); } /** Writes contents to Parcel */ void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeDouble(mTotalPowerConsumed); dest.writeDoubleArray(mPowerComponents); + dest.writeLongArray(mTimeComponents); } /** @@ -94,15 +98,58 @@ class PowerComponents { } /** + * 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}. + * @return Amount of time in milliseconds. + */ + public long getUsageDurationMillis(@UidBatteryConsumer.TimeComponent int componentId) { + if (componentId >= UidBatteryConsumer.TIME_COMPONENT_COUNT) { + throw new IllegalArgumentException( + "Unsupported time component ID: " + componentId); + } + try { + return mTimeComponents[componentId]; + } catch (ArrayIndexOutOfBoundsException e) { + throw new IllegalArgumentException("Unsupported power component ID: " + componentId); + } + } + + /** + * Returns the amount of usage time attributed to the specified custom component. + * + * @param componentId The ID of the custom power component. + * @return Amount of time in milliseconds. + */ + public long getUsageDurationForCustomComponentMillis(int componentId) { + if (componentId < UidBatteryConsumer.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]; + } catch (ArrayIndexOutOfBoundsException e) { + throw new IllegalArgumentException( + "Unsupported custom time component ID: " + componentId); + } + } + + /** * Builder for PowerComponents. */ static final class Builder { private double mTotalPowerConsumed; private final double[] mPowerComponents; + private final long[] mTimeComponents; - Builder(int customPowerComponentCount) { - mPowerComponents = new double[BatteryConsumer.POWER_COMPONENT_COUNT + Builder(int customPowerComponentCount, int customTimeComponentCount) { + mPowerComponents = new double[UidBatteryConsumer.POWER_COMPONENT_COUNT + customPowerComponentCount]; + mTimeComponents = new long[UidBatteryConsumer.TIME_COMPONENT_COUNT + + customTimeComponentCount]; } /** @@ -160,6 +207,53 @@ class PowerComponents { } /** + * Sets the amount of time used by the specified component, e.g. CPU, WiFi etc. + * + * @param componentId The ID of the time component, e.g. + * {@link UidBatteryConsumer#TIME_COMPONENT_CPU}. + * @param componentUsageDurationMillis Amount of time in milliseconds. + */ + @NonNull + public Builder setUsageDurationMillis(@UidBatteryConsumer.TimeComponent int componentId, + long componentUsageDurationMillis) { + if (componentId >= UidBatteryConsumer.TIME_COMPONENT_COUNT) { + throw new IllegalArgumentException( + "Unsupported time component ID: " + componentId); + } + try { + mTimeComponents[componentId] = componentUsageDurationMillis; + } catch (ArrayIndexOutOfBoundsException e) { + throw new IllegalArgumentException( + "Unsupported time component ID: " + componentId); + } + return this; + } + + /** + * Sets the amount of time used by the specified custom component. + * + * @param componentId The ID of the custom power component. + * @param componentUsageDurationMillis Amount of time in milliseconds. + */ + @NonNull + public Builder setUsageDurationForCustomComponentMillis(int componentId, + long componentUsageDurationMillis) { + if (componentId < UidBatteryConsumer.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] = + componentUsageDurationMillis; + } catch (ArrayIndexOutOfBoundsException e) { + throw new IllegalArgumentException( + "Unsupported custom time component ID: " + componentId); + } + return this; + } + + /** * Creates a read-only object out of the Builder values. */ @NonNull diff --git a/core/java/android/os/RemoteException.java b/core/java/android/os/RemoteException.java index 98c66d1beaf4..e9fc2f38072b 100644 --- a/core/java/android/os/RemoteException.java +++ b/core/java/android/os/RemoteException.java @@ -37,6 +37,11 @@ public class RemoteException extends AndroidException { super(message, cause, enableSuppression, writableStackTrace); } + /** @hide */ + public RemoteException(Throwable cause) { + this(cause.getMessage(), cause, true, false); + } + /** * Rethrow this as an unchecked runtime exception. * <p> diff --git a/core/java/android/os/StatFs.java b/core/java/android/os/StatFs.java index eb8e71761294..bb6066e78a52 100644 --- a/core/java/android/os/StatFs.java +++ b/core/java/android/os/StatFs.java @@ -109,7 +109,7 @@ public class StatFs { * The total number of blocks that are free on the file system, including * reserved blocks (that are not available to normal applications). This * corresponds to the Unix {@code statvfs.f_bfree} field. Most applications - * will want to use {@link #getAvailableBlocks()} instead. + * will want to use {@link #getAvailableBlocksLong()} instead. */ public long getFreeBlocksLong() { return mStat.f_bfree; diff --git a/core/java/android/os/SystemBatteryConsumer.java b/core/java/android/os/SystemBatteryConsumer.java new file mode 100644 index 000000000000..570a2dc6aebf --- /dev/null +++ b/core/java/android/os/SystemBatteryConsumer.java @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os; + +import android.annotation.IntDef; +import android.annotation.NonNull; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + + +/** + * Contains power consumption data attributed to a system-wide drain type. + * + * {@hide} + */ +public class SystemBatteryConsumer extends BatteryConsumer implements Parcelable { + + // **************** + // This list must be kept current with atoms.proto (frameworks/base/cmds/statsd/src/atoms.proto) + // so the constant values must never change. + // **************** + @IntDef(prefix = {"DRAIN_TYPE_"}, value = { + DRAIN_TYPE_AMBIENT_DISPLAY, + // Reserved: APP + DRAIN_TYPE_BLUETOOTH, + DRAIN_TYPE_CAMERA, + DRAIN_TYPE_CELL, + DRAIN_TYPE_FLASHLIGHT, + DRAIN_TYPE_IDLE, + DRAIN_TYPE_MEMORY, + DRAIN_TYPE_OVERCOUNTED, + DRAIN_TYPE_PHONE, + DRAIN_TYPE_SCREEN, + DRAIN_TYPE_UNACCOUNTED, + // Reserved: USER, + DRAIN_TYPE_WIFI, + }) + @Retention(RetentionPolicy.SOURCE) + public static @interface DrainType { + } + + public static final int DRAIN_TYPE_AMBIENT_DISPLAY = 0; + public static final int DRAIN_TYPE_BLUETOOTH = 2; + public static final int DRAIN_TYPE_CAMERA = 3; + public static final int DRAIN_TYPE_CELL = 4; + public static final int DRAIN_TYPE_FLASHLIGHT = 5; + public static final int DRAIN_TYPE_IDLE = 6; + public static final int DRAIN_TYPE_MEMORY = 7; + public static final int DRAIN_TYPE_OVERCOUNTED = 8; + public static final int DRAIN_TYPE_PHONE = 9; + public static final int DRAIN_TYPE_SCREEN = 10; + public static final int DRAIN_TYPE_UNACCOUNTED = 11; + public static final int DRAIN_TYPE_WIFI = 13; + + @DrainType + private final int mDrainType; + + @DrainType + public int getDrainType() { + return mDrainType; + } + + private SystemBatteryConsumer(@NonNull SystemBatteryConsumer.Builder builder) { + super(builder.mPowerComponentsBuilder.build()); + mDrainType = builder.mDrainType; + } + + private SystemBatteryConsumer(Parcel in) { + super(new PowerComponents(in)); + mDrainType = in.readInt(); + } + + /** + * Writes the contents into a Parcel. + */ + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + super.writeToParcel(dest, flags); + dest.writeInt(mDrainType); + } + + public static final Creator<SystemBatteryConsumer> CREATOR = + new Creator<SystemBatteryConsumer>() { + @Override + public SystemBatteryConsumer createFromParcel(Parcel in) { + return new SystemBatteryConsumer(in); + } + + @Override + public SystemBatteryConsumer[] newArray(int size) { + return new SystemBatteryConsumer[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + /** + * Builder for SystemBatteryConsumer. + */ + public static final class Builder extends BaseBuilder<Builder> { + @DrainType + private final int mDrainType; + + Builder(int customPowerComponentCount, int customTimeComponentCount, + @DrainType int drainType) { + super(customPowerComponentCount, customTimeComponentCount); + mDrainType = drainType; + } + + /** + * Creates a read-only object out of the Builder values. + */ + @NonNull + public SystemBatteryConsumer build() { + return new SystemBatteryConsumer(this); + } + } +} diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java index 5c9067ac3c3e..0330500f0997 100644 --- a/core/java/android/os/SystemVibrator.java +++ b/core/java/android/os/SystemVibrator.java @@ -18,6 +18,7 @@ package android.os; import android.annotation.CallbackExecutor; import android.annotation.NonNull; +import android.annotation.Nullable; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.media.AudioAttributes; @@ -38,8 +39,12 @@ public class SystemVibrator extends Vibrator { private static final String TAG = "Vibrator"; private final IVibratorService mService; + private final IVibratorManagerService mManagerService; + private final Object mLock = new Object(); private final Binder mToken = new Binder(); private final Context mContext; + @GuardedBy("mLock") + private VibratorInfo mVibratorInfo; @GuardedBy("mDelegates") private final ArrayMap<OnVibratorStateChangedListener, @@ -49,6 +54,8 @@ public class SystemVibrator extends Vibrator { public SystemVibrator() { mContext = null; mService = IVibratorService.Stub.asInterface(ServiceManager.getService("vibrator")); + mManagerService = IVibratorManagerService.Stub.asInterface( + ServiceManager.getService("vibrator_manager")); } @UnsupportedAppUsage @@ -56,6 +63,8 @@ public class SystemVibrator extends Vibrator { super(context); mContext = context; mService = IVibratorService.Stub.asInterface(ServiceManager.getService("vibrator")); + mManagerService = IVibratorManagerService.Stub.asInterface( + ServiceManager.getService("vibrator_manager")); } @Override @@ -207,13 +216,14 @@ public class SystemVibrator extends Vibrator { @Override public boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, VibrationEffect effect, AudioAttributes attributes) { - if (mService == null) { + if (mManagerService == null) { Log.w(TAG, "Failed to set always-on effect; no vibrator service."); return false; } try { VibrationAttributes atr = new VibrationAttributes.Builder(attributes, effect).build(); - return mService.setAlwaysOnEffect(uid, opPkg, alwaysOnId, effect, atr); + CombinedVibrationEffect combinedEffect = CombinedVibrationEffect.createSynced(effect); + return mManagerService.setAlwaysOnEffect(uid, opPkg, alwaysOnId, combinedEffect, atr); } catch (RemoteException e) { Log.w(TAG, "Failed to set always-on effect.", e); } @@ -236,26 +246,28 @@ public class SystemVibrator extends Vibrator { @Override public int[] areEffectsSupported(@VibrationEffect.EffectType int... effectIds) { - try { - return mService.areEffectsSupported(effectIds); - } catch (RemoteException e) { - Log.w(TAG, "Failed to query effect support"); - throw e.rethrowAsRuntimeException(); + VibratorInfo vibratorInfo = getVibratorInfo(); + int[] supported = new int[effectIds.length]; + for (int i = 0; i < effectIds.length; i++) { + supported[i] = vibratorInfo == null + ? Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN + : vibratorInfo.isEffectSupported(effectIds[i]); } + return supported; } @Override public boolean[] arePrimitivesSupported( @NonNull @VibrationEffect.Composition.Primitive int... primitiveIds) { - try { - return mService.arePrimitivesSupported(primitiveIds); - } catch (RemoteException e) { - Log.w(TAG, "Failed to query effect support"); - throw e.rethrowAsRuntimeException(); + VibratorInfo vibratorInfo = getVibratorInfo(); + boolean[] supported = new boolean[primitiveIds.length]; + for (int i = 0; i < primitiveIds.length; i++) { + supported[i] = vibratorInfo == null + ? false : vibratorInfo.isPrimitiveSupported(primitiveIds[i]); } + return supported; } - @Override public void cancel() { if (mService == null) { @@ -267,4 +279,22 @@ public class SystemVibrator extends Vibrator { Log.w(TAG, "Failed to cancel vibration.", e); } } + + @Nullable + private VibratorInfo getVibratorInfo() { + try { + synchronized (mLock) { + if (mVibratorInfo != null) { + return mVibratorInfo; + } + if (mService == null) { + return null; + } + return mVibratorInfo = mService.getVibratorInfo(); + } + } catch (RemoteException e) { + Log.w(TAG, "Failed to query vibrator info"); + throw e.rethrowFromSystemServer(); + } + } } diff --git a/core/java/android/os/UidBatteryConsumer.java b/core/java/android/os/UidBatteryConsumer.java index 7dcbf7d4cef3..06cf4a688ae1 100644 --- a/core/java/android/os/UidBatteryConsumer.java +++ b/core/java/android/os/UidBatteryConsumer.java @@ -80,56 +80,32 @@ public final class UidBatteryConsumer extends BatteryConsumer implements Parcela /** * Builder for UidBatteryConsumer. */ - public static final class Builder { - private final PowerComponents.Builder mPowerComponentsBuilder; + public static final class Builder extends BaseBuilder<Builder> { + private final BatteryStats.Uid mBatteryStatsUid; private final int mUid; private String mPackageWithHighestDrain; - public Builder(int customPowerComponentCount, int uid) { - mPowerComponentsBuilder = new PowerComponents.Builder(customPowerComponentCount); - mUid = uid; + public Builder(int customPowerComponentCount, int customTimeComponentCount, + BatteryStats.Uid batteryStatsUid) { + super(customPowerComponentCount, customTimeComponentCount); + mBatteryStatsUid = batteryStatsUid; + mUid = batteryStatsUid.getUid(); } - /** - * Creates a read-only object out of the Builder values. - */ - @NonNull - public UidBatteryConsumer build() { - return new UidBatteryConsumer(this); - } - - /** - * Sets the amount of drain attributed to the specified drain type, e.g. CPU, WiFi etc. - * - * @param componentId The ID of the power component, e.g. - * {@link BatteryConsumer#POWER_COMPONENT_CPU}. - * @param componentPower Amount of consumed power in mAh. - */ - @NonNull - public Builder setConsumedPower(@PowerComponent int componentId, double componentPower) { - mPowerComponentsBuilder.setConsumedPower(componentId, componentPower); - return this; + public BatteryStats.Uid getBatteryStatsUid() { + return mBatteryStatsUid; } - /** - * Sets the amount of drain attributed to the specified custom drain type. - * - * @param componentId The ID of the custom power component. - * @param componentPower Amount of consumed power in mAh. - */ - @NonNull - public Builder setConsumedPowerForCustomComponent(int componentId, double componentPower) { - mPowerComponentsBuilder.setConsumedPowerForCustomComponent(componentId, componentPower); - return this; + public int getUid() { + return mUid; } /** - * Sets the amount of power consumed since BatteryStats reset, mAh. + * Creates a read-only object out of the Builder values. */ @NonNull - public Builder setConsumedPower(double consumedPower) { - mPowerComponentsBuilder.setTotalPowerConsumed(consumedPower); - return this; + public UidBatteryConsumer build() { + return new UidBatteryConsumer(this); } /** diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java index d6720248720a..7e50ebc419dd 100644 --- a/core/java/android/os/UserHandle.java +++ b/core/java/android/os/UserHandle.java @@ -223,6 +223,14 @@ public final class UserHandle implements Parcelable { } /** + * Whether a UID belongs to a shared app gid. + * @hide + */ + public static boolean isSharedAppGid(int uid) { + return getAppIdFromSharedAppGid(uid) != -1; + } + + /** * Returns the user for a given uid. * @param uid A uid for an application running in a particular user. * @return A {@link UserHandle} for that user. diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java index f76eb86f0fca..b57418d751bc 100644 --- a/core/java/android/os/VibrationEffect.java +++ b/core/java/android/os/VibrationEffect.java @@ -477,6 +477,28 @@ public abstract class VibrationEffect implements Parcelable { } /** @hide */ + public static String effectIdToString(int effectId) { + switch (effectId) { + case EFFECT_CLICK: + return "CLICK"; + case EFFECT_TICK: + return "TICK"; + case EFFECT_HEAVY_CLICK: + return "HEAVY_CLICK"; + case EFFECT_DOUBLE_CLICK: + return "DOUBLE_CLICK"; + case EFFECT_POP: + return "POP"; + case EFFECT_THUD: + return "THUD"; + case EFFECT_TEXTURE_TICK: + return "TEXTURE_TICK"; + default: + return Integer.toString(effectId); + } + } + + /** @hide */ @TestApi public static class OneShot extends VibrationEffect implements Parcelable { private final long mDuration; @@ -1201,10 +1223,8 @@ public abstract class VibrationEffect implements Parcelable { return "PRIMITIVE_QUICK_FALL"; case PRIMITIVE_TICK: return "PRIMITIVE_TICK"; - default: return Integer.toString(id); - } } diff --git a/core/java/android/os/VibratorInfo.aidl b/core/java/android/os/VibratorInfo.aidl new file mode 100644 index 000000000000..9a7cb1303b93 --- /dev/null +++ b/core/java/android/os/VibratorInfo.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.os; + +parcelable VibratorInfo; diff --git a/core/java/android/os/VibratorInfo.java b/core/java/android/os/VibratorInfo.java new file mode 100644 index 000000000000..07272e756e77 --- /dev/null +++ b/core/java/android/os/VibratorInfo.java @@ -0,0 +1,229 @@ +/* + * 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.NonNull; +import android.annotation.Nullable; +import android.util.SparseBooleanArray; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + +/** + * A VibratorInfo describes the capabilities of a {@link Vibrator}. + * + * This description includes its capabilities, list of supported effects and composition primitives. + * + * @hide + */ +public final class VibratorInfo implements Parcelable { + + /** + * Capability to set amplitude values to vibrations. + * @hide + */ + // Internally this maps to the HAL constant IVibrator::CAP_AMPLITUDE_CONTROL + public static final int CAPABILITY_AMPLITUDE_CONTROL = 4; + + /** + * Capability to compose primitives into a single effect. + * @hide + */ + // Internally this maps to the HAL constant IVibrator::CAP_COMPOSE_EFFECTS + public static final int CAPABILITY_COMPOSE_EFFECTS = 32; + + private final int mId; + private final long mCapabilities; + @Nullable + private final SparseBooleanArray mSupportedEffects; + @Nullable + private final SparseBooleanArray mSupportedPrimitives; + + VibratorInfo(Parcel in) { + mId = in.readInt(); + mCapabilities = in.readLong(); + mSupportedEffects = in.readSparseBooleanArray(); + mSupportedPrimitives = in.readSparseBooleanArray(); + } + + /** @hide */ + public VibratorInfo(int id, long capabilities, int[] supportedEffects, + int[] supportedPrimitives) { + mId = id; + mCapabilities = capabilities; + mSupportedEffects = toSparseBooleanArray(supportedEffects); + mSupportedPrimitives = toSparseBooleanArray(supportedPrimitives); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mId); + dest.writeLong(mCapabilities); + dest.writeSparseBooleanArray(mSupportedEffects); + dest.writeSparseBooleanArray(mSupportedPrimitives); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof VibratorInfo)) { + return false; + } + VibratorInfo that = (VibratorInfo) o; + return mId == that.mId && mCapabilities == that.mCapabilities + && Objects.equals(mSupportedEffects, that.mSupportedEffects) + && Objects.equals(mSupportedPrimitives, that.mSupportedPrimitives); + } + + @Override + public int hashCode() { + return Objects.hash(mId, mCapabilities, mSupportedEffects, mSupportedPrimitives); + } + + @Override + public String toString() { + return "VibratorInfo{" + + "mId=" + mId + + ", mCapabilities=" + Arrays.toString(getCapabilitiesNames()) + + ", mCapabilities flags=" + mCapabilities + + ", mSupportedEffects=" + Arrays.toString(getSupportedEffectsNames()) + + ", mSupportedPrimitives=" + Arrays.toString(getSupportedPrimitivesNames()) + + '}'; + } + + /** Return the id of this vibrator. */ + public int getId() { + return mId; + } + + /** + * Check whether the vibrator has amplitude control. + * + * @return True if the hardware can control the amplitude of the vibrations, otherwise false. + */ + public boolean hasAmplitudeControl() { + return hasCapability(CAPABILITY_AMPLITUDE_CONTROL); + } + + /** + * Query whether the vibrator supports the given effect. + * + * @param effectId Which effects to query for. + * @return {@link Vibrator#VIBRATION_EFFECT_SUPPORT_YES} if the effect is supported, + * {@link Vibrator#VIBRATION_EFFECT_SUPPORT_NO} if it isn't supported, or + * {@link Vibrator#VIBRATION_EFFECT_SUPPORT_UNKNOWN} if the system can't determine whether it's + * supported or not. + */ + @Vibrator.VibrationEffectSupport + public int isEffectSupported(@VibrationEffect.EffectType int effectId) { + if (mSupportedEffects == null) { + return Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN; + } + return mSupportedEffects.get(effectId, false) ? Vibrator.VIBRATION_EFFECT_SUPPORT_YES + : Vibrator.VIBRATION_EFFECT_SUPPORT_NO; + } + + /** + * Query whether the vibrator supports the given primitive. + * + * @param primitiveId Which primitives to query for. + * @return Whether the primitive is supported. + */ + public boolean isPrimitiveSupported(@VibrationEffect.Composition.Primitive int primitiveId) { + return hasCapability(CAPABILITY_COMPOSE_EFFECTS) && mSupportedPrimitives != null + && mSupportedPrimitives.get(primitiveId, false); + } + + /** + * Check against this vibrator capabilities. + * + * @param capability one of IVibrator.CAP_* + * @return true if this vibrator has this capability, false otherwise + * @hide + */ + public boolean hasCapability(long capability) { + return (mCapabilities & capability) == capability; + } + + private String[] getCapabilitiesNames() { + List<String> names = new ArrayList<>(); + if (hasCapability(CAPABILITY_AMPLITUDE_CONTROL)) { + names.add("AMPLITUDE_CONTROL"); + } + if (hasCapability(CAPABILITY_COMPOSE_EFFECTS)) { + names.add("COMPOSE_EFFECTS"); + } + return names.toArray(new String[names.size()]); + } + + private String[] getSupportedEffectsNames() { + if (mSupportedEffects == null) { + return new String[0]; + } + String[] names = new String[mSupportedEffects.size()]; + for (int i = 0; i < mSupportedEffects.size(); i++) { + names[i] = VibrationEffect.effectIdToString(mSupportedEffects.keyAt(i)); + } + return names; + } + + private String[] getSupportedPrimitivesNames() { + if (mSupportedPrimitives == null) { + return new String[0]; + } + String[] names = new String[mSupportedPrimitives.size()]; + for (int i = 0; i < mSupportedPrimitives.size(); i++) { + names[i] = VibrationEffect.Composition.primitiveToString(mSupportedPrimitives.keyAt(i)); + } + return names; + } + + @Nullable + private static SparseBooleanArray toSparseBooleanArray(int[] values) { + if (values == null) { + return null; + } + SparseBooleanArray array = new SparseBooleanArray(); + for (int value : values) { + array.put(value, true); + } + return array; + } + + @NonNull + public static final Creator<VibratorInfo> CREATOR = + new Creator<VibratorInfo>() { + @Override + public VibratorInfo createFromParcel(Parcel in) { + return new VibratorInfo(in); + } + + @Override + public VibratorInfo[] newArray(int size) { + return new VibratorInfo[size]; + } + }; +} diff --git a/core/java/android/permission/ILegacyPermissionManager.aidl b/core/java/android/permission/ILegacyPermissionManager.aidl new file mode 100644 index 000000000000..3bd4bf549df0 --- /dev/null +++ b/core/java/android/permission/ILegacyPermissionManager.aidl @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.permission; + +import android.content.pm.ParceledListSlice; +import android.content.pm.PermissionGroupInfo; +import android.content.pm.PermissionInfo; +import android.content.pm.permission.SplitPermissionInfoParcelable; +import android.os.UserHandle; +import android.permission.IOnPermissionsChangeListener; + +/** + * Interface to communicate directly with the legacy permission manager service. + * + * @see PermissionManager + * @hide + */ +interface ILegacyPermissionManager { + int checkDeviceIdentifierAccess(String packageName, String callingFeatureId, String message, int pid, int uid); + + void grantDefaultPermissionsToEnabledCarrierApps(in String[] packageNames, int userId); + + void grantDefaultPermissionsToEnabledImsServices(in String[] packageNames, int userId); + + void grantDefaultPermissionsToEnabledTelephonyDataServices( + in String[] packageNames, int userId); + + void revokeDefaultPermissionsFromDisabledTelephonyDataServices( + in String[] packageNames, int userId); + + void grantDefaultPermissionsToActiveLuiApp(in String packageName, int userId); + + void revokeDefaultPermissionsFromLuiApps(in String[] packageNames, int userId); +} diff --git a/core/java/android/permission/IPermissionManager.aidl b/core/java/android/permission/IPermissionManager.aidl index a94077dd7ad6..4ad17ef58945 100644 --- a/core/java/android/permission/IPermissionManager.aidl +++ b/core/java/android/permission/IPermissionManager.aidl @@ -52,8 +52,6 @@ interface IPermissionManager { int checkUidPermission(String permName, int uid); - int checkDeviceIdentifierAccess(String packageName, String callingFeatureId, String message, int pid, int uid); - void addOnPermissionsChangeListener(in IOnPermissionsChangeListener listener); void removeOnPermissionsChangeListener(in IOnPermissionsChangeListener listener); @@ -73,20 +71,6 @@ interface IPermissionManager { void resetRuntimePermissions(); - void grantDefaultPermissionsToEnabledCarrierApps(in String[] packageNames, int userId); - - void grantDefaultPermissionsToEnabledImsServices(in String[] packageNames, int userId); - - void grantDefaultPermissionsToEnabledTelephonyDataServices( - in String[] packageNames, int userId); - - void revokeDefaultPermissionsFromDisabledTelephonyDataServices( - in String[] packageNames, int userId); - - void grantDefaultPermissionsToActiveLuiApp(in String packageName, int userId); - - void revokeDefaultPermissionsFromLuiApps(in String[] packageNames, int userId); - boolean shouldShowRequestPermissionRationale(String permName, String packageName, int userId); diff --git a/core/java/android/permission/LegacyPermissionManager.java b/core/java/android/permission/LegacyPermissionManager.java new file mode 100644 index 000000000000..b66dd82965d3 --- /dev/null +++ b/core/java/android/permission/LegacyPermissionManager.java @@ -0,0 +1,217 @@ +/* + * 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.permission; + +import android.Manifest; +import android.annotation.CallbackExecutor; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.RequiresPermission; +import android.annotation.SystemService; +import android.content.Context; +import android.content.pm.PackageManager; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.UserHandle; + +import com.android.internal.annotations.VisibleForTesting; + +import java.util.concurrent.Executor; +import java.util.function.Consumer; + +/** + * System level service for accessing the permission capabilities of the platform, version 2. + * + * @hide + */ +//@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) +@SystemService(Context.LEGACY_PERMISSION_SERVICE) +public final class LegacyPermissionManager { + private final ILegacyPermissionManager mLegacyPermissionManager; + + /** + * Creates a new instance. + * + * @hide + */ + public LegacyPermissionManager() throws ServiceManager.ServiceNotFoundException { + this(ILegacyPermissionManager.Stub.asInterface(ServiceManager.getServiceOrThrow( + "legacy_permission"))); + } + + /** + * Creates a new instance with the provided instantiation of the ILegacyPermissionManager. + * + * @param legacyPermissionManager injectable legacy permission manager service + * + * @hide + */ + @VisibleForTesting + public LegacyPermissionManager(@NonNull ILegacyPermissionManager legacyPermissionManager) { + mLegacyPermissionManager = legacyPermissionManager; + } + + /** + * Checks whether the package with the given pid/uid can read device identifiers. + * + * @param packageName the name of the package to be checked for identifier access + * @param message the message to be used for logging during identifier access + * verification + * @param callingFeatureId the feature in the package + * @param pid the process id of the package to be checked + * @param uid the uid of the package to be checked + * @return {@link PackageManager#PERMISSION_GRANTED} if the package is allowed identifier + * access, {@link PackageManager#PERMISSION_DENIED} otherwise + * @hide + */ + //@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public int checkDeviceIdentifierAccess(@Nullable String packageName, @Nullable String message, + @Nullable String callingFeatureId, int pid, int uid) { + try { + return mLegacyPermissionManager.checkDeviceIdentifierAccess(packageName, message, + callingFeatureId, pid, uid); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Grant default permissions to currently active LUI app + * @param packageName The package name for the LUI app + * @param user The user handle + * @param executor The executor for the callback + * @param callback The callback provided by caller to be notified when grant completes + * @hide + */ + @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS) + public void grantDefaultPermissionsToLuiApp( + @NonNull String packageName, @NonNull UserHandle user, + @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) { + try { + mLegacyPermissionManager.grantDefaultPermissionsToActiveLuiApp( + packageName, user.getIdentifier()); + executor.execute(() -> callback.accept(true)); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + /** + * Revoke default permissions to currently active LUI app + * @param packageNames The package names for the LUI apps + * @param user The user handle + * @param executor The executor for the callback + * @param callback The callback provided by caller to be notified when grant completes + * @hide + */ + @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS) + public void revokeDefaultPermissionsFromLuiApps( + @NonNull String[] packageNames, @NonNull UserHandle user, + @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) { + try { + mLegacyPermissionManager.revokeDefaultPermissionsFromLuiApps( + packageNames, user.getIdentifier()); + executor.execute(() -> callback.accept(true)); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + /** + * Grant default permissions to currently active Ims services + * @param packageNames The package names for the Ims services + * @param user The user handle + * @param executor The executor for the callback + * @param callback The callback provided by caller to be notified when grant completes + * @hide + */ + @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS) + public void grantDefaultPermissionsToEnabledImsServices( + @NonNull String[] packageNames, @NonNull UserHandle user, + @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) { + try { + mLegacyPermissionManager.grantDefaultPermissionsToEnabledImsServices( + packageNames, user.getIdentifier()); + executor.execute(() -> callback.accept(true)); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + /** + * Grant default permissions to currently enabled telephony data services + * @param packageNames The package name for the services + * @param user The user handle + * @param executor The executor for the callback + * @param callback The callback provided by caller to be notified when grant completes + * @hide + */ + @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS) + public void grantDefaultPermissionsToEnabledTelephonyDataServices( + @NonNull String[] packageNames, @NonNull UserHandle user, + @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) { + try { + mLegacyPermissionManager.grantDefaultPermissionsToEnabledTelephonyDataServices( + packageNames, user.getIdentifier()); + executor.execute(() -> callback.accept(true)); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + /** + * Revoke default permissions to currently active telephony data services + * @param packageNames The package name for the services + * @param user The user handle + * @param executor The executor for the callback + * @param callback The callback provided by caller to be notified when revoke completes + * @hide + */ + @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS) + public void revokeDefaultPermissionsFromDisabledTelephonyDataServices( + @NonNull String[] packageNames, @NonNull UserHandle user, + @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) { + try { + mLegacyPermissionManager.revokeDefaultPermissionsFromDisabledTelephonyDataServices( + packageNames, user.getIdentifier()); + executor.execute(() -> callback.accept(true)); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } + + /** + * Grant default permissions to currently enabled carrier apps + * @param packageNames Package names of the apps to be granted permissions + * @param user The user handle + * @param executor The executor for the callback + * @param callback The callback provided by caller to be notified when grant completes + * @hide + */ + @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS) + public void grantDefaultPermissionsToEnabledCarrierApps(@NonNull String[] packageNames, + @NonNull UserHandle user, @NonNull @CallbackExecutor Executor executor, + @NonNull Consumer<Boolean> callback) { + try { + mLegacyPermissionManager.grantDefaultPermissionsToEnabledCarrierApps(packageNames, + user.getIdentifier()); + executor.execute(() -> callback.accept(true)); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + } +} diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java index e4220dd00a5b..d31e0129fb27 100644 --- a/core/java/android/permission/PermissionManager.java +++ b/core/java/android/permission/PermissionManager.java @@ -19,7 +19,7 @@ package android.permission; import static android.os.Build.VERSION_CODES.S; import android.Manifest; -import android.annotation.CallbackExecutor; +import android.annotation.CheckResult; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; @@ -29,6 +29,7 @@ import android.annotation.SystemService; import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.ActivityThread; +import android.app.AppGlobals; import android.app.IActivityManager; import android.app.PropertyInvalidatedCache; import android.compat.annotation.ChangeId; @@ -36,15 +37,25 @@ import android.compat.annotation.EnabledAfter; import android.content.Context; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; +import android.content.pm.ParceledListSlice; +import android.content.pm.PermissionGroupInfo; +import android.content.pm.PermissionInfo; import android.content.pm.permission.SplitPermissionInfoParcelable; +import android.os.Build; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; +import android.util.ArrayMap; +import android.util.ArraySet; +import android.util.DebugUtils; +import android.util.Log; import android.util.Slog; import com.android.internal.annotations.Immutable; -import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.CollectionUtils; import java.util.ArrayList; @@ -52,8 +63,6 @@ import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Set; -import java.util.concurrent.Executor; -import java.util.function.Consumer; /** * System level service for accessing the permission capabilities of the platform. @@ -63,7 +72,7 @@ import java.util.function.Consumer; @SystemApi @SystemService(Context.PERMISSION_SERVICE) public final class PermissionManager { - private static final String TAG = PermissionManager.class.getName(); + private static final String LOG_TAG = PermissionManager.class.getName(); /** @hide */ public static final String KILL_APP_REASON_PERMISSIONS_REVOKED = @@ -83,244 +92,765 @@ public final class PermissionManager { @EnabledAfter(targetSdkVersion = S) public static final long CANNOT_INSTALL_WITH_BAD_PERMISSION_GROUPS = 146211400; + /** + * Note: Changing this won't do anything on its own - you should also change the filtering in + * {@link #shouldTraceGrant}. + * + * @hide + */ + public static final boolean DEBUG_TRACE_GRANTS = false; + /** + * @hide + */ + public static final boolean DEBUG_TRACE_PERMISSION_UPDATES = false; + private final @NonNull Context mContext; private final IPackageManager mPackageManager; private final IPermissionManager mPermissionManager; + private final LegacyPermissionManager mLegacyPermissionManager; + + private final ArrayMap<PackageManager.OnPermissionsChangedListener, + IOnPermissionsChangeListener> mPermissionListeners = new ArrayMap<>(); + private List<SplitPermissionInfo> mSplitPermissionInfos; /** * Creates a new instance. * - * @param context The current context in which to operate. + * @param context The current context in which to operate + * * @hide */ - public PermissionManager(@NonNull Context context, IPackageManager packageManager) + public PermissionManager(@NonNull Context context) throws ServiceManager.ServiceNotFoundException { - this(context, packageManager, IPermissionManager.Stub.asInterface( - ServiceManager.getServiceOrThrow("permissionmgr"))); + mContext = context; + mPackageManager = AppGlobals.getPackageManager(); + mPermissionManager = IPermissionManager.Stub.asInterface(ServiceManager.getServiceOrThrow( + "permissionmgr")); + mLegacyPermissionManager = context.getSystemService(LegacyPermissionManager.class); + } + + /** + * Retrieve all of the information we know about a particular permission. + * + * @param permissionName the fully qualified name (e.g. com.android.permission.LOGIN) of the + * permission you are interested in + * @param flags additional option flags to modify the data returned + * @return a {@link PermissionInfo} containing information about the permission, or {@code null} + * if not found + * + * @hide Pending API + */ + @Nullable + public PermissionInfo getPermissionInfo(@NonNull String permissionName, + @PackageManager.PermissionInfoFlags int flags) { + try { + final String packageName = mContext.getOpPackageName(); + return mPermissionManager.getPermissionInfo(permissionName, packageName, flags); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Query for all of the permissions associated with a particular group. + * + * @param groupName the fully qualified name (e.g. com.android.permission.LOGIN) of the + * permission group you are interested in. Use {@code null} to find all of the + * permissions not associated with a group + * @param flags additional option flags to modify the data returned + * @return a list of {@link PermissionInfo} containing information about all of the permissions + * in the given group, or {@code null} if the group is not found + * + * @hide Pending API + */ + @Nullable + public List<PermissionInfo> queryPermissionsByGroup(@NonNull String groupName, + @PackageManager.PermissionInfoFlags int flags) { + try { + final ParceledListSlice<PermissionInfo> parceledList = + mPermissionManager.queryPermissionsByGroup(groupName, flags); + if (parceledList == null) { + return null; + } + return parceledList.getList(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Add a new dynamic permission to the system. For this to work, your package must have defined + * a permission tree through the + * {@link android.R.styleable#AndroidManifestPermissionTree <permission-tree>} tag in its + * manifest. A package can only add permissions to trees that were defined by either its own + * package or another with the same user id; a permission is in a tree if it matches the name of + * the permission tree + ".": for example, "com.foo.bar" is a member of the permission tree + * "com.foo". + * <p> + * It is good to make your permission tree name descriptive, because you are taking possession + * of that entire set of permission names. Thus, it must be under a domain you control, with a + * suffix that will not match any normal permissions that may be declared in any applications + * that are part of that domain. + * <p> + * New permissions must be added before any .apks are installed that use those permissions. + * Permissions you add through this method are remembered across reboots of the device. If the + * given permission already exists, the info you supply here will be used to update it. + * + * @param permissionInfo description of the permission to be added + * @param async whether the persistence of the permission should be asynchronous, allowing it to + * return quicker and batch a series of adds, at the expense of no guarantee the + * added permission will be retained if the device is rebooted before it is + * written. + * @return {@code true} if a new permission was created, {@code false} if an existing one was + * updated + * @throws SecurityException if you are not allowed to add the given permission name + * + * @see #removePermission(String) + * + * @hide Pending API + */ + public boolean addPermission(@NonNull PermissionInfo permissionInfo, boolean async) { + try { + return mPermissionManager.addPermission(permissionInfo, async); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Removes a permission that was previously added with + * {@link #addPermission(PermissionInfo, boolean)}. The same ownership rules apply -- you are + * only allowed to remove permissions that you are allowed to add. + * + * @param permissionName the name of the permission to remove + * @throws SecurityException if you are not allowed to remove the given permission name + * + * @see #addPermission(PermissionInfo, boolean) + * + * @hide Pending API + */ + public void removePermission(@NonNull String permissionName) { + try { + mPermissionManager.removePermission(permissionName); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Retrieve all of the information we know about a particular group of permissions. + * + * @param groupName the fully qualified name (e.g. com.android.permission_group.APPS) of the + * permission you are interested in + * @param flags additional option flags to modify the data returned + * @return a {@link PermissionGroupInfo} containing information about the permission, or + * {@code null} if not found + * + * @hide Pending API + */ + @Nullable + public PermissionGroupInfo getPermissionGroupInfo(@NonNull String groupName, + @PackageManager.PermissionGroupInfoFlags int flags) { + try { + return mPermissionManager.getPermissionGroupInfo(groupName, flags); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Retrieve all of the known permission groups in the system. + * + * @param flags additional option flags to modify the data returned + * @return a list of {@link PermissionGroupInfo} containing information about all of the known + * permission groups + * + * @hide Pending API + */ + @NonNull + public List<PermissionGroupInfo> getAllPermissionGroups( + @PackageManager.PermissionGroupInfoFlags int flags) { + try { + final ParceledListSlice<PermissionGroupInfo> parceledList = + mPermissionManager.getAllPermissionGroups(flags); + if (parceledList == null) { + return Collections.emptyList(); + } + return parceledList.getList(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Checks whether a particular permissions has been revoked for a package by policy. Typically + * the device owner or the profile owner may apply such a policy. The user cannot grant policy + * revoked permissions, hence the only way for an app to get such a permission is by a policy + * change. + * + * @param packageName the name of the package you are checking against + * @param permissionName the name of the permission you are checking for + * + * @return whether the permission is restricted by policy + * + * @hide Pending API + */ + @CheckResult + public boolean isPermissionRevokedByPolicy(@NonNull String packageName, + @NonNull String permissionName) { + try { + return mPermissionManager.isPermissionRevokedByPolicy(permissionName, packageName, + mContext.getUserId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** @hide */ + public static boolean shouldTraceGrant(String packageName, String permissionName, int userId) { + // To be modified when debugging + return false; } /** - * Creates a new instance with the provided instantiation of the IPermissionManager. + * Grant a runtime permission to an application which the application does not already have. The + * permission must have been requested by the application. If the application is not allowed to + * hold the permission, a {@link java.lang.SecurityException} is thrown. If the package or + * permission is invalid, a {@link java.lang.IllegalArgumentException} is thrown. + * <p> + * <strong>Note: </strong>Using this API requires holding + * {@code android.permission.GRANT_RUNTIME_PERMISSIONS} and if the user ID is not the current + * user {@code android.permission.INTERACT_ACROSS_USERS_FULL}. + * + * @param packageName the package to which to grant the permission + * @param permissionName the permission name to grant + * @param user the user for which to grant the permission + * + * @see #revokeRuntimePermission(String, String, android.os.UserHandle) * - * @param context the current context in which to operate - * @param packageManager package manager service to be used for package related permission - * requests - * @param permissionManager injectable permission manager service * @hide */ - @VisibleForTesting - public PermissionManager(@NonNull Context context, IPackageManager packageManager, - IPermissionManager permissionManager) { - mContext = context; - mPackageManager = packageManager; - mPermissionManager = permissionManager; + @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) + //@SystemApi + public void grantRuntimePermission(@NonNull String packageName, + @NonNull String permissionName, @NonNull UserHandle user) { + if (DEBUG_TRACE_GRANTS + && shouldTraceGrant(packageName, permissionName, user.getIdentifier())) { + Log.i(LOG_TAG, "App " + mContext.getPackageName() + " is granting " + packageName + " " + + permissionName + " for user " + user.getIdentifier(), new RuntimeException()); + } + try { + mPermissionManager.grantRuntimePermission(packageName, permissionName, + user.getIdentifier()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** - * Gets the version of the runtime permission database. + * Revoke a runtime permission that was previously granted by + * {@link #grantRuntimePermission(String, String, android.os.UserHandle)}. The permission must + * have been requested by and granted to the application. If the application is not allowed to + * hold the permission, a {@link java.lang.SecurityException} is thrown. If the package or + * permission is invalid, a {@link java.lang.IllegalArgumentException} is thrown. + * <p> + * <strong>Note: </strong>Using this API requires holding + * {@code android.permission.REVOKE_RUNTIME_PERMISSIONS} and if the user ID is not the current + * user {@code android.permission.INTERACT_ACROSS_USERS_FULL}. * - * @return The database version, -1 when this is an upgrade from pre-Q, 0 when this is a fresh - * install. + * @param packageName the package from which to revoke the permission + * @param permName the permission name to revoke + * @param user the user for which to revoke the permission + * @param reason the reason for the revoke, or {@code null} for unspecified + * + * @see #grantRuntimePermission(String, String, android.os.UserHandle) * * @hide */ - @SystemApi + @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS) + //@SystemApi + public void revokeRuntimePermission(@NonNull String packageName, + @NonNull String permName, @NonNull UserHandle user, @Nullable String reason) { + if (DEBUG_TRACE_PERMISSION_UPDATES + && shouldTraceGrant(packageName, permName, user.getIdentifier())) { + Log.i(LOG_TAG, "App " + mContext.getPackageName() + " is revoking " + packageName + " " + + permName + " for user " + user.getIdentifier() + " with reason " + + reason, new RuntimeException()); + } + try { + mPermissionManager + .revokeRuntimePermission(packageName, permName, user.getIdentifier(), reason); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Gets the state flags associated with a permission. + * + * @param packageName the package name for which to get the flags + * @param permissionName the permission for which to get the flags + * @param user the user for which to get permission flags + * @return the permission flags + * + * @hide + */ + @PackageManager.PermissionFlags @RequiresPermission(anyOf = { - Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY, - Manifest.permission.UPGRADE_RUNTIME_PERMISSIONS + android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, + android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, + android.Manifest.permission.GET_RUNTIME_PERMISSIONS }) - public @IntRange(from = 0) int getRuntimePermissionsVersion() { + //@SystemApi + public int getPermissionFlags(@NonNull String packageName, @NonNull String permissionName, + @NonNull UserHandle user) { try { - return mPackageManager.getRuntimePermissionsVersion(mContext.getUserId()); + return mPermissionManager.getPermissionFlags(permissionName, packageName, + user.getIdentifier()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** - * Sets the version of the runtime permission database. + * Updates the flags associated with a permission by replacing the flags in the specified mask + * with the provided flag values. * - * @param version The new version. + * @param packageName The package name for which to update the flags + * @param permissionName The permission for which to update the flags + * @param flagMask The flags which to replace + * @param flagValues The flags with which to replace + * @param user The user for which to update the permission flags * * @hide */ - @SystemApi @RequiresPermission(anyOf = { - Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY, - Manifest.permission.UPGRADE_RUNTIME_PERMISSIONS + android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, + android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS }) - public void setRuntimePermissionsVersion(@IntRange(from = 0) int version) { + //@SystemApi + public void updatePermissionFlags(@NonNull String packageName, @NonNull String permissionName, + @PackageManager.PermissionFlags int flagMask, + @PackageManager.PermissionFlags int flagValues, @NonNull UserHandle user) { + if (DEBUG_TRACE_PERMISSION_UPDATES && shouldTraceGrant(packageName, permissionName, + user.getIdentifier())) { + Log.i(LOG_TAG, "App " + mContext.getPackageName() + " is updating flags for " + + packageName + " " + permissionName + " for user " + + user.getIdentifier() + ": " + DebugUtils.flagsToString( + PackageManager.class, "FLAG_PERMISSION_", flagMask) + " := " + + DebugUtils.flagsToString(PackageManager.class, "FLAG_PERMISSION_", + flagValues), new RuntimeException()); + } try { - mPackageManager.setRuntimePermissionsVersion(version, mContext.getUserId()); + final boolean checkAdjustPolicyFlagPermission = + mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.Q; + mPermissionManager.updatePermissionFlags(permissionName, packageName, flagMask, + flagValues, checkAdjustPolicyFlagPermission, user.getIdentifier()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** - * Get set of permissions that have been split into more granular or dependent permissions. + * Gets the restricted permissions that have been allowlisted and the app is allowed to have + * them granted in their full form. + * <p> + * Permissions can be hard restricted which means that the app cannot hold them or soft + * restricted where the app can hold the permission but in a weaker form. Whether a permission + * is {@link PermissionInfo#FLAG_HARD_RESTRICTED hard restricted} or + * {@link PermissionInfo#FLAG_SOFT_RESTRICTED soft restricted} depends on the permission + * declaration. Allowlisting a hard restricted permission allows for the to hold that permission + * and allowlisting a soft restricted permission allows the app to hold the permission in its + * full, unrestricted form. + * <p> + * There are four allowlists: + * <ol> + * <li> + * One for cases where the system permission policy allowlists a permission. This list + * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM} flag. Can only be + * accessed by pre-installed holders of a dedicated permission. + * <li> + * One for cases where the system allowlists the permission when upgrading from an OS version in + * which the permission was not restricted to an OS version in which the permission is + * restricted. This list corresponds to the + * {@link PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE} flag. Can be accessed by + * pre-installed holders of a dedicated permission or the installer on record. + * <li> + * One for cases where the installer of the package allowlists a permission. This list + * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER} flag. Can be + * accessed by pre-installed holders of a dedicated permission or the installer on record. + * <li> + * One for cases where the system exempts the permission when granting a role. This list + * corresponds to the {@link PackageManager#FLAG_PERMISSION_ALLOWLIST_ROLE} flag. Can be + * accessed by pre-installed holders of a dedicated permission. + * </ol> * - * <p>E.g. before {@link android.os.Build.VERSION_CODES#Q} an app that was granted - * {@link Manifest.permission#ACCESS_COARSE_LOCATION} could access the location while it was in - * foreground and background. On platforms after {@link android.os.Build.VERSION_CODES#Q} - * the location permission only grants location access while the app is in foreground. This - * would break apps that target before {@link android.os.Build.VERSION_CODES#Q}. Hence whenever - * such an old app asks for a location permission (i.e. the - * {@link SplitPermissionInfo#getSplitPermission()}), then the - * {@link Manifest.permission#ACCESS_BACKGROUND_LOCATION} permission (inside - * {@link SplitPermissionInfo#getNewPermissions}) is added. + * @param packageName the app for which to get allowlisted permissions + * @param allowlistFlag the flag to determine which allowlist to query. Only one flag can be + * passed. + * @return the allowlisted permissions that are on any of the allowlists you query for + * @throws SecurityException if you try to access a allowlist that you have no access to * - * <p>Note: Regular apps do not have to worry about this. The platform and permission controller - * automatically add the new permissions where needed. + * @see #addAllowlistedRestrictedPermission(String, String, int) + * @see #removeAllowlistedRestrictedPermission(String, String, int) + * @see PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM + * @see PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE + * @see PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER + * @see PackageManager#FLAG_PERMISSION_ALLOWLIST_ROLE * - * @return All permissions that are split. + * @hide Pending API */ - public @NonNull List<SplitPermissionInfo> getSplitPermissions() { - if (mSplitPermissionInfos != null) { - return mSplitPermissionInfos; + @NonNull + @RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS, + conditional = true) + public Set<String> getAllowlistedRestrictedPermissions(@NonNull String packageName, + @PackageManager.PermissionWhitelistFlags int allowlistFlag) { + try { + final List<String> allowlist = mPermissionManager.getWhitelistedRestrictedPermissions( + packageName, allowlistFlag, mContext.getUserId()); + if (allowlist == null) { + return Collections.emptySet(); + } + return new ArraySet<>(allowlist); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); } + } - List<SplitPermissionInfoParcelable> parcelableList; + /** + * Adds a allowlisted restricted permission for an app. + * <p> + * Permissions can be hard restricted which means that the app cannot hold them or soft + * restricted where the app can hold the permission but in a weaker form. Whether a permission + * is {@link PermissionInfo#FLAG_HARD_RESTRICTED hard restricted} or + * {@link PermissionInfo#FLAG_SOFT_RESTRICTED soft restricted} depends on the permission + * declaration. Allowlisting a hard restricted permission allows for the to hold that permission + * and allowlisting a soft restricted permission allows the app to hold the permission in its + * full, unrestricted form. + * <p>There are four allowlists: + * <ol> + * <li> + * One for cases where the system permission policy allowlists a permission. This list + * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM} flag. Can only be + * accessed by pre-installed holders of a dedicated permission. + * <li> + * One for cases where the system allowlists the permission when upgrading from an OS version in + * which the permission was not restricted to an OS version in which the permission is + * restricted. This list corresponds to the + * {@link PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE} flag. Can be accessed by + * pre-installed holders of a dedicated permission or the installer on record. + * <li> + * One for cases where the installer of the package allowlists a permission. This list + * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER} flag. Can be + * accessed by pre-installed holders of a dedicated permission or the installer on record. + * <li> + * One for cases where the system exempts the permission when granting a role. This list + * corresponds to the {@link PackageManager#FLAG_PERMISSION_ALLOWLIST_ROLE} flag. Can be + * accessed by pre-installed holders of a dedicated permission. + * </ol> + * <p> + * You need to specify the allowlists for which to set the allowlisted permissions which will + * clear the previous allowlisted permissions and replace them with the provided ones. + * + * @param packageName the app for which to get allowlisted permissions + * @param permissionName the allowlisted permission to add + * @param allowlistFlags the allowlists to which to add. Passing multiple flags updates all + * specified allowlists. + * @return whether the permission was added to the allowlist + * @throws SecurityException if you try to modify a allowlist that you have no access to. + * + * @see #getAllowlistedRestrictedPermissions(String, int) + * @see #removeAllowlistedRestrictedPermission(String, String, int) + * @see PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM + * @see PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE + * @see PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER + * @see PackageManager#FLAG_PERMISSION_ALLOWLIST_ROLE + * + * @hide Pending API + */ + @RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS, + conditional = true) + public boolean addAllowlistedRestrictedPermission(@NonNull String packageName, + @NonNull String permissionName, + @PackageManager.PermissionWhitelistFlags int allowlistFlags) { try { - parcelableList = ActivityThread.getPermissionManager().getSplitPermissions(); + return mPermissionManager.addWhitelistedRestrictedPermission(packageName, + permissionName, allowlistFlags, mContext.getUserId()); } catch (RemoteException e) { - Slog.e(TAG, "Error getting split permissions", e); - return Collections.emptyList(); + throw e.rethrowFromSystemServer(); } + } - mSplitPermissionInfos = splitPermissionInfoListToNonParcelableList(parcelableList); - - return mSplitPermissionInfos; + /** + * Removes a allowlisted restricted permission for an app. + * <p> + * Permissions can be hard restricted which means that the app cannot hold them or soft + * restricted where the app can hold the permission but in a weaker form. Whether a permission + * is {@link PermissionInfo#FLAG_HARD_RESTRICTED hard restricted} or + * {@link PermissionInfo#FLAG_SOFT_RESTRICTED soft restricted} depends on the permission + * declaration. Allowlisting a hard restricted permission allows for the to hold that permission + * and allowlisting a soft restricted permission allows the app to hold the permission in its + * full, unrestricted form. + * <p>There are four allowlists: + * <ol> + * <li> + * One for cases where the system permission policy allowlists a permission. This list + * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM} flag. Can only be + * accessed by pre-installed holders of a dedicated permission. + * <li> + * One for cases where the system allowlists the permission when upgrading from an OS version in + * which the permission was not restricted to an OS version in which the permission is + * restricted. This list corresponds to the + * {@link PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE} flag. Can be accessed by + * pre-installed holders of a dedicated permission or the installer on record. + * <li> + * One for cases where the installer of the package allowlists a permission. This list + * corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER} flag. Can be + * accessed by pre-installed holders of a dedicated permission or the installer on record. + * <li> + * One for cases where the system exempts the permission when granting a role. This list + * corresponds to the {@link PackageManager#FLAG_PERMISSION_ALLOWLIST_ROLE} flag. Can be + * accessed by pre-installed holders of a dedicated permission. + * </ol> + * <p> + * You need to specify the allowlists for which to set the allowlisted permissions which will + * clear the previous allowlisted permissions and replace them with the provided ones. + * + * @param packageName the app for which to get allowlisted permissions + * @param permissionName the allowlisted permission to remove + * @param allowlistFlags the allowlists from which to remove. Passing multiple flags updates all + * specified allowlists. + * @return whether the permission was removed from the allowlist + * @throws SecurityException if you try to modify a allowlist that you have no access to. + * + * @see #getAllowlistedRestrictedPermissions(String, int) + * @see #addAllowlistedRestrictedPermission(String, String, int) + * @see PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM + * @see PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE + * @see PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER + * @see PackageManager#FLAG_PERMISSION_ALLOWLIST_ROLE + * + * @hide Pending API + */ + @RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS, + conditional = true) + public boolean removeAllowlistedRestrictedPermission(@NonNull String packageName, + @NonNull String permissionName, + @PackageManager.PermissionWhitelistFlags int allowlistFlags) { + try { + return mPermissionManager.removeWhitelistedRestrictedPermission(packageName, + permissionName, allowlistFlags, mContext.getUserId()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } } /** - * Grant default permissions to currently active LUI app - * @param packageName The package name for the LUI app - * @param user The user handle - * @param executor The executor for the callback - * @param callback The callback provided by caller to be notified when grant completes - * @hide + * Checks whether an application is exempted from having its permissions be automatically + * revoked when the app is unused for an extended period of time. + * <p> + * Only the installer on record that installed the given package, or a holder of + * {@code WHITELIST_AUTO_REVOKE_PERMISSIONS} is allowed to call this. + * + * @param packageName the app for which to set exemption + * @return whether the app is exempted + * @throws SecurityException if you you have no access to this + * + * @see #setAutoRevokeExempted + * + * @hide Pending API */ - @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS) - public void grantDefaultPermissionsToLuiApp( - @NonNull String packageName, @NonNull UserHandle user, - @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) { + @RequiresPermission(value = Manifest.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS, + conditional = true) + public boolean isAutoRevokeExempted(@NonNull String packageName) { try { - mPermissionManager.grantDefaultPermissionsToActiveLuiApp( - packageName, user.getIdentifier()); - executor.execute(() -> callback.accept(true)); + return mPermissionManager.isAutoRevokeWhitelisted(packageName, mContext.getUserId()); } catch (RemoteException e) { - e.rethrowFromSystemServer(); + throw e.rethrowFromSystemServer(); } } /** - * Revoke default permissions to currently active LUI app - * @param packageNames The package names for the LUI apps - * @param user The user handle - * @param executor The executor for the callback - * @param callback The callback provided by caller to be notified when grant completes - * @hide + * Marks an application exempted from having its permissions be automatically revoked when the + * app is unused for an extended period of time. + * <p> + * Only the installer on record that installed the given package is allowed to call this. + * <p> + * Packages start in exempted state, and it is the installer's responsibility to un-exempt the + * packages it installs, unless auto-revoking permissions from that package would cause + * breakages beyond having to re-request the permission(s). + * + * @param packageName the app for which to set exemption + * @param exempted whether the app should be exempted + * @return whether any change took effect + * @throws SecurityException if you you have no access to modify this + * + * @see #isAutoRevokeExempted + * + * @hide Pending API */ - @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS) - public void revokeDefaultPermissionsFromLuiApps( - @NonNull String[] packageNames, @NonNull UserHandle user, - @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) { + @RequiresPermission(value = Manifest.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS, + conditional = true) + public boolean setAutoRevokeExempted(@NonNull String packageName, boolean exempted) { try { - mPermissionManager.revokeDefaultPermissionsFromLuiApps( - packageNames, user.getIdentifier()); - executor.execute(() -> callback.accept(true)); + return mPermissionManager.setAutoRevokeWhitelisted(packageName, exempted, + mContext.getUserId()); } catch (RemoteException e) { - e.rethrowFromSystemServer(); + throw e.rethrowFromSystemServer(); } } /** - * Grant default permissions to currently active Ims services - * @param packageNames The package names for the Ims services - * @param user The user handle - * @param executor The executor for the callback - * @param callback The callback provided by caller to be notified when grant completes + * Get whether you should show UI with rationale for requesting a permission. You should do this + * only if you do not have the permission and the context in which the permission is requested + * does not clearly communicate to the user what would be the benefit from grating this + * permission. + * + * @param permissionName a permission your app wants to request + * @return whether you can show permission rationale UI + * * @hide */ - @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS) - public void grantDefaultPermissionsToEnabledImsServices( - @NonNull String[] packageNames, @NonNull UserHandle user, - @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) { + //@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + public boolean shouldShowRequestPermissionRationale(@NonNull String permissionName) { try { - mPermissionManager.grantDefaultPermissionsToEnabledImsServices( - packageNames, user.getIdentifier()); - executor.execute(() -> callback.accept(true)); + final String packageName = mContext.getPackageName(); + return mPermissionManager.shouldShowRequestPermissionRationale(permissionName, + packageName, mContext.getUserId()); } catch (RemoteException e) { - e.rethrowFromSystemServer(); + throw e.rethrowFromSystemServer(); + } + } + + /** + * Add a listener for permission changes for installed packages. + * + * @param listener the listener to add + * + * @hide + */ + //@SystemApi + @RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS) + public void addOnPermissionsChangeListener( + @NonNull PackageManager.OnPermissionsChangedListener listener) { + synchronized (mPermissionListeners) { + if (mPermissionListeners.get(listener) != null) { + return; + } + final OnPermissionsChangeListenerDelegate delegate = + new OnPermissionsChangeListenerDelegate(listener, Looper.getMainLooper()); + try { + mPermissionManager.addOnPermissionsChangeListener(delegate); + mPermissionListeners.put(listener, delegate); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + } + + /** + * Remove a listener for permission changes for installed packages. + * + * @param listener the listener to remove + * + * @hide + */ + //@SystemApi + @RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS) + public void removeOnPermissionsChangeListener( + @NonNull PackageManager.OnPermissionsChangedListener listener) { + synchronized (mPermissionListeners) { + final IOnPermissionsChangeListener delegate = mPermissionListeners.get(listener); + if (delegate != null) { + try { + mPermissionManager.removeOnPermissionsChangeListener(delegate); + mPermissionListeners.remove(listener); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } } } /** - * Grant default permissions to currently enabled telephony data services - * @param packageNames The package name for the services - * @param user The user handle - * @param executor The executor for the callback - * @param callback The callback provided by caller to be notified when grant completes + * Gets the version of the runtime permission database. + * + * @return The database version, -1 when this is an upgrade from pre-Q, 0 when this is a fresh + * install. + * * @hide */ - @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS) - public void grantDefaultPermissionsToEnabledTelephonyDataServices( - @NonNull String[] packageNames, @NonNull UserHandle user, - @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) { + @SystemApi + @RequiresPermission(anyOf = { + Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY, + Manifest.permission.UPGRADE_RUNTIME_PERMISSIONS + }) + public @IntRange(from = 0) int getRuntimePermissionsVersion() { try { - mPermissionManager.grantDefaultPermissionsToEnabledTelephonyDataServices( - packageNames, user.getIdentifier()); - executor.execute(() -> callback.accept(true)); + return mPackageManager.getRuntimePermissionsVersion(mContext.getUserId()); } catch (RemoteException e) { - e.rethrowFromSystemServer(); + throw e.rethrowFromSystemServer(); } } /** - * Revoke default permissions to currently active telephony data services - * @param packageNames The package name for the services - * @param user The user handle - * @param executor The executor for the callback - * @param callback The callback provided by caller to be notified when revoke completes + * Sets the version of the runtime permission database. + * + * @param version The new version. + * * @hide */ - @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS) - public void revokeDefaultPermissionsFromDisabledTelephonyDataServices( - @NonNull String[] packageNames, @NonNull UserHandle user, - @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) { + @SystemApi + @RequiresPermission(anyOf = { + Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY, + Manifest.permission.UPGRADE_RUNTIME_PERMISSIONS + }) + public void setRuntimePermissionsVersion(@IntRange(from = 0) int version) { try { - mPermissionManager.revokeDefaultPermissionsFromDisabledTelephonyDataServices( - packageNames, user.getIdentifier()); - executor.execute(() -> callback.accept(true)); + mPackageManager.setRuntimePermissionsVersion(version, mContext.getUserId()); } catch (RemoteException e) { - e.rethrowFromSystemServer(); + throw e.rethrowFromSystemServer(); } } /** - * Grant default permissions to currently enabled carrier apps - * @param packageNames Package names of the apps to be granted permissions - * @param user The user handle - * @param executor The executor for the callback - * @param callback The callback provided by caller to be notified when grant completes - * @hide + * Get set of permissions that have been split into more granular or dependent permissions. + * + * <p>E.g. before {@link android.os.Build.VERSION_CODES#Q} an app that was granted + * {@link Manifest.permission#ACCESS_COARSE_LOCATION} could access the location while it was in + * foreground and background. On platforms after {@link android.os.Build.VERSION_CODES#Q} + * the location permission only grants location access while the app is in foreground. This + * would break apps that target before {@link android.os.Build.VERSION_CODES#Q}. Hence whenever + * such an old app asks for a location permission (i.e. the + * {@link SplitPermissionInfo#getSplitPermission()}), then the + * {@link Manifest.permission#ACCESS_BACKGROUND_LOCATION} permission (inside + * {@link SplitPermissionInfo#getNewPermissions}) is added. + * + * <p>Note: Regular apps do not have to worry about this. The platform and permission controller + * automatically add the new permissions where needed. + * + * @return All permissions that are split. */ - @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS) - public void grantDefaultPermissionsToEnabledCarrierApps(@NonNull String[] packageNames, - @NonNull UserHandle user, @NonNull @CallbackExecutor Executor executor, - @NonNull Consumer<Boolean> callback) { + public @NonNull List<SplitPermissionInfo> getSplitPermissions() { + if (mSplitPermissionInfos != null) { + return mSplitPermissionInfos; + } + + List<SplitPermissionInfoParcelable> parcelableList; try { - mPermissionManager.grantDefaultPermissionsToEnabledCarrierApps(packageNames, - user.getIdentifier()); - executor.execute(() -> callback.accept(true)); + parcelableList = ActivityThread.getPermissionManager().getSplitPermissions(); } catch (RemoteException e) { - e.rethrowFromSystemServer(); + Slog.e(LOG_TAG, "Error getting split permissions", e); + return Collections.emptyList(); } + + mSplitPermissionInfos = splitPermissionInfoListToNonParcelableList(parcelableList); + + return mSplitPermissionInfos; } /** @@ -530,12 +1060,8 @@ public final class PermissionManager { @SystemApi public int checkDeviceIdentifierAccess(@Nullable String packageName, @Nullable String message, @Nullable String callingFeatureId, int pid, int uid) { - try { - return mPermissionManager.checkDeviceIdentifierAccess(packageName, message, - callingFeatureId, pid, uid); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + return mLegacyPermissionManager.checkDeviceIdentifierAccess(packageName, message, + callingFeatureId, pid, uid); } /* @hide */ @@ -547,10 +1073,11 @@ public final class PermissionManager { // permission this is. final int appId = UserHandle.getAppId(uid); if (appId == Process.ROOT_UID || appId == Process.SYSTEM_UID) { - Slog.w(TAG, "Missing ActivityManager; assuming " + uid + " holds " + permission); + Slog.w(LOG_TAG, "Missing ActivityManager; assuming " + uid + " holds " + + permission); return PackageManager.PERMISSION_GRANTED; } - Slog.w(TAG, "Missing ActivityManager; assuming " + uid + " does not hold " + Slog.w(LOG_TAG, "Missing ActivityManager; assuming " + uid + " does not hold " + permission); return PackageManager.PERMISSION_DENIED; } @@ -730,4 +1257,35 @@ public final class PermissionManager { sPackageNamePermissionCache.disableLocal(); } + private final class OnPermissionsChangeListenerDelegate + extends IOnPermissionsChangeListener.Stub implements Handler.Callback{ + private static final int MSG_PERMISSIONS_CHANGED = 1; + + private final PackageManager.OnPermissionsChangedListener mListener; + private final Handler mHandler; + + public OnPermissionsChangeListenerDelegate( + PackageManager.OnPermissionsChangedListener listener, Looper looper) { + mListener = listener; + mHandler = new Handler(looper, this); + } + + @Override + public void onPermissionsChanged(int uid) { + mHandler.obtainMessage(MSG_PERMISSIONS_CHANGED, uid, 0).sendToTarget(); + } + + @Override + public boolean handleMessage(Message msg) { + switch (msg.what) { + case MSG_PERMISSIONS_CHANGED: { + final int uid = msg.arg1; + mListener.onPermissionsChanged(uid); + return true; + } + default: + return false; + } + } + } } diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java index 105ffaa4718e..d1aa48914e70 100644 --- a/core/java/android/provider/CallLog.java +++ b/core/java/android/provider/CallLog.java @@ -17,7 +17,14 @@ package android.provider; +import android.Manifest; +import android.annotation.CallbackExecutor; +import android.annotation.IntDef; import android.annotation.LongDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.RequiresPermission; +import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.ContentProvider; import android.content.ContentResolver; @@ -30,6 +37,9 @@ import android.location.Country; import android.location.CountryDetector; import android.net.Uri; import android.os.Build; +import android.os.OutcomeReceiver; +import android.os.ParcelFileDescriptor; +import android.os.ParcelableException; import android.os.UserHandle; import android.os.UserManager; import android.provider.ContactsContract.CommonDataKinds.Callable; @@ -44,9 +54,15 @@ import android.telephony.PhoneNumberUtils; import android.text.TextUtils; import android.util.Log; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.List; +import java.util.Objects; +import java.util.concurrent.Executor; /** * The CallLog provider contains information about placed and received calls. @@ -63,6 +79,12 @@ public class CallLog { public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY); + /** @hide */ + public static final String CALL_COMPOSER_SEGMENT = "call_composer"; + + /** @hide */ + public static final Uri CALL_COMPOSER_PICTURE_URI = + CONTENT_URI.buildUpon().appendPath(CALL_COMPOSER_SEGMENT).build(); /** * The "shadow" provider stores calllog when the real calllog provider is encrypted. The @@ -75,6 +97,172 @@ public class CallLog { public static final String SHADOW_AUTHORITY = "call_log_shadow"; /** + * Describes an error encountered while storing a call composer picture in the call log. + * @hide + */ + @SystemApi + public static class CallComposerLoggingException extends Throwable { + /** + * Indicates an unknown error. + */ + public static final int ERROR_UNKNOWN = 0; + + /** + * Indicates that the process hosting the call log died or otherwise encountered an + * unrecoverable error while storing the picture. + * + * The caller should retry if this error is encountered. + */ + public static final int ERROR_REMOTE_END_CLOSED = 1; + + /** + * Indicates that the device has insufficient space to store this picture. + * + * The caller should not retry if this error is encountered. + */ + public static final int ERROR_STORAGE_FULL = 2; + + /** + * Indicates that the {@link InputStream} passed to {@link #storeCallComposerPictureAsUser} + * was closed. + * + * The caller should retry if this error is encountered, and be sure to not close the stream + * before the callback is called this time. + */ + public static final int ERROR_INPUT_CLOSED = 3; + + /** @hide */ + @IntDef(prefix = {"ERROR_"}, value = { + ERROR_UNKNOWN, + ERROR_REMOTE_END_CLOSED, + ERROR_STORAGE_FULL, + ERROR_INPUT_CLOSED, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface CallComposerLoggingError { } + + private final int mErrorCode; + + /** @hide */ + public CallComposerLoggingException(@CallComposerLoggingError int errorCode) { + mErrorCode = errorCode; + } + + /** + * @return The error code for this exception. + */ + public @CallComposerLoggingError int getErrorCode() { + return mErrorCode; + } + } + + /** + * Supplies a call composer picture to the call log for persistent storage. + * + * This method is used by Telephony to store pictures selected by the user or sent from the + * remote party as part of a voice call with call composer. The {@link Uri} supplied in the + * callback can be used to retrieve the image via {@link ContentResolver#openFile} or stored in + * the {@link Calls} table in the TODO: link column name. + * + * The caller is responsible for closing the {@link InputStream} after the callback indicating + * success or failure. + * + * @param context An instance of {@link Context}. + * @param user The user for whom the picture is stored. If {@code null}, the picture will be + * stored for all users. + * @param input An input stream from which the picture to store should be read. The input data + * must be decodeable as either a JPEG, PNG, or GIF image. + * @param executor The {@link Executor} on which to perform the file transfer operation and + * call the supplied callback. + * @param callback Callback that's called after the picture is successfully stored or when an + * error occurs. + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.WRITE_CALL_LOG) + public static void storeCallComposerPictureAsUser(@NonNull Context context, + @Nullable UserHandle user, + @NonNull InputStream input, + @CallbackExecutor @NonNull Executor executor, + @NonNull OutcomeReceiver<Uri, CallComposerLoggingException> callback) { + Objects.requireNonNull(context); + Objects.requireNonNull(input); + Objects.requireNonNull(executor); + Objects.requireNonNull(callback); + + executor.execute(() -> { + Uri pictureFileUri; + Uri pictureInsertionUri = context.getSystemService(UserManager.class) + .isUserUnlocked() ? CALL_COMPOSER_PICTURE_URI + : CALL_COMPOSER_PICTURE_URI.buildUpon().authority(SHADOW_AUTHORITY).build(); + try { + // ContentResolver#insert says that the second argument is nullable. It is in fact + // not nullable. + ContentValues cv = new ContentValues(); + pictureFileUri = context.getContentResolver().insert(pictureInsertionUri, cv); + } catch (ParcelableException e) { + // Most likely an IOException. We don't have a good way of distinguishing them so + // just return an unknown error. + sendCallComposerError(callback, CallComposerLoggingException.ERROR_UNKNOWN); + return; + } + if (pictureFileUri == null) { + // If the call log provider returns null, it means that there's not enough space + // left to store the maximum-sized call composer image. + sendCallComposerError(callback, CallComposerLoggingException.ERROR_STORAGE_FULL); + return; + } + + boolean wroteSuccessfully = false; + try (ParcelFileDescriptor pfd = + context.getContentResolver().openFileDescriptor(pictureFileUri, "w")) { + FileOutputStream output = new FileOutputStream(pfd.getFileDescriptor()); + byte[] buffer = new byte[1024]; + int bytesRead; + while (true) { + try { + bytesRead = input.read(buffer); + } catch (IOException e) { + sendCallComposerError(callback, + CallComposerLoggingException.ERROR_INPUT_CLOSED); + throw e; + } + if (bytesRead < 0) { + break; + } + try { + output.write(buffer, 0, bytesRead); + } catch (IOException e) { + sendCallComposerError(callback, + CallComposerLoggingException.ERROR_REMOTE_END_CLOSED); + throw e; + } + } + wroteSuccessfully = true; + } catch (FileNotFoundException e) { + callback.onError(new CallComposerLoggingException( + CallComposerLoggingException.ERROR_UNKNOWN)); + } catch (IOException e) { + Log.e(LOG_TAG, "IOException while writing call composer pic to call log: " + + e); + } + + if (wroteSuccessfully) { + callback.onResult(pictureFileUri); + } else { + // Clean up our mess if we didn't successfully write the file. + context.getContentResolver().delete(pictureFileUri, null); + } + }); + } + + // Only call on the correct executor. + private static void sendCallComposerError(OutcomeReceiver<?, CallComposerLoggingException> cb, + int error) { + cb.onError(new CallComposerLoggingException(error)); + } + + /** * Contains the recent calls. */ public static class Calls implements BaseColumns { diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java index f58fa1595f4a..ec4d81c10b5b 100644 --- a/core/java/android/provider/DeviceConfig.java +++ b/core/java/android/provider/DeviceConfig.java @@ -444,6 +444,14 @@ public final class DeviceConfig { public static final String NAMESPACE_PERMISSIONS = "permissions"; /** + * Namespace for ota related features. + * + * @hide + */ + @SystemApi + public static final String NAMESPACE_OTA = "ota"; + + /** * Namespace for all widget related features. * * @hide diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index fb0aea05ba4b..2dbd3edd960e 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -1848,7 +1848,7 @@ public final class Settings { /** * Activity Action: Show notification bubble settings for a single app. - * See {@link NotificationManager#areBubblesAllowed()}. + * See {@link NotificationManager#getBubblePreference()}. * <p> * Input: {@link #EXTRA_APP_PACKAGE}, the package to display. * <p> @@ -3060,6 +3060,7 @@ public final class Settings { // com.android.providers.settings.SettingsProtoDumpUtil#dumpProtoSystemSettingsLocked. private static final float DEFAULT_FONT_SCALE = 1.0f; + private static final int DEFAULT_FONT_WEIGHT = 0; /** * The content:// style URL for this table @@ -3581,9 +3582,7 @@ public final class Settings { outConfig.fontScale = DEFAULT_FONT_SCALE; } outConfig.fontWeightAdjustment = Settings.Secure.getIntForUser( - cr, Settings.Secure.FONT_WEIGHT_ADJUSTMENT, - Configuration.FONT_WEIGHT_ADJUSTMENT_UNDEFINED, - userHandle); + cr, Settings.Secure.FONT_WEIGHT_ADJUSTMENT, DEFAULT_FONT_WEIGHT, userHandle); final String localeValue = Settings.System.getStringForUser(cr, SYSTEM_LOCALES, userHandle); @@ -7761,6 +7760,32 @@ public final class Settings { "minimal_post_processing_allowed"; /** + * No mode switching will happen. + * + * @see #MATCH_CONTENT_FRAME_RATE + * @hide + */ + public static final int MATCH_CONTENT_FRAMERATE_NEVER = 0; + + /** + * Allow only refresh rate switching between modes in the same configuration group. + * This way only switches without visual interruptions for the user will be allowed. + * + * @see #MATCH_CONTENT_FRAME_RATE + * @hide + */ + public static final int MATCH_CONTENT_FRAMERATE_SEAMLESSS_ONLY = 1; + + /** + * Allow refresh rate switching between all refresh rates even if the switch will have + * visual interruptions for the user. + * + * @see #MATCH_CONTENT_FRAME_RATE + * @hide + */ + public static final int MATCH_CONTENT_FRAMERATE_ALWAYS = 2; + + /** * User's preference for refresh rate switching. * * <p>Values: @@ -7770,6 +7795,9 @@ public final class Settings { * for the user. * * @see android.view.Surface#setFrameRate + * @see #MATCH_CONTENT_FRAMERATE_NEVER + * @see #MATCH_CONTENT_FRAMERATE_SEAMLESSS_ONLY + * @see #MATCH_CONTENT_FRAMERATE_ALWAYS * @hide */ public static final String MATCH_CONTENT_FRAME_RATE = diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java index 6ef9e7e3d9b8..017f40521a81 100644 --- a/core/java/android/security/keymaster/KeymasterDefs.java +++ b/core/java/android/security/keymaster/KeymasterDefs.java @@ -16,18 +16,18 @@ package android.security.keymaster; -import android.hardware.keymint.Algorithm; -import android.hardware.keymint.BlockMode; -import android.hardware.keymint.Digest; -import android.hardware.keymint.ErrorCode; -import android.hardware.keymint.HardwareAuthenticatorType; -import android.hardware.keymint.KeyFormat; -import android.hardware.keymint.KeyOrigin; -import android.hardware.keymint.KeyPurpose; -import android.hardware.keymint.PaddingMode; -import android.hardware.keymint.SecurityLevel; -import android.hardware.keymint.Tag; -import android.hardware.keymint.TagType; +import android.hardware.security.keymint.Algorithm; +import android.hardware.security.keymint.BlockMode; +import android.hardware.security.keymint.Digest; +import android.hardware.security.keymint.ErrorCode; +import android.hardware.security.keymint.HardwareAuthenticatorType; +import android.hardware.security.keymint.KeyFormat; +import android.hardware.security.keymint.KeyOrigin; +import android.hardware.security.keymint.KeyPurpose; +import android.hardware.security.keymint.PaddingMode; +import android.hardware.security.keymint.SecurityLevel; +import android.hardware.security.keymint.Tag; +import android.hardware.security.keymint.TagType; import java.util.HashMap; import java.util.Map; diff --git a/core/java/android/service/textservice/OWNERS b/core/java/android/service/textservice/OWNERS index a637754ba17a..10b8b7637431 100644 --- a/core/java/android/service/textservice/OWNERS +++ b/core/java/android/service/textservice/OWNERS @@ -1,5 +1,3 @@ # Bug component: 34867 -ogunwale@google.com -roosa@google.com -yukawa@google.com +include ../../inputmethodservice/OWNERS
\ No newline at end of file diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java index 0b6d371d8235..c1b66c7b446e 100644 --- a/core/java/android/service/voice/VoiceInteractionSession.java +++ b/core/java/android/service/voice/VoiceInteractionSession.java @@ -1220,7 +1220,7 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall * your UI, which will eventually culminate in {@link #onShow}. This is similar to calling * {@link VoiceInteractionService#showSession VoiceInteractionService.showSession}. * @param args Arbitrary arguments that will be propagated {@link #onShow}. - * @param flags Indicates additional optional behavior that should be performed. May + * @param flags Indicates additional optional behavior that should be performed. May * be any combination of * {@link VoiceInteractionSession#SHOW_WITH_ASSIST VoiceInteractionSession.SHOW_WITH_ASSIST} and * {@link VoiceInteractionSession#SHOW_WITH_SCREENSHOT @@ -1583,6 +1583,11 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall * * @param args The arguments that were supplied to * {@link VoiceInteractionService#showSession VoiceInteractionService.showSession}. + * Some example keys include : "invocation_type", "invocation_phone_state", + * "invocation_time_ms", Intent.EXTRA_TIME ("android.intent.extra.TIME") indicating timing + * in milliseconds of the KeyEvent that triggered Assistant and + * Intent.EXTRA_ASSIST_INPUT_DEVICE_ID (android.intent.extra.ASSIST_INPUT_DEVICE_ID) + * referring to the device that sent the request. * @param showFlags The show flags originally provided to * {@link VoiceInteractionService#showSession VoiceInteractionService.showSession}. */ diff --git a/core/java/android/telephony/OWNERS b/core/java/android/telephony/OWNERS new file mode 100644 index 000000000000..640baf2297b4 --- /dev/null +++ b/core/java/android/telephony/OWNERS @@ -0,0 +1 @@ +include /telephony/OWNERS diff --git a/core/java/android/timezone/OWNERS b/core/java/android/timezone/OWNERS index 09447a971bdd..8f8089717e3b 100644 --- a/core/java/android/timezone/OWNERS +++ b/core/java/android/timezone/OWNERS @@ -1 +1,3 @@ -include /core/java/android/app/timezone/OWNERS +# Bug component: 847766 +mingaleev@google.com +include /core/java/android/app/timedetector/OWNERS diff --git a/core/java/android/util/ExceptionUtils.java b/core/java/android/util/ExceptionUtils.java index 1a397b39ef3c..4b511acc280f 100644 --- a/core/java/android/util/ExceptionUtils.java +++ b/core/java/android/util/ExceptionUtils.java @@ -98,4 +98,6 @@ public class ExceptionUtils { } return t; } + + }
\ No newline at end of file diff --git a/core/java/android/util/TypedXmlPullParser.java b/core/java/android/util/TypedXmlPullParser.java index b3b51b54e651..aa68bf42fe52 100644 --- a/core/java/android/util/TypedXmlPullParser.java +++ b/core/java/android/util/TypedXmlPullParser.java @@ -30,67 +30,168 @@ import org.xmlpull.v1.XmlPullParserException; */ public interface TypedXmlPullParser extends XmlPullParser { /** + * @return index of requested attribute, otherwise {@code -1} if undefined + */ + default int getAttributeIndex(@Nullable String namespace, @NonNull String name) { + final boolean namespaceNull = (namespace == null); + final int count = getAttributeCount(); + for (int i = 0; i < count; i++) { + if ((namespaceNull || namespace.equals(getAttributeNamespace(i))) + && name.equals(getAttributeName(i))) { + return i; + } + } + return -1; + } + + /** + * @return index of requested attribute + * @throws XmlPullParserException if the value is undefined + */ + default int getAttributeIndexOrThrow(@Nullable String namespace, @NonNull String name) + throws XmlPullParserException { + final int index = getAttributeIndex(namespace, name); + if (index == -1) { + throw new XmlPullParserException("Missing attribute " + name); + } else { + return index; + } + } + + /** + * @return decoded strongly-typed {@link #getAttributeValue} + * @throws XmlPullParserException if the value is malformed + */ + @NonNull byte[] getAttributeBytesHex(int index) throws XmlPullParserException; + + /** + * @return decoded strongly-typed {@link #getAttributeValue} + * @throws XmlPullParserException if the value is malformed + */ + @NonNull byte[] getAttributeBytesBase64(int index) throws XmlPullParserException; + + /** + * @return decoded strongly-typed {@link #getAttributeValue} + * @throws XmlPullParserException if the value is malformed + */ + int getAttributeInt(int index) throws XmlPullParserException; + + /** + * @return decoded strongly-typed {@link #getAttributeValue} + * @throws XmlPullParserException if the value is malformed + */ + int getAttributeIntHex(int index) throws XmlPullParserException; + + /** + * @return decoded strongly-typed {@link #getAttributeValue} + * @throws XmlPullParserException if the value is malformed + */ + long getAttributeLong(int index) throws XmlPullParserException; + + /** + * @return decoded strongly-typed {@link #getAttributeValue} + * @throws XmlPullParserException if the value is malformed + */ + long getAttributeLongHex(int index) throws XmlPullParserException; + + /** + * @return decoded strongly-typed {@link #getAttributeValue} + * @throws XmlPullParserException if the value is malformed + */ + float getAttributeFloat(int index) throws XmlPullParserException; + + /** + * @return decoded strongly-typed {@link #getAttributeValue} + * @throws XmlPullParserException if the value is malformed + */ + double getAttributeDouble(int index) throws XmlPullParserException; + + /** + * @return decoded strongly-typed {@link #getAttributeValue} + * @throws XmlPullParserException if the value is malformed + */ + boolean getAttributeBoolean(int index) throws XmlPullParserException; + + /** * @return decoded strongly-typed {@link #getAttributeValue} * @throws XmlPullParserException if the value is malformed or undefined */ - @NonNull byte[] getAttributeBytesHex(@Nullable String namespace, @NonNull String name) - throws XmlPullParserException; + default @NonNull byte[] getAttributeBytesHex(@Nullable String namespace, + @NonNull String name) throws XmlPullParserException { + return getAttributeBytesHex(getAttributeIndexOrThrow(namespace, name)); + } /** * @return decoded strongly-typed {@link #getAttributeValue} * @throws XmlPullParserException if the value is malformed or undefined */ - @NonNull byte[] getAttributeBytesBase64(@Nullable String namespace, @NonNull String name) - throws XmlPullParserException; + default @NonNull byte[] getAttributeBytesBase64(@Nullable String namespace, + @NonNull String name) throws XmlPullParserException { + return getAttributeBytesBase64(getAttributeIndexOrThrow(namespace, name)); + } /** * @return decoded strongly-typed {@link #getAttributeValue} * @throws XmlPullParserException if the value is malformed or undefined */ - int getAttributeInt(@Nullable String namespace, @NonNull String name) - throws XmlPullParserException; + default int getAttributeInt(@Nullable String namespace, @NonNull String name) + throws XmlPullParserException { + return getAttributeInt(getAttributeIndexOrThrow(namespace, name)); + } /** * @return decoded strongly-typed {@link #getAttributeValue} * @throws XmlPullParserException if the value is malformed or undefined */ - int getAttributeIntHex(@Nullable String namespace, @NonNull String name) - throws XmlPullParserException; + default int getAttributeIntHex(@Nullable String namespace, @NonNull String name) + throws XmlPullParserException { + return getAttributeIntHex(getAttributeIndexOrThrow(namespace, name)); + } /** * @return decoded strongly-typed {@link #getAttributeValue} * @throws XmlPullParserException if the value is malformed or undefined */ - long getAttributeLong(@Nullable String namespace, @NonNull String name) - throws XmlPullParserException; + default long getAttributeLong(@Nullable String namespace, @NonNull String name) + throws XmlPullParserException { + return getAttributeLong(getAttributeIndexOrThrow(namespace, name)); + } /** * @return decoded strongly-typed {@link #getAttributeValue} * @throws XmlPullParserException if the value is malformed or undefined */ - long getAttributeLongHex(@Nullable String namespace, @NonNull String name) - throws XmlPullParserException; + default long getAttributeLongHex(@Nullable String namespace, @NonNull String name) + throws XmlPullParserException { + return getAttributeLongHex(getAttributeIndexOrThrow(namespace, name)); + } /** * @return decoded strongly-typed {@link #getAttributeValue} * @throws XmlPullParserException if the value is malformed or undefined */ - float getAttributeFloat(@Nullable String namespace, @NonNull String name) - throws XmlPullParserException; + default float getAttributeFloat(@Nullable String namespace, @NonNull String name) + throws XmlPullParserException { + return getAttributeFloat(getAttributeIndexOrThrow(namespace, name)); + } /** * @return decoded strongly-typed {@link #getAttributeValue} * @throws XmlPullParserException if the value is malformed or undefined */ - double getAttributeDouble(@Nullable String namespace, @NonNull String name) - throws XmlPullParserException; + default double getAttributeDouble(@Nullable String namespace, @NonNull String name) + throws XmlPullParserException { + return getAttributeDouble(getAttributeIndexOrThrow(namespace, name)); + } /** * @return decoded strongly-typed {@link #getAttributeValue} * @throws XmlPullParserException if the value is malformed or undefined */ - boolean getAttributeBoolean(@Nullable String namespace, @NonNull String name) - throws XmlPullParserException; + default boolean getAttributeBoolean(@Nullable String namespace, @NonNull String name) + throws XmlPullParserException { + return getAttributeBoolean(getAttributeIndexOrThrow(namespace, name)); + } /** * @return decoded strongly-typed {@link #getAttributeValue}, otherwise @@ -98,8 +199,10 @@ public interface TypedXmlPullParser extends XmlPullParser { */ default @Nullable byte[] getAttributeBytesHex(@Nullable String namespace, @NonNull String name, @Nullable byte[] defaultValue) { + final int index = getAttributeIndex(namespace, name); + if (index == -1) return defaultValue; try { - return getAttributeBytesHex(namespace, name); + return getAttributeBytesHex(index); } catch (Exception ignored) { return defaultValue; } @@ -111,8 +214,10 @@ public interface TypedXmlPullParser extends XmlPullParser { */ default @Nullable byte[] getAttributeBytesBase64(@Nullable String namespace, @NonNull String name, @Nullable byte[] defaultValue) { + final int index = getAttributeIndex(namespace, name); + if (index == -1) return defaultValue; try { - return getAttributeBytesBase64(namespace, name); + return getAttributeBytesBase64(index); } catch (Exception ignored) { return defaultValue; } @@ -124,8 +229,10 @@ public interface TypedXmlPullParser extends XmlPullParser { */ default int getAttributeInt(@Nullable String namespace, @NonNull String name, int defaultValue) { + final int index = getAttributeIndex(namespace, name); + if (index == -1) return defaultValue; try { - return getAttributeInt(namespace, name); + return getAttributeInt(index); } catch (Exception ignored) { return defaultValue; } @@ -137,8 +244,10 @@ public interface TypedXmlPullParser extends XmlPullParser { */ default int getAttributeIntHex(@Nullable String namespace, @NonNull String name, int defaultValue) { + final int index = getAttributeIndex(namespace, name); + if (index == -1) return defaultValue; try { - return getAttributeIntHex(namespace, name); + return getAttributeIntHex(index); } catch (Exception ignored) { return defaultValue; } @@ -150,8 +259,10 @@ public interface TypedXmlPullParser extends XmlPullParser { */ default long getAttributeLong(@Nullable String namespace, @NonNull String name, long defaultValue) { + final int index = getAttributeIndex(namespace, name); + if (index == -1) return defaultValue; try { - return getAttributeLong(namespace, name); + return getAttributeLong(index); } catch (Exception ignored) { return defaultValue; } @@ -163,8 +274,10 @@ public interface TypedXmlPullParser extends XmlPullParser { */ default long getAttributeLongHex(@Nullable String namespace, @NonNull String name, long defaultValue) { + final int index = getAttributeIndex(namespace, name); + if (index == -1) return defaultValue; try { - return getAttributeLongHex(namespace, name); + return getAttributeLongHex(index); } catch (Exception ignored) { return defaultValue; } @@ -176,8 +289,10 @@ public interface TypedXmlPullParser extends XmlPullParser { */ default float getAttributeFloat(@Nullable String namespace, @NonNull String name, float defaultValue) { + final int index = getAttributeIndex(namespace, name); + if (index == -1) return defaultValue; try { - return getAttributeFloat(namespace, name); + return getAttributeFloat(index); } catch (Exception ignored) { return defaultValue; } @@ -189,8 +304,10 @@ public interface TypedXmlPullParser extends XmlPullParser { */ default double getAttributeDouble(@Nullable String namespace, @NonNull String name, double defaultValue) { + final int index = getAttributeIndex(namespace, name); + if (index == -1) return defaultValue; try { - return getAttributeDouble(namespace, name); + return getAttributeDouble(index); } catch (Exception ignored) { return defaultValue; } @@ -202,8 +319,10 @@ public interface TypedXmlPullParser extends XmlPullParser { */ default boolean getAttributeBoolean(@Nullable String namespace, @NonNull String name, boolean defaultValue) { + final int index = getAttributeIndex(namespace, name); + if (index == -1) return defaultValue; try { - return getAttributeBoolean(namespace, name); + return getAttributeBoolean(index); } catch (Exception ignored) { return defaultValue; } diff --git a/core/java/android/view/IRecentsAnimationController.aidl b/core/java/android/view/IRecentsAnimationController.aidl index f209d88ac825..cac91a9f07d7 100644 --- a/core/java/android/view/IRecentsAnimationController.aidl +++ b/core/java/android/view/IRecentsAnimationController.aidl @@ -136,4 +136,13 @@ interface IRecentsAnimationController { * @return {@code true} when target removed successfully, {@code false} otherwise. */ boolean removeTask(int taskId); + + /** + * Detach navigation bar from app. + * + * The system reparents the leash of navigation bar to the app when the recents animation starts + * and Launcher should call this method to let system restore the navigation bar to its + * original position when the quick switch gesture is finished. + */ + void detachNavigationBarFromApp(); } diff --git a/core/java/android/view/InsetsAnimationThreadControlRunner.java b/core/java/android/view/InsetsAnimationThreadControlRunner.java index 4a5fa0f971ae..0939336132a8 100644 --- a/core/java/android/view/InsetsAnimationThreadControlRunner.java +++ b/core/java/android/view/InsetsAnimationThreadControlRunner.java @@ -81,6 +81,7 @@ public class InsetsAnimationThreadControlRunner implements InsetsAnimationContro SyncRtSurfaceTransactionApplier.SurfaceParams surfaceParams = params[i]; applyParams(t, surfaceParams, mTmpFloat9); } + t.setFrameTimelineVsync(Choreographer.getSfInstance().getVsyncId()); t.apply(); t.close(); } diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java index a8d261553a8f..52b7cffbc340 100644 --- a/core/java/android/view/MotionEvent.java +++ b/core/java/android/view/MotionEvent.java @@ -477,6 +477,14 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int FLAG_IS_GENERATED_GESTURE = 0x8; /** + * This flag associated with {@link #ACTION_POINTER_UP}, this indicates that the pointer + * has been canceled. Typically this is used for palm event when the user has accidental + * touches. + * @hide + */ + public static final int FLAG_CANCELED = 0x20; + + /** * Private flag that indicates when the system has detected that this motion event * may be inconsistent with respect to the sequence of previously delivered motion events, * such as when a pointer move event is sent but the pointer is not down. @@ -3477,7 +3485,8 @@ public final class MotionEvent extends InputEvent implements Parcelable { } else if (newPointerCount == 1) { // The first/last pointer went down/up. newAction = oldActionMasked == ACTION_POINTER_DOWN - ? ACTION_DOWN : ACTION_UP; + ? ACTION_DOWN + : (getFlags() & FLAG_CANCELED) == 0 ? ACTION_UP : ACTION_CANCEL; } else { // A secondary pointer went down/up. newAction = oldActionMasked diff --git a/core/java/android/view/OWNERS b/core/java/android/view/OWNERS index 4f82b86f260c..72fa4c39f1bc 100644 --- a/core/java/android/view/OWNERS +++ b/core/java/android/view/OWNERS @@ -8,19 +8,67 @@ nduca@google.com sumir@google.com ogunwale@google.com jjaggi@google.com +roosa@google.com # Display -per-file Display.java = michaelwr@google.com, santoscordon@google.com -per-file DisplayInfo.java = michaelwr@google.com, santoscordon@google.com +per-file Display*.java = file:/services/core/java/com/android/server/display/OWNERS +per-file Display*.aidl = file:/services/core/java/com/android/server/display/OWNERS # Haptics -per-file HapticFeedbackConstants.java = michaelwr@google.com, santoscordon@google.com +per-file HapticFeedbackConstants.java = file:/services/core/java/com/android/server/input/OWNERS + +# Ime +per-file Ime*.java = file:/core/java/android/view/inputmethod/OWNERS # Input -per-file IInputMonitorHost.aidl = michaelwr@google.com, svv@google.com -per-file Input*.java = michaelwr@google.com, svv@google.com -per-file Input*.aidl = michaelwr@google.com, svv@google.com -per-file KeyEvent.java = michaelwr@google.com, svv@google.com -per-file MotionEvent.java = michaelwr@google.com, svv@google.com -per-file PointerIcon.java = michaelwr@google.com, svv@google.com -per-file SimulatedDpad.java = michaelwr@google.com, svv@google.com +per-file IInput*.aidl = file:/services/core/java/com/android/server/input/OWNERS +per-file Input*.java = file:/services/core/java/com/android/server/input/OWNERS +per-file Input*.aidl = file:/services/core/java/com/android/server/input/OWNERS +per-file KeyEvent.java = file:/services/core/java/com/android/server/input/OWNERS +per-file MotionEvent.java = file:/services/core/java/com/android/server/input/OWNERS +per-file PointerIcon.java = file:/services/core/java/com/android/server/input/OWNERS +per-file SimulatedDpad.java = file:/services/core/java/com/android/server/input/OWNERS + +# InputWindowHandle +per-file InputWindowHandle.java = file:/services/core/java/com/android/server/input/OWNERS +per-file InputWindowHandle.java = file:/services/core/java/com/android/server/wm/OWNERS + +# Surface +per-file Surface.java = file:/graphics/java/android/graphics/OWNERS +per-file Surface.java = file:/services/core/java/com/android/server/wm/OWNERS +per-file SurfaceView.java = file:/graphics/java/android/graphics/OWNERS +per-file SurfaceView.java = file:/services/core/java/com/android/server/wm/OWNERS +per-file SurfaceHolder.java = file:/graphics/java/android/graphics/OWNERS +per-file SurfaceHolder.java = file:/services/core/java/com/android/server/wm/OWNERS + +# View +per-file View.java = file:/services/accessibility/OWNERS +per-file View.java = file:/core/java/android/service/autofill/OWNERS +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 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 + +# WindowManager +per-file DisplayCutout.aidl = file:/services/core/java/com/android/server/wm/OWNERS +per-file DisplayCutout.java = file:/services/core/java/com/android/server/wm/OWNERS +per-file IDisplay*.aidl = file:/services/core/java/com/android/server/wm/OWNERS +per-file Inset*.java = file:/services/core/java/com/android/server/wm/OWNERS +per-file Inset*.aidl = file:/services/core/java/com/android/server/wm/OWNERS +per-file IPinnedStackListener.aidl = file:/services/core/java/com/android/server/wm/OWNERS +per-file IRecents*.aidl = file:/services/core/java/com/android/server/wm/OWNERS +per-file IRemote*.aidl = file:/services/core/java/com/android/server/wm/OWNERS +per-file IWindow*.aidl = file:/services/core/java/com/android/server/wm/OWNERS +per-file RemoteAnimation*.java = file:/services/core/java/com/android/server/wm/OWNERS +per-file RemoteAnimation*.aidl = file:/services/core/java/com/android/server/wm/OWNERS +per-file SurfaceControl*.java = file:/services/core/java/com/android/server/wm/OWNERS +per-file SurfaceControl*.aidl = file:/services/core/java/com/android/server/wm/OWNERS +per-file SurfaceSession.java = file:/services/core/java/com/android/server/wm/OWNERS +per-file SyncRtSurfaceTransactionApplier.java = file:/services/core/java/com/android/server/wm/OWNERS +per-file ViewRootInsetsControllerHost.java = file:/services/core/java/com/android/server/wm/OWNERS +per-file Window*.java = file:/services/core/java/com/android/server/wm/OWNERS +per-file Window*.aidl = file:/services/core/java/com/android/server/wm/OWNERS diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index d7ee6ad15166..23de215eeefc 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -26,6 +26,7 @@ import static android.view.SurfaceControlProto.HASH_CODE; import static android.view.SurfaceControlProto.NAME; import android.annotation.FloatRange; +import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; @@ -54,12 +55,15 @@ import android.util.proto.ProtoOutputStream; import android.view.Surface.OutOfResourcesException; import com.android.internal.annotations.GuardedBy; +import com.android.internal.util.VirtualRefBasePtr; import dalvik.system.CloseGuard; import libcore.util.NativeAllocationRegistry; import java.io.Closeable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -224,6 +228,10 @@ public final class SurfaceControl implements Parcelable { IBinder focusedToken, int displayId); private static native void nativeSetFrameTimelineVsync(long transactionObj, long frameTimelineVsyncId); + private static native void nativeAddJankDataListener(long nativeListener, + long nativeSurfaceControl); + private static native void nativeRemoveJankDataListener(long nativeListener); + private static native long nativeCreateJankDataListenerWrapper(OnJankDataListener listener); @Nullable @GuardedBy("mLock") @@ -249,6 +257,73 @@ public final class SurfaceControl implements Parcelable { void onReparent(@NonNull Transaction transaction, @Nullable SurfaceControl parent); } + /** + * Jank information to be fed back via {@link OnJankDataListener}. + * @hide + */ + public static class JankData { + + /** @hide */ + @IntDef(flag = true, value = {JANK_NONE, + JANK_DISPLAY, + JANK_SURFACEFLINGER_DEADLINE_MISSED, + JANK_SURFACEFLINGER_GPU_DEADLINE_MISSED, + JANK_APP_DEADLINE_MISSED, + JANK_PREDICTION_EXPIRED, + JANK_SURFACEFLINGER_EARLY_LATCH}) + @Retention(RetentionPolicy.SOURCE) + public @interface JankType {} + + // Needs to be kept in sync with frameworks/native/libs/gui/include/gui/JankInfo.h + + // No Jank + public static final int JANK_NONE = 0x0; + + // Jank not related to SurfaceFlinger or the App + public static final int JANK_DISPLAY = 0x1; + // SF took too long on the CPU + public static final int JANK_SURFACEFLINGER_DEADLINE_MISSED = 0x2; + // SF took too long on the GPU + public static final int JANK_SURFACEFLINGER_GPU_DEADLINE_MISSED = 0x4; + // Either App or GPU took too long on the frame + public static final int JANK_APP_DEADLINE_MISSED = 0x8; + // Predictions live for 120ms, if prediction is expired for a frame, there is definitely a + // jank + // associated with the App if this is for a SurfaceFrame, and SF for a DisplayFrame. + public static final int JANK_PREDICTION_EXPIRED = 0x10; + // Latching a buffer early might cause an early present of the frame + public static final int JANK_SURFACEFLINGER_EARLY_LATCH = 0x20; + + public JankData(long frameVsyncId, @JankType int jankType) { + this.frameVsyncId = frameVsyncId; + this.jankType = jankType; + } + + public final long frameVsyncId; + public final @JankType int jankType; + } + + /** + * Listener interface to be informed about SurfaceFlinger's jank classification for a specific + * surface. + * + * @see JankData + * @see #addJankDataListener + * @hide + */ + public static abstract class OnJankDataListener { + private final VirtualRefBasePtr mNativePtr; + + public OnJankDataListener() { + mNativePtr = new VirtualRefBasePtr(nativeCreateJankDataListenerWrapper(this)); + } + + /** + * Called when new jank classifications are available. + */ + public abstract void onJankDataAvailable(JankData[] jankStats); + } + private final CloseGuard mCloseGuard = CloseGuard.get(); private String mName; @@ -1526,97 +1601,6 @@ public final class SurfaceControl implements Parcelable { /** * @hide */ - public void deferTransactionUntil(SurfaceControl barrier, long frame) { - synchronized(SurfaceControl.class) { - sGlobalTransaction.deferTransactionUntil(this, barrier, frame); - } - } - - /** - * @hide - */ - public void reparentChildren(SurfaceControl newParent) { - synchronized(SurfaceControl.class) { - sGlobalTransaction.reparentChildren(this, newParent); - } - } - - /** - * @hide - */ - public void detachChildren() { - synchronized(SurfaceControl.class) { - sGlobalTransaction.detachChildren(this); - } - } - - /** - * @hide - */ - @UnsupportedAppUsage - public void setLayer(int zorder) { - checkNotReleased(); - synchronized(SurfaceControl.class) { - sGlobalTransaction.setLayer(this, zorder); - } - } - - /** - * @hide - */ - @UnsupportedAppUsage - public void setPosition(float x, float y) { - checkNotReleased(); - synchronized(SurfaceControl.class) { - sGlobalTransaction.setPosition(this, x, y); - } - } - - /** - * @hide - */ - public void setBufferSize(int w, int h) { - checkNotReleased(); - synchronized(SurfaceControl.class) { - sGlobalTransaction.setBufferSize(this, w, h); - } - } - - /** - * @hide - */ - @UnsupportedAppUsage - public void hide() { - checkNotReleased(); - synchronized(SurfaceControl.class) { - sGlobalTransaction.hide(this); - } - } - - /** - * @hide - */ - @UnsupportedAppUsage - public void show() { - checkNotReleased(); - synchronized(SurfaceControl.class) { - sGlobalTransaction.show(this); - } - } - - /** - * @hide - */ - public void setTransparentRegionHint(Region region) { - checkNotReleased(); - synchronized(SurfaceControl.class) { - sGlobalTransaction.setTransparentRegionHint(this, region); - } - } - - /** - * @hide - */ public boolean clearContentFrameStats() { checkNotReleased(); return nativeClearContentFrameStats(mNativeObject); @@ -1647,87 +1631,6 @@ public final class SurfaceControl implements Parcelable { /** * @hide */ - public void setAlpha(float alpha) { - checkNotReleased(); - synchronized(SurfaceControl.class) { - sGlobalTransaction.setAlpha(this, alpha); - } - } - - /** - * @hide - */ - public void setBackgroundBlurRadius(int blur) { - checkNotReleased(); - synchronized (SurfaceControl.class) { - sGlobalTransaction.setBackgroundBlurRadius(this, blur); - } - } - - /** - * @hide - */ - public void setMatrix(float dsdx, float dtdx, float dtdy, float dsdy) { - checkNotReleased(); - synchronized(SurfaceControl.class) { - sGlobalTransaction.setMatrix(this, dsdx, dtdx, dtdy, dsdy); - } - } - - /** - * Sets the Surface to be color space agnostic. If a surface is color space agnostic, - * the color can be interpreted in any color space. - * @param agnostic A boolean to indicate whether the surface is color space agnostic - * @hide - */ - public void setColorSpaceAgnostic(boolean agnostic) { - checkNotReleased(); - synchronized (SurfaceControl.class) { - sGlobalTransaction.setColorSpaceAgnostic(this, agnostic); - } - } - - /** - * Bounds the surface and its children to the bounds specified. Size of the surface will be - * ignored and only the crop and buffer size will be used to determine the bounds of the - * surface. If no crop is specified and the surface has no buffer, the surface bounds is only - * constrained by the size of its parent bounds. - * - * @param crop Bounds of the crop to apply. - * @hide - */ - public void setWindowCrop(Rect crop) { - checkNotReleased(); - synchronized (SurfaceControl.class) { - sGlobalTransaction.setWindowCrop(this, crop); - } - } - - /** - * @hide - */ - public void setOpaque(boolean isOpaque) { - checkNotReleased(); - - synchronized (SurfaceControl.class) { - sGlobalTransaction.setOpaque(this, isOpaque); - } - } - - /** - * @hide - */ - public void setSecure(boolean isSecure) { - checkNotReleased(); - - synchronized (SurfaceControl.class) { - sGlobalTransaction.setSecure(this, isSecure); - } - } - - /** - * @hide - */ public int getWidth() { synchronized (mLock) { return mWidth; @@ -2519,6 +2422,22 @@ public final class SurfaceControl implements Parcelable { nativeSetGlobalShadowSettings(ambientColor, spotColor, lightPosY, lightPosZ, lightRadius); } + /** + * Adds a callback to be informed about SF's jank classification for a specific surface. + * @hide + */ + public static void addJankDataListener(OnJankDataListener listener, SurfaceControl surface) { + nativeAddJankDataListener(listener.mNativePtr.get(), surface.mNativeObject); + } + + /** + * Removes a jank callback previously added with {@link #addJankDataListener} + * @hide + */ + public static void removeJankDataListener(OnJankDataListener listener) { + nativeRemoveJankDataListener(listener.mNativePtr.get()); + } + /** * An atomic set of changes to a set of SurfaceControl. */ diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 29cc4b507acc..de320b81f7e9 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -154,6 +154,7 @@ import com.android.internal.widget.ScrollBarUtils; import com.google.android.collect.Lists; import com.google.android.collect.Maps; +import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; @@ -29023,6 +29024,33 @@ public class View implements Drawable.Callback, KeyEvent.Callback, boolean mUse32BitDrawingCache; /** + * For windows that are full-screen but using insets to layout inside + * of the screen decorations, these are the current insets for the + * content of the window. + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, + publicAlternatives = "Use {@link WindowInsets#getInsets(int)}") + final Rect mContentInsets = new Rect(); + + /** + * For windows that are full-screen but using insets to layout inside + * of the screen decorations, these are the current insets for the + * actual visible parts of the window. + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, + publicAlternatives = "Use {@link WindowInsets#getInsets(int)}") + final Rect mVisibleInsets = new Rect(); + + /** + * For windows that are full-screen but using insets to layout inside + * of the screen decorations, these are the current insets for the + * stable system windows. + */ + @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, + publicAlternatives = "Use {@link WindowInsets#getInsets(int)}") + final Rect mStableInsets = new Rect(); + + /** * Current caption insets to the display coordinate. */ final Rect mCaptionInsets = new Rect(); @@ -29415,6 +29443,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } return mScrollCaptureInternal; } + + public void dump(String prefix, PrintWriter writer) { + String innerPrefix = prefix + " "; + writer.println(prefix + "AttachInfo:"); + writer.println(innerPrefix + "mHasWindowFocus=" + mHasWindowFocus); + writer.println(innerPrefix + "mWindowVisibility=" + mWindowVisibility); + writer.println(innerPrefix + "mInTouchMode=" + mInTouchMode); + writer.println(innerPrefix + "mUnbufferedDispatchRequested=" + + mUnbufferedDispatchRequested); + } } /** diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 2d633cbeb353..37c18b54cabc 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -200,7 +200,6 @@ import com.android.internal.view.BaseSurfaceHolder; import com.android.internal.view.RootViewSurfaceTaker; import com.android.internal.view.SurfaceCallbackHelper; -import java.io.FileDescriptor; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; @@ -582,9 +581,6 @@ public final class ViewRootImpl implements ViewParent, = new ViewTreeObserver.InternalInsetsInfo(); private WindowInsets mLastWindowInsets; - private final Rect mSystemInsetsCache = new Rect(); - private final Rect mVisibleInsetsCache = new Rect(); - private final Rect mStableInsetsCache = new Rect(); // Insets types hidden by legacy window flags or system UI flags. private @InsetsType int mTypesHiddenByFlags = 0; @@ -2341,9 +2337,9 @@ public final class ViewRootImpl implements ViewParent, (mWindowAttributes.systemUiVisibility | mWindowAttributes.subtreeSystemUiVisibility)); - mSystemInsetsCache.set(mLastWindowInsets.getSystemWindowInsets().toRect()); - mStableInsetsCache.set(mLastWindowInsets.getStableInsets().toRect()); - mVisibleInsetsCache.set(mInsetsController.calculateVisibleInsets( + mAttachInfo.mContentInsets.set(mLastWindowInsets.getSystemWindowInsets().toRect()); + mAttachInfo.mStableInsets.set(mLastWindowInsets.getStableInsets().toRect()); + mAttachInfo.mVisibleInsets.set(mInsetsController.calculateVisibleInsets( mWindowAttributes.softInputMode)); } return mLastWindowInsets; @@ -2846,7 +2842,7 @@ public final class ViewRootImpl implements ViewParent, && mWinFrame.height() == mPendingBackDropFrame.height(); // TODO: Need cutout? startDragResizing(mPendingBackDropFrame, !backdropSizeMatchesFrame, - mSystemInsetsCache, mStableInsetsCache, mResizeMode); + mAttachInfo.mContentInsets, mAttachInfo.mStableInsets, mResizeMode); } else { // We shouldn't come here, but if we come we should end the resize. endDragResizing(); @@ -4478,8 +4474,8 @@ public final class ViewRootImpl implements ViewParent, } boolean scrollToRectOrFocus(Rect rectangle, boolean immediate) { - final Rect ci = mSystemInsetsCache; - final Rect vi = mVisibleInsetsCache; + final Rect ci = mAttachInfo.mContentInsets; + final Rect vi = mAttachInfo.mVisibleInsets; int scrollY = 0; boolean handled = false; @@ -7575,7 +7571,7 @@ public final class ViewRootImpl implements ViewParent, // XXX This is really broken, and probably all needs to be done // in the window manager, and we need to know more about whether // we want the area behind or in front of the IME. - final Rect insets = mVisibleInsetsCache; + final Rect insets = mAttachInfo.mVisibleInsets; outFrame.left += insets.left; outFrame.top += insets.top; outFrame.right -= insets.right; @@ -7690,12 +7686,18 @@ public final class ViewRootImpl implements ViewParent, mImeFocusController.dumpDebug(proto, IME_FOCUS_CONTROLLER); } - public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { + /** + * Dump information about this ViewRootImpl + * @param prefix the prefix that will be prepended to each line of the produced output + * @param writer the writer that will receive the resulting text + */ + public void dump(String prefix, PrintWriter writer) { String innerPrefix = prefix + " "; writer.println(prefix + "ViewRoot:"); writer.println(innerPrefix + "mAdded=" + mAdded); writer.println(innerPrefix + "mRemoved=" + mRemoved); writer.println(innerPrefix + "mStopped=" + mStopped); + writer.println(innerPrefix + "mPausedForTransition=" + mPausedForTransition); writer.println(innerPrefix + "mConsumeBatchedInputScheduled=" + mConsumeBatchedInputScheduled); writer.println(innerPrefix + "mConsumeBatchedInputImmediatelyScheduled=" @@ -7710,6 +7712,12 @@ public final class ViewRootImpl implements ViewParent, writer.println(innerPrefix + "mIsAmbientMode=" + mIsAmbientMode); writer.println(innerPrefix + "mUnbufferedInputSource=" + Integer.toHexString(mUnbufferedInputSource)); + if (mAttachInfo != null) { + writer.print(innerPrefix + "mAttachInfo= "); + mAttachInfo.dump(innerPrefix, writer); + } else { + writer.println(innerPrefix + "mAttachInfo=<null>"); + } mFirstInputStage.dump(innerPrefix, writer); @@ -7913,7 +7921,7 @@ public final class ViewRootImpl implements ViewParent, synchronized (mWindowCallbacks) { for (int i = mWindowCallbacks.size() - 1; i >= 0; i--) { mWindowCallbacks.get(i).onWindowSizeIsChanging(backDropFrame, fullscreen, - mVisibleInsetsCache, mStableInsetsCache); + mAttachInfo.mVisibleInsets, mAttachInfo.mStableInsets); } } } diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index 13d9eb9d3c7d..af18293398da 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -16,7 +16,11 @@ package android.view; +import static android.Manifest.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS; +import static android.Manifest.permission.HIDE_OVERLAY_WINDOWS; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; +import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; import android.annotation.ColorInt; import android.annotation.DrawableRes; @@ -24,6 +28,7 @@ import android.annotation.IdRes; import android.annotation.LayoutRes; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.annotation.StyleRes; import android.annotation.SystemApi; import android.annotation.TestApi; @@ -991,6 +996,26 @@ public abstract class Window { } /** + * Prevent non-system overlay windows from being drawn on top of this window. + * + * @param hide whether non-system overlay windows should be hidden. + */ + @RequiresPermission(HIDE_OVERLAY_WINDOWS) + public final void setHideOverlayWindows(boolean hide) { + // This permission check is here to throw early and let the developer know that they need + // to hold HIDE_OVERLAY_WINDOWS for the flag to have any effect. The WM verifies that the + // owner of the window has the permission before applying the flag, but this is done + // asynchronously. + if (mContext.checkSelfPermission(HIDE_NON_SYSTEM_OVERLAY_WINDOWS) != PERMISSION_GRANTED + && mContext.checkSelfPermission(HIDE_OVERLAY_WINDOWS) != PERMISSION_GRANTED) { + throw new SecurityException( + "Permission denial: setHideOverlayWindows: HIDE_OVERLAY_WINDOWS"); + } + setPrivateFlags(hide ? SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS : 0, + SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); + } + + /** * Take ownership of this window's surface. The window's view hierarchy * will no longer draw into the surface, though it will otherwise continue * to operate (such as for receiving input events). The given SurfaceHolder diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index b9afbc95de0d..6d88d637dc24 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -343,23 +343,48 @@ public interface WindowManager extends ViewManager { /** @hide */ int TRANSIT_NONE = 0; - /** @hide */ + /** + * A window that didn't exist before has been created and made visible. + * @hide + */ int TRANSIT_OPEN = 1; - /** @hide */ + /** + * A window that was visible no-longer exists (was finished or destroyed). + * @hide + */ int TRANSIT_CLOSE = 2; - /** @hide */ + /** + * A window that already existed but was not visible is made visible. + * @hide + */ int TRANSIT_TO_FRONT = 3; - /** @hide */ + /** + * A window that was visible is made invisible but still exists. + * @hide + */ int TRANSIT_TO_BACK = 4; /** @hide */ int TRANSIT_RELAUNCH = 5; - /** @hide */ - int TRANSIT_CHANGE_WINDOWING_MODE = 6; - /** @hide */ + /** + * A window is visible before and after but changes in some way (eg. it resizes or changes + * windowing-mode). + * @hide + */ + int TRANSIT_CHANGE = 6; + /** + * The keyguard was visible and has been dismissed. + * @hide + */ int TRANSIT_KEYGUARD_GOING_AWAY = 7; - /** @hide */ + /** + * A window is appearing above a locked keyguard. + * @hide + */ int TRANSIT_KEYGUARD_OCCLUDE = 8; - /** @hide */ + /** + * A window is made invisible revealing a locked keyguard. + * @hide + */ int TRANSIT_KEYGUARD_UNOCCLUDE = 9; /** @@ -372,7 +397,7 @@ public interface WindowManager extends ViewManager { TRANSIT_TO_FRONT, TRANSIT_TO_BACK, TRANSIT_RELAUNCH, - TRANSIT_CHANGE_WINDOWING_MODE, + TRANSIT_CHANGE, TRANSIT_KEYGUARD_GOING_AWAY, TRANSIT_KEYGUARD_OCCLUDE, TRANSIT_KEYGUARD_UNOCCLUDE, @@ -418,6 +443,12 @@ public interface WindowManager extends ViewManager { int TRANSIT_FLAG_OPEN_BEHIND = 0x20; /** + * Transition flag: The keyguard is locked throughout the whole transition. + * @hide + */ + int TRANSIT_FLAG_KEYGUARD_LOCKED = 0x40; + + /** * @hide */ @IntDef(flag = true, prefix = { "TRANSIT_FLAG_" }, value = { @@ -426,7 +457,8 @@ public interface WindowManager extends ViewManager { TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER, TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION, TRANSIT_FLAG_APP_CRASHED, - TRANSIT_FLAG_OPEN_BEHIND + TRANSIT_FLAG_OPEN_BEHIND, + TRANSIT_FLAG_KEYGUARD_LOCKED }) @Retention(RetentionPolicy.SOURCE) @interface TransitionFlags {} diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java index 16fd383fa7ff..3c18b6b89af8 100644 --- a/core/java/android/view/contentcapture/MainContentCaptureSession.java +++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java @@ -43,6 +43,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.IBinder.DeathRecipient; import android.os.RemoteException; +import android.text.TextUtils; import android.util.LocalLog; import android.util.Log; import android.util.TimeUtils; @@ -334,15 +335,22 @@ public final class MainContentCaptureSession extends ContentCaptureSession { if (!mEvents.isEmpty() && eventType == TYPE_VIEW_TEXT_CHANGED) { final ContentCaptureEvent lastEvent = mEvents.get(mEvents.size() - 1); - // TODO(b/121045053): check if flags match + // We merge two consecutive text change event, unless one of them clears the text. if (lastEvent.getType() == TYPE_VIEW_TEXT_CHANGED && lastEvent.getId().equals(event.getId())) { - if (sVerbose) { + boolean bothNonEmpty = !TextUtils.isEmpty(lastEvent.getText()) + && !TextUtils.isEmpty(event.getText()); + boolean equalContent = TextUtils.equals(lastEvent.getText(), event.getText()); + if (equalContent) { + addEvent = false; + } else if (bothNonEmpty) { + lastEvent.mergeEvent(event); + addEvent = false; + } + if (!addEvent && sVerbose) { Log.v(TAG, "Buffering VIEW_TEXT_CHANGED event, updated text=" + getSanitizedString(event.getText())); } - lastEvent.mergeEvent(event); - addEvent = false; } } diff --git a/core/java/android/view/textservice/OWNERS b/core/java/android/view/textservice/OWNERS index a637754ba17a..582be8dc4594 100644 --- a/core/java/android/view/textservice/OWNERS +++ b/core/java/android/view/textservice/OWNERS @@ -1,5 +1,3 @@ # Bug component: 34867 -ogunwale@google.com -roosa@google.com -yukawa@google.com +include ../inputmethod/OWNERS diff --git a/core/java/android/widget/OWNERS b/core/java/android/widget/OWNERS index fbb975b806f1..718076b49f77 100644 --- a/core/java/android/widget/OWNERS +++ b/core/java/android/widget/OWNERS @@ -7,3 +7,5 @@ aurimas@google.com siyamed@google.com per-file TextView.java, EditText.java, Editor.java = siyamed@google.com, nona@google.com, clarabayarri@google.com + +per-file SpellChecker.java = file:../view/inputmethod/OWNERS diff --git a/core/java/android/window/TaskOrganizer.java b/core/java/android/window/TaskOrganizer.java index c4bdb5a72689..12c4b5b7794a 100644 --- a/core/java/android/window/TaskOrganizer.java +++ b/core/java/android/window/TaskOrganizer.java @@ -210,6 +210,15 @@ public class TaskOrganizer extends WindowOrganizer { } } + /** + * Gets the executor to run callbacks on. + * @hide + */ + @NonNull + public Executor getExecutor() { + return mExecutor; + } + private final ITaskOrganizer mInterface = new ITaskOrganizer.Stub() { @Override public void addStartingWindow(ActivityManager.RunningTaskInfo taskInfo, IBinder appToken) { diff --git a/core/java/android/window/TransitionInfo.java b/core/java/android/window/TransitionInfo.java index b4e7d6a9269f..52ab38fa2889 100644 --- a/core/java/android/window/TransitionInfo.java +++ b/core/java/android/window/TransitionInfo.java @@ -16,6 +16,13 @@ package android.window; +import static android.view.WindowManager.TRANSIT_CHANGE; +import static android.view.WindowManager.TRANSIT_CLOSE; +import static android.view.WindowManager.TRANSIT_NONE; +import static android.view.WindowManager.TRANSIT_OPEN; +import static android.view.WindowManager.TRANSIT_TO_BACK; +import static android.view.WindowManager.TRANSIT_TO_FRONT; + import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -35,48 +42,38 @@ import java.util.List; */ public final class TransitionInfo implements Parcelable { - /** No transition mode. This is a placeholder, don't use this as an actual mode. */ - public static final int TRANSIT_NONE = 0; - - /** The container didn't exist before but will exist and be visible after. */ - public static final int TRANSIT_OPEN = 1; - - /** The container existed and was visible before but won't exist after. */ - public static final int TRANSIT_CLOSE = 2; - - /** The container existed before but was invisible and will be visible after. */ - public static final int TRANSIT_SHOW = 3; - - /** The container is going from visible to invisible but it will still exist after. */ - public static final int TRANSIT_HIDE = 4; - - /** The container exists and is visible before and after but it changes. */ - public static final int TRANSIT_CHANGE = 5; - - /** @hide */ + /** + * Modes are only a sub-set of all the transit-types since they are per-container + * @hide + */ @IntDef(prefix = { "TRANSIT_" }, value = { TRANSIT_NONE, TRANSIT_OPEN, TRANSIT_CLOSE, - TRANSIT_SHOW, - TRANSIT_HIDE, + // Note: to_front/to_back really mean show/hide respectively at the container level. + TRANSIT_TO_FRONT, + TRANSIT_TO_BACK, TRANSIT_CHANGE }) public @interface TransitionMode {} private final @WindowManager.TransitionOldType int mType; + private final @WindowManager.TransitionFlags int mFlags; private final ArrayList<Change> mChanges = new ArrayList<>(); private SurfaceControl mRootLeash; private final Point mRootOffset = new Point(); /** @hide */ - public TransitionInfo(@WindowManager.TransitionOldType int type) { + public TransitionInfo(@WindowManager.TransitionOldType int type, + @WindowManager.TransitionFlags int flags) { mType = type; + mFlags = flags; } private TransitionInfo(Parcel in) { mType = in.readInt(); + mFlags = in.readInt(); in.readList(mChanges, null /* classLoader */); mRootLeash = new SurfaceControl(); mRootLeash.readFromParcel(in); @@ -87,6 +84,7 @@ public final class TransitionInfo implements Parcelable { /** @hide */ public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeInt(mType); + dest.writeInt(mFlags); dest.writeList(mChanges); mRootLeash.writeToParcel(dest, flags); mRootOffset.writeToParcel(dest, flags); @@ -122,6 +120,10 @@ public final class TransitionInfo implements Parcelable { return mType; } + public int getFlags() { + return mFlags; + } + /** * @return a surfacecontrol that can serve as a parent surfacecontrol for all the changing * participants to animate within. This will generally be placed at the highest-z-order @@ -170,7 +172,8 @@ public final class TransitionInfo implements Parcelable { @Override public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("{t=" + mType + " ro=" + mRootOffset + " c=["); + sb.append("{t=" + mType + " f=" + Integer.toHexString(mFlags) + + " ro=" + mRootOffset + " c=["); for (int i = 0; i < mChanges.size(); ++i) { if (i > 0) { sb.append(','); @@ -188,8 +191,8 @@ public final class TransitionInfo implements Parcelable { case TRANSIT_NONE: return "NONE"; case TRANSIT_OPEN: return "OPEN"; case TRANSIT_CLOSE: return "CLOSE"; - case TRANSIT_SHOW: return "SHOW"; - case TRANSIT_HIDE: return "HIDE"; + case TRANSIT_TO_FRONT: return "SHOW"; + case TRANSIT_TO_BACK: return "HIDE"; case TRANSIT_CHANGE: return "CHANGE"; default: return "<unknown:" + mode + ">"; } @@ -200,7 +203,7 @@ public final class TransitionInfo implements Parcelable { private final WindowContainerToken mContainer; private WindowContainerToken mParent; private final SurfaceControl mLeash; - private int mMode = TRANSIT_NONE; + private @TransitionMode int mMode = TRANSIT_NONE; private final Rect mStartAbsBounds = new Rect(); private final Rect mEndAbsBounds = new Rect(); private final Point mEndRelOffset = new Point(); diff --git a/core/java/com/android/internal/app/IAppOpsNotedCallback.aidl b/core/java/com/android/internal/app/IAppOpsNotedCallback.aidl index fa5c30a03e78..cb280cd14180 100644 --- a/core/java/com/android/internal/app/IAppOpsNotedCallback.aidl +++ b/core/java/com/android/internal/app/IAppOpsNotedCallback.aidl @@ -18,5 +18,5 @@ package com.android.internal.app; // Iterface to observe op note/checks of ops oneway interface IAppOpsNotedCallback { - void opNoted(int op, int uid, String packageName, int mode); + void opNoted(int op, int uid, String packageName, int flags, int mode); } diff --git a/core/java/com/android/internal/app/IAppOpsStartedCallback.aidl b/core/java/com/android/internal/app/IAppOpsStartedCallback.aidl index ed521e656981..b0cb2a8ceb64 100644 --- a/core/java/com/android/internal/app/IAppOpsStartedCallback.aidl +++ b/core/java/com/android/internal/app/IAppOpsStartedCallback.aidl @@ -18,5 +18,5 @@ package com.android.internal.app; // Iterface to observe op starts oneway interface IAppOpsStartedCallback { - void opStarted(int op, int uid, String packageName, int mode); + void opStarted(int op, int uid, String packageName, int flags, int mode); } diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java index 3e1fa1d5fe59..0f37dc5949f9 100644 --- a/core/java/com/android/internal/app/IntentForwarderActivity.java +++ b/core/java/com/android/internal/app/IntentForwarderActivity.java @@ -24,7 +24,6 @@ import static com.android.internal.app.ResolverActivity.EXTRA_SELECTED_PROFILE; import android.annotation.Nullable; import android.annotation.StringRes; import android.app.Activity; -import android.app.ActivityTaskManager; import android.app.ActivityThread; import android.app.AppGlobals; import android.app.admin.DevicePolicyManager; @@ -199,18 +198,8 @@ public class IntentForwarderActivity extends Activity { /* ignoreTargetSecurity= */ false, userId); } catch (RuntimeException e) { - int launchedFromUid = -1; - String launchedFromPackage = "?"; - try { - launchedFromUid = ActivityTaskManager.getService().getLaunchedFromUid( - getActivityToken()); - launchedFromPackage = ActivityTaskManager.getService() - .getLaunchedFromPackage(getActivityToken()); - } catch (RemoteException ignored) { - } - - Slog.wtf(TAG, "Unable to launch as UID " + launchedFromUid + " package " - + launchedFromPackage + ", while running in " + Slog.wtf(TAG, "Unable to launch as UID " + getLaunchedFromUid() + " package " + + getLaunchedFromPackage() + ", while running in " + ActivityThread.currentProcessName(), e); } } diff --git a/core/java/com/android/internal/app/OWNERS b/core/java/com/android/internal/app/OWNERS new file mode 100644 index 000000000000..108ab92f0e9b --- /dev/null +++ b/core/java/com/android/internal/app/OWNERS @@ -0,0 +1 @@ +per-file *AppOp* = file:/core/java/android/permission/OWNERS diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index 1a640d3acf66..6f9da6fa94a3 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -350,13 +350,7 @@ public class ResolverActivity extends Activity implements // from managed profile to owner or other way around. setProfileSwitchMessageId(intent.getContentUserHint()); - try { - mLaunchedFromUid = ActivityTaskManager.getService().getLaunchedFromUid( - getActivityToken()); - } catch (RemoteException e) { - mLaunchedFromUid = -1; - } - + mLaunchedFromUid = getLaunchedFromUid(); if (mLaunchedFromUid < 0 || UserHandle.isIsolated(mLaunchedFromUid)) { // Gulp! finish(); @@ -1300,15 +1294,8 @@ public class ResolverActivity extends Activity implements maybeLogCrossProfileTargetLaunch(cti, currentUserHandle); } } catch (RuntimeException e) { - String launchedFromPackage; - try { - launchedFromPackage = ActivityTaskManager.getService().getLaunchedFromPackage( - getActivityToken()); - } catch (RemoteException e2) { - launchedFromPackage = "??"; - } Slog.wtf(TAG, "Unable to launch as uid " + mLaunchedFromUid - + " package " + launchedFromPackage + ", while running in " + + " package " + getLaunchedFromPackage() + ", while running in " + ActivityThread.currentProcessName(), e); } } diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java index 777534e72d73..13358daf05a1 100644 --- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java +++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java @@ -47,6 +47,21 @@ public final class SystemUiDeviceConfigFlags { */ public static final String NAS_MAX_SUGGESTIONS = "nas_max_suggestions"; + /** + * Whether the Notification Assistant can change ranking. + */ + public static final String ENABLE_NAS_RANKING = "enable_nas_ranking"; + + /** + * Whether the Notification Assistant can prioritize notification. + */ + public static final String ENABLE_NAS_PRIORITIZER = "enable_nas_prioritizer"; + + /** + * Whether to enable feedback UI for Notification Assistant + */ + public static final String ENABLE_NAS_FEEDBACK = "enable_nas_feedback"; + // Flags related to screenshot intelligence /** diff --git a/core/java/com/android/internal/inputmethod/CallbackUtils.java b/core/java/com/android/internal/inputmethod/CallbackUtils.java index ec6779216ae5..a315e5a4fc94 100644 --- a/core/java/com/android/internal/inputmethod/CallbackUtils.java +++ b/core/java/com/android/internal/inputmethod/CallbackUtils.java @@ -45,8 +45,21 @@ public final class CallbackUtils { @AnyThread public static void onResult(@NonNull IInputBindResultResultCallback callback, @NonNull Supplier<InputBindResult> resultSupplier) { + InputBindResult result = null; + Throwable exception = null; + + try { + result = resultSupplier.get(); + } catch (Throwable throwable) { + exception = throwable; + } + try { - callback.onResult(resultSupplier.get()); + 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 b9e1cf09dc07..bd8c23e66e51 100644 --- a/core/java/com/android/internal/inputmethod/Completable.java +++ b/core/java/com/android/internal/inputmethod/Completable.java @@ -16,13 +16,17 @@ package com.android.internal.inputmethod; +import static java.lang.annotation.RetentionPolicy.SOURCE; + import android.annotation.AnyThread; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.util.Log; import com.android.internal.annotations.GuardedBy; +import java.lang.annotation.Retention; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -51,21 +55,100 @@ public final class Completable { /** * Lock {@link Object} to guard complete operations within this class. */ - protected final Object mValueLock = new Object(); + protected final Object mStateLock = new Object(); /** - * {@code true} after {@link #onComplete()} gets called. + * Indicates the completion state of this object. */ - @GuardedBy("mValueLock") - protected boolean mHasValue = false; + @GuardedBy("mStateLock") + @CompletionState + protected int mState = CompletionState.NOT_COMPLETED; /** - * @return {@link true} if {@link #onComplete()} gets called already. + * {@link Throwable} message passed to {@link #onError(ThrowableHolder)}. + * + * <p>This is not {@code null} only when {@link #mState} is + * {@link CompletionState#COMPLETED_WITH_ERROR}.</p> + */ + @GuardedBy("mStateLock") + @Nullable + protected String mMessage = null; + + @Retention(SOURCE) + @IntDef({ + CompletionState.NOT_COMPLETED, + CompletionState.COMPLETED_WITH_VALUE, + CompletionState.COMPLETED_WITH_ERROR}) + protected @interface CompletionState { + /** + * This object is not completed yet. + */ + int NOT_COMPLETED = 0; + /** + * This object is already completed with a value. + */ + int COMPLETED_WITH_VALUE = 1; + /** + * This object is already completed with an error. + */ + int COMPLETED_WITH_ERROR = 2; + } + + /** + * Converts the given {@link CompletionState} into a human-readable string. + * + * @param state {@link CompletionState} to be converted. + * @return a human-readable {@link String} for the given {@code state}. + */ + @AnyThread + protected static String stateToString(@CompletionState int state) { + switch (state) { + case CompletionState.NOT_COMPLETED: + return "NOT_COMPLETED"; + case CompletionState.COMPLETED_WITH_VALUE: + return "COMPLETED_WITH_VALUE"; + case CompletionState.COMPLETED_WITH_ERROR: + return "COMPLETED_WITH_ERROR"; + default: + return "Unknown(value=" + state + ")"; + } + } + + /** + * @return {@link true} if {@link #onComplete()} gets called and {@link #mState} is + * {@link CompletionState#COMPLETED_WITH_VALUE} . */ @AnyThread public boolean hasValue() { - synchronized (mValueLock) { - return mHasValue; + synchronized (mStateLock) { + return mState == CompletionState.COMPLETED_WITH_VALUE; + } + } + + /** + * Provides the base implementation of {@code getValue()} for derived classes. + * + * <p>Must be called after acquiring {@link #mStateLock}.</p> + * + * @throws RuntimeException when {@link #mState} is + * {@link CompletionState#COMPLETED_WITH_ERROR}. + * @throws UnsupportedOperationException when {@link #mState} is not + * {@link CompletionState#COMPLETED_WITH_VALUE} and + * {@link CompletionState#COMPLETED_WITH_ERROR}. + */ + @GuardedBy("mStateLock") + protected void enforceGetValueLocked() { + switch (mState) { + case CompletionState.NOT_COMPLETED: + throw new UnsupportedOperationException( + "getValue() is allowed only if hasValue() returns true"); + case CompletionState.COMPLETED_WITH_VALUE: + return; + case CompletionState.COMPLETED_WITH_ERROR: + throw new RuntimeException(mMessage); + default: + throw new UnsupportedOperationException( + "getValue() is not allowed on state=" + stateToString(mState)); } } @@ -78,6 +161,27 @@ public final class Completable { } /** + * Notify when exception happened. + * + * @param throwableHolder contains the {@link Throwable} object when exception happened. + */ + @AnyThread + protected void onError(ThrowableHolder throwableHolder) { + synchronized (mStateLock) { + switch (mState) { + case CompletionState.NOT_COMPLETED: + mMessage = throwableHolder.getMessage(); + mState = CompletionState.COMPLETED_WITH_ERROR; + break; + default: + throw new UnsupportedOperationException( + "onError() is not allowed on state=" + stateToString(mState)); + } + } + onComplete(); + } + + /** * Blocks the calling thread until at least one of the following conditions is met. * * <p> @@ -140,7 +244,7 @@ public final class Completable { * Completable object of integer primitive. */ public static final class Int extends ValueBase { - @GuardedBy("mValueLock") + @GuardedBy("mStateLock") private int mValue = 0; /** @@ -150,29 +254,30 @@ public final class Completable { */ @AnyThread void onComplete(int value) { - synchronized (mValueLock) { - if (mHasValue) { - throw new UnsupportedOperationException( - "onComplete() cannot be called multiple times"); + synchronized (mStateLock) { + switch (mState) { + case CompletionState.NOT_COMPLETED: + mValue = value; + mState = CompletionState.COMPLETED_WITH_VALUE; + break; + default: + throw new UnsupportedOperationException( + "onComplete() is not allowed on state=" + stateToString(mState)); } - mValue = value; - mHasValue = true; } onComplete(); } /** * @return value associated with this object. + * @throws RuntimeException when called while {@link #onError} happened. * @throws UnsupportedOperationException when called while {@link #hasValue()} returns * {@code false}. */ @AnyThread public int getValue() { - synchronized (mValueLock) { - if (!mHasValue) { - throw new UnsupportedOperationException( - "getValue() is allowed only if hasValue() returns true"); - } + synchronized (mStateLock) { + enforceGetValueLocked(); return mValue; } } @@ -184,7 +289,7 @@ public final class Completable { * @param <T> type associated with this completable object. */ public static class Values<T> extends ValueBase { - @GuardedBy("mValueLock") + @GuardedBy("mStateLock") @Nullable private T mValue = null; @@ -195,30 +300,31 @@ public final class Completable { */ @AnyThread void onComplete(@Nullable T value) { - synchronized (mValueLock) { - if (mHasValue) { - throw new UnsupportedOperationException( - "onComplete() cannot be called multiple times"); + synchronized (mStateLock) { + switch (mState) { + case CompletionState.NOT_COMPLETED: + mValue = value; + mState = CompletionState.COMPLETED_WITH_VALUE; + break; + default: + throw new UnsupportedOperationException( + "onComplete() is not allowed on state=" + stateToString(mState)); } - mValue = value; - mHasValue = true; } onComplete(); } /** * @return value associated with this object. + * @throws RuntimeException when called while {@link #onError} happened * @throws UnsupportedOperationException when called while {@link #hasValue()} returns * {@code false}. */ @AnyThread @Nullable public T getValue() { - synchronized (mValueLock) { - if (!mHasValue) { - throw new UnsupportedOperationException( - "getValue() is allowed only if hasValue() returns true"); - } + synchronized (mStateLock) { + enforceGetValueLocked(); return mValue; } } diff --git a/core/java/com/android/internal/inputmethod/IInputBindResultResultCallback.aidl b/core/java/com/android/internal/inputmethod/IInputBindResultResultCallback.aidl index b52b3b100ed0..269198404873 100644 --- a/core/java/com/android/internal/inputmethod/IInputBindResultResultCallback.aidl +++ b/core/java/com/android/internal/inputmethod/IInputBindResultResultCallback.aidl @@ -17,7 +17,9 @@ package com.android.internal.inputmethod; import com.android.internal.view.InputBindResult; +import com.android.internal.inputmethod.ThrowableHolder; oneway interface IInputBindResultResultCallback { void onResult(in InputBindResult 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 c59dcf4ce420..1929b6f22f8b 100644 --- a/core/java/com/android/internal/inputmethod/ResultCallbacks.java +++ b/core/java/com/android/internal/inputmethod/ResultCallbacks.java @@ -181,6 +181,16 @@ public final class ResultCallbacks { } value.onComplete(result); } + + @BinderThread + @Override + public void onError(ThrowableHolder throwableHolder) { + final Completable.InputBindResult value = unwrap(atomicRef); + if (value == null) { + return; + } + value.onError(throwableHolder); + } }; } } diff --git a/core/java/com/android/internal/inputmethod/ThrowableHolder.aidl b/core/java/com/android/internal/inputmethod/ThrowableHolder.aidl new file mode 100644 index 000000000000..ed1129345061 --- /dev/null +++ b/core/java/com/android/internal/inputmethod/ThrowableHolder.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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.inputmethod; + +parcelable ThrowableHolder;
\ No newline at end of file diff --git a/core/java/com/android/internal/inputmethod/ThrowableHolder.java b/core/java/com/android/internal/inputmethod/ThrowableHolder.java new file mode 100644 index 000000000000..b6f449864e54 --- /dev/null +++ b/core/java/com/android/internal/inputmethod/ThrowableHolder.java @@ -0,0 +1,91 @@ +/* + * 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.inputmethod; + +import android.annotation.AnyThread; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * A {@link Parcelable} helper class to encapsulate the exception information. + */ +public final class ThrowableHolder implements Parcelable { + + @Nullable + private final String mMessage; + + ThrowableHolder(@NonNull Throwable throwable) { + mMessage = throwable.getMessage(); + } + + ThrowableHolder(Parcel source) { + mMessage = source.readString(); + } + + /** + * Returns a {@link ThrowableHolder} with given {@link Throwable}. + */ + @NonNull + @AnyThread + public static ThrowableHolder of(@NonNull Throwable throwable) { + return new ThrowableHolder(throwable); + } + + /** + * Gets the message in this {@link ThrowableHolder}. + */ + @Nullable + @AnyThread + String getMessage() { + return mMessage; + } + + @Override + public int describeContents() { + return 0; + } + + /** + * Used to package this object into a {@link Parcel}. + * + * @param dest The {@link Parcel} to be written. + * @param flags The flags used for parceling. + */ + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(mMessage); + } + + /** + * Used to make this class parcelable. + */ + public static final Parcelable.Creator<ThrowableHolder> CREATOR = + new Parcelable.Creator<ThrowableHolder>() { + + @Override + public ThrowableHolder createFromParcel(Parcel source) { + return new ThrowableHolder(source); + } + + @Override + public ThrowableHolder[] newArray(int size) { + return new ThrowableHolder[size]; + } + }; +} diff --git a/core/java/com/android/internal/jank/OWNERS b/core/java/com/android/internal/jank/OWNERS new file mode 100644 index 000000000000..352c132fda4f --- /dev/null +++ b/core/java/com/android/internal/jank/OWNERS @@ -0,0 +1,6 @@ +include /services/core/java/com/android/server/wm/OWNERS + +# Jank people +ahanwu@google.com +vadimt@google.com +marcinoc@google.com
\ No newline at end of file diff --git a/core/java/com/android/internal/net/OWNERS b/core/java/com/android/internal/net/OWNERS index fec56c3cc506..050cb5c2b44e 100644 --- a/core/java/com/android/internal/net/OWNERS +++ b/core/java/com/android/internal/net/OWNERS @@ -3,7 +3,7 @@ set noparent codewiz@google.com ek@google.com jchalard@google.com -jsharkey@google.com +jsharkey@android.com lorenzo@google.com reminv@google.com satk@google.com diff --git a/core/java/com/android/internal/notification/OWNERS b/core/java/com/android/internal/notification/OWNERS new file mode 100644 index 000000000000..396fd1213aca --- /dev/null +++ b/core/java/com/android/internal/notification/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/notification/OWNERS diff --git a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java index 62e9f98181ab..b97fdc90b4e0 100644 --- a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java +++ b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java @@ -17,13 +17,17 @@ package com.android.internal.os; import android.content.Context; -import android.os.BatteryConsumer; +import android.hardware.SensorManager; +import android.net.ConnectivityManager; import android.os.BatteryStats; import android.os.BatteryUsageStats; import android.os.Bundle; -import android.os.UidBatteryConsumer; +import android.os.SystemClock; +import android.os.UserHandle; import android.os.UserManager; +import android.util.SparseArray; +import java.util.ArrayList; import java.util.List; /** @@ -33,10 +37,53 @@ import java.util.List; public class BatteryUsageStatsProvider { private final Context mContext; private final BatteryStatsImpl mStats; + private final PowerProfile mPowerProfile; + private final Object mLock = new Object(); + private List<PowerCalculator> mPowerCalculators; public BatteryUsageStatsProvider(Context context, BatteryStatsImpl stats) { mContext = context; mStats = stats; + mPowerProfile = new PowerProfile(mContext); + } + + private List<PowerCalculator> getPowerCalculators() { + synchronized (mLock) { + if (mPowerCalculators == null) { + mPowerCalculators = new ArrayList<>(); + + // Power calculators are applied in the order of registration + mPowerCalculators.add(new CpuPowerCalculator(mPowerProfile)); + mPowerCalculators.add(new MemoryPowerCalculator(mPowerProfile)); + mPowerCalculators.add(new WakelockPowerCalculator(mPowerProfile)); + if (!isWifiOnlyDevice(mContext)) { + mPowerCalculators.add(new MobileRadioPowerCalculator(mPowerProfile)); + } + mPowerCalculators.add(new WifiPowerCalculator(mPowerProfile)); + mPowerCalculators.add(new BluetoothPowerCalculator(mPowerProfile)); + mPowerCalculators.add(new SensorPowerCalculator(mPowerProfile, + mContext.getSystemService(SensorManager.class))); + mPowerCalculators.add(new CameraPowerCalculator(mPowerProfile)); + mPowerCalculators.add(new FlashlightPowerCalculator(mPowerProfile)); + mPowerCalculators.add(new MediaPowerCalculator(mPowerProfile)); + mPowerCalculators.add(new PhonePowerCalculator(mPowerProfile)); + mPowerCalculators.add(new ScreenPowerCalculator(mPowerProfile)); + mPowerCalculators.add(new AmbientDisplayPowerCalculator(mPowerProfile)); + mPowerCalculators.add(new SystemServicePowerCalculator(mPowerProfile)); + mPowerCalculators.add(new IdlePowerCalculator(mPowerProfile)); + + mPowerCalculators.add(new UserPowerCalculator()); + } + } + return mPowerCalculators; + } + + private static boolean isWifiOnlyDevice(Context context) { + ConnectivityManager cm = context.getSystemService(ConnectivityManager.class); + if (cm == null) { + return false; + } + return !cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE); } /** @@ -49,28 +96,43 @@ public class BatteryUsageStatsProvider { false /* collectBatteryBroadcast */); batteryStatsHelper.create((Bundle) null); final UserManager userManager = mContext.getSystemService(UserManager.class); - batteryStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, - userManager.getUserProfiles()); + final List<UserHandle> asUsers = userManager.getUserProfiles(); + final int n = asUsers.size(); + SparseArray<UserHandle> users = new SparseArray<>(n); + for (int i = 0; i < n; ++i) { + UserHandle userHandle = asUsers.get(i); + users.put(userHandle.getIdentifier(), userHandle); + } + + batteryStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, users); // TODO(b/174186358): read extra power component number from configuration final int customPowerComponentCount = 0; - final BatteryUsageStats.Builder batteryUsageStatsBuilder = new BatteryUsageStats.Builder() - .setDischargePercentage(batteryStatsHelper.getStats().getDischargeAmount(0)) - .setConsumedPower(batteryStatsHelper.getTotalPower()); + final int customTimeComponentCount = 0; + final BatteryUsageStats.Builder batteryUsageStatsBuilder = + new BatteryUsageStats.Builder(customPowerComponentCount, customTimeComponentCount) + .setDischargePercentage(batteryStatsHelper.getStats().getDischargeAmount(0)) + .setConsumedPower(batteryStatsHelper.getTotalPower()); final List<BatterySipper> usageList = batteryStatsHelper.getUsageList(); for (int i = 0; i < usageList.size(); i++) { final BatterySipper sipper = usageList.get(i); if (sipper.drainType == BatterySipper.DrainType.APP) { - batteryUsageStatsBuilder.addUidBatteryConsumer( - new UidBatteryConsumer.Builder(customPowerComponentCount, sipper.getUid()) - .setPackageWithHighestDrain(sipper.packageWithHighestDrain) - .setConsumedPower(sipper.sumPower()) - .setConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU, - sipper.cpuPowerMah) - .build()); + batteryUsageStatsBuilder.getOrCreateUidBatteryConsumerBuilder(sipper.uidObj) + .setPackageWithHighestDrain(sipper.packageWithHighestDrain) + .setConsumedPower(sipper.sumPower()); } } + + final long realtimeUs = SystemClock.elapsedRealtime() * 1000; + final long uptimeUs = SystemClock.uptimeMillis() * 1000; + + final List<PowerCalculator> powerCalculators = getPowerCalculators(); + for (PowerCalculator powerCalculator : powerCalculators) { + powerCalculator.calculate(batteryUsageStatsBuilder, mStats, realtimeUs, uptimeUs, + BatteryStats.STATS_SINCE_CHARGED, users); + } + return batteryUsageStatsBuilder.build(); } } diff --git a/core/java/com/android/internal/os/CpuPowerCalculator.java b/core/java/com/android/internal/os/CpuPowerCalculator.java index dac62a678665..0f0839c8430c 100644 --- a/core/java/com/android/internal/os/CpuPowerCalculator.java +++ b/core/java/com/android/internal/os/CpuPowerCalculator.java @@ -16,6 +16,7 @@ package com.android.internal.os; import android.os.BatteryStats; +import android.os.UidBatteryConsumer; import android.util.ArrayMap; import android.util.Log; @@ -30,9 +31,9 @@ public class CpuPowerCalculator extends PowerCalculator { } @Override - protected void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs, - long rawUptimeUs, int statsType) { - app.cpuTimeMs = (u.getUserCpuTimeUs(statsType) + u.getSystemCpuTimeUs(statsType)) / 1000; + protected void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u, + long rawRealtimeUs, long rawUptimeUs, int statsType) { + long cpuTimeMs = (u.getUserCpuTimeUs(statsType) + u.getSystemCpuTimeUs(statsType)) / 1000; final int numClusters = mProfile.getNumCpuClusters(); double cpuPowerMaUs = 0; @@ -70,47 +71,53 @@ public class CpuPowerCalculator extends PowerCalculator { + numClusters + " actual # " + cpuClusterTimes.length); } } - app.cpuPowerMah = cpuPowerMaUs / MICROSEC_IN_HR; + final double cpuPowerMah = cpuPowerMaUs / MICROSEC_IN_HR; - if (DEBUG && (app.cpuTimeMs != 0 || app.cpuPowerMah != 0)) { - Log.d(TAG, "UID " + u.getUid() + ": CPU time=" + app.cpuTimeMs + " ms power=" - + formatCharge(app.cpuPowerMah)); + if (DEBUG && (cpuTimeMs != 0 || cpuPowerMah != 0)) { + Log.d(TAG, "UID " + u.getUid() + ": CPU time=" + cpuTimeMs + " ms power=" + + formatCharge(cpuPowerMah)); } // Keep track of the package with highest drain. double highestDrain = 0; - - app.cpuFgTimeMs = 0; + String packageWithHighestDrain = null; + long cpuFgTimeMs = 0; final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats(); final int processStatsCount = processStats.size(); for (int i = 0; i < processStatsCount; i++) { final BatteryStats.Uid.Proc ps = processStats.valueAt(i); final String processName = processStats.keyAt(i); - app.cpuFgTimeMs += ps.getForegroundTime(statsType); + cpuFgTimeMs += ps.getForegroundTime(statsType); final long costValue = ps.getUserTime(statsType) + ps.getSystemTime(statsType) + ps.getForegroundTime(statsType); // Each App can have multiple packages and with multiple running processes. // Keep track of the package who's process has the highest drain. - if (app.packageWithHighestDrain == null || - app.packageWithHighestDrain.startsWith("*")) { + if (packageWithHighestDrain == null || packageWithHighestDrain.startsWith("*")) { highestDrain = costValue; - app.packageWithHighestDrain = processName; + packageWithHighestDrain = processName; } else if (highestDrain < costValue && !processName.startsWith("*")) { highestDrain = costValue; - app.packageWithHighestDrain = processName; + packageWithHighestDrain = processName; } } + // Ensure that the CPU times make sense. - if (app.cpuFgTimeMs > app.cpuTimeMs) { - if (DEBUG && app.cpuFgTimeMs > app.cpuTimeMs + 10000) { + if (cpuFgTimeMs > cpuTimeMs) { + if (DEBUG && cpuFgTimeMs > cpuTimeMs + 10000) { Log.d(TAG, "WARNING! Cputime is more than 10 seconds behind Foreground time"); } // Statistics may not have been gathered yet. - app.cpuTimeMs = app.cpuFgTimeMs; + cpuTimeMs = cpuFgTimeMs; } + + app.setConsumedPower(UidBatteryConsumer.POWER_COMPONENT_CPU, cpuPowerMah) + .setUsageDurationMillis(UidBatteryConsumer.TIME_COMPONENT_CPU, cpuTimeMs) + .setUsageDurationMillis(UidBatteryConsumer.TIME_COMPONENT_CPU_FOREGROUND, + cpuFgTimeMs) + .setPackageWithHighestDrain(packageWithHighestDrain); } } diff --git a/core/java/com/android/internal/os/OWNERS b/core/java/com/android/internal/os/OWNERS index 633d093435ee..8f78b2a3a5ea 100644 --- a/core/java/com/android/internal/os/OWNERS +++ b/core/java/com/android/internal/os/OWNERS @@ -1 +1,8 @@ +per-file *Power* = file:/services/core/java/com/android/server/power/OWNERS per-file *Zygote* = file:/ZYGOTE_OWNERS + +# BatteryStats +per-file BatterySipper.java = file:/BATTERY_STATS_OWNERS +per-file BatteryStats* = file:/BATTERY_STATS_OWNERS +per-file BatteryUsageStats* = file:/BATTERY_STATS_OWNERS +per-file *PowerCalculator* = file:/BATTERY_STATS_OWNERS diff --git a/core/java/com/android/internal/os/PhonePowerCalculator.java b/core/java/com/android/internal/os/PhonePowerCalculator.java index b68899edd81d..27f19c069f7f 100644 --- a/core/java/com/android/internal/os/PhonePowerCalculator.java +++ b/core/java/com/android/internal/os/PhonePowerCalculator.java @@ -16,7 +16,10 @@ package com.android.internal.os; +import android.os.BatteryConsumer; import android.os.BatteryStats; +import android.os.BatteryUsageStats; +import android.os.SystemBatteryConsumer; import android.os.UserHandle; import android.util.SparseArray; @@ -33,6 +36,19 @@ public class PhonePowerCalculator extends PowerCalculator { } @Override + public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats, + long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) { + long phoneOnTimeMs = batteryStats.getPhoneOnTime(rawRealtimeUs, statsType) / 1000; + double phoneOnPower = mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ACTIVE) + * phoneOnTimeMs / (60 * 60 * 1000); + if (phoneOnPower != 0) { + builder.getOrCreateSystemBatteryConsumerBuilder(SystemBatteryConsumer.DRAIN_TYPE_PHONE) + .setConsumedPower(BatteryConsumer.POWER_COMPONENT_USAGE, phoneOnPower) + .setUsageDurationMillis(BatteryConsumer.TIME_COMPONENT_USAGE, phoneOnTimeMs); + } + } + + @Override public void calculate(List<BatterySipper> sippers, BatteryStats batteryStats, long rawRealtimeUs, long rawUptimeUs, int statsType, SparseArray<UserHandle> asUsers) { long phoneOnTimeMs = batteryStats.getPhoneOnTime(rawRealtimeUs, statsType) / 1000; diff --git a/core/java/com/android/internal/os/PowerCalculator.java b/core/java/com/android/internal/os/PowerCalculator.java index f171b0d99acc..23f96d9350a7 100644 --- a/core/java/com/android/internal/os/PowerCalculator.java +++ b/core/java/com/android/internal/os/PowerCalculator.java @@ -16,6 +16,8 @@ package com.android.internal.os; import android.os.BatteryStats; +import android.os.BatteryUsageStats; +import android.os.UidBatteryConsumer; import android.os.UserHandle; import android.util.SparseArray; @@ -55,6 +57,34 @@ public abstract class PowerCalculator { } /** + * Attributes the total amount of power used by this subsystem to various consumers such + * as apps. + * + * @param builder {@link BatteryUsageStats.Builder that contains a list of + * per-UID battery consumer builders for attribution data. + * The calculator may modify the builder and its constituent parts. + * @param batteryStats The recorded battery stats. + * @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 asUsers An array of users for which the attribution is requested. It may + * contain {@link UserHandle#USER_ALL} to indicate that the attribution + * should be performed for all users. + */ + public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats, + long rawRealtimeUs, long rawUptimeUs, int statsType, 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); + } + } + + /** * Calculate the amount of power an app used for this subsystem. * @param app The BatterySipper that represents the power use of an app. * @param u The recorded stats for the app. @@ -66,7 +96,36 @@ public abstract class PowerCalculator { * {@link BatteryStats#STATS_SINCE_UNPLUGGED} are deprecated. */ protected void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs, - long rawUptimeUs, int statsType) {} + long rawUptimeUs, int statsType) { + + // 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); + final UidBatteryConsumer uidBatteryConsumer = builder.build(); + app.cpuPowerMah = uidBatteryConsumer.getConsumedPower( + UidBatteryConsumer.POWER_COMPONENT_CPU); + app.cpuTimeMs = uidBatteryConsumer.getUsageDurationMillis( + UidBatteryConsumer.TIME_COMPONENT_CPU); + app.cpuFgTimeMs = uidBatteryConsumer.getUsageDurationMillis( + UidBatteryConsumer.TIME_COMPONENT_CPU_FOREGROUND); + app.packageWithHighestDrain = uidBatteryConsumer.getPackageWithHighestDrain(); + } + + /** + * Calculate the amount of power an app used for this subsystem. + * @param app The UidBatteryConsumer.Builder that represents the power use of an app. + * @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. + */ + protected void calculateApp(UidBatteryConsumer.Builder app, BatteryStats.Uid u, + long rawRealtimeUs, long rawUptimeUs, int statsType) { + } /** * Reset any state maintained in this calculator. diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java index f89e52d4f91d..141dc79f4c93 100644 --- a/core/java/com/android/internal/policy/PhoneWindow.java +++ b/core/java/com/android/internal/policy/PhoneWindow.java @@ -3140,6 +3140,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { // On TVs, if the app doesn't implement search, we want to launch assist. Bundle args = new Bundle(); args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, event.getDeviceId()); + args.putLong(Intent.EXTRA_TIME, event.getEventTime()); ((SearchManager) getContext().getSystemService(Context.SEARCH_SERVICE)) .launchAssist(args); return true; diff --git a/core/java/com/android/internal/telephony/OWNERS b/core/java/com/android/internal/telephony/OWNERS new file mode 100644 index 000000000000..640baf2297b4 --- /dev/null +++ b/core/java/com/android/internal/telephony/OWNERS @@ -0,0 +1 @@ +include /telephony/OWNERS diff --git a/core/java/com/android/internal/util/BinaryXmlPullParser.java b/core/java/com/android/internal/util/BinaryXmlPullParser.java index ff7743fbe361..68921ade3080 100644 --- a/core/java/com/android/internal/util/BinaryXmlPullParser.java +++ b/core/java/com/android/internal/util/BinaryXmlPullParser.java @@ -414,29 +414,21 @@ public final class BinaryXmlPullParser implements TypedXmlPullParser { mAttributeCount = 0; } - /** - * Search through the pool of currently allocated {@link Attribute} - * instances for one that matches the given name. - */ - private @NonNull Attribute findAttribute(@NonNull String name) - throws XmlPullParserException { + @Override + public int getAttributeIndex(String namespace, String name) { + if (namespace != null && !namespace.isEmpty()) throw illegalNamespace(); for (int i = 0; i < mAttributeCount; i++) { if (Objects.equals(mAttributes[i].name, name)) { - return mAttributes[i]; + return i; } } - throw new XmlPullParserException("Missing attribute " + name); + return -1; } @Override public String getAttributeValue(String namespace, String name) { - if (namespace != null && !namespace.isEmpty()) throw illegalNamespace(); - try { - return findAttribute(name).getValueString(); - } catch (XmlPullParserException e) { - // Missing attributes default to null - return null; - } + final int index = getAttributeIndex(namespace, name); + return mAttributes[index].getValueString(); } @Override @@ -445,66 +437,48 @@ public final class BinaryXmlPullParser implements TypedXmlPullParser { } @Override - public byte[] getAttributeBytesHex(String namespace, String name) - throws XmlPullParserException { - if (namespace != null && !namespace.isEmpty()) throw illegalNamespace(); - return findAttribute(name).getValueBytesHex(); + public byte[] getAttributeBytesHex(int index) throws XmlPullParserException { + return mAttributes[index].getValueBytesHex(); } @Override - public byte[] getAttributeBytesBase64(String namespace, String name) - throws XmlPullParserException { - if (namespace != null && !namespace.isEmpty()) throw illegalNamespace(); - return findAttribute(name).getValueBytesBase64(); + public byte[] getAttributeBytesBase64(int index) throws XmlPullParserException { + return mAttributes[index].getValueBytesBase64(); } @Override - public int getAttributeInt(String namespace, String name) - throws XmlPullParserException { - if (namespace != null && !namespace.isEmpty()) throw illegalNamespace(); - return findAttribute(name).getValueInt(); + public int getAttributeInt(int index) throws XmlPullParserException { + return mAttributes[index].getValueInt(); } @Override - public int getAttributeIntHex(String namespace, String name) - throws XmlPullParserException { - if (namespace != null && !namespace.isEmpty()) throw illegalNamespace(); - return findAttribute(name).getValueIntHex(); + public int getAttributeIntHex(int index) throws XmlPullParserException { + return mAttributes[index].getValueIntHex(); } @Override - public long getAttributeLong(String namespace, String name) - throws XmlPullParserException { - if (namespace != null && !namespace.isEmpty()) throw illegalNamespace(); - return findAttribute(name).getValueLong(); + public long getAttributeLong(int index) throws XmlPullParserException { + return mAttributes[index].getValueLong(); } @Override - public long getAttributeLongHex(String namespace, String name) - throws XmlPullParserException { - if (namespace != null && !namespace.isEmpty()) throw illegalNamespace(); - return findAttribute(name).getValueLongHex(); + public long getAttributeLongHex(int index) throws XmlPullParserException { + return mAttributes[index].getValueLongHex(); } @Override - public float getAttributeFloat(String namespace, String name) - throws XmlPullParserException { - if (namespace != null && !namespace.isEmpty()) throw illegalNamespace(); - return findAttribute(name).getValueFloat(); + public float getAttributeFloat(int index) throws XmlPullParserException { + return mAttributes[index].getValueFloat(); } @Override - public double getAttributeDouble(String namespace, String name) - throws XmlPullParserException { - if (namespace != null && !namespace.isEmpty()) throw illegalNamespace(); - return findAttribute(name).getValueDouble(); + public double getAttributeDouble(int index) throws XmlPullParserException { + return mAttributes[index].getValueDouble(); } @Override - public boolean getAttributeBoolean(String namespace, String name) - throws XmlPullParserException { - if (namespace != null && !namespace.isEmpty()) throw illegalNamespace(); - return findAttribute(name).getValueBoolean(); + public boolean getAttributeBoolean(int index) throws XmlPullParserException { + return mAttributes[index].getValueBoolean(); } @Override diff --git a/core/java/com/android/internal/util/LatencyTracker.java b/core/java/com/android/internal/util/LatencyTracker.java index 8012540ed314..254c2997fa65 100644 --- a/core/java/com/android/internal/util/LatencyTracker.java +++ b/core/java/com/android/internal/util/LatencyTracker.java @@ -86,6 +86,11 @@ public class LatencyTracker { */ public static final int ACTION_FACE_WAKE_AND_UNLOCK = 7; + /** + * Time between the swipe-up gesture and window drawn of recents activity. + */ + public static final int ACTION_START_RECENTS_ANIMATION = 8; + private static final String[] NAMES = new String[]{ "expand panel", "toggle recents", @@ -94,7 +99,9 @@ public class LatencyTracker { "check credential unlocked", "turn on screen", "rotate the screen", - "face wake-and-unlock"}; + "face wake-and-unlock", + "start recents-animation", + }; private static final int[] STATSD_ACTION = new int[]{ FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_EXPAND_PANEL, @@ -105,6 +112,7 @@ public class LatencyTracker { FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_TURN_ON_SCREEN, FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_ROTATE_SCREEN, FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_FACE_WAKE_AND_UNLOCK, + FrameworkStatsLog.UIACTION_LATENCY_REPORTED__ACTION__ACTION_START_RECENTS_ANIMATION, }; private static LatencyTracker sLatencyTracker; @@ -170,6 +178,8 @@ public class LatencyTracker { return "ACTION_ROTATE_SCREEN"; case 8: return "ACTION_FACE_WAKE_AND_UNLOCK"; + case 9: + return "ACTION_START_RECENTS_ANIMATION"; default: throw new IllegalArgumentException("Invalid action"); } diff --git a/core/java/com/android/internal/util/XmlUtils.java b/core/java/com/android/internal/util/XmlUtils.java index 244efc596926..de6b65f36eed 100644 --- a/core/java/com/android/internal/util/XmlUtils.java +++ b/core/java/com/android/internal/util/XmlUtils.java @@ -142,95 +142,104 @@ public class XmlUtils { } @Override - public byte[] getAttributeBytesHex(String namespace, String name) + public byte[] getAttributeBytesHex(int index) throws XmlPullParserException { try { - return HexDump.hexStringToByteArray(getAttributeValue(namespace, name)); + return HexDump.hexStringToByteArray(getAttributeValue(index)); } catch (Exception e) { - throw new XmlPullParserException("Invalid attribute " + name + ": " + e); + throw new XmlPullParserException( + "Invalid attribute " + getAttributeName(index) + ": " + e); } } @Override - public byte[] getAttributeBytesBase64(String namespace, String name) + public byte[] getAttributeBytesBase64(int index) throws XmlPullParserException { try { - return Base64.decode(getAttributeValue(namespace, name), Base64.NO_WRAP); + return Base64.decode(getAttributeValue(index), Base64.NO_WRAP); } catch (Exception e) { - throw new XmlPullParserException("Invalid attribute " + name + ": " + e); + throw new XmlPullParserException( + "Invalid attribute " + getAttributeName(index) + ": " + e); } } @Override - public int getAttributeInt(String namespace, String name) + public int getAttributeInt(int index) throws XmlPullParserException { try { - return Integer.parseInt(getAttributeValue(namespace, name)); + return Integer.parseInt(getAttributeValue(index)); } catch (Exception e) { - throw new XmlPullParserException("Invalid attribute " + name + ": " + e); + throw new XmlPullParserException( + "Invalid attribute " + getAttributeName(index) + ": " + e); } } @Override - public int getAttributeIntHex(String namespace, String name) + public int getAttributeIntHex(int index) throws XmlPullParserException { try { - return Integer.parseInt(getAttributeValue(namespace, name), 16); + return Integer.parseInt(getAttributeValue(index), 16); } catch (Exception e) { - throw new XmlPullParserException("Invalid attribute " + name + ": " + e); + throw new XmlPullParserException( + "Invalid attribute " + getAttributeName(index) + ": " + e); } } @Override - public long getAttributeLong(String namespace, String name) + public long getAttributeLong(int index) throws XmlPullParserException { try { - return Long.parseLong(getAttributeValue(namespace, name)); + return Long.parseLong(getAttributeValue(index)); } catch (Exception e) { - throw new XmlPullParserException("Invalid attribute " + name + ": " + e); + throw new XmlPullParserException( + "Invalid attribute " + getAttributeName(index) + ": " + e); } } @Override - public long getAttributeLongHex(String namespace, String name) + public long getAttributeLongHex(int index) throws XmlPullParserException { try { - return Long.parseLong(getAttributeValue(namespace, name), 16); + return Long.parseLong(getAttributeValue(index), 16); } catch (Exception e) { - throw new XmlPullParserException("Invalid attribute " + name + ": " + e); + throw new XmlPullParserException( + "Invalid attribute " + getAttributeName(index) + ": " + e); } } @Override - public float getAttributeFloat(String namespace, String name) + public float getAttributeFloat(int index) throws XmlPullParserException { try { - return Float.parseFloat(getAttributeValue(namespace, name)); + return Float.parseFloat(getAttributeValue(index)); } catch (Exception e) { - throw new XmlPullParserException("Invalid attribute " + name + ": " + e); + throw new XmlPullParserException( + "Invalid attribute " + getAttributeName(index) + ": " + e); } } @Override - public double getAttributeDouble(String namespace, String name) + public double getAttributeDouble(int index) throws XmlPullParserException { try { - return Double.parseDouble(getAttributeValue(namespace, name)); + return Double.parseDouble(getAttributeValue(index)); } catch (Exception e) { - throw new XmlPullParserException("Invalid attribute " + name + ": " + e); + throw new XmlPullParserException( + "Invalid attribute " + getAttributeName(index) + ": " + e); } } @Override - public boolean getAttributeBoolean(String namespace, String name) + public boolean getAttributeBoolean(int index) throws XmlPullParserException { - final String value = getAttributeValue(namespace, name); + final String value = getAttributeValue(index); if ("true".equalsIgnoreCase(value)) { return true; } else if ("false".equalsIgnoreCase(value)) { return false; } else { - throw new XmlPullParserException("Invalid attribute " + name + ": " + value); + throw new XmlPullParserException( + "Invalid attribute " + getAttributeName(index) + ": " + value); } } } diff --git a/core/java/com/android/internal/util/dump/DualDumpOutputStream.java b/core/java/com/android/internal/util/dump/DualDumpOutputStream.java index 3ac38edaddb4..20419db80e88 100644 --- a/core/java/com/android/internal/util/dump/DualDumpOutputStream.java +++ b/core/java/com/android/internal/util/dump/DualDumpOutputStream.java @@ -18,11 +18,10 @@ package com.android.internal.util.dump; import android.annotation.NonNull; import android.annotation.Nullable; +import android.util.IndentingPrintWriter; import android.util.Log; import android.util.proto.ProtoOutputStream; -import com.android.internal.util.IndentingPrintWriter; - import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; diff --git a/core/java/com/android/internal/view/OWNERS b/core/java/com/android/internal/view/OWNERS new file mode 100644 index 000000000000..851d1f37522a --- /dev/null +++ b/core/java/com/android/internal/view/OWNERS @@ -0,0 +1,20 @@ +# Bug component: 25700 + +file:/core/java/android/view/OWNERS + +# Autofill +per-file IInlineSuggestions*.aidl = file:/core/java/android/service/autofill/OWNERS +per-file InlineSuggestions*.java = file:/core/java/android/service/autofill/OWNERS + +# Ime +per-file *Input* = file:/services/core/java/com/android/server/inputmethod/OWNERS + +# Surface +per-file *Surface* = file:/graphics/java/android/graphics/OWNERS +per-file *Surface* = file:/services/core/java/com/android/server/wm/OWNERS + +# WindowManager +per-file AppearanceRegion = file:/services/core/java/com/android/server/wm/OWNERS +per-file BaseIWIndow.java = file:/services/core/java/com/android/server/wm/OWNERS +per-file RotationPolicy.java = file:/services/core/java/com/android/server/wm/OWNERS +per-file WindowManagerPolicyThread.java = file:/services/core/java/com/android/server/wm/OWNERS diff --git a/core/jni/OWNERS b/core/jni/OWNERS index bcd1278d87e7..54b0340f5ef7 100644 --- a/core/jni/OWNERS +++ b/core/jni/OWNERS @@ -6,21 +6,31 @@ per-file *Camera*,*camera* = shuzhenwang@google.com, yinchiayeh@google.com, zhij per-file android_net_* = codewiz@google.com, jchalard@google.com, lorenzo@google.com, reminv@google.com, satk@google.com # Display -per-file android_hardware_display_* = michaelwr@google.com, santoscordon@google.com +per-file android_hardware_display_* = file:/services/core/java/com/android/server/display/OWNERS # Input -per-file android_hardware_input* = michaelwr@google.com, svv@google.com -per-file android_view_Input* = michaelwr@google.com, svv@google.com -per-file android_view_KeyCharacterMap.* = michaelwr@google.com, svv@google.com -per-file android_view_*KeyEvent.* = michaelwr@google.com, svv@google.com -per-file android_view_*MotionEvent.* = michaelwr@google.com, svv@google.com -per-file android_view_PointerIcon.* = michaelwr@google.com, svv@google.com +per-file android_hardware_input* = file:/services/core/java/com/android/server/input/OWNERS +per-file android_view_Input* = file:/services/core/java/com/android/server/input/OWNERS +per-file android_view_KeyCharacterMap.* = file:/services/core/java/com/android/server/input/OWNERS +per-file android_view_*KeyEvent.* = file:/services/core/java/com/android/server/input/OWNERS +per-file android_view_*MotionEvent.* = file:/services/core/java/com/android/server/input/OWNERS +per-file android_view_PointerIcon.* = file:/services/core/java/com/android/server/input/OWNERS + +# WindowManager +per-file android_graphics_BLASTBufferQueue.cpp = file:/services/core/java/com/android/server/wm/OWNERS +per-file android_view_Surface* = file:/services/core/java/com/android/server/wm/OWNERS + +# Resources +per-file android_content_res_* = file:/core/java/android/content/res/OWNERS +per-file android_util_AssetManager* = file:/core/java/android/content/res/OWNERS +per-file android_util_StringBlock* = file:/core/java/android/content/res/OWNERS +per-file android_util_XmlBlock* = file:/core/java/android/content/res/OWNERS +per-file com_android_internal_content_om_OverlayConfig* = file:/core/java/android/content/res/OWNERS per-file *Zygote* = file:/ZYGOTE_OWNERS per-file Android.bp = file:platform/build/soong:/OWNERS per-file android_animation_* = file:/core/java/android/animation/OWNERS per-file android_app_admin_* = file:/core/java/android/app/admin/OWNERS -per-file android_content_res_* = file:/core/java/android/content/res/OWNERS per-file android_graphics_* = file:/graphics/java/android/graphics/OWNERS per-file android_hardware_Usb* = file:/services/usb/OWNERS per-file android_hardware_display_* = file:/core/java/android/hardware/display/OWNERS diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index 1ca45fe9f70b..a95ee4f12c51 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -48,8 +48,9 @@ static const char* const kClassPathName = "android/media/AudioSystem"; static jclass gArrayListClass; static struct { - jmethodID add; - jmethodID toArray; + jmethodID cstor; + jmethodID add; + jmethodID toArray; } gArrayListMethods; static jclass gBooleanClass; @@ -185,6 +186,9 @@ jmethodID gMidAudioRecordRoutingProxy_release; jclass gClsAudioTrackRoutingProxy; jclass gClsAudioRecordRoutingProxy; +jclass gAudioProfileClass; +jmethodID gAudioProfileCstor; + static Mutex gLock; enum AudioError { @@ -807,13 +811,6 @@ android_media_AudioSystem_checkAudioFlinger(JNIEnv *env, jobject clazz) return (jint) check_AudioSystem_Command(AudioSystem::checkAudioFlinger()); } - -static bool useInChannelMask(audio_port_type_t type, audio_port_role_t role) -{ - return ((type == AUDIO_PORT_TYPE_DEVICE) && (role == AUDIO_PORT_ROLE_SOURCE)) || - ((type == AUDIO_PORT_TYPE_MIX) && (role == AUDIO_PORT_ROLE_SINK)); -} - static void convertAudioGainConfigToNative(JNIEnv *env, struct audio_gain_config *nAudioGainConfig, const jobject jAudioGainConfig, @@ -873,7 +870,7 @@ static jint convertAudioPortConfigToNative(JNIEnv *env, configMask |= AUDIO_PORT_CONFIG_SAMPLE_RATE; } - bool useInMask = useInChannelMask(nAudioPortConfig->type, nAudioPortConfig->role); + bool useInMask = audio_port_config_has_input_direction(nAudioPortConfig); audio_channel_mask_t nMask; jint jMask = env->GetIntField(jAudioPortConfig, gAudioPortConfigFields.mChannelMask); @@ -1000,7 +997,7 @@ static jint convertAudioPortConfigFromNative(JNIEnv *env, audioportCreated = true; } - bool useInMask = useInChannelMask(nAudioPortConfig->type, nAudioPortConfig->role); + bool useInMask = audio_port_config_has_input_direction(nAudioPortConfig); audio_channel_mask_t nMask; jint jMask; @@ -1137,15 +1134,6 @@ exit: return jStatus; } -static bool hasFormat(int* formats, size_t size, int format) { - for (size_t index = 0; index < size; index++) { - if (formats[index] == format) { - return true; // found - } - } - return false; // not found -} - // TODO: pull out to separate file template <typename T, size_t N> static constexpr size_t array_size(const T (&)[N]) { @@ -1167,43 +1155,46 @@ static jintArray convertEncapsulationInfoFromNative(JNIEnv *env, uint32_t encaps return result; } -static jint convertAudioPortFromNative(JNIEnv *env, - jobject *jAudioPort, const struct audio_port *nAudioPort) -{ +static bool isAudioPortArrayCountOutOfBounds(const struct audio_port_v7 *nAudioPort, + std::stringstream &ss) { + ss << " num_audio_profiles " << nAudioPort->num_audio_profiles << " num_gains " + << nAudioPort->num_gains; + if (nAudioPort->num_audio_profiles > array_size(nAudioPort->audio_profiles) || + nAudioPort->num_gains > array_size(nAudioPort->gains)) { + return true; + } + for (size_t i = 0; i < nAudioPort->num_audio_profiles; ++i) { + ss << " (" << i << ") audio profile," + << " num_sample_rates " << nAudioPort->audio_profiles[i].num_sample_rates + << " num_channel_masks " << nAudioPort->audio_profiles[i].num_channel_masks; + if (nAudioPort->audio_profiles[i].num_sample_rates > + array_size(nAudioPort->audio_profiles[i].sample_rates) || + nAudioPort->audio_profiles[i].num_channel_masks > + array_size(nAudioPort->audio_profiles[i].channel_masks)) { + return true; + } + } + return false; +} + +static jint convertAudioPortFromNative(JNIEnv *env, jobject *jAudioPort, + const struct audio_port_v7 *nAudioPort) { jint jStatus = (jint)AUDIO_JAVA_SUCCESS; - jintArray jSamplingRates = NULL; - jintArray jChannelMasks = NULL; - jintArray jChannelIndexMasks = NULL; jintArray jEncapsulationModes = NULL; jintArray jEncapsulationMetadataTypes = NULL; - int* cFormats = NULL; - jintArray jFormats = NULL; jobjectArray jGains = NULL; jobject jHandle = NULL; jobject jAudioPortConfig = NULL; jstring jDeviceName = NULL; + jobject jAudioProfiles = NULL; bool useInMask; - size_t numPositionMasks = 0; - size_t numIndexMasks = 0; - size_t numUniqueFormats = 0; ALOGV("convertAudioPortFromNative id %d role %d type %d name %s", nAudioPort->id, nAudioPort->role, nAudioPort->type, nAudioPort->name); // Verify audio port array count info. - if (nAudioPort->num_sample_rates > array_size(nAudioPort->sample_rates) - || nAudioPort->num_channel_masks > array_size(nAudioPort->channel_masks) - || nAudioPort->num_formats > array_size(nAudioPort->formats) - || nAudioPort->num_gains > array_size(nAudioPort->gains)) { - - std::stringstream ss; - ss << "convertAudioPortFromNative array count out of bounds:" - << " num_sample_rates " << nAudioPort->num_sample_rates - << " num_channel_masks " << nAudioPort->num_channel_masks - << " num_formats " << nAudioPort->num_formats - << " num_gains " << nAudioPort->num_gains - ; - std::string s = ss.str(); + if (std::stringstream ss; isAudioPortArrayCountOutOfBounds(nAudioPort, ss)) { + std::string s = "convertAudioPortFromNative array count out of bounds:" + ss.str(); // Prefer to log through Java wtf instead of native ALOGE. ScopedLocalRef<jclass> jLogClass(env, env->FindClass("android/util/Log")); @@ -1222,69 +1213,68 @@ static jint convertAudioPortFromNative(JNIEnv *env, goto exit; } - jSamplingRates = env->NewIntArray(nAudioPort->num_sample_rates); - if (jSamplingRates == NULL) { + useInMask = audio_has_input_direction(nAudioPort->type, nAudioPort->role); + jAudioProfiles = env->NewObject(gArrayListClass, gArrayListMethods.cstor); + if (jAudioProfiles == nullptr) { jStatus = (jint)AUDIO_JAVA_ERROR; goto exit; } - if (nAudioPort->num_sample_rates) { - env->SetIntArrayRegion(jSamplingRates, 0, nAudioPort->num_sample_rates, - (jint *)nAudioPort->sample_rates); - } - - // count up how many masks are positional and indexed - for(size_t index = 0; index < nAudioPort->num_channel_masks; index++) { - const audio_channel_mask_t mask = nAudioPort->channel_masks[index]; - if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) { - numIndexMasks++; - } else { - numPositionMasks++; + for (size_t i = 0; i < nAudioPort->num_audio_profiles; ++i) { + size_t numPositionMasks = 0; + size_t numIndexMasks = 0; + // count up how many masks are positional and indexed + for (size_t index = 0; index < nAudioPort->audio_profiles[i].num_channel_masks; index++) { + const audio_channel_mask_t mask = nAudioPort->audio_profiles[i].channel_masks[index]; + if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) { + numIndexMasks++; + } else { + numPositionMasks++; + } } - } - jChannelMasks = env->NewIntArray(numPositionMasks); - if (jChannelMasks == NULL) { - jStatus = (jint)AUDIO_JAVA_ERROR; - goto exit; - } - jChannelIndexMasks = env->NewIntArray(numIndexMasks); - if (jChannelIndexMasks == NULL) { - jStatus = (jint)AUDIO_JAVA_ERROR; - goto exit; - } - useInMask = useInChannelMask(nAudioPort->type, nAudioPort->role); + ScopedLocalRef<jintArray> jSamplingRates(env, + env->NewIntArray(nAudioPort->audio_profiles[i] + .num_sample_rates)); + ScopedLocalRef<jintArray> jChannelMasks(env, env->NewIntArray(numPositionMasks)); + ScopedLocalRef<jintArray> jChannelIndexMasks(env, env->NewIntArray(numIndexMasks)); + if (!jSamplingRates.get() || !jChannelMasks.get() || !jChannelIndexMasks.get()) { + jStatus = (jint)AUDIO_JAVA_ERROR; + goto exit; + } - // put the masks in the output arrays - for (size_t maskIndex = 0, posMaskIndex = 0, indexedMaskIndex = 0; - maskIndex < nAudioPort->num_channel_masks; maskIndex++) { - const audio_channel_mask_t mask = nAudioPort->channel_masks[maskIndex]; - if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) { - jint jMask = audio_channel_mask_get_bits(mask); - env->SetIntArrayRegion(jChannelIndexMasks, indexedMaskIndex++, 1, &jMask); - } else { - jint jMask = useInMask ? inChannelMaskFromNative(mask) - : outChannelMaskFromNative(mask); - env->SetIntArrayRegion(jChannelMasks, posMaskIndex++, 1, &jMask); + if (nAudioPort->audio_profiles[i].num_sample_rates) { + env->SetIntArrayRegion(jSamplingRates.get(), 0 /*start*/, + nAudioPort->audio_profiles[i].num_sample_rates, + (jint *)nAudioPort->audio_profiles[i].sample_rates); } - } - // formats - if (nAudioPort->num_formats != 0) { - cFormats = new int[nAudioPort->num_formats]; - for (size_t index = 0; index < nAudioPort->num_formats; index++) { - int format = audioFormatFromNative(nAudioPort->formats[index]); - if (!hasFormat(cFormats, numUniqueFormats, format)) { - cFormats[numUniqueFormats++] = format; + // put the masks in the output arrays + for (size_t maskIndex = 0, posMaskIndex = 0, indexedMaskIndex = 0; + maskIndex < nAudioPort->audio_profiles[i].num_channel_masks; maskIndex++) { + const audio_channel_mask_t mask = + nAudioPort->audio_profiles[i].channel_masks[maskIndex]; + if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) { + jint jMask = audio_channel_mask_get_bits(mask); + env->SetIntArrayRegion(jChannelIndexMasks.get(), indexedMaskIndex++, 1, &jMask); + } else { + jint jMask = + useInMask ? inChannelMaskFromNative(mask) : outChannelMaskFromNative(mask); + env->SetIntArrayRegion(jChannelMasks.get(), posMaskIndex++, 1, &jMask); } } - } - jFormats = env->NewIntArray(numUniqueFormats); - if (jFormats == NULL) { - jStatus = (jint)AUDIO_JAVA_ERROR; - goto exit; - } - if (numUniqueFormats != 0) { - env->SetIntArrayRegion(jFormats, 0, numUniqueFormats, cFormats); + + ScopedLocalRef<jobject> + jAudioProfile(env, + env->NewObject(gAudioProfileClass, gAudioProfileCstor, + audioFormatFromNative( + nAudioPort->audio_profiles[i].format), + jSamplingRates.get(), jChannelMasks.get(), + jChannelIndexMasks.get())); + if (jAudioProfile == nullptr) { + jStatus = (jint)AUDIO_JAVA_ERROR; + goto exit; + } + env->CallBooleanMethod(jAudioProfiles, gArrayListMethods.add, jAudioProfile.get()); } // gains @@ -1342,18 +1332,16 @@ static jint convertAudioPortFromNative(JNIEnv *env, convertEncapsulationInfoFromNative(env, nAudioPort->ext.device .encapsulation_metadata_types); - *jAudioPort = env->NewObject(gAudioDevicePortClass, gAudioDevicePortCstor, jHandle, - jDeviceName, jSamplingRates, jChannelMasks, jChannelIndexMasks, - jFormats, jGains, nAudioPort->ext.device.type, jAddress, - jEncapsulationModes, jEncapsulationMetadataTypes); + *jAudioPort = + env->NewObject(gAudioDevicePortClass, gAudioDevicePortCstor, jHandle, jDeviceName, + jAudioProfiles, jGains, nAudioPort->ext.device.type, jAddress, + jEncapsulationModes, jEncapsulationMetadataTypes); env->DeleteLocalRef(jAddress); } else if (nAudioPort->type == AUDIO_PORT_TYPE_MIX) { ALOGV("convertAudioPortFromNative is a mix"); - *jAudioPort = env->NewObject(gAudioMixPortClass, gAudioMixPortCstor, - jHandle, nAudioPort->ext.mix.handle, - nAudioPort->role, jDeviceName, - jSamplingRates, jChannelMasks, jChannelIndexMasks, - jFormats, jGains); + *jAudioPort = env->NewObject(gAudioMixPortClass, gAudioMixPortCstor, jHandle, + nAudioPort->ext.mix.handle, nAudioPort->role, jDeviceName, + jAudioProfiles, jGains); } else { ALOGE("convertAudioPortFromNative unknown nAudioPort type %d", nAudioPort->type); jStatus = (jint)AUDIO_JAVA_ERROR; @@ -1378,26 +1366,14 @@ exit: if (jDeviceName != NULL) { env->DeleteLocalRef(jDeviceName); } - if (jSamplingRates != NULL) { - env->DeleteLocalRef(jSamplingRates); - } - if (jChannelMasks != NULL) { - env->DeleteLocalRef(jChannelMasks); - } - if (jChannelIndexMasks != NULL) { - env->DeleteLocalRef(jChannelIndexMasks); - } if (jEncapsulationModes != NULL) { env->DeleteLocalRef(jEncapsulationModes); } if (jEncapsulationMetadataTypes != NULL) { env->DeleteLocalRef(jEncapsulationMetadataTypes); } - if (cFormats != NULL) { - delete[] cFormats; - } - if (jFormats != NULL) { - env->DeleteLocalRef(jFormats); + if (jAudioProfiles != NULL) { + env->DeleteLocalRef(jAudioProfiles); } if (jGains != NULL) { env->DeleteLocalRef(jGains); @@ -1436,7 +1412,7 @@ android_media_AudioSystem_listAudioPorts(JNIEnv *env, jobject clazz, unsigned int generation; unsigned int numPorts; jint *nGeneration; - struct audio_port *nPorts = NULL; + struct audio_port_v7 *nPorts = nullptr; int attempts = MAX_PORT_GENERATION_SYNC_ATTEMPTS; jint jStatus; @@ -1448,11 +1424,8 @@ android_media_AudioSystem_listAudioPorts(JNIEnv *env, jobject clazz, } numPorts = 0; - status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE, - AUDIO_PORT_TYPE_NONE, - &numPorts, - NULL, - &generation1); + status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE, AUDIO_PORT_TYPE_NONE, &numPorts, + nullptr, &generation1); if (status != NO_ERROR) { ALOGE_IF(status != NO_ERROR, "AudioSystem::listAudioPorts error %d", status); break; @@ -1461,13 +1434,10 @@ android_media_AudioSystem_listAudioPorts(JNIEnv *env, jobject clazz, jStatus = (jint)AUDIO_JAVA_SUCCESS; goto exit; } - nPorts = (struct audio_port *)realloc(nPorts, numPorts * sizeof(struct audio_port)); + nPorts = (struct audio_port_v7 *)realloc(nPorts, numPorts * sizeof(struct audio_port_v7)); - status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE, - AUDIO_PORT_TYPE_NONE, - &numPorts, - nPorts, - &generation); + status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE, AUDIO_PORT_TYPE_NONE, &numPorts, + nPorts, &generation); ALOGV("listAudioPorts AudioSystem::listAudioPorts numPorts %d generation %d generation1 %d", numPorts, generation, generation1); } while (generation1 != generation && status == NO_ERROR); @@ -2113,10 +2083,9 @@ android_media_AudioSystem_getStreamVolumeDB(JNIEnv *env, jobject thiz, (audio_devices_t)device); } -static jboolean -android_media_AudioSystem_isOffloadSupported(JNIEnv *env, jobject thiz, - jint encoding, jint sampleRate, jint channelMask, jint channelIndexMask, jint streamType) -{ +static jint android_media_AudioSystem_getOffloadSupport(JNIEnv *env, jobject thiz, jint encoding, + jint sampleRate, jint channelMask, + jint channelIndexMask, jint streamType) { audio_offload_info_t format = AUDIO_INFO_INITIALIZER; format.format = (audio_format_t) audioFormatToNative(encoding); format.sample_rate = (uint32_t) sampleRate; @@ -2128,7 +2097,7 @@ android_media_AudioSystem_isOffloadSupported(JNIEnv *env, jobject thiz, // client side code cannot access "audio.offload.min.duration.secs" property to make a query // agnostic of duration, so using acceptable estimate of 2mn format.duration_us = 120 * 1000000; - return AudioSystem::isOffloadSupported(format); + return AudioSystem::getOffloadSupport(format); } static jint @@ -2604,8 +2573,8 @@ static const JNINativeMethod gMethods[] = (void *)android_media_AudioSystem_registerRecordingCallback}, {"systemReady", "()I", (void *)android_media_AudioSystem_systemReady}, {"getStreamVolumeDB", "(III)F", (void *)android_media_AudioSystem_getStreamVolumeDB}, - {"native_is_offload_supported", "(IIIII)Z", - (void *)android_media_AudioSystem_isOffloadSupported}, + {"native_get_offload_support", "(IIIII)I", + (void *)android_media_AudioSystem_getOffloadSupport}, {"getMicrophones", "(Ljava/util/ArrayList;)I", (void *)android_media_AudioSystem_getMicrophones}, {"getSurroundFormats", "(Ljava/util/Map;Z)I", @@ -2671,6 +2640,7 @@ int register_android_media_AudioSystem(JNIEnv *env) jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList"); gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass); + gArrayListMethods.cstor = GetMethodIDOrDie(env, arrayListClass, "<init>", "()V"); gArrayListMethods.add = GetMethodIDOrDie(env, arrayListClass, "add", "(Ljava/lang/Object;)Z"); gArrayListMethods.toArray = GetMethodIDOrDie(env, arrayListClass, "toArray", "()[Ljava/lang/Object;"); @@ -2733,7 +2703,7 @@ int register_android_media_AudioSystem(JNIEnv *env) gAudioDevicePortClass = MakeGlobalRefOrDie(env, audioDevicePortClass); gAudioDevicePortCstor = GetMethodIDOrDie(env, audioDevicePortClass, "<init>", - "(Landroid/media/AudioHandle;Ljava/lang/String;[I[I[I[I" + "(Landroid/media/AudioHandle;Ljava/lang/String;Ljava/util/List;" "[Landroid/media/AudioGain;ILjava/lang/String;[I[I)V"); // When access AudioPort as AudioDevicePort @@ -2743,8 +2713,10 @@ int register_android_media_AudioSystem(JNIEnv *env) jclass audioMixPortClass = FindClassOrDie(env, "android/media/AudioMixPort"); gAudioMixPortClass = MakeGlobalRefOrDie(env, audioMixPortClass); - gAudioMixPortCstor = GetMethodIDOrDie(env, audioMixPortClass, "<init>", - "(Landroid/media/AudioHandle;IILjava/lang/String;[I[I[I[I[Landroid/media/AudioGain;)V"); + gAudioMixPortCstor = + GetMethodIDOrDie(env, audioMixPortClass, "<init>", + "(Landroid/media/AudioHandle;IILjava/lang/String;Ljava/util/List;" + "[Landroid/media/AudioGain;)V"); jclass audioGainClass = FindClassOrDie(env, "android/media/AudioGain"); gAudioGainClass = MakeGlobalRefOrDie(env, audioGainClass); @@ -2846,6 +2818,10 @@ int register_android_media_AudioSystem(JNIEnv *env) jclass listClass = FindClassOrDie(env, "java/util/List"); gListMethods.add = GetMethodIDOrDie(env, listClass, "add", "(Ljava/lang/Object;)Z"); + jclass audioProfileClass = FindClassOrDie(env, "android/media/AudioProfile"); + gAudioProfileClass = MakeGlobalRefOrDie(env, audioProfileClass); + gAudioProfileCstor = GetMethodIDOrDie(env, audioProfileClass, "<init>", "(I[I[I[I)V"); + AudioSystem::addErrorCallback(android_media_AudioSystem_error_callback); RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods)); diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 6ec656c16790..a21545c21011 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -52,6 +52,7 @@ #include <ui/Rect.h> #include <ui/Region.h> #include <utils/Log.h> +#include <utils/LightRefBase.h> // ---------------------------------------------------------------------------- @@ -206,6 +207,16 @@ static struct { jfieldID appRequestRefreshRateMax; } gDesiredDisplayConfigSpecsClassInfo; +static struct { + jclass clazz; + jmethodID onJankDataAvailable; +} gJankDataListenerClassInfo; + +static struct { + jclass clazz; + jmethodID ctor; +} gJankDataClassInfo; + class JNamedColorSpace { public: // ColorSpace.Named.SRGB.ordinal() = 0; @@ -1601,6 +1612,73 @@ static void nativeSetFrameTimelineVsync(JNIEnv* env, jclass clazz, jlong transac transaction->setFrameTimelineVsync(frameTimelineVsyncId); } +class JankDataListenerWrapper : public JankDataListener { +public: + JankDataListenerWrapper(JNIEnv* env, jobject onJankDataListenerObject) { + mOnJankDataListenerWeak = env->NewWeakGlobalRef(onJankDataListenerObject); + env->GetJavaVM(&mVm); + } + + ~JankDataListenerWrapper() { + JNIEnv* env = getEnv(); + env->DeleteWeakGlobalRef(mOnJankDataListenerWeak); + } + + void onJankDataAvailable(const std::vector<JankData>& jankData) { + JNIEnv* env = getEnv(); + + jobject target = env->NewLocalRef(mOnJankDataListenerWeak); + if (target == nullptr) return; + + jobjectArray jJankDataArray = env->NewObjectArray(jankData.size(), + gJankDataClassInfo.clazz, nullptr); + for (int i = 0; i < jankData.size(); i++) { + jobject jJankData = env->NewObject(gJankDataClassInfo.clazz, + gJankDataClassInfo.ctor, jankData[i].frameVsyncId, jankData[i].jankType); + env->SetObjectArrayElement(jJankDataArray, i, jJankData); + } + env->CallVoidMethod(target, + gJankDataListenerClassInfo.onJankDataAvailable, + jJankDataArray); + env->DeleteLocalRef(target); + } + +private: + + JNIEnv* getEnv() { + JNIEnv* env; + mVm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6); + return env; + } + + JavaVM* mVm; + jobject mOnJankDataListenerWeak; +}; + +static void nativeAddJankDataListener(JNIEnv* env, jclass clazz, + jlong jankDataCallbackListenerPtr, + jlong nativeSurfaceControl) { + sp<SurfaceControl> surface(reinterpret_cast<SurfaceControl *>(nativeSurfaceControl)); + if (surface == nullptr) { + return; + } + JankDataListenerWrapper* wrapper = + reinterpret_cast<JankDataListenerWrapper*>(jankDataCallbackListenerPtr); + TransactionCompletedListener::getInstance()->addJankListener(wrapper, surface); +} + +static void nativeRemoveJankDataListener(JNIEnv* env, jclass clazz, + jlong jankDataCallbackListenerPtr) { + JankDataListenerWrapper* wrapper = + reinterpret_cast<JankDataListenerWrapper*>(jankDataCallbackListenerPtr); + TransactionCompletedListener::getInstance()->removeJankListener(wrapper); +} + +static jlong nativeCreateJankDataListenerWrapper(JNIEnv* env, jclass clazz, + jobject jankDataListenerObject) { + return reinterpret_cast<jlong>(new JankDataListenerWrapper(env, jankDataListenerObject)); +} + // ---------------------------------------------------------------------------- static const JNINativeMethod sSurfaceControlMethods[] = { @@ -1785,6 +1863,12 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeSetFocusedWindow}, {"nativeSetFrameTimelineVsync", "(JJ)V", (void*)nativeSetFrameTimelineVsync }, + {"nativeAddJankDataListener", "(JJ)V", + (void*)nativeAddJankDataListener }, + {"nativeRemoveJankDataListener", "(J)V", + (void*)nativeRemoveJankDataListener }, + {"nativeCreateJankDataListenerWrapper", "(Landroid/view/SurfaceControl$OnJankDataListener;)J", + (void*)nativeCreateJankDataListenerWrapper }, // clang-format on }; @@ -1966,6 +2050,18 @@ int register_android_view_SurfaceControl(JNIEnv* env) gScreenCaptureListenerClassInfo.onScreenCaptureComplete = GetMethodIDOrDie(env, screenCaptureListenerClazz, "onScreenCaptureComplete", "(Landroid/view/SurfaceControl$ScreenshotHardwareBuffer;)V"); + + jclass jankDataClazz = + FindClassOrDie(env, "android/view/SurfaceControl$JankData"); + gJankDataClassInfo.clazz = MakeGlobalRefOrDie(env, jankDataClazz); + gJankDataClassInfo.ctor = + GetMethodIDOrDie(env, gJankDataClassInfo.clazz, "<init>", "(JI)V"); + jclass onJankDataListenerClazz = + FindClassOrDie(env, "android/view/SurfaceControl$OnJankDataListener"); + gJankDataListenerClassInfo.clazz = MakeGlobalRefOrDie(env, onJankDataListenerClazz); + gJankDataListenerClassInfo.onJankDataAvailable = + GetMethodIDOrDie(env, onJankDataListenerClazz, "onJankDataAvailable", + "([Landroid/view/SurfaceControl$JankData;)V"); return err; } diff --git a/core/proto/android/hardware/sensorprivacy.proto b/core/proto/android/hardware/sensorprivacy.proto new file mode 100644 index 000000000000..07e938ddfc5d --- /dev/null +++ b/core/proto/android/hardware/sensorprivacy.proto @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +syntax = "proto2"; +package android.service; + +option java_multiple_files = true; +option java_outer_classname = "SensorPrivacyServiceProto"; + +import "frameworks/base/core/proto/android/privacy.proto"; + +message SensorPrivacyServiceDumpProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + // Is global sensor privacy enabled + optional bool is_enabled = 1; + + // Per sensor privacy enabled + repeated SensorPrivacyIndividualEnabledSensorProto individual_enabled_sensor = 2; +} + +message SensorPrivacyIndividualEnabledSensorProto { + option (android.msg_privacy).dest = DEST_AUTOMATIC; + + enum Sensor { + UNKNOWN = 0; + + MICROPHONE = 1; + CAMERA = 2; + } + + // Sensor for which privacy might be enabled + optional Sensor sensor = 1; + + // If sensor privacy is enabled for this sensor + optional bool is_enabled = 2; +}
\ No newline at end of file diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 7cd497ef471e..ef7edc2f2dd2 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1361,7 +1361,7 @@ android:description="@string/permdesc_systemCamera" android:protectionLevel="system|signature" /> - <!-- Allows receiving the camera service notifications when a camera is opened + <!-- @SystemApi Allows receiving the camera service notifications when a camera is opened (by a certain application package) or closed. @hide --> <permission android:name="android.permission.CAMERA_OPEN_CLOSE_LISTENER" @@ -2259,7 +2259,9 @@ <!-- Allows to query ongoing call details and manage ongoing calls <p>Protection level: signature|appop --> <permission android:name="android.permission.MANAGE_ONGOING_CALLS" - android:protectionLevel="signature|appop" /> + android:protectionLevel="signature|appop" + android:label="@string/permlab_manageOngoingCalls" + android:description="@string/permdesc_manageOngoingCalls" /> <!-- Allows the app to request network scans from telephony. <p>Not for use by third-party applications. @@ -2730,6 +2732,10 @@ <permission android:name="android.permission.TOGGLE_AUTOMOTIVE_PROJECTION" android:protectionLevel="signature|privileged" /> + <!-- Allows an app to prevent non-system-overlay windows from being drawn on top of it --> + <permission android:name="android.permission.HIDE_OVERLAY_WINDOWS" + android:protectionLevel="normal" /> + <!-- ================================== --> <!-- Permissions affecting the system wallpaper --> <!-- ================================== --> @@ -3284,6 +3290,7 @@ {@link android.view.WindowManager.LayoutsParams#SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS} to hide non-system-overlay windows. <p>Not for use by third-party applications. + @deprecated Use {@link android.Manifest.permission#HIDE_OVERLAY_WINDOWS} instead @hide --> <permission android:name="android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS" @@ -3962,6 +3969,12 @@ <permission android:name="android.permission.MANAGE_COMPANION_DEVICES" android:protectionLevel="signature" /> + <!-- Allows an application to subscribe to notifications about the presence status change + of their associated companion device + --> + <permission android:name="android.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE" + android:protectionLevel="normal" /> + <!-- @SystemApi Allows an application to use SurfaceFlinger's low level features. <p>Not for use by third-party applications. @hide @@ -4639,7 +4652,7 @@ <!-- Allows access to keyguard secure storage. Only allowed for system processes. @hide --> <permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" - android:protectionLevel="signature" /> + android:protectionLevel="signature|setup" /> <!-- Allows applications to set the initial lockscreen state. <p>Not for use by third-party applications. @hide --> diff --git a/core/res/res/drawable-car/car_button_background.xml b/core/res/res/drawable-car/car_button_background.xml index 3e2610c5047b..e568aebfe81d 100644 --- a/core/res/res/drawable-car/car_button_background.xml +++ b/core/res/res/drawable-car/car_button_background.xml @@ -13,24 +13,48 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> -<!-- Default background styles for car buttons when enabled/disabled. --> -<ripple - xmlns:android="http://schemas.android.com/apk/res/android" - android:color="?android:attr/colorControlHighlight"> +<!-- Default background styles for car buttons when enabled/disabled, + focused/unfocused, and pressed/unpressed --> +<!-- TODO(b/175161842) Add rotary fill color --> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_focused="true" android:state_enabled="false"> + <shape android:shape="rectangle"> + <corners android:radius="@*android:dimen/car_button_radius"/> + <solid android:color="@*android:color/car_grey_300"/> + <stroke android:width="8dp" + android:color="#0059B3"/> + </shape> + </item> + <item android:state_focused="true" android:state_pressed="true"> + <shape android:shape="rectangle"> + <corners android:radius="@*android:dimen/car_button_radius"/> + <solid android:color="?android:attr/colorButtonNormal"/> + <stroke android:width="4dp" + android:color="#0059B3"/> + </shape> + </item> + <item android:state_focused="true"> + <shape android:shape="rectangle"> + <corners android:radius="@*android:dimen/car_button_radius"/> + <solid android:color="?android:attr/colorButtonNormal"/> + <stroke android:width="8dp" + android:color="#0059B3"/> + </shape> + </item> + <item android:state_enabled="false"> + <shape android:shape="rectangle"> + <corners android:radius="@*android:dimen/car_button_radius"/> + <solid android:color="@*android:color/car_grey_300"/> + </shape> + </item> <item> - <selector> - <item android:state_enabled="false"> - <shape android:shape="rectangle"> - <corners android:radius="@*android:dimen/car_button_radius"/> - <solid android:color="@*android:color/car_grey_300"/> - </shape> - </item> + <ripple android:color="?android:attr/colorControlHighlight"> <item> <shape android:shape="rectangle"> <corners android:radius="@*android:dimen/car_button_radius"/> <solid android:color="?android:attr/colorButtonNormal"/> </shape> </item> - </selector> + </ripple> </item> -</ripple> +</selector> diff --git a/core/res/res/drawable-car/car_switch_thumb.xml b/core/res/res/drawable-car/car_switch_thumb.xml index 03efc189aa95..66cf4438418d 100644 --- a/core/res/res/drawable-car/car_switch_thumb.xml +++ b/core/res/res/drawable-car/car_switch_thumb.xml @@ -14,12 +14,15 @@ See the License for the specific language governing permissions and limitations under the License. --> - -<shape - xmlns:android="http://schemas.android.com/apk/res/android" - android:shape="oval"> - <solid android:color="@color/car_switch"/> - <size - android:width="@dimen/car_seekbar_thumb_size" - android:height="@dimen/car_seekbar_thumb_size"/> -</shape> +<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:gravity="center_vertical|fill_horizontal" + android:top="@dimen/car_switch_thumb_margin_size" + android:bottom="@dimen/car_switch_thumb_margin_size"> + <shape android:shape="oval"> + <solid android:color="@color/car_switch"/> + <size + android:width="@dimen/car_switch_thumb_size" + android:height="@dimen/car_switch_thumb_size"/> + </shape> + </item> +</layer-list> diff --git a/core/res/res/drawable-car/car_switch_track.xml b/core/res/res/drawable-car/car_switch_track.xml new file mode 100644 index 000000000000..cb0b9beeeab6 --- /dev/null +++ b/core/res/res/drawable-car/car_switch_track.xml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. +--> +<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> + <item + android:height="@dimen/car_touch_target_size_minus_one" + android:width="@dimen/car_touch_target_size_minus_one" + android:gravity="center"> + <selector> + <item android:state_focused="true" android:state_pressed="true"> + <shape android:shape="oval"> + <solid android:color="#8A94CBFF"/> + <stroke android:width="4dp" + android:color="#94CBFF"/> + </shape> + </item> + <item android:state_focused="true"> + <shape android:shape="oval"> + <solid android:color="#3D94CBFF"/> + <stroke android:width="8dp" + android:color="#94CBFF"/> + </shape> + </item> + </selector> + </item> + <item android:gravity="center_vertical|fill_horizontal" + android:left="@dimen/car_switch_track_margin_size" + android:right="@dimen/car_switch_track_margin_size"> + <shape + android:shape="rectangle" + android:tint="@color/switch_track_material"> + <corners android:radius="7dp" /> + <solid android:color="@color/white_disabled_material" /> + <size android:height="14dp" /> + <padding + android:right="@dimen/car_switch_track_margin_size" + android:left="@dimen/car_switch_track_margin_size"/> + </shape> + </item> +</layer-list> diff --git a/core/res/res/drawable/ic_feedback_alerted.xml b/core/res/res/drawable/ic_feedback_alerted.xml new file mode 100644 index 000000000000..550500a889aa --- /dev/null +++ b/core/res/res/drawable/ic_feedback_alerted.xml @@ -0,0 +1,30 @@ +<!-- + ~ Copyright (C) 2020 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. +--> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="16dp" + android:height="16dp" + android:viewportWidth="16" + android:viewportHeight="16"> + <path + android:pathData="M3.3333,5.6667H6V9.6667H10V5.6667H12.6667L8,1L3.3333,5.6667Z" + android:fillColor="#EA4335"/> + <path + android:strokeWidth="1" + android:pathData="M2.9798,8.9798L2.1262,9.8333H3.3333H5.5V13.3333V13.8333H6H10H10.5V13.3333V9.8333H12.6667H13.8738L13.0202,8.9798L8.3536,4.3131L8,3.9596L7.6465,4.3131L2.9798,8.9798Z" + android:fillColor="#EA4335" + android:strokeColor="#ffffff"/> +</vector> diff --git a/core/res/res/drawable/ic_feedback_downrank.xml b/core/res/res/drawable/ic_feedback_downrank.xml new file mode 100644 index 000000000000..c48505e2e4bd --- /dev/null +++ b/core/res/res/drawable/ic_feedback_downrank.xml @@ -0,0 +1,24 @@ +<!-- + ~ Copyright (C) 2020 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="16dp" + android:height="16dp" + android:viewportWidth="16" + android:viewportHeight="16"> + <path + android:pathData="M12.6667,8H10V4H6V8H3.3333L8,12.6667L12.6667,8Z" + android:fillColor="#4285F4"/> +</vector> diff --git a/core/res/res/drawable/ic_feedback_silenced.xml b/core/res/res/drawable/ic_feedback_silenced.xml new file mode 100644 index 000000000000..aa221b205e34 --- /dev/null +++ b/core/res/res/drawable/ic_feedback_silenced.xml @@ -0,0 +1,34 @@ +<!-- + ~ Copyright (C) 2020 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. +--> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="16dp" + android:height="16dp" + android:viewportWidth="16" + android:viewportHeight="16"> + <group> + <clip-path + android:pathData="M16,16l-16,-0l-0,-16l16,-0z"/> + <path + android:pathData="M12.6667,10.3333H10V6.3333H6V10.3333H3.3333L8,15L12.6667,10.3333Z" + android:fillColor="#4285F4"/> + <path + android:strokeWidth="1" + android:pathData="M13.0202,7.0202L13.8738,6.1667H12.6667H10.5V2.6667L10.5,2.1667H10H6H5.5V2.6667V6.1667H3.3333H2.1262L2.9798,7.0202L7.6464,11.6869L8,12.0405L8.3535,11.6869L13.0202,7.0202Z" + android:fillColor="#4285F4" + android:strokeColor="#ffffff"/> + </group> +</vector>
\ No newline at end of file diff --git a/core/res/res/drawable/ic_feedback_uprank.xml b/core/res/res/drawable/ic_feedback_uprank.xml new file mode 100644 index 000000000000..340780ce0030 --- /dev/null +++ b/core/res/res/drawable/ic_feedback_uprank.xml @@ -0,0 +1,24 @@ +<!-- + ~ Copyright (C) 2020 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="16dp" + android:height="16dp" + android:viewportWidth="16" + android:viewportHeight="16"> + <path + android:pathData="M3.3333,8H6V12H10V8H12.6667L8,3.3333L3.3333,8Z" + android:fillColor="#EA4335"/> +</vector> diff --git a/core/res/res/layout/notification_top_line_views.xml b/core/res/res/layout/notification_top_line_views.xml index 60507eddba22..361b7a393448 100644 --- a/core/res/res/layout/notification_top_line_views.xml +++ b/core/res/res/layout/notification_top_line_views.xml @@ -112,9 +112,8 @@ android:id="@+id/feedback" android:layout_width="@dimen/notification_feedback_size" android:layout_height="@dimen/notification_feedback_size" - android:layout_marginStart="6dp" - android:layout_marginEnd="6dp" - android:baseline="10dp" + android:layout_marginStart="4dp" + android:layout_marginEnd="4dp" android:scaleType="fitCenter" android:src="@drawable/ic_feedback_indicator" android:background="?android:selectableItemBackgroundBorderless" diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml index 171d89628518..9f92d723b5e1 100644 --- a/core/res/res/values-af/strings.xml +++ b/core/res/res/values-af/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS-diens"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Sensorkennisgewingdiens"</string> <string name="twilight_service" msgid="8964898045693187224">"Skemerdiens"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Tydsonebespeurder (geen konnektiwiteit nie)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Jou toestel sal uitgevee word"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Die administrasieprogram kan nie gebruik word nie. Jou toestel sal nou uitgevee word.\n\nKontak jou organisasie se administrateur as jy vrae het."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Druk is gedeaktiveer deur <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB-verbinding"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Program loop tans"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Programme wat batterykrag gebruik"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Vergroting"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> gebruik tans batterykrag"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> programme gebruik tans batterykrag"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tik vir besonderhede oor battery- en datagebruik"</string> @@ -353,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Laat die program toe om MMS-boodskappe te ontvang en te verwerk. Dit beteken dat die program boodskappe wat na jou toestel gestuur is kan monitor of uitvee, sonder dat jy dit gesien het."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Stuur seluitsendingboodskappe aan"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Laat die program toe om die seluitsendingmodule te bind om seluitsendingboodskappe aan te stuur wanneer hulle ontvang word. Seluitsendingwaarskuwings word in sommige liggings gelewer om jou oor noodsituasies te waarsku. Kwaadwillige programme kan met die werkverrigting of werking van jou toestel inmeng wanneer \'n noodseluitsending ontvang word."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Bestuur voortgaande oproepe"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Stel \'n program in staat om besonderhede oor voortgaande oproepe op jou toestel te sien, en hierdie oproepe te beheer."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"lees seluitsending-boodskappe"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Laat die program toe om seluitsending-boodskappe te lees wat deur jou toestel ontvang word. Seluitsending-waarskuwings word in sommige plekke afgelewer om jou van noodsituasies te waarsku. Kwaadwillige programme mag inmeng met die prestasie of die werking van jou toestel wanneer \'n noodgeval se seluitsending ontvang word."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lees ingetekende nuus"</string> @@ -2190,12 +2192,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nuut: Venstervergrootglas"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Jy kan nou jou hele skerm of \'n deel daarvan vergroot"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Skakel aan in Instellings"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Maak toe"</string> </resources> diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml index 5871fe24920a..dea4aa6ad50f 100644 --- a/core/res/res/values-am/strings.xml +++ b/core/res/res/values-am/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS አገልግሎት"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"የዳሳሽ ማሳወቂያ አገልግሎት"</string> <string name="twilight_service" msgid="8964898045693187224">"የውጋገን አገልግሎት"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"የሰዓት ሰቅ አንባቢ (ግንኙነት የለም)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"የእርስዎ መሣሪያ ይደመሰሳል"</string> <string name="factory_reset_message" msgid="2657049595153992213">"የአስተዳዳሪ መተግበሪያ ስራ ላይ ሊውል አይችልም። የእርስዎን መሣሪያ አሁን ይደመሰሳል።\n\nጥያቄዎች ካለዎት የድርጅትዎን አስተዳዳሪ ያነጋግሩ።"</string> <string name="printing_disabled_by" msgid="3517499806528864633">"ማተም በ<xliff:g id="OWNER_APP">%s</xliff:g> ተሰናክሏል።"</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"የዩኤስቢ ግንኙነት"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"APP እየሠራ ነው"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ባትሪ በመፍጀት ላይ ያሉ መተግበሪያዎች"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ማጉላት"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ባትሪ እየተጠቀመ ነው"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> መተግበሪያዎች ባትሪ እየተጠቀሙ ነው"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"በባትሪ እና ውሂብ አጠቃቀም ላይ ዝርዝሮችን ለማግኘት መታ ያድርጉ"</string> @@ -353,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"መተግበሪያው የኤም.ኤም.ኤስ. መልዕክቶችን እንዲያነብ እና እንዲያካሂድ ይፈቅዳል። ይህ ማለት መተግበሪያው ወደ መሳሪያህ የተላኩ መልዕክቶችን ላንተ ሳያሳይህ ሊቆጣጠር ወይም ሊሰርዝ ይችላል።"</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"የሕዋስ ስርጭት መልዕክቶችን ማስተላለፍ"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"የሕዋስ ስርጭት መልዕክቶች እንደመጡ ለማስተላለፍ መተግበሪያው ከሕዋስ ስርጭት ሞዱሉ ጋር እንዲተሳሰር ያስችለዋል። የሕዋስ ስርጭት ማንቂያዎች አስቸኳይ ሁኔታዎች ሲያጋጥሙ አንዳንድ አካባቢዎች ላይ የሚላኩ ናቸው። የሕዋስ ስርጭት ሲደርስ ተንኮል-አዘል መተግበሪያዎች በመሣሪያዎ አፈጻጸም ወይም አሰራር ላይ ጣልቃ ሊገቡ ይችላሉ።"</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"በመካሄድ ላይ ያሉ ጥሪዎችን አስተዳድር"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"አንድ መተግበሪያ በመካሄድ ላይ ስላሉ ጥሪዎች ዝርዝሮችን እንዲመለከት ያስችለዋል።"</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"የህዋስ ስርጭት መልዕክቶችን አንብብ"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"መሣሪያህ የህዋስ ስርጭት መልዕክቶች ሲቀበል መተግበሪያው እንዲያነበው ይፈቅድለታል። የህዋስ ስርጭት ማንቂያዎች አስቸኳይ ሁኔታዎች ሲያጋጥሙ አንዳንድ አካባቢዎች ላይ የሚላኩ ናቸው። የህዋስ ስርጭት ሲደርስ ተንኮል አዘል መተግበሪያዎች በመሣሪያህ አፈጻጸም ወይም አሰራር ላይ ጣልቃ ሊገቡ ይችላሉ።"</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"የምዝገባ መግቦች አንበብ"</string> @@ -2190,12 +2192,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"አዲስ፦ የመስኮት ማጉያ"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"አሁን የተወሰነ ወይም ሁሉንም ማያ ገጽዎን ማጉላት ይችላሉ"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"በቅንብሮች ውስጥ ያብሩ"</string> + <string name="dismiss_action" msgid="1728820550388704784">"አሰናብት"</string> </resources> diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml index b57876906a94..7ad157c30dd5 100644 --- a/core/res/res/values-ar/strings.xml +++ b/core/res/res/values-ar/strings.xml @@ -207,6 +207,7 @@ <string name="gnss_service" msgid="8907781262179951385">"خدمة GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"خدمة إشعارات جهاز الاستشعار"</string> <string name="twilight_service" msgid="8964898045693187224">"خدمة الغسق"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"أداة التعرّف على المنطقة الزمنية (ليس هناك حاجة للاتصال بالشبكة)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"سيتم محو بيانات جهازك."</string> <string name="factory_reset_message" msgid="2657049595153992213">"تعذّر استخدام تطبيق المشرف. سيتم محو بيانات جهازك الآن.\n\nإذا كانت لديك أسئلة، اتصل بمشرف مؤسستك."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"تم إيقاف الطباعة بواسطة <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -299,8 +300,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"اتصال USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"التطبيق قيد التشغيل"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"التطبيقات التي تستهلك البطارية"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"التكبير"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"يستخدم تطبيق <xliff:g id="APP_NAME">%1$s</xliff:g> البطارية"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"تستخدم <xliff:g id="NUMBER">%1$d</xliff:g> من التطبيقات البطارية"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"انقر للحصول على تفاصيل حول البطارية واستخدام البيانات"</string> @@ -365,6 +365,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"للسماح للتطبيق بتلقي ومعالجة رسائل الوسائط المتعددة. وهذا يعني أنه يمكن للتطبيق مراقبة الرسائل التي يتم إرسالها لجهازك أو حذفها بدون عرضها لك."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"إعادة توجيه رسائل البث الخلوي"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"يسمح للتطبيق بالارتباط بوحدة البث الخلوي لإعادة توجيه رسائل البث الخلوي بينما يتم استقبالها. ويتم تسليم تنبيهات البث الخلوي في بعض المواقع لتحذيرك في حالات الطوارئ. ويمكن أن تؤثر التطبيقات الضارة على أداء الجهاز أو تشغيله عندما يتم تلقي بث خلوي في حالات الطوارئ."</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"قراءة رسائل بث الخلية"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"السماح للتطبيق بقراءة رسائل بث الخلية التي يتلقاها هذا الجهاز. يتم تسليم اشعارات بث الخلية في بعض المواقع لتحذيرك من حالات طارئة. يمكن أن تتداخل التطبيقات الضارة مع أداء أو تشغيل الجهاز عندما يتم تلقي بث خلية طارئ."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"قراءة الخلاصات المشتركة"</string> @@ -2326,12 +2330,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"جديد: Window Magnifier"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"يمكنك الآن تكبير الشاشة كلها أو جزء منها."</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"التفعيل من خلال \"الإعدادات\""</string> + <string name="dismiss_action" msgid="1728820550388704784">"إغلاق"</string> </resources> diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml index f1b0d84883a0..e6ab01a12a80 100644 --- a/core/res/res/values-as/strings.xml +++ b/core/res/res/values-as/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS সেৱা"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"ছেন্সৰ জাননী সেৱা"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight সেৱা"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"সময় মণ্ডল চিনাক্তকাৰী (সংযোগ নাই)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"আপোনাৰ ডিভাইচৰ ডেটা মচা হ\'ব"</string> <string name="factory_reset_message" msgid="2657049595153992213">"এই প্ৰশাসক এপটো ব্যৱহাৰ কৰিব নোৱাৰি। এতিয়া আপোনাৰ ডিভাইচটোৰ ডেটা মচা হ\'ব।\n\nআপোনাৰ কিবা প্ৰশ্ন থাকিলে আপোনাৰ প্ৰতিষ্ঠানৰ প্ৰশাসকৰ সৈতে যোগাযোগ কৰক।"</string> <string name="printing_disabled_by" msgid="3517499806528864633">"প্ৰিণ্ট কৰা কাৰ্য <xliff:g id="OWNER_APP">%s</xliff:g>এ অক্ষম কৰি ৰাখিছে।"</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"ইউএছবি সংযোগ"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"এপ্ চলি আছে"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"বেটাৰি খৰচ কৰা এপসমূহ"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"বিবৰ্ধন"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ বেটাৰি ব্যৱহাৰ কৰি আছে"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g>টা এপে বেটাৰি ব্যৱহাৰ কৰি আছে"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"বেটাৰি আৰু ডেটাৰ ব্যৱহাৰৰ বিষয়ে বিশদভাৱে জানিবলৈ টিপক"</string> @@ -353,6 +353,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"এমএমএছ বার্তাবোৰ লাভ আৰু ইয়াৰ প্ৰক্ৰিয়া সম্পন্ন কৰিবলৈ এপক অনুমতি দিয়ে। ইয়াৰ অৰ্থ হৈছে এই এপে আপোনাৰ ডিভাইচলৈ প্ৰেৰণ কৰা বার্তাসমূহ আপোনাক নেদেখুৱাকৈয়ে পৰ্যবেক্ষণ আৰু মচিব পাৰে।"</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"চেল সম্প্ৰচাৰ বাৰ্তাসমূহ ফৰৱাৰ্ড কৰক"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"চেল সম্প্ৰচাৰ বাৰ্তাসমূহ লাভ কৰিলে সেইবোৰ ফৰৱাৰ্ড কৰিবলৈ এপ্টোক চেল সম্প্ৰচাৰ মডিউলটোৰ সৈতে সংযুক্ত হ\'বলৈ অনুমতি দিয়ে। আপোনাক জৰুৰীকালীন পৰিস্থিতিসমূহৰ বিষয়ে সতৰ্ক কৰিবলৈ কিছুমান অৱস্থানত চেল সম্প্ৰচাৰ সতৰ্কবাৰ্তাসমূহ ডেলিভাৰ কৰা হয়। কোনো জৰুৰীকালীন চেল সম্প্ৰচাৰ লাভ কৰিলে ক্ষতিকাৰক এপ্সমূহে আপোনাৰ ডিভাইচটোৰ কাৰ্যক্ষমতা অথবা কাৰ্যপ্ৰণালীত হস্তক্ষেপ কৰিব পাৰে।"</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"চেল সম্প্ৰচাৰৰ বার্তাবোৰ পঢ়ক"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"আপোনাৰ ডিভাইচে লাভ কৰা চেল সম্প্ৰচাৰৰ বার্তাবোৰ পঢ়িবলৈ এপক অনুমতি দিয়ে। আপোনাক জৰুৰীকালীন পৰিস্থিতিবোৰত সর্তক কৰিবলৈ চেল সম্প্ৰচাৰৰ বার্তাবোৰ প্ৰেৰণ কৰা হয়। জৰুৰীকালীন চেল সম্প্ৰচাৰ লাভ কৰাৰ সময়ত আপোনাৰ ডিভাইচৰ কাৰ্যদক্ষতা বা কাৰ্যপ্ৰণালীত ক্ষতিকাৰক এপবোৰে হস্তক্ষেপ কৰিব পাৰে।"</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"আপুনি সদস্যভুক্ত হোৱা ফীডসমূহ পঢ়ক"</string> @@ -2190,12 +2194,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"নতুন: ৱিণ্ড’ বিৱৰ্ধক"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"আপুনি সকলো অথবা কেইখনমান স্ক্ৰীন বিবৰ্ধন কৰিব পাৰে"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ছেটিঙত অন কৰক"</string> + <string name="dismiss_action" msgid="1728820550388704784">"অগ্ৰাহ্য কৰক"</string> </resources> diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml index 01fb48e18462..763bd2a741c6 100644 --- a/core/res/res/values-az/strings.xml +++ b/core/res/res/values-az/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS Xidməti"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Sensor Bildiriş Xidməti"</string> <string name="twilight_service" msgid="8964898045693187224">"Alaqaranlıq Xidməti"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Saat Qurşağı Aşkarlayıcısı (Bağlantı yoxdur)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Cihazınız təmizlənəcəkdir"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Admin tətbiqini istifadə etmək mümkün deyil. Cihaz indi təmizlənəcək.\n\nSualınız varsa, təşkilatın admini ilə əlaqə saxlayın."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Çap <xliff:g id="OWNER_APP">%s</xliff:g> tərəfindən deaktiv edildi."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB əlaqə"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Tətbiq işləyir"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Batareyadan istifadə edən tətbiqlər"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Böyütmə"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> batareyadan istifadə edir"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> tətbiq batareyadan istifadə edir"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Batareya və data istifadəsi haqqında ətraflı məlumat üçün klikləyin"</string> @@ -353,6 +353,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Tətbiqə MMS mesajlarını qəbul və emal üçün imkan verir. Bu o deməkdir ki, bu tətbiq sizə göstərmədən cihazınıza göndərilən mesajları silə bilər."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Şəbəkə yayımı mesajlarını yönləndirin"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Tətbiqə şəbəkə yayım mesajlarını əldə edildiyi anda yönləndirmək üçün şəbəkə yayımı moduluna bağlanmaq icazəsi verir. Şəbəkə yayımı bəzi məkanlarda olan fövqəladə hadisələrlə bağlı Sizi xəbərdar etmək üçün qəbul edilir. Zərərli tətbiqlər fövqəladə şəbəkə yayımı əldə edildiyi zaman cihazın performansına və əməliyyatına müdaxilə edə bilər."</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"mobil yayım mesajlarını oxuyur"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Tətbiqə telefonunuz tərəfindən alınmış yayım mesajlarını oxuma icazəsi verir. Telefon yayımı bəzi məkanlarda olan fövqəladə hadisələrlə bağlı sizi xəbərdar etmək üçün qəbul edilir. Zərərli tətbiqlər təcili mobil yayım qəbul edildiyi zaman telefonunun performansına və əməliyyatına müdaxilə edə bilər."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"abunə olunmuş xəbərləri oxuyur"</string> @@ -2190,12 +2194,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Yeni: Pəncərə Böyüdücüsü"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"İndi ekranı qismən və ya tam şəkildə böyüdə bilərsiniz"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Ayarlarda aktiv edin"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Qapadın"</string> </resources> diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml index bfbd3e4586f2..77220b23dae9 100644 --- a/core/res/res/values-b+sr+Latn/strings.xml +++ b/core/res/res/values-b+sr+Latn/strings.xml @@ -201,6 +201,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS usluga"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Usluga obaveštenja senzora"</string> <string name="twilight_service" msgid="8964898045693187224">"Usluga Sumrak"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detektor vremenske zone (nema internet veze)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Uređaj će biti obrisan"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Ne možete da koristite ovu aplikaciju za administratore. Uređaj će sada biti obrisan.\n\nAko imate pitanja, kontaktirajte administratora organizacije."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Štampanje je onemogućila aplikacija <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -290,8 +291,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB veza"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aktivna aplikacija"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacije koje troše bateriju"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Uvećanje"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> koristi bateriju"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Aplikacije (<xliff:g id="NUMBER">%1$d</xliff:g>) koriste bateriju"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Dodirnite za detalje o bateriji i potrošnji podataka"</string> @@ -356,6 +356,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Dozvoljava aplikaciji da prima i obrađuje MMS poruke. To znači da aplikacija može da nadgleda ili briše poruke koje se šalju uređaju, a da vam ih ne prikaže."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Prosleđivanje poruka za mobilne uređaje na lokalitetu"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Dozvoljava aplikaciji da se vezuje za modul poruka za mobilne uređaje na lokalitetu da bi prosleđivala poruke za mobilne uređaje na lokalitetu onako kako su primljene. Obaveštenja poruka za mobilne uređaje na lokalitetu se na nekim lokacijama primaju kao upozorenja na hitne slučajeve. Zlonamerne aplikacije mogu da utiču na učinak ili ometaju rad uređaja kada se primi poruka o hitnom slučaju za mobilne uređaje na lokalitetu."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Upravljanje odlaznim pozivima"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Omogućava aplikaciji da vidi detalje o odlaznim pozivima na uređaju i da kontroliše te pozive."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"čitanje poruka info servisa"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Omogućava aplikaciji da čita poruke info servisa koje uređaj prima. Upozorenja info servisa se na nekim lokacijama primaju kao upozorenja na hitne slučajeve. Zlonamerne aplikacije mogu da utiču na učinak ili ometaju funkcionisanje uređaja kada se primi poruka info servisa o hitnom slučaju."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"čitanje prijavljenih fidova"</string> @@ -932,7 +934,7 @@ <string name="granularity_label_link" msgid="9007852307112046526">"link"</string> <string name="granularity_label_line" msgid="376204904280620221">"red"</string> <string name="factorytest_failed" msgid="3190979160945298006">"Fabričko testiranje nije uspelo"</string> - <string name="factorytest_not_system" msgid="5658160199925519869">"Radnja FACTORY_TEST je podržana samo za pakete instalirane u direktorijumu /system/app."</string> + <string name="factorytest_not_system" msgid="5658160199925519869">"Radnja FACTORY_TEST je podržana samo za pakete instalirane u folderu /system/app."</string> <string name="factorytest_no_action" msgid="339252838115675515">"Nije pronađen nijedan paket koji obezbeđuje radnju FACTORY_TEST."</string> <string name="factorytest_reboot" msgid="2050147445567257365">"Restartuj"</string> <string name="js_dialog_title" msgid="7464775045615023241">"Na stranici na adresi „<xliff:g id="TITLE">%s</xliff:g>“ piše:"</string> @@ -2048,7 +2050,7 @@ <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Baterija telefona je dovoljno napunjena. Funkcije više nisu ograničene."</string> <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Baterija tableta je dovoljno napunjena. Funkcije više nisu ograničene."</string> <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Baterija uređaja je dovoljno napunjena. Funkcije više nisu ograničene."</string> - <string name="mime_type_folder" msgid="2203536499348787650">"Direktorijum"</string> + <string name="mime_type_folder" msgid="2203536499348787650">"Folder"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Android aplikacija"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Datoteka"</string> <string name="mime_type_generic_ext" msgid="9220220924380909486">"<xliff:g id="EXTENSION">%1$s</xliff:g> datoteka"</string> @@ -2224,12 +2226,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Novo: Lupa za prozor"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Možete da uvećate deo ekrana ili ceo ekran"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Uključite u Podešavanjima"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Odbaci"</string> </resources> diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml index c4a3a7e980c4..d092ad6f7925 100644 --- a/core/res/res/values-be/strings.xml +++ b/core/res/res/values-be/strings.xml @@ -203,6 +203,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Служба GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Служба апавяшчэнняў датчыка"</string> <string name="twilight_service" msgid="8964898045693187224">"Служба Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Дэтэктар часавога пояса (няма падключэння)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Даныя вашай прылады будуць сцерты"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Немагчыма выкарыстоўваць праграму адміністравання. Звесткі на вашай прыладзе будуць выдалены.\n\nКалі ў вас ёсць пытанні, звярніцеся да адміністратара арганізацыі."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Друк адключаны ўладальнікам праграмы <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -293,8 +294,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Падключэнне USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Праграма працуе"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Праграмы, якія выкарыстоўваюць акумулятар"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Павелічэнне"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> выкарыстоўвае акумулятар"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Наступная колькасць праграм выкарыстоўваюць акумулятар: <xliff:g id="NUMBER">%1$d</xliff:g>"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Дакраніцеся, каб даведацца пра выкарыстанне трафіка і акумулятара"</string> @@ -359,6 +359,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Дазваляе прыкладанням атрымліваць і апрацоўваць MMS-паведамленнi. Гэта значыць, што прыкладанне можа кантраляваць або выдаляць паведамленні, адпраўленыя на прыладу, не паказваючы іх вам."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Пераадрасоўваць паведамленні сотавай трансляцыі"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Дазваляе праграме звязвацца з модулем сотавай трансляцыі, каб пераадрасоўваць атрыманыя там паведамленні. Абвесткі сотавай трансляцыі дасылаюцца ў некаторыя месцы, каб папярэджваць вас пра надзвычайныя сітуацыі. Шкодныя праграмы могуць негатыўна ўплываць на прадукцыйнасць або працу прылады падчас атрымання паведамленняў сотавай трансляцыі пра надзвычайныя сітуацыі."</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"чытаць паведамленні базавай станцыі"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Дазваляе прыкладанню чытаць паведамленні базавай станцыі, атрыманыя прыладай. Папярэджанні базавай станцыі дасылаюцца ў некаторыя месцы, каб папярэдзіць вас аб надзвычайных сітуацыях. Шкоднасныя прыкладанні могуць уплываць на прадукцыйнасць ці працу прылады пры атрыманні паведамлення базавай станцыі аб надзвычайнай сітуацыі."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"чытаць падпісаныя каналы"</string> @@ -2258,12 +2262,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Новая функцыя Window Magnifier"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Цяпер можна павялічваць увесь экран ці яго частку."</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Уключыць у Наладах"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Адхіліць"</string> </resources> diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml index 07f1ce7b9bf9..c648398e3713 100644 --- a/core/res/res/values-bg/strings.xml +++ b/core/res/res/values-bg/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Услуга за GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Услуга за известия за сензорите"</string> <string name="twilight_service" msgid="8964898045693187224">"Услуга Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Инструмент за установяване на часовата зона (няма връзка)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Данните на устройството ви ще бъдат изтрити"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Приложението за администриране не може да се използва. Сега данните на устройството ви ще бъдат изтрити.\n\nАко имате въпроси, свържете се с администратора на организацията си."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Отпечатването е деактивиранo от <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB връзка"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Приложението работи"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Приложения, използващи батерията"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Увеличение"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> използва батерията"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> приложения използват батерията"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Докоснете за информация относно използването на батерията и преноса на данни"</string> @@ -353,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Разрешава на приложението да получава и обработва MMS съобщения. Това означава, че то може да наблюдава или изтрива изпратените до устройството ви, без да ви ги покаже."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Препращане на съобщения с клетъчно излъчване"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Разрешава на приложението да се обвърже с модула за клетъчно излъчване, за да препраща получените съобщения с клетъчно излъчване. Сигналите с клетъчно излъчване се получават на някои местоположения, за да ви предупредят за спешни случаи. Злонамерените приложения могат да възпрепятстват изпълнението или работата на устройството ви при получаване на такова спешно излъчване."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Управление на текущите обаждания"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Разрешава на приложението да вижда подробности за текущите обаждания на устройството ви и да ги управлява."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"четене на съобщения с клетъчно излъчване"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Разрешава на приложението да чете съобщения с клетъчно излъчване, получени от устройството ви. Сигналите с клетъчно излъчване се получават на някои местоположения, за да ви предупредят за спешни ситуации. Злонамерените приложения могат да възпрепятстват изпълнението или работата на устройството ви при получаване на такова спешно излъчване."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"четене на емисиите с абонамент"</string> @@ -2190,12 +2192,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Ново: Увеличаване на прозорци"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Можете да увеличите целия екран или част от него"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Включете от настройките"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Отхвърляне"</string> </resources> diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml index 9b85fc7a4d7d..6de7e2dc5ba2 100644 --- a/core/res/res/values-bn/strings.xml +++ b/core/res/res/values-bn/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS পরিষেবা"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"সেন্সর বিজ্ঞপ্তি পরিষেবা"</string> <string name="twilight_service" msgid="8964898045693187224">"গোধূলি পরিষেবা"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"টাইম জোন ডিটেক্টর (কানেকশন নেই)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"আপনার ডিভাইসটি মুছে ফেলা হবে"</string> <string name="factory_reset_message" msgid="2657049595153992213">"অ্যাডমিন অ্যাপটি ব্যবহার করা যাবে না। আপনার ডিভাইসে থাকা সবকিছু এখন মুছে ফেলা হবে।\n\nকোনও প্রশ্ন থাকলে আপনার প্রতিষ্ঠানের অ্যাডমিনের সাথে যোগাযোগ করুন।"</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> প্রিন্টিং বন্ধ রেখেছে।"</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB সংযোগ"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"অ্যাপ চলছে"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"কিছু অ্যাপ ব্যাটারি ব্যবহার করছে"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"বড় করে দেখুন"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> অ্যাপটি ব্যাটারি ব্যবহার করছে"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g>টি অ্যাপ ব্যাটারি ব্যবহার করছে"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ব্যাটারি এবং ডেটার ব্যবহারের বিশদ বিবরণের জন্য ট্যাপ করুন"</string> @@ -353,6 +353,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"অ্যাপ্লিকেশানটিকে MMS মেসেজ প্রাপ্ত করার এবং প্রক্রিয়া করার অনুমতি দেয়৷ এর মানে হল অ্যাপ্লিকেশানটি আপনার ডিভাইস থেকে পাঠানো মেসেজগুলিকে পর্যবেক্ষণ করতে পারে এবং মুছতে পারে সেগুলিকে আপনাকে না দেখিয়ে৷"</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"সেল ব্রডকাস্টের মাধ্যমে মেসেজ ফরওয়ার্ড করুন"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"সেল ব্রডকাস্ট মেসেজ পেলে এটি সেল ব্রডকাস্ট মডিউলের সাথে তা যুক্ত করে যাতে সেই মেসেজ ফরওয়ার্ড করা যায়। আপনাকে জরুরি অবস্থা সম্পর্কে সাবধান করতে কিছু লোকেশনে সেল ব্রডকাস্ট অ্যালার্ট মেসেজ ডেলিভার করা হয়। জরুরি সেল ব্রডকাস্ট পাওয়া গেলে ক্ষতিকারক অ্যাপ আপনার ডিভাইসের পারফর্ম্যান্স ও অপারেশনে বাধা সৃষ্টি করতে পারে।"</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"সেল সম্প্রচার মেসেজ পড়ুন"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"আপনার ডিভাইস দ্বারা প্রাপ্ত সেল সম্প্রচার পড়তে অ্যাপ্লিকেশানটিকে অনুমতি দেয়৷ কয়েকটি স্থানে আপনাকে জরুরি অবস্থার জন্য সতর্ক করতে জরুরি সতর্কতাগুলি বিতরণ করা হয়৷ যখন একটি জরুরি সেল সম্প্রচার প্রাপ্ত হয় তখন ক্ষতিকারক অ্যাপ্লিকেশানগুলি আপনার ডিভাইসের কার্য সম্পাদনা বা কার্যকলাপে প্রতিবন্ধকতার সৃষ্টি করতে পারে৷"</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"গ্রাহক হিসেবে নেওয়া ফিডগুলি পড়ে"</string> @@ -2190,12 +2194,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"নতুন: উইন্ডো ম্যাগনিফায়ার"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"এখন আপনি কিছু বা সবকটি স্ক্রিন বড় করে দেখতে পারেন"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"সেটিংস থেকে চালু করুন"</string> + <string name="dismiss_action" msgid="1728820550388704784">"বাতিল করুন"</string> </resources> diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml index 3d2249b17122..53a03a73ea91 100644 --- a/core/res/res/values-bs/strings.xml +++ b/core/res/res/values-bs/strings.xml @@ -201,6 +201,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Usluga GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Usluga obavještavanja putem senzora"</string> <string name="twilight_service" msgid="8964898045693187224">"Usluga Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detektor vremenske zone (nije povezan)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Uređaj će biti izbrisan"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Nije moguće koristiti aplikaciju administratora. Potpuno će se izbrisati podaci na vašem uređaju.\n\nAko imate pitanja, obratite se administratoru svoje organizacije."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Štampanje je onemogućila aplikacija <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -290,8 +291,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB veza"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Pokrenuta aplikacija"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacije koje troše bateriju"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Uvećavanje"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> troši bateriju"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Broj aplikacija koje troše bateriju: <xliff:g id="NUMBER">%1$d</xliff:g>"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Dodirnite za detalje o potrošnji baterije i prijenosa podataka"</string> @@ -356,6 +356,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Omogućava aplikaciji prijem i obradu MMS poruka. Ovo znači da aplikacija može pratiti ili brisati poruke poslane na vaš uređaj, a da vam ih pritom ne prikazuje."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Prosljeđivanje poruka info servisa"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Dopušta aplikaciji da se veže za modul info servisa kako bi prosljeđivala poruke info servisa. Upozorenja koja emitira info servis se isporučuju na nekim lokacijama kako bi vas upozorila na vanredne situacije. Zlonamjerne aplikacije mogu ometati performanse ili rad vašeg uređaja kada primite informacije o vanrednoj situaciji od info servisa."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Upravljanje pozivima u toku"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Omogućava aplikaciji da vidi detalje o pozivima u toku na vašem uređaju i da ih kontrolira."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"čitanje poruka info servisa"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Omogućava aplikaciji čitanje poruka info servisa koje je primio vaš uređaj. Upozorenja koja emitira info servis se isporučuju na nekim lokacijama kako bi vas upozorila na vanredne situacije. Zlonamjerne aplikacije mogu ometati performanse ili rad vašeg uređaja kada primite informaciju o vanrednoj situaciji od info servisa."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"čitanje sadržaja na koje ste pretplaćeni"</string> @@ -2224,12 +2226,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Novo: povećalo prozora"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Sada možete uvećati dio ekrana ili cijeli ekran"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Uključite u Postavkama"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Odbaci"</string> </resources> diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index f1845e340afa..5ce2ff29bdfe 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Servei GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Servei de notificacions de sensor"</string> <string name="twilight_service" msgid="8964898045693187224">"Servei Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detector de zona horària (sense connectivitat)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"El contingut del dispositiu s\'esborrarà"</string> <string name="factory_reset_message" msgid="2657049595153992213">"No es pot utilitzar l\'aplicació d\'administració. S\'esborraran les dades del dispositiu.\n\nSi tens cap dubte, contacta amb l\'administrador de la teva organització."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ha desactivat la impressió."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Connexió USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplicació en execució"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplicacions que consumeixen bateria"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ampliació"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> està consumint bateria"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicacions estan consumint bateria"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Toca per obtenir informació sobre l\'ús de dades i de bateria"</string> @@ -353,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Permet que l\'aplicació rebi i processi missatges MMS. Això vol dir que l\'aplicació pot controlar o suprimir missatges que s\'han enviat al teu dispositiu sense mostrar-te\'ls."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Reenviar els missatges de difusió mòbil"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Permet que l\'aplicació es vinculi al mòdul de difusió mòbil per poder reenviar els missatges de difusió mòbil a mesura que es reben. Les alertes de difusió mòbil s\'entreguen en algunes ubicacions per alertar de situacions d\'emergència. És possible que les aplicacions malicioses interfereixin en el rendiment o en el funcionament del dispositiu quan es rebi una difusió mòbil d\'emergència."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Gestiona les trucades en curs"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Permet que una aplicació vegi els detalls sobre les trucades en curs al dispositiu i que controli aquestes trucades."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"llegir missatges de difusió mòbil"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Permet que l\'aplicació llegeixi missatges de difusió mòbil rebuts pel dispositiu. Les alertes de difusió mòbil s\'entreguen en algunes ubicacions per alertar de situacions d\'emergència. És possible que les aplicacions malicioses interfereixin en el rendiment o en el funcionament del dispositiu quan es rep una difusió mòbil d\'emergència."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"llegir els feeds als quals esteu subscrit"</string> @@ -1800,8 +1802,8 @@ <string name="package_updated_device_owner" msgid="7560272363805506941">"Actualitzat per l\'administrador"</string> <string name="package_deleted_device_owner" msgid="2292335928930293023">"Suprimit per l\'administrador"</string> <string name="confirm_battery_saver" msgid="5247976246208245754">"D\'acord"</string> - <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Per allargar la durada de la bateria, la funció Estalvi de bateria fa el següent:\n\n• Activa el tema fosc.\n• Desactiva o restringeix l\'activitat en segon pla, alguns efectes visuals i altres funcions com \"Ok Google\".\n\n"<annotation id="url">"Més informació"</annotation></string> - <string name="battery_saver_description" msgid="6794188153647295212">"Per allargar la durada de la bateria, la funció Estalvi de bateria fa el següent:\n\n• Activa el tema fosc.\n• Desactiva o restringeix l\'activitat en segon pla, alguns efectes visuals i altres funcions com \"Ok Google\"."</string> + <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Per allargar la durada de la bateria, la funció Estalvi de bateria:\n\n• Activa el tema fosc.\n• Desactiva o restringeix l\'activitat en segon pla, alguns efectes visuals i altres funcions com \"Ok Google\".\n\n"<annotation id="url">"Més informació"</annotation></string> + <string name="battery_saver_description" msgid="6794188153647295212">"Per allargar la durada de la bateria, la funció Estalvi de bateria:\n\n• Activa el tema fosc.\n• Desactiva o restringeix l\'activitat en segon pla, alguns efectes visuals i altres funcions com \"Ok Google\"."</string> <string name="data_saver_description" msgid="4995164271550590517">"Per reduir l\'ús de dades, la funció Economitzador de dades evita que determinades aplicacions enviïn o rebin dades en segon pla. L\'aplicació que estiguis fent servir podrà accedir a les dades, però menys sovint. Això vol dir, per exemple, que les imatges no es mostraran fins que no les toquis."</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"Activar l\'Economitzador de dades?"</string> <string name="data_saver_enable_button" msgid="4399405762586419726">"Activa"</string> @@ -2190,12 +2192,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Novetat: Window Magnifier"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Ara pots ampliar la pantalla completa o una part"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Activa a Configuració"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Ignora"</string> </resources> diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index 42d56369c3af..6840e2dde2da 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -203,6 +203,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Služba GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Služba oznámení ze senzoru"</string> <string name="twilight_service" msgid="8964898045693187224">"Služba detekce soumraku"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detektor časového pásma (bez připojení)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Zařízení bude vymazáno"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Aplikaci pro správu nelze použít. Zařízení teď bude vymazáno.\n\nV případě dotazů vám pomůže administrátor organizace."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Aplikace <xliff:g id="OWNER_APP">%s</xliff:g> tisk zakazuje."</string> @@ -293,8 +294,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Připojení USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplikace je spuštěna"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikace spotřebovávají baterii"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Zvětšení"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> využívá baterii"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Aplikace (<xliff:g id="NUMBER">%1$d</xliff:g>) využívají baterii"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Klepnutím zobrazíte podrobnosti o využití baterie a dat"</string> @@ -359,6 +359,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Umožňuje aplikaci přijmout a zpracovat zprávy MMS. Znamená to, že aplikace může sledovat zprávy odeslané do vašeho zařízení nebo je smazat, aniž by se vám zobrazily."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Přesměrování zpráv informačních služeb"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Umožňuje aplikaci vytvořit vazbu s modulem informačních služeb za účelem přesměrovávání přijatých zpráv informačních služeb. Výstražná upozornění informačních služeb jsou v některých oblastech odesílána za účelem varování před výjimečnými událostmi. Škodlivé aplikace mohou narušit výkon či provoz vašeho zařízení během přijímání zpráv informačních služeb."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Správa probíhajících hovorů"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Umožňuje aplikaci zobrazit podrobnosti o probíhajících hovorech v zařízení a tyto hovory ovládat."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"čtení zpráv informačních služeb"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Umožňuje aplikaci číst zprávy informačních služeb přijaté ve vašem zařízení. Výstražná upozornění informačních služeb jsou v některých oblastech odesílána za účelem varování před výjimečnými událostmi. Škodlivé aplikace mohou narušit výkon či provoz vašeho zařízení během přijímání zpráv informačních služeb."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"čtení zdrojů přihlášených k odběru"</string> @@ -1282,7 +1284,7 @@ <string name="volume_icon_description_notification" msgid="579091344110747279">"Hlasitost oznámení"</string> <string name="ringtone_default" msgid="9118299121288174597">"Výchozí vyzvánění"</string> <string name="ringtone_default_with_actual" msgid="2709686194556159773">"Výchozí (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string> - <string name="ringtone_silent" msgid="397111123930141876">"Žádný"</string> + <string name="ringtone_silent" msgid="397111123930141876">"Žádné"</string> <string name="ringtone_picker_title" msgid="667342618626068253">"Vyzvánění"</string> <string name="ringtone_picker_title_alarm" msgid="7438934548339024767">"Zvuky budíku"</string> <string name="ringtone_picker_title_notification" msgid="6387191794719608122">"Zvuky upozornění"</string> @@ -2258,12 +2260,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Novinka: Zvětšení oken"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Nyní můžete zvětšit celou obrazovku nebo její část"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Zapnout v Nastavení"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Zavřít"</string> </resources> diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml index 0487406d4e7c..d7ff335dfdd8 100644 --- a/core/res/res/values-da/strings.xml +++ b/core/res/res/values-da/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS-tjeneste"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Tjenesten Sensor Notification"</string> <string name="twilight_service" msgid="8964898045693187224">"Tjenesten Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Tidszoneregistrering (ingen forbindelse)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Enheden slettes"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Administrationsappen kan ikke bruges. Enheden vil nu blive ryddet. \n\nKontakt din organisations administrator, hvis du har spørgsmål."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Udskrivning er deaktiveret af <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB-forbindelse"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Appen kører"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps, der bruger batteri"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Forstørrelse"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> bruger batteri"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps bruger batteri"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tryk for at se info om batteri- og dataforbrug"</string> @@ -353,6 +353,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Tillader, at appen kan modtage og behandle mms-beskeder. Det betyder, at appen kan overvåge eller slette de beskeder, der sendes til din enhed, uden at vise dem til dig."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Videresend Cell Broadcast-meddelelser"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Tillader, at appen bindes til Cell Broadcast-modulet, så Cell Broadcast-meddelelser kan videresendes, når de modtages. I nogle områder sendes der Cell Broadcast-underretninger for at advare dig om nødsituationer. Ondsindede apps kan forstyrre effektiviteten eller driften af din enhed, når den modtager en Cell Broadcast-meddelelse om en nødsituation."</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"læse Cell Broadcast-meddelelser"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Tillader, at appen læser Cell Broadcast-underretninger, der modtages af din enhed. I nogle områder sendes der Cell Broadcast-underretninger for at advare om nødsituationer. Ondsindede apps kan forstyrre ydelsen eller driften af din enhed, når der modtages en Cell Broadcast-meddelelse om en nødsituation."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"læse feeds, jeg abonnerer på"</string> @@ -2190,12 +2194,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nyhed: Forstørrelse af vindue"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Du kan nu forstørre dele af eller hele skærmen"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Aktivér i Indstillinger"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Luk"</string> </resources> diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index ebbde3c9afef..41f4f8ab053a 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS-Dienst"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Sensor Notification Service"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight Service"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Zeitzonen-Erkennung (keine Verbindung)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Die Daten auf deinem Gerät werden gelöscht."</string> <string name="factory_reset_message" msgid="2657049595153992213">"Die Admin-App kann nicht verwendet werden. Die Daten auf deinem Gerät werden nun gelöscht.\n\nBitte wende dich bei Fragen an den Administrator deiner Organisation."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Drucken wurde von <xliff:g id="OWNER_APP">%s</xliff:g> deaktiviert."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB-Verbindung"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App wird ausgeführt"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Strom verbrauchende Apps"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Vergrößerung"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> verbraucht Strom"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> Apps verbrauchen Strom"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Für Details zur Akku- und Datennutzung tippen"</string> @@ -353,6 +353,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Ermöglicht der App, MMS zu empfangen und zu verarbeiten. Das bedeutet, dass die App an dein Gerät gesendete Nachrichten überwachen und löschen kann, ohne sie dir anzuzeigen."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Cell-Broadcast-Nachrichten weiterleiten"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Ermöglicht der App, sich mit dem Cell-Broadcast-Modul zu verbinden, um empfangene Cell-Broadcast-Nachrichten weiterzuleiten. Cell-Broadcast-Benachrichtigungen können in einigen Ländern oder Regionen gesendet werden, um dich bei Notfallsituationen zu warnen. Schädliche Apps können die Leistung oder den Betrieb deines Geräts beeinträchtigen, wenn eine Cell-Broadcast-Notfallbenachrichtigung eingeht."</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"Cell Broadcast-Nachrichten lesen"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Ermöglicht der App, von deinem Gerät empfangene Cell Broadcast-Nachrichten zu lesen. Cell Broadcast-Benachrichtigungen werden an einigen Standorten gesendet, um dich über Notfallsituationen zu informieren. Schädliche Apps können die Leistung oder den Betrieb deines Geräts beeinträchtigen, wenn eine Cell Broadcast-Notfallbenachrichtigung eingeht."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"Abonnierte Feeds lesen"</string> @@ -2190,12 +2194,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Neu: Fenstervergrößerung"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Du kannst das Display teilweise oder ganz vergrößern"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"In den Einstellungen aktivieren"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Schließen"</string> </resources> diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml index 306d36e0ae9f..aa2ee690b431 100644 --- a/core/res/res/values-el/strings.xml +++ b/core/res/res/values-el/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Υπηρεσία GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Υπηρεσία ειδοποίησης αισθητήρα"</string> <string name="twilight_service" msgid="8964898045693187224">"Υπηρεσία Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Εντοπισμός ζώνης ώρας (χωρίς συνδεσιμότητα)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Η συσκευή σας θα διαγραφεί"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Δεν είναι δυνατή η χρήση της εφαρμογής διαχειριστή. Η συσκευή σας θα διαγραφεί.\n\nΕάν έχετε ερωτήσεις, επικοινωνήστε με τον διαχειριστή του οργανισμού σας."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Η εκτύπωση απενεργοποιήθηκε από τον χρήστη <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Σύνδεση USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Η εφαρμογή εκτελείται"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Εφαρμογές που καταναλώνουν μπαταρία"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Μεγιστοποίηση"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> χρησιμοποιεί μπαταρία"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> εφαρμογές χρησιμοποιούν μπαταρία"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Πατήστε για λεπτομέρειες σχετικά με τη χρήση μπαταρίας και δεδομένων"</string> @@ -353,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Επιτρέπει στην εφαρμογή τη λήψη και την επεξεργασία μηνυμάτων MMS. Αυτό σημαίνει ότι η εφαρμογή θα μπορούσε να παρακολουθήσει ή να διαγράψει τα μηνύματα που αποστέλλονται στη συσκευή σας χωρίς αυτά να εμφανιστούν σε εσάς."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Προώθηση μηνυμάτων εκπομπής κινητής τηλεφωνίας"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Επιτρέπει στην εφαρμογή να συνδέεται στη λειτουργική μονάδα εκπομπής κινητής τηλεφωνίας, προκειμένου να προωθεί τα μηνύματα εκπομπής κινητής τηλεφωνίας κατά τη λήψη τους. Οι ειδοποιήσεις εκπομπής κινητής τηλεφωνίας προβάλλονται σε ορισμένες τοποθεσίες, για να σας προειδοποιήσουν σχετικά με καταστάσεις έκτακτης ανάγκης. Οι κακόβουλες εφαρμογές μπορεί να επηρεάσουν την απόδοση ή τη λειτουργία της συσκευής σας κατά τη λήψη μιας εκπομπής κινητής τηλεφωνίας έκτακτης ανάγκης."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Διαχείριση κλήσεων σε εξέλιξη"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Επιτρέπει σε μια εφαρμογή να βλέπει λεπτομέρειες σχετικά με τις κλήσεις σε εξέλιξη στη συσκευή σας και να τις ελέγχει."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"διαβάζει μηνύματα που έχουν μεταδοθεί μέσω κινητού τηλεφώνου"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Επιτρέπει στην εφαρμογή την ανάγνωση μηνυμάτων που έχουν μεταδοθεί μέσω κινητού τηλεφώνου και έχουν ληφθεί από τη συσκευή σας. Ειδοποιήσεις που μεταδίδονται μέσω κινητού παραδίδονται σε ορισμένες τοποθεσίες για να σας προειδοποιήσουν για καταστάσεις έκτακτης ανάγκης. Κακόβουλες εφαρμογές ενδέχεται να παρεμποδίσουν την απόδοση ή τη λειτουργία της συσκευής σας κατά τη λήψη μετάδοσης μέσω κινητού σχετικά με μια επείγουσα κατάσταση."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"διαβάζει ροές δεδομένων στις οποίες έχετε εγγραφεί"</string> @@ -2190,12 +2192,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Νέο: Μεγέθυνση παραθύρου"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Μεγεθύνετε μέρος ή ολόκληρη την οθόνη σας"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Ενεργοποίηση στις Ρυθμίσεις"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Παράβλεψη"</string> </resources> diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml index a8706cbe32c2..de5dba291329 100644 --- a/core/res/res/values-en-rAU/strings.xml +++ b/core/res/res/values-en-rAU/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS service"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Sensor Notification Service"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight Service"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Time zone detector (no connectivity)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Your device will be erased"</string> <string name="factory_reset_message" msgid="2657049595153992213">"The admin app can\'t be used. Your device will now be erased.\n\nIf you have questions, contact your organisation\'s admin."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Printing disabled by <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -352,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Allows the app to receive and process MMS messages. This means that the app could monitor or delete messages sent to your device without showing them to you."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Forward cell broadcast messages"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Allows the app to bind to the cell broadcast module in order to forward cell broadcast messages as they are received. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency cell broadcast is received."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Manage ongoing calls"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Allows an app to see details about ongoing calls on your device and to control these calls."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"read mobile broadcast messages"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Allows the app to read mobile broadcast messages received by your device. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency mobile broadcast is received."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"read subscribed feeds"</string> diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml index 57e2eae62f9c..7bd62aa9f3ae 100644 --- a/core/res/res/values-en-rCA/strings.xml +++ b/core/res/res/values-en-rCA/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS service"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Sensor Notification Service"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight Service"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Time zone detector (no connectivity)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Your device will be erased"</string> <string name="factory_reset_message" msgid="2657049595153992213">"The admin app can\'t be used. Your device will now be erased.\n\nIf you have questions, contact your organisation\'s admin."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Printing disabled by <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -352,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Allows the app to receive and process MMS messages. This means that the app could monitor or delete messages sent to your device without showing them to you."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Forward cell broadcast messages"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Allows the app to bind to the cell broadcast module in order to forward cell broadcast messages as they are received. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency cell broadcast is received."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Manage ongoing calls"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Allows an app to see details about ongoing calls on your device and to control these calls."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"read mobile broadcast messages"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Allows the app to read mobile broadcast messages received by your device. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency mobile broadcast is received."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"read subscribed feeds"</string> diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml index 33ffbe386fc4..b21b67d57a37 100644 --- a/core/res/res/values-en-rGB/strings.xml +++ b/core/res/res/values-en-rGB/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS service"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Sensor Notification Service"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight Service"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Time zone detector (no connectivity)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Your device will be erased"</string> <string name="factory_reset_message" msgid="2657049595153992213">"The admin app can\'t be used. Your device will now be erased.\n\nIf you have questions, contact your organisation\'s admin."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Printing disabled by <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -352,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Allows the app to receive and process MMS messages. This means that the app could monitor or delete messages sent to your device without showing them to you."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Forward cell broadcast messages"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Allows the app to bind to the cell broadcast module in order to forward cell broadcast messages as they are received. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency cell broadcast is received."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Manage ongoing calls"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Allows an app to see details about ongoing calls on your device and to control these calls."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"read mobile broadcast messages"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Allows the app to read mobile broadcast messages received by your device. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency mobile broadcast is received."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"read subscribed feeds"</string> diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml index f5be6fd8c337..69acec63a3d1 100644 --- a/core/res/res/values-en-rIN/strings.xml +++ b/core/res/res/values-en-rIN/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS service"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Sensor Notification Service"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight Service"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Time zone detector (no connectivity)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Your device will be erased"</string> <string name="factory_reset_message" msgid="2657049595153992213">"The admin app can\'t be used. Your device will now be erased.\n\nIf you have questions, contact your organisation\'s admin."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Printing disabled by <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -352,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Allows the app to receive and process MMS messages. This means that the app could monitor or delete messages sent to your device without showing them to you."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Forward cell broadcast messages"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Allows the app to bind to the cell broadcast module in order to forward cell broadcast messages as they are received. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency cell broadcast is received."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Manage ongoing calls"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Allows an app to see details about ongoing calls on your device and to control these calls."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"read mobile broadcast messages"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Allows the app to read mobile broadcast messages received by your device. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency mobile broadcast is received."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"read subscribed feeds"</string> diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml index cd3ff368c289..ae57206baf45 100644 --- a/core/res/res/values-en-rXC/strings.xml +++ b/core/res/res/values-en-rXC/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS Service"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Sensor Notification Service"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight Service"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Time Zone Detector (No connectivity)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Your device will be erased"</string> <string name="factory_reset_message" msgid="2657049595153992213">"The admin app can\'t be used. Your device will now be erased.\n\nIf you have questions, contact your organization\'s admin."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Printing disabled by <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -352,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Allows the app to receive and process MMS messages. This means the app could monitor or delete messages sent to your device without showing them to you."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Forward cell broadcast messages"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Allows the app to bind to the cell broadcast module in order to forward cell broadcast messages as they are received. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency cell broadcast is received."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Manage ongoing calls"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Allows an app to see details about ongoing calls on your device and to control these calls."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"read cell broadcast messages"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Allows the app to read cell broadcast messages received by your device. Cell broadcast alerts are delivered in some locations to warn you of emergency situations. Malicious apps may interfere with the performance or operation of your device when an emergency cell broadcast is received."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"read subscribed feeds"</string> diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index 2d521b3290c2..f5bd810b5225 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Servicio de Sistemas Globales de Navegación por Satélites (GNSS)"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Servicio de notificaciones del sensor"</string> <string name="twilight_service" msgid="8964898045693187224">"Servicio de Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detector de zona horaria (sin conexión)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Se borrarán los datos del dispositivo"</string> <string name="factory_reset_message" msgid="2657049595153992213">"No se puede usar la app de administrador. Ahora se borrará tu dispositivo.\n\nSi tienes preguntas, comunícate con el administrador de tu organización."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> inhabilitó la impresión."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Conexión USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App en ejecución"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps que consumen batería"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ampliación"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> está consumiendo batería"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps están consumiendo batería"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Presiona para obtener información sobre el uso de datos y de la batería"</string> @@ -353,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Permite que la aplicación reciba y procese mensajes MMS, lo que significa que podría controlar o eliminar mensajes enviados al dispositivo sin mostrártelos."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Reenviar mensajes de emisión móvil"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Permite que la app se vincule al módulo de emisión móvil para reenviar los mensajes de este tipo a medida que se reciben. En algunas ubicaciones, se envían alertas de emisión móvil para advertirte en situaciones de emergencia. Es posible que las apps maliciosas interfieran con el rendimiento o el funcionamiento de tu dispositivo cuando recibes una emisión móvil de emergencia."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Administrar llamadas en curso"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Permite que una app vea detalles sobre las llamadas en curso del dispositivo y las controle."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"Leer mensajes de difusión móvil"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Permite a la aplicación leer los mensajes de difusión móvil que recibe tu dispositivo. En algunas ubicaciones, las alertas de difusión móvil se envían para informar situaciones de emergencia. Las aplicaciones maliciosas pueden afectar el rendimiento o funcionamiento de tu dispositivo cuando se recibe un un mensaje de difusión móvil de emergencia."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"leer canales suscritos"</string> @@ -2190,12 +2192,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nueva: Ampliación de ventanas"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Puedes ampliar toda tu pantalla o parte de ella"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Activar en Configuración"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Descartar"</string> </resources> diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index abc694686bee..e234efbfffd6 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Servicio GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Servicio de notificación de sensor"</string> <string name="twilight_service" msgid="8964898045693187224">"Servicio de Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detector de zona horaria (sin conexión)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Tu dispositivo se borrará"</string> <string name="factory_reset_message" msgid="2657049595153992213">"No se puede utilizar la aplicación de administración. Se borrarán todos los datos del dispositivo.\n\nSi tienes alguna pregunta, ponte en contacto con el administrador de tu organización."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ha inhabilitado la impresión."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Conexión USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplicación en ejecución"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplicaciones que consumen batería"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ampliación"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> está usando la batería"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicaciones están usando la batería"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Toca para ver información detallada sobre el uso de datos y de la batería"</string> @@ -353,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Permite que la aplicación reciba y procese mensajes MMS, lo que significa que podría utilizar este permiso para controlar o eliminar mensajes enviados al dispositivo sin mostrárselos al usuario."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Reenviar mensajes de difusión móvil"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Permite que la aplicación se vincule con el módulo de difusión móvil para reenviar los mensajes de ese tipo en cuanto se reciben. En ciertas ubicaciones se envían alertas de difusión móvil para avisar de situaciones de emergencia. Cuando se recibe una alerta de difusión móvil de emergencia, ciertas aplicaciones malintencionadas podrían interferir en el rendimiento o en el funcionamiento del dispositivo."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Gestionar llamadas en curso"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Permite que una aplicación consulte datos de llamadas que estén en curso en tu dispositivo y controle esas llamadas."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"leer mensajes de difusión móvil"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Permite que la aplicación lea mensajes de difusión móvil que haya recibido el dispositivo. Las alertas de difusión móvil se envían en algunas ubicaciones para avisar de situaciones de emergencia. Es posible que las aplicaciones malintencionadas interfieran en el rendimiento o en el funcionamiento del dispositivo si se recibe una alerta de difusión móvil de emergencia."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"leer feeds a los que está suscrito el usuario"</string> @@ -832,7 +834,7 @@ <string name="keyguard_password_enter_pin_password_code" msgid="7792964196473964340">"Introduce el código PIN para desbloquear."</string> <string name="keyguard_password_wrong_pin_code" msgid="8583732939138432793">"Código PIN incorrecto"</string> <string name="keyguard_label_text" msgid="3841953694564168384">"Para desbloquear el teléfono, pulsa la tecla de menú y, a continuación, pulsa 0."</string> - <string name="emergency_call_dialog_number_for_display" msgid="2978165477085612673">"Llamada de emergencia"</string> + <string name="emergency_call_dialog_number_for_display" msgid="2978165477085612673">"Número de emergencia"</string> <string name="lockscreen_carrier_default" msgid="6192313772955399160">"Sin servicio"</string> <string name="lockscreen_screen_locked" msgid="7364905540516041817">"Pantalla bloqueada"</string> <string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Pulsa la tecla de menú para desbloquear el teléfono o realizar una llamada de emergencia."</string> @@ -2190,12 +2192,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nuevo: Lupa de ventanas"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Ahora puedes ampliar toda la pantalla o una parte"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Activar en Ajustes"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Cerrar"</string> </resources> diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml index 130ef6e47b9f..543b5a1da879 100644 --- a/core/res/res/values-et/strings.xml +++ b/core/res/res/values-et/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS-teenus"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Anduri märguande teenus"</string> <string name="twilight_service" msgid="8964898045693187224">"Teenus Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Ajavööndi tuvastaja (ühenduvus puudub)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Seade kustutatakse"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Administraatori rakendust ei saa kasutada. Teie seade tühjendatakse nüüd.\n\nKui teil on küsimusi, võtke ühendust organisatsiooni administraatoriga."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Rakendus <xliff:g id="OWNER_APP">%s</xliff:g> on printimise keelanud."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB-ühendus"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Rakendus töötab"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Rakendused kasutavad akutoidet"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Suurendus"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> kasutab akutoidet"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> rakendust kasutab akutoidet"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Aku ja andmekasutuse üksikasjade nägemiseks puudutage"</string> @@ -353,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Võimaldab rakendusel vastu võtta ja töödelda multimeediumsõnumeid. See tähendab, et rakendus võib jälgida või kustutada teie seadmele saadetud sõnumeid neid teile näitamata."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Kärjeteadete edasisaatmine"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Võimaldab rakendusel luua ühenduse kärjeteadete mooduliga, et saabunud kärjeteateid edasi saata. Kärjeteateid edastatakse mõnes asukohas eriolukorrast teavitamiseks. Pahatahtlikud rakendused võivad seadme toimivust või tööd eriolukorra kärjeteate vastuvõtmisel segada."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Käimasolevate kõnede haldamine"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Võimaldab rakendusel näha teie seadmes käimasolevate kõnede üksikasju ja neid kõnesid hallata."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"mobiilsidesõnumite lugemine"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Võimaldab rakendusel lugeda seadme vastu võetud mobiilsidesõnumeid. Mobiilsidemärguandeid edastatakse mõnes asukohas eriolukorrast teavitamiseks. Pahatahtlikud rakendused võivad segada seadme toimivust või tööd eriolukorra sõnumi vastuvõtmisel."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"loe tellitud kanaleid"</string> @@ -2190,12 +2192,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Uus: akna suurendaja"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Nüüd saab suurendada kogu ekraanikuva või osa sellest"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Lülitage sisse menüüs Seaded"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Loobu"</string> </resources> diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml index 5273a48fa3b5..c552e8f39e52 100644 --- a/core/res/res/values-eu/strings.xml +++ b/core/res/res/values-eu/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS zerbitzua"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Sentsorearen jakinarazpen-zerbitzua"</string> <string name="twilight_service" msgid="8964898045693187224">"Ilunabarreko zerbitzua"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Ordu-zonaren hautemailea (ez zaude konektatuta sarera)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Gailuko datuak ezabatu egingo dira"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Ezin da erabili administratzeko aplikazioa. Ezabatu egingo da gailuko eduki guztia.\n\nZalantzarik baduzu, jarri erakundeko administratzailearekin harremanetan."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> aplikazioak desgaitu egin du inprimatzeko aukera."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB konexioa"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplikazio bat abian da"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Bateria kontsumitzen ari diren aplikazioak"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Lupa"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ari da bateria erabiltzen"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplikazio ari dira bateria erabiltzen"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Sakatu bateria eta datuen erabilerari buruzko xehetasunak ikusteko"</string> @@ -353,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"MMS mezuak jasotzeko eta prozesatzeko baimena ematen die aplikazioei. Horrela, aplikazioak gailura bidalitako mezuak kontrola eta ezaba ditzake zuri erakutsi gabe."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"desbideratu sare mugikor bidezko igorpen-mezuak"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Sare mugikor bidezko igorpen-modulura lotzeko baimena ematen dio aplikazioari, sare mugikor bidezko igorpen-mezuak jaso ahala desbideratu ahal izateko. Sare mugikor bidezko igorpen-alertak kokapen batzuetan entregatzen dira larrialdi-egoeren berri emateko. Sare mugikor bidezko larrialdi-igorpenak jasotzean, aplikazio gaiztoek gailuaren errendimenduari edota funtzionamenduari eragin diezaiokete."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Kudeatu abian dauden deiak"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Gailuak jasotzen dituen deiei buruzko xehetasunak ikusteko eta dei horiek kontrolatzeko baimena ematen die aplikazioei."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"irakurri sare mugikor bidezko igorpen-mezuak"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Gailuak jasotako sare mugikor bidezko igorpenen mezuak irakurtzeko baimena ematen die aplikazioei. Sare mugikor bidezko igorpen-alertak kokapen batzuetan ematen dira larrialdi-egoeren berri emateko. Aplikazio gaiztoek gailuaren errendimendua edo funtzionamendua oztopa dezakete larrialdi-igorpen horietako bat jasotzen denean."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"irakurri harpidetutako jarioak"</string> @@ -500,7 +502,7 @@ <string name="permdesc_changeNetworkState" msgid="649341947816898736">"Sarearen konexioaren egoera aldatzeko baimena ematen die aplikazioei."</string> <string name="permlab_changeTetherState" msgid="9079611809931863861">"aldatu telefono bidezko konektagarritasuna"</string> <string name="permdesc_changeTetherState" msgid="3025129606422533085">"Partekatutako Interneterako konexioaren egoera aldatzeko baimena ematen die aplikazioei."</string> - <string name="permlab_accessWifiState" msgid="5552488500317911052">"ikusi wifi bidezko konexioak"</string> + <string name="permlab_accessWifiState" msgid="5552488500317911052">"ikusi wifi-konexioak"</string> <string name="permdesc_accessWifiState" msgid="6913641669259483363">"Wi-Fi sareei buruzko informazioa ikusteko baimena ematen die aplikazioei, adibidez, Wi-Fi konexioa aktibatuta dagoen eta konektatutako Wi-Fi gailuen izenak zein diren."</string> <string name="permlab_changeWifiState" msgid="7947824109713181554">"konektatu wifira edo deskonektatu bertatik"</string> <string name="permdesc_changeWifiState" msgid="7170350070554505384">"Wi-Fi sarbide-puntuetara konektatzeko edo haietatik deskonektatzeko baimena ematen die aplikazioei, baita Wi-Fi sareen gailu-konfigurazioari aldaketak egitekoa ere."</string> @@ -2190,12 +2192,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Berria: leihoen lupa"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Orain, pantaila osoa edo haren zati bat handi dezakezu"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Aktibatu ezarpenetan"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Baztertu"</string> </resources> diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index 7596bab30f16..3d523fdb79e9 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"سرویس GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"سرویس اعلان حسگر"</string> <string name="twilight_service" msgid="8964898045693187224">"سرویس Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"شناساگر منطقه زمانی (بدون اتصال)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"دستگاهتان پاک خواهد شد"</string> <string name="factory_reset_message" msgid="2657049595153992213">"برنامه سرپرست سیستم را نمیتوان استفاده کرد. دستگاه شما در این لحظه پاک میشود.\n\nاگر سؤالی دارید، با سرپرست سیستم سازمانتان تماس بگیرید."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> چاپ کردن را غیرفعال کرده است."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"اتصال USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"برنامه درحال اجرا"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"برنامههای مصرفکننده باتری"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"درشتنمایی"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> درحال استفاده کردن از باتری است"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> برنامه درحال استفاده کردن از باتری هستند"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"برای جزئیات مربوط به مصرف باتری و داده، ضربه بزنید"</string> @@ -353,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"به برنامه اجازه میدهد پیامهای فراپیام را دریافت و پردازش کند. این یعنی برنامه میتواند پیامهای ارسالی به دستگاه شما را بدون نمایش آنها به شما حذف یا کنترل کند."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"بازارسال پیامهای پخش سلولی"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"به برنامه امکان میدهد به مدول پخش سلولی متصل شود تا پیامهای پخش سلولی را به محض دریافت بازارسال کند. هشدارهای پخش سلولی در برخی از موقعیتهای مکانی ارسال میشوند تا موقعیتهای اضطراری را به شما اعلام کنند. وقتی پخش سلولی دریافت میشود، ممکن است برنامههای مخرب در عملکرد یا کارکرد دستگاه شما اختلال ایجاد کنند."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"مدیریت تماسهای درحال انجام"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"به برنامه اجازه میدهد جزئیات تماسهای درحال انجام در دستگاه را ببیند و این تماسها را کنترل کند."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"خواندن پیامهای پخش سلولی"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"به برنامه اجازه میدهد پیامهای پخش سلولی دستگاه شما را بخواند. هشدارهای پخش سلولی در برخی از موقعیتهای مکانی تحویل داده میشوند تا موقعیتهای اضطراری را به شما اعلام کنند. وقتی پخش سلولی دریافت میشود، ممکن است برنامههای مخرب در عملکرد یا کارکرد دستگاه شما اختلال ایجاد کنند."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"خواندن فیدهای مشترک"</string> @@ -2190,12 +2192,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"جدید: Window Magnifier"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"اکنون میتوانید بخشی از صفحه یا کل آن را درشت کنید"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"روشن کردن در «تنظیمات»"</string> + <string name="dismiss_action" msgid="1728820550388704784">"رد شدن"</string> </resources> diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml index d3373154196a..81546d9c99d8 100644 --- a/core/res/res/values-fi/strings.xml +++ b/core/res/res/values-fi/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS-palvelu"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Anturin ilmoituspalvelu"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight-palvelu"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Aikavyöhykkeen tunnistin (ei yhteyttä)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Laitteen tiedot poistetaan"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Hallintasovellusta ei voi käyttää. Laitteen tiedot pyyhitään.\n\nPyydä ohjeita järjestelmänvalvojaltasi."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> on poistanut tulostuksen käytöstä."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB-yhteys"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Sovellus käynnissä"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Akkua kuluttavat sovellukset"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Suurennus"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> käyttää akkua."</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> sovellusta käyttää akkua."</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Katso lisätietoja akun ja datan käytöstä napauttamalla."</string> @@ -353,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Antaa sovelluksen vastaanottaa ja käsitellä multimediaviestejä. Sovellus voi valvoa tai poistaa laitteeseesi lähetettyjä viestejä näyttämättä niitä sinulle."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Lähetä solulähetysviestit edelleen"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Sallii sovelluksen sitoutua solulähetysmoduuliin lähettääkseen solulähetysviestejä edelleen sitä mukaa kun ne saapuvat. Solulähetysilmoitusten avulla ilmoitetaan hätätilanteista joissakin paikoissa. Haitalliset sovellukset voivat häiritä laitteen toimintaa laitteen vastaanottaessa hätätilanteeseen liittyvän solulähetysviestin."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Ylläpidä käynnissä olevia puheluita"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Sovellus voi nähdä tietoja laitteella käynnissä olevista puheluista ja ohjata näitä puheluita."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"lue tiedotteita"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Antaa sovelluksen lukea laitteesi vastaanottamia tiedotteita. Tiedotteiden avulla ilmoitetaan hätätilanteista joissakin paikoissa. Haitalliset sovellukset voivat häiritä laitteen toimintaa laitteen vastaanottaessa hätätiedotteen."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lukea tilattuja syötteitä"</string> @@ -2190,12 +2192,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Uutta: ikkunan suurennus"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Voit nyt suurentaa näytön osittain tai kokonaan"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Laita päälle asetuksista"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Hylkää"</string> </resources> diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml index d2c89bc8d842..cdfa15dd751e 100644 --- a/core/res/res/values-fr-rCA/strings.xml +++ b/core/res/res/values-fr-rCA/strings.xml @@ -201,6 +201,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Service GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Service de notification de capteur"</string> <string name="twilight_service" msgid="8964898045693187224">"Service de crépuscule"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Détecteur de fuseau horaire (aucune connectivité)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Le contenu de votre appareil sera effacé"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Impossible d\'utiliser l\'application d\'administration. Les données de votre appareil vont maintenant être effacées.\n\nSi vous avez des questions, communiquez avec l\'administrateur de votre organisation."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Impression désactivée par <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -290,8 +291,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Connexion USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Application en cours d\'exécution"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Applications qui sollicitent la pile"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Agrandissement"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> sollicite la pile"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> applications sollicitent la pile"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Touchez pour afficher des détails sur l\'utilisation de la pile et des données"</string> @@ -356,6 +356,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Permet à l\'application de recevoir et de traiter les messages multimédias. Cette autorisation lui donne la possibilité de surveiller ou de supprimer les messages envoyés à votre appareil sans vous les montrer."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Transférer les messages de diffusion cellulaire"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Permet à l\'application d\'établir un lien avec le module de diffusion cellulaire afin de transférer les messages de diffusion cellulaire à mesure de leur réception. Dans certaines régions, des alertes de diffusion cellulaire sont envoyées afin de vous avertir de situations d\'urgence. Des applications malveillantes peuvent interférer avec les performances ou le fonctionnement de votre appareil lors de la réception d\'une alerte d\'urgence par diffusion cellulaire."</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"lire les messages de diffusion cellulaire"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Permet à l\'application de lire les messages de diffusion cellulaire que votre appareil reçoit. Dans certaines zones géographiques, des alertes vous sont envoyées afin de vous prévenir en cas de situation d\'urgence. Des applications malveillantes peuvent venir perturber les performances ou le fonctionnement de votre appareil lors de la réception d\'un message de diffusion cellulaire."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lire les flux auxquels vous êtes abonné"</string> @@ -2224,12 +2228,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nouveauté : Loupe de fenêtre"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Vous pouvez agrandir une partie ou la totalité de votre écran"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Activer dans les paramètres"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Fermer"</string> </resources> diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index 1992068a4a85..9e0f60c21fc6 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -201,6 +201,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Service GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Service de notification du capteur"</string> <string name="twilight_service" msgid="8964898045693187224">"Service Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Outil de détection du fuseau horaire (aucune connectivité)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Les données de votre appareil vont être effacées"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Impossible d\'utiliser l\'application d\'administration. Les données de votre appareil vont maintenant être effacées.\n\nSi vous avez des questions, contactez l\'administrateur de votre organisation."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Impression désactivée par <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -290,8 +291,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Connexion USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Application en cours d\'exécution"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Applications utilisant la batterie"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Agrandissement"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> utilise la batterie"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> applications utilisent la batterie"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Appuyer pour obtenir des informations sur l\'utilisation de la batterie et des données"</string> @@ -356,6 +356,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Permet à l\'application de recevoir et de traiter les MMS. Cette autorisation lui donne la possibilité de surveiller ou supprimer les messages envoyés à votre appareil sans vous les montrer."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Transférer les messages reçus via un canal de diffusion cellulaire"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Autorise l\'application à établir une connexion avec le module de diffusion cellulaire afin de transférer les messages reçus via un canal de diffusion cellulaire. Des alertes de diffusion cellulaire sont générées dans certaines régions afin de vous avertir de situations d\'urgence. Des applications malveillantes peuvent interférer avec les performances ou le fonctionnement de votre appareil lors de la réception d\'une alerte d\'urgence par diffusion cellulaire."</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"lire les messages reçus via un canal de diffusion cellulaire"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Permet à l\'application de lire les messages que votre appareil reçoit via un canal de diffusion cellulaire. Dans certaines zones géographiques, des alertes vous sont envoyées afin de vous prévenir en cas de situation d\'urgence. Les applications malveillantes peuvent venir perturber les performances ou le fonctionnement de votre appareil lorsqu\'un message est reçu via un canal de diffusion cellulaire."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lire les flux auxquels vous êtes abonné"</string> @@ -1823,7 +1827,7 @@ <string name="package_updated_device_owner" msgid="7560272363805506941">"Mis à jour par votre administrateur"</string> <string name="package_deleted_device_owner" msgid="2292335928930293023">"Supprimé par votre administrateur"</string> <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string> - <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Pour prolonger l\'autonomie de la batterie, l\'économiseur de batterie :\n\n·• active le thème sombre ;\n·• désactive ou restreint les activités en arrière-plan, certains effets visuels et d\'autres fonctionnalités, comme \"Hey Google\".\n\n"<annotation id="url">"En savoir plus"</annotation></string> + <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Pour prolonger l\'autonomie de la batterie, l\'économiseur de batterie :\n\n • active le thème sombre ;\n • désactive ou restreint les activités en arrière-plan, certains effets visuels et d\'autres fonctionnalités, comme \"Hey Google\".\n\n"<annotation id="url">"En savoir plus"</annotation></string> <string name="battery_saver_description" msgid="6794188153647295212">"Pour prolonger l\'autonomie de la batterie, l\'économiseur de batterie :\n\n• active le thème sombre ;\n • désactive ou restreint les activités en arrière-plan, certains effets visuels et d\'autres fonctionnalités, comme \"Hey Google\"."</string> <string name="data_saver_description" msgid="4995164271550590517">"Pour réduire la consommation de données, l\'économiseur de données empêche certaines applications d\'envoyer ou de recevoir des données en arrière-plan. Ainsi, les applications que vous utilisez peuvent toujours accéder aux données, mais pas en permanence. Par exemple, il se peut que les images ne s\'affichent pas tant que vous n\'appuyez pas dessus."</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"Activer l\'économiseur de données ?"</string> @@ -2224,12 +2228,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nouveau : agrandissement de la fenêtre"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Vous pouvez agrandir tout ou partie de l\'écran"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Activer dans les paramètres"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Fermer"</string> </resources> diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml index 7583502fb988..423b97fcc6e7 100644 --- a/core/res/res/values-gl/strings.xml +++ b/core/res/res/values-gl/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Servizo GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Servizo de notificacións dos sensores"</string> <string name="twilight_service" msgid="8964898045693187224">"Servizo Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detector de fuso horario (non require conexión)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Borrarase o teu dispositivo"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Non se pode utilizar a aplicación de administración. Borrarase o teu dispositivo.\n\nSe tes preguntas, contacta co administrador da organización."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> desactivou a impresión."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"conexión USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Estase executando a aplicación"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplicacións que consomen batería"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ampliación"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"A aplicación <xliff:g id="APP_NAME">%1$s</xliff:g> está consumindo batería"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicacións están consumindo batería"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Toca para obter información sobre o uso de datos e a batería"</string> @@ -353,6 +353,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Permite á aplicación recibir e procesar mensaxes MMS. Isto significa que a aplicación pode supervisar ou eliminar mensaxes enviadas ao teu dispositivo sen mostrarchas."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Reenviar mensaxes de difusión móbil"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Permite que a aplicación se vincule ao módulo de difusión móbil para reenviar as mensaxes deste tipo segundo se reciban. As alertas de difusión móbil envíanse nalgunhas localizacións para avisar de situacións de emerxencia. As aplicacións maliciosas poden interferir no rendemento ou funcionamento do teu dispositivo cando se reciba unha difusión móbil de emerxencia."</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"ler mensaxes de difusión móbil"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Permite á aplicación ler mensaxes de difusión móbil recibidas polo teu dispositivo. As alertas de difusión móbil envíanse nalgunhas localizacións para avisar de situacións de emerxencia. É posible que aplicacións maliciosas afecten ao rendemento ou funcionamento do teu dispositivo cando se recibe unha difusión móbil de emerxencia."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"ler feeds subscritos"</string> @@ -2190,12 +2194,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nova función: Lupa de ventá"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Agora podes ampliar toda a pantalla ou parte dela"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Activar en Configuración"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Ignorar"</string> </resources> diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml index 6f140c4b5d85..14347eebffac 100644 --- a/core/res/res/values-gu/strings.xml +++ b/core/res/res/values-gu/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS સેવા"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"સેન્સર નોટિફિકેશન સેવા"</string> <string name="twilight_service" msgid="8964898045693187224">"ટ્વાઇલાઇટ સેવા"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"સમય ઝોન શોધવાની સુવિધા (કનેક્ટિવિટી જરૂરી નથી)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"તમારું ઉપકરણ કાઢી નાખવામાં આવશે"</string> <string name="factory_reset_message" msgid="2657049595153992213">"વ્યવસ્થાપક ઍપનો ઉપયોગ કરી શકાશે નહીં. તમારું ઉપકરણ હવે કાઢી નાખવામાં આવશે.\n\nજો તમને પ્રશ્નો હોય, તો તમારી સંસ્થાના વ્યવસ્થાપકનો સંપર્ક કરો."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> દ્વારા પ્રિન્ટ કરવાનું બંધ કરાયું છે."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB કનેક્શન"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ઍપ ચાલી રહ્યું છે"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ઍપ બૅટરીનો વપરાશ કરી રહ્યાં છે"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"મોટું કરવાની સુવિધા"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> બૅટરીનો ઉપયોગ કરી રહ્યું છે"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ઍપ બૅટરીનો ઉપયોગ કરી રહ્યાં છે"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"બૅટરી અને ડેટા વપરાશ વિશેની વિગતો માટે ટૅપ કરો"</string> @@ -353,6 +353,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"ઍપ્લિકેશનને MMS સંદેશા પ્રાપ્ત કરવાની અને તેના પર પ્રક્રિયા કરવાની મંજૂરી આપે છે. આનો અર્થ એ કે ઍપ્લિકેશન તમને દર્શાવ્યા વિના તમારા ઉપકરણ પર મોકલેલ સંદેશાઓનું નિરીક્ષણ કરી શકે છે અથવા કાઢી નાખી શકે છે."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"સેલ બ્રોડકાસ્ટ સંદેશા ફૉરવર્ડ કરો"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"સેલ બ્રોડકાસ્ટ સંદેશા પ્રાપ્ત થાય કે તરત ફૉરવર્ડ કરવા માટે સેલ બ્રોડકાસ્ટ મૉડ્યૂલ સાથે પ્રતિબદ્ધ થવા બાબતે ઍપને મંજૂરી આપે છે. તમને કટોકટીની પરિસ્થિતિની ચેતવણી આપવા માટે સેલ બ્રોડકાસ્ટ અલર્ટ અમુક સ્થાનોમાં ડિલિવર કરવામાં આવે છે. કટોકટી અંગેનો સેલ બ્રોડકાસ્ટ પ્રાપ્ત થાય, ત્યારે દુર્ભાવનાપૂર્ણ ઍપ તમારા ડિવાઇસના કાર્યપ્રદર્શન અથવા ઑપરેશનમાં વિક્ષેપ પાડે તેમ બની શકે છે."</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"સેલ બ્રોડકાસ્ટ સંદેશા વાંચો"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"એપ્લિકેશનને તમારા ઉપકરણ દ્વારા પ્રાપ્ત થયેલ સેલ બ્રોડકાસ્ટ સંદેશાને વાંચવાની મંજૂરી આપે છે. સેલ બ્રોડકાસ્ટ ચેતવણીઓ તમને કટોકટીની સ્થિતિઓ અંગે ચેતવવા માટે કેટલાક સ્થાનોમાં વિતરિત થાય છે. જ્યારે કટોકટીનો સેલ બ્રોડકાસ્ટ પ્રાપ્ત થાય ત્યારે દુર્ભાવનાપૂર્ણ ઍપ્લિકેશનો તમારા ઉપકરણના પ્રદર્શન અથવા ઓપરેશનમાં હસ્તક્ષેપ કરી શકે છે."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"સબ્સ્ક્રાઇબ કરેલ ફીડ્સ વાંચો"</string> @@ -2190,12 +2194,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"નવી: વિંડો મોટી કરવાની સુવિધા"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"હવે તમે તમારી કેટલીક કે આખી સ્ક્રીનને મોટી કરી શકો છો"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"સેટિંગમાં ચાલુ કરો"</string> + <string name="dismiss_action" msgid="1728820550388704784">"છોડી દો"</string> </resources> diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml index 5892dab23628..e63e50225ed7 100644 --- a/core/res/res/values-hi/strings.xml +++ b/core/res/res/values-hi/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"जीएनएसएस सेवा"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"सेंसर से जुड़ी सूचना सेवा"</string> <string name="twilight_service" msgid="8964898045693187224">"ट्वाइलाइट समय बताने वाली सेवा"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"समय क्षेत्र का पता लगाने वाली सुविधा (ऑफ़लाइन होने पर)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"आपके डिवाइस को मिटा दिया जाएगा"</string> <string name="factory_reset_message" msgid="2657049595153992213">"एडमिन ऐप्लिकेशन का इस्तेमाल नहीं किया जा सकता. आपके डिवाइस पर मौजूद डेटा अब मिटा दिया जाएगा.\n\nअगर आप कुछ पूछना चाहते हैं तो, अपने संगठन के एडमिन से संपर्क करें."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ने प्रिंटिंग सुविधा बंद कर दी है."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB कनेक्शन"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ऐप अभी इस्तेमाल हो रहा है"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"बैटरी की खपत करने वाले ऐप"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ज़ूम करने की सुविधा"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> बैटरी का इस्तेमाल कर रहा है"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ऐप बैटरी का इस्तेमाल कर रहे हैं"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"बैटरी और डेटा खर्च की जानकारी के लिए छूएं"</string> @@ -353,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"ऐप को मल्टीमीडिया मैसेज (एमएमएस) को पाने और उन पर कार्रवाई करने देता है. इसका मतलब है कि ऐप आपके डिवाइस पर भेजे गए मैसेज की निगरानी आपको दिखाए बिना कर सकता है और उन्हें हटा सकता है."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"सेल ब्रॉडकास्ट (CBC) मैसेज दूसरे नंबर पर भेजें"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"सेल ब्रॉडकास्ट (CBC) मैसेज आते ही उसे दूसरे नंबर पर भेजने के लिए, ऐप्लिकेशन को सेल ब्रॉडकास्ट (CBC) मॉड्यूल पर बाइंड करने की अनुमति देता है. कुछ जगहों में सेल ब्रॉडकास्ट (CBC) अलर्ट आपातकालीन स्थितियों के बारे में चेतावनी देने के लिए भेजा जाता है. नुकसान पहुंचाने वाले ऐप्लिकेशन, आपातकाल में सेल ब्रॉडकास्ट (CBC) मैसेज मिलने पर आपके डिवाइस के काम करते समय या इसके परफ़ॉर्मेंस में रुकावट पैदा कर सकते हैं."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"चल रहे कॉल प्रबंधित करें"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"इससे, ऐप्लिकेशन को आपके डिवाइस पर चल रहे कॉल की जानकारी देखने और उन्हें कंट्रोल करने की अनुमति मिलती है."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"सेल ब्रॉडकास्ट (CBC) मैसेज पढ़ें"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"ऐप को, वो सेल ब्रॉडकास्ट (CBC) मैसेज पढ़ने देता है जो आपके डिवाइस को मिले हैं. सेल ब्रॉडकास्ट (CBC) अलर्ट कुछ स्थानों (लोकेशन) पर आपको आपातकालीन स्थितियों की चेतावनी देने के लिए दिए जाते हैं. आपातकालीन सेल ब्रॉडकास्ट (CBC) मिलने पर, धोखा देने वाले ऐप आपके डिवाइस के परफ़ॉर्मेंस या कार्यवाही में दखल दे सकते हैं."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"सदस्यता वाली फ़ीड पढ़ें"</string> @@ -2190,12 +2192,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"नई सुविधा: विंडो को ज़ूम करके देखने की सुविधा"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"अब अपनी पूरी स्क्रीन या कुछ हिस्से को ज़ूम करके देख सकते हैं"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"सेटिंग में जाकर, इस सुविधा को चालू करें"</string> + <string name="dismiss_action" msgid="1728820550388704784">"खारिज करें"</string> </resources> diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml index f4d984275576..45c89a62e12d 100644 --- a/core/res/res/values-hr/strings.xml +++ b/core/res/res/values-hr/strings.xml @@ -201,6 +201,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Usluga GNSS-a"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Usluga Obavijesti senzora"</string> <string name="twilight_service" msgid="8964898045693187224">"Usluga Sumrak"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detektor vremenske zone (nije povezan)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Uređaj će se izbrisati"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Administratorska aplikacija ne može se upotrebljavati. Uređaj će se izbrisati.\n\nAko imate pitanja, obratite se administratoru organizacije."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Ispis je onemogućila aplikacija <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -290,8 +291,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB veza"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Izvodi se aplikacija"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacije troše bateriju"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Povećavanje"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> koristi bateriju"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Broj aplikacija koje koriste bateriju: <xliff:g id="NUMBER">%1$d</xliff:g>"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Dodirnite da biste vidjeli pojedinosti o potrošnji baterije i podatkovnom prometu"</string> @@ -356,6 +356,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Aplikaciji omogućuje primanje i obradu MMS poruka. To znači da aplikacija može nadzirati ili izbrisati poruke poslane na vaš uređaj, a da vam ih ne prikaže."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Prosljeđivanje poruka emitiranja na mobitele"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Omogućuje aplikaciji da se poveže s modulom za emitiranje na mobitele kako bi prosljeđivala poruke koje se emitiraju na mobitele po njihovom primitku. Upozorenja značajke emitiranja na mobitele dostavljaju se na nekim lokacijama kako bi upozorila korisnike na hitne situacije. Zlonamjerne aplikacije mogu ometati izvršavanje ili rad vašeg uređaja kada stigne hitno emitiranje na mobitele."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Upravljanje tekućim pozivima"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Omogućuje aplikaciji pregled pojedinosti o tekućim pozivima na uređaju i upravljanje tim pozivima."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"čitaj poruke koje se emitiraju unutar mobilne mreže"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Omogućuje aplikaciji čitanje poruka emitiranih unutar mobilne mreže koje prima vaš uređaj. Upozorenja koja se emitiraju na području mobilne mreže dostavljaju se na nekim lokacijama kako bi upozorila korisnike na hitne situacije. Zlonamjerne aplikacije mogu ometati izvršavanje ili rad vašeg uređaja kada stigne hitno upozorenje koje se emitira unutar mobilne mreže."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"čitanje pretplaćenih feedova"</string> @@ -2224,12 +2226,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Novo: alat za povećanje prozora"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Sad možete povećati dio zaslona ili cijeli zaslon"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Uključite u Postavkama"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Odbaci"</string> </resources> diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml index bff17731ac84..ec0715b52338 100644 --- a/core/res/res/values-hu/strings.xml +++ b/core/res/res/values-hu/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS-szolgáltatás"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Szenzoros értesítési szolgáltatás"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight szolgáltatás"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Időzóna-felismerő (Offline)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"A rendszer törölni fogja eszközét"</string> <string name="factory_reset_message" msgid="2657049595153992213">"A rendszergazdai alkalmazás nem használható. A rendszer most törli az eszközt.\n\nKérdéseivel forduljon szervezete rendszergazdájához."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"A(z) <xliff:g id="OWNER_APP">%s</xliff:g> letiltotta a nyomtatást."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB-kapcsolat"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Jelenleg futó alkalmazás"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Akkumulátort használó alkalmazások"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Nagyítás"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"A(z) <xliff:g id="APP_NAME">%1$s</xliff:g> alkalmazás használja az akkumulátort"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> alkalmazás használja az akkumulátort"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Koppintson az akkumulátor- és adathasználat részleteinek megtekintéséhez"</string> @@ -353,6 +353,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Lehetővé teszi az alkalmazás számára, hogy MMS-eket fogadjon és dolgozzon fel. Ez azt jelenti, hogy az alkalmazás megfigyelheti vagy törölheti a beérkező üzeneteket anélkül, hogy Ön látná azokat."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Cellán belüli üzenetek továbbítása"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Az alkalmazás összekapcsolódhat a cellán belüli üzenetszórás moduljával, hogy az érkezésükkor továbbítani tudja a cellán belüli üzeneteket. Bizonyos helyeken figyelmeztető üzeneteket kaphat a cellán belül a vészhelyzetekről. A rosszindulatú alkalmazások vészhelyzeti cellaüzenet érkezésekor befolyásolhatják az eszköz teljesítményét és működését."</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"cellán belüli üzenetek olvasása"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Lehetővé teszi az alkalmazás számára az eszközre érkező cellán belüli üzenetek olvasását. Bizonyos helyeken figyelmeztető üzeneteket kaphat a cellán belül a vészhelyzetekről. A rosszindulatú alkalmazások befolyásolhatják az eszköz teljesítményét vagy működését vészhelyzeti cellaüzenet érkezésekor."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"feliratkozott hírcsatornák olvasása"</string> @@ -2190,12 +2194,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Újdonság: Ablaknagyító"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Ezután nagyíthatja a képernyőt vagy egy részét"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Bekapcsolás a Beállításokban"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Elvetés"</string> </resources> diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml index 1f2e642c74c6..b28e5fd3c185 100644 --- a/core/res/res/values-hy/strings.xml +++ b/core/res/res/values-hy/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS ծառայություն"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Տվիչների ծանուցումների մշակման ծառայություն"</string> <string name="twilight_service" msgid="8964898045693187224">"Մթնշաղի սկիզբը որոշող ծառայություն"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Ժամային գոտու դետեկտոր (աշխատում է առանց ինտերնետի)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Ձեր սարքը ջնջվելու է"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Հնարավոր չէ օգտագործել ադմինիստրատորի հավելվածը։ Ձեր սարքից բոլոր տվյալները կջնջվեն։\n\nՀարցեր ունենալու դեպքում դիմեք ձեր կազմակերպության ադմինիստրատորին։"</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Տպումն անջատված է <xliff:g id="OWNER_APP">%s</xliff:g> հավելվածի կողմից։"</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB կապակցում"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Հավելվածն աշխատում է"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Մարտկոցի լիցքը ծախսող հավելվածներ"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Խոշորացում"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"«<xliff:g id="APP_NAME">%1$s</xliff:g>» հավելվածը ծախսում է մարտկոցի լիցքը"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> հավելված ծախսում է մարտկոցի լիցքը"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Հպեք՝ մարտկոցի և թրաֆիկի մանրամասները տեսնելու համար"</string> @@ -353,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Թույլ է տալիս հավելվածին ստանալ և մշակել MMS հաղորդագրությունները: Սա նշանակում է, որ հավելվածը կարող է ստուգել կամ ջնջել ձեր սարքին ուղարկված հաղորդագրությունները` առանց դրանք ձեզ ցուցադրելու:"</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Բջջային հեռարձակման հաղորդագրությունների վերահասցեավորում"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Թույլ է տալիս հավելվածին կապ հաստատել բջջային հեռարձակման մոդուլի հետ՝ բնակչությանը ծանուցող հաղորդագրությունները վերահասցեավորելու համար։ Որոշ երկրներում այս հաղորդագրություններն օգտագործվում են բնակչությանը արտակարգ իրավիճակների մասին զգուշացնելու համար: Վնասարար հավելվածները կարող են խանգարել ձեր սարքի աշխատանքին, որին ուղարկվում են այս հաղորդագրությունները:"</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Ընթացիկ զանգերի կառավարում"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Թույլ է տալիս հավելվածին ձեր սարքում տեսնել ընթացիկ զանգերի մասին տեղեկությունները և կառավարել այդ զանգերը։"</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"կարդալ բջջային զեկուցվող հաղորդագրությունները"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Թույլ է տալիս հավելվածին կարդալ ձեր սարքի կողմից ստացված բջջային հեռարձակվող հաղորդագրությունները: Բջջային հեռարձակվող զգուշացումները ուղարկվում են որոշ վայրերում` արտակարգ իրավիճակների մասին ձեզ զգուշացնելու համար: Վնասարար հավելվածները կարող են խանգարել ձեր սարքի արդյունավետությանը կամ շահագործմանը, երբ ստացվում է արտակարգ իրավիճակի մասին բջջային հաղորդում:"</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"կարդալ բաժանորդագրված հոսքերը"</string> @@ -2190,12 +2192,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Նոր գործառույթ. Պատուհանի խոշորացույց"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Այժմ կարող եք խոշորացնել ամբողջ էկրանը կամ դրա մի մասը"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Միացնել կարգավորումներում"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Փակել"</string> </resources> diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml index 4f26eb687082..099f819cfbc4 100644 --- a/core/res/res/values-in/strings.xml +++ b/core/res/res/values-in/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Layanan GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Layanan Notifikasi Sensor"</string> <string name="twilight_service" msgid="8964898045693187224">"Layanan Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Pendeteksi Zona Waktu (Tidak ada konektivitas)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Perangkat akan dihapus"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Aplikasi admin tidak dapat digunakan. Perangkat Anda kini akan dihapus.\n\nJika ada pertanyaan, hubungi admin organisasi."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Fitur pencetakan dinonaktifkan oleh <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Sambungan USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplikasi berjalan"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikasi yang menggunakan baterai"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Pembesaran"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> sedang menggunakan baterai"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplikasi sedang meggunakan baterai"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Ketuk untuk melihat detail penggunaan baterai dan data"</string> @@ -353,6 +353,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Memungkinkan aplikasi menerima dan memproses pesan MMS. Ini artinya aplikasi dapat memantau atau menghapus pesan yang dikirim ke perangkat Anda tanpa menunjukkannya kepada Anda."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Teruskan pesan cell broadcast"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Mengizinkan aplikasi mem-binding ke modul cell broadcast untuk meneruskan pesan cell broadcast saat pesan tersebut diterima. Notifikasi cell broadcast dikirim di beberapa lokasi untuk memperingatkan Anda tentang situasi darurat. Aplikasi berbahaya dapat mengganggu performa atau operasi perangkat saat cell broadcast darurat diterima."</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"membaca pesan siaran seluler"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Mengizinkan aplikasi membaca pesan siaran seluler yang diterima perangkat Anda. Notifikasi siaran seluler dikirimkan di beberapa lokasi untuk memperingatkan Anda tentang situasi darurat. Aplikasi berbahaya dapat mengganggu kinerja atau operasi perangkat Anda saat siaran seluler darurat diterima."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"baca feed langganan"</string> @@ -2190,12 +2194,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Baru: Pembesar Jendela"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Anda bisa memperbesar sebagian atau seluruh layar"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Aktifkan di Setelan"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Tutup"</string> </resources> diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml index d5539a395206..867fca85f141 100644 --- a/core/res/res/values-is/strings.xml +++ b/core/res/res/values-is/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS-þjónusta"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Tilkynningaþjónusta nema"</string> <string name="twilight_service" msgid="8964898045693187224">"Ljósaskiptaþjónusta"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Tímabeltisgreinir (engin tenging)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Tækið verður hreinsað"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Ekki er hægt að nota stjórnunarforritið. Tækinu verður eytt.\n\nEf spurningar vakna skaltu hafa samband við kerfisstjóra fyrirtækisins."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> lokaði á prentun."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB-tenging"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Forrit er í gangi"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Forrit sem nota rafhlöðuorku"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Stækkun"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> notar rafhlöðuorku"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> forrit nota rafhlöðuorku"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Ýttu til að fá upplýsingar um rafhlöðu- og gagnanotkun"</string> @@ -353,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Leyfir forriti að taka á móti og vinna úr MMS-skilaboðum. Þetta þýðir að forritið getur fylgst með eða eytt skilaboðum sem send eru í tækið án þess að birta þér þau."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Framsenda skilaboð frá endurvarpa"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Heimilar forritinu að bindast endurvarpseiningunni til að framsenda skilaboð frá endurvarpa þegar þau berast. Viðvaranir frá endurvarpa berast á tilteknum stöðum til að vara þig við neyðarástandi. Spilliforrit geta truflað afköst eða virkni tækisins þegar neyðarboð berast frá endurvarpa."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Stjórna símtölum sem eru í gangi"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Leyfir forriti að sjá upplýsingar um og stjórna símtölum sem eru í gangi í tækinu þínu."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"lesa skilaboð frá endurvarpa"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Leyfir forriti að lesa skilaboð frá endurvarpa sem tækið móttekur. Viðvaranir frá endurvarpa berast á tilteknum stöðum til að vara þig við neyðarástandi. Spilliforrit geta truflað afköst eða virkni tækisins þegar neyðarboð berast frá endurvarpa."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lesa strauma í áskrift"</string> @@ -1801,7 +1803,7 @@ <string name="package_deleted_device_owner" msgid="2292335928930293023">"Kerfisstjóri eyddi"</string> <string name="confirm_battery_saver" msgid="5247976246208245754">"Í lagi"</string> <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Til að auka rafhlöðuendingu gerir rafhlöðusparnaður eftirfarandi:\n\n•·Kveikir á dökku þema\n•·Slekkur á eða takmarkar bakgrunnsvirkni, tilteknar myndbrellur og aðra eiginleika eins og „Ok Google“\n\n"<annotation id="url">"Frekari upplýsingar"</annotation></string> - <string name="battery_saver_description" msgid="6794188153647295212">"Til að auka rafhlöðuendingu gerir rafhlöðusparnaður eftirfarandi:\n\n•·Kveikir á dökku þema\n•·Slekkur á eða takmarkar bakgrunnsvirkni, tilteknar myndbrellur og aðra eiginleika eins og „Ok Google“"</string> + <string name="battery_saver_description" msgid="6794188153647295212">"Til að auka rafhlöðuendingu gerir rafhlöðusparnaður eftirfarandi:\n\n• Kveikir á dökku þema\n• Slekkur á eða takmarkar bakgrunnsvirkni, tilteknar myndbrellur og aðra eiginleika eins og „Ok Google“"</string> <string name="data_saver_description" msgid="4995164271550590517">"Gagnasparnaður getur hjálpað til við að draga úr gagnanotkun með því að hindra forrit í að senda eða sækja gögn í bakgrunni. Forrit sem er í notkun getur náð í gögn, en gerir það kannski sjaldnar. Niðurstaðan getur verið, svo dæmi sé tekið, að myndir eru ekki birtar fyrr en þú ýtir á þær."</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"Kveikja á gagnasparnaði?"</string> <string name="data_saver_enable_button" msgid="4399405762586419726">"Kveikja"</string> @@ -2190,12 +2192,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nýtt: Gluggastækkun"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Nú geturðu stækkað allan skjáinn eða hluta hans"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Kveikja á í stillingum"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Hunsa"</string> </resources> diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index 152cfee90863..6f2e158626ad 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Servizio GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Servizio di notifica dei sensori"</string> <string name="twilight_service" msgid="8964898045693187224">"Servizio Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Rilevatore di fuso orario (connessione a Internet non necessaria)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Il dispositivo verrà resettato"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Impossibile usare l\'app di amministrazione. Il dispositivo verrà resettato.\n\nPer eventuali domande, contatta l\'amministratore della tua organizzazione."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Stampa disattivata da <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -352,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Consente all\'applicazione di ricevere ed elaborare messaggi MMS. Significa che l\'applicazione potrebbe monitorare o eliminare i messaggi inviati al tuo dispositivo senza mostrarteli."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Inoltro di messaggi cell broadcast"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Consente all\'app di essere associata al modulo di cell broadcast al fine di inoltrare i messaggi di cell broadcast man mano che arrivano. Gli avvisi cell broadcast vengono trasmessi in alcune località per avvertire di situazioni di emergenza. Le app dannose potrebbero interferire con le prestazioni o con il funzionamento del dispositivo quando si riceve un messaggio cell broadcast di emergenza."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Gestione delle chiamate in corso"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Consente a un\'app di accedere a dettagli relativi alle chiamate in corso sul tuo dispositivo e di controllare tali chiamate."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"lettura di messaggi cell broadcast"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Consente all\'applicazione di leggere i messaggi cell broadcast ricevuti dal dispositivo. Gli avvisi cell broadcast vengono trasmessi in alcune località per avvertire di eventuali situazioni di emergenza. Le app dannose potrebbero interferire con le prestazioni o con il funzionamento del dispositivo quando si riceve un messaggio cell broadcast di emergenza."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lettura feed sottoscritti"</string> @@ -1451,7 +1454,7 @@ <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Tocca per uscire dall\'app di guida."</string> <string name="back_button_label" msgid="4078224038025043387">"Indietro"</string> <string name="next_button_label" msgid="6040209156399907780">"Avanti"</string> - <string name="skip_button_label" msgid="3566599811326688389">"Ignora"</string> + <string name="skip_button_label" msgid="3566599811326688389">"Salta"</string> <string name="no_matches" msgid="6472699895759164599">"Nessuna corrispondenza"</string> <string name="find_on_page" msgid="5400537367077438198">"Trova nella pagina"</string> <plurals name="matches_found" formatted="false" msgid="1101758718194295554"> @@ -1799,8 +1802,8 @@ <string name="package_updated_device_owner" msgid="7560272363805506941">"Aggiornato dall\'amministratore"</string> <string name="package_deleted_device_owner" msgid="2292335928930293023">"Eliminato dall\'amministratore"</string> <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string> - <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Per estendere la durata della batteria, la funzionalità di risparmio energetico:\n\n• Attiva il tema scuro\n• Disattiva o limita le attività in background, alcuni effetti visivi e altre funzionalità come \"Ok Google\"\n\n"<annotation id="url">"Ulteriori informazioni"</annotation></string> - <string name="battery_saver_description" msgid="6794188153647295212">"Per estendere la durata della batteria, la funzionalità di risparmio energetico:\n\n• Attiva il tema scuro\n• Disattiva o limita le attività in background, alcuni effetti visivi e altre funzionalità come \"Ok Google\""</string> + <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Per estendere la durata della batteria, la funzionalità di risparmio energetico:\n\n• Attiva il tema scuro\n• Disattiva o limita le attività in background, alcuni effetti visivi e altre funzionalità come \"Hey Google\"\n\n"<annotation id="url">"Scopri di più"</annotation></string> + <string name="battery_saver_description" msgid="6794188153647295212">"Per estendere la durata della batteria, la funzionalità di risparmio energetico:\n\n• Attiva il tema scuro\n• Disattiva o limita le attività in background, alcuni effetti visivi e altre funzionalità come \"Hey Google\""</string> <string name="data_saver_description" msgid="4995164271550590517">"Per contribuire a ridurre l\'utilizzo dei dati, la funzione Risparmio dati impedisce ad alcune app di inviare o ricevere dati in background. Un\'app in uso può accedere ai dati, ma potrebbe farlo con meno frequenza. Esempio: le immagini non vengono visualizzate finché non le tocchi."</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"Attivare Risparmio dati?"</string> <string name="data_saver_enable_button" msgid="4399405762586419726">"Attiva"</string> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index 5ae9436dd1b3..2846508b3bc0 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -203,6 +203,7 @@ <string name="gnss_service" msgid="8907781262179951385">"שירות GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"שירות להתראות מחיישנים"</string> <string name="twilight_service" msgid="8964898045693187224">"שירות דמדומים"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"מזהה אזור זמן (ללא צורך בקישוריות)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"תתבצע מחיקה של המכשיר"</string> <string name="factory_reset_message" msgid="2657049595153992213">"לא ניתן להשתמש באפליקציה של מנהל המערכת.\n\nאם יש לך שאלות, יש ליצור קשר עם מנהל המערכת של הארגון."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"ההדפסה הושבתה על ידי <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -293,8 +294,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"חיבור USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"אפליקציה פועלת"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"אפליקציות שמרוקנות את הסוללה"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"הגדלה"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> משתמשת בסוללה"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> אפליקציות משתמשות בסוללה"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"הקש לקבלת פרטים על צריכה של נתונים וסוללה"</string> @@ -359,6 +359,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"מאפשר לאפליקציה לקבל ולעבד הודעות MMS. משמעות הדבר היא שהאפליקציה יכולה לעקוב אחר הודעות שנשלחו למכשיר או למחוק אותן מבלי להציג לך אותן."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"העברת הודעות של שידור סלולרי"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"מאפשרת לאפליקציה להתחייב למודול של השידור הסלולרי כדי להעביר הודעות של שידור סלולרי כשהן מתקבלות. התראות שידור סלולרי נשלחות במקומות מסוימים כדי להזהיר אותך מפני מצבי חירום. אפליקציות זדוניות עשויות להפריע לביצועים או לפעולה של המכשיר כאשר מתקבל שידור חירום סלולרי."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"ניהול שיחות שנערכות"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"לאפליקציה תהיה אפשרות לראות פרטים על שיחות שנערכות במכשיר ולשלוט בשיחות האלה."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"קריאת הודעות שידור סלולרי"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"מאפשר לאפליקציה לקרוא הודעות שידור סלולרי שהתקבלו במכשיר שלך. התראות שידור סלולרי נשלחות במקומות מסוימים על מנת להזהיר אותך מפני מצבי חירום. אפליקציות זדוניות עשויות להפריע לביצועים או לפעולה של המכשיר שלך כאשר מתקבל שידור חירום סלולרי."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"קרא עדכוני מנויים"</string> @@ -2258,12 +2260,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"חדש: Window Magnifier"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"עכשיו אפשר להגדיל את המסך או חלקים ממנו"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"הפעלה בהגדרות"</string> + <string name="dismiss_action" msgid="1728820550388704784">"סגירה"</string> </resources> diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index 7a54a1594501..c6e8a149df92 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS サービス"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"センサー通知サービス"</string> <string name="twilight_service" msgid="8964898045693187224">"トワイライト サービス"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Time Zone Detector(未接続)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"デバイスのデータが消去されます"</string> <string name="factory_reset_message" msgid="2657049595153992213">"管理アプリを使用できません。デバイスのデータはこれから消去されます。\n\nご不明な点がある場合は、組織の管理者にお問い合わせください。"</string> <string name="printing_disabled_by" msgid="3517499806528864633">"「<xliff:g id="OWNER_APP">%s</xliff:g>」により印刷は無効にされています。"</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB 接続"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"実行中のアプリ"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"電池を消費しているアプリ"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"拡大"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」が電池を使用しています"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> 個のアプリが電池を使用しています"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"タップして電池やデータの使用量を確認"</string> @@ -353,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"MMSメッセージの受信と処理をアプリに許可します。これにより、アプリがデバイスに届いたメッセージを表示することなく監視または削除できるようになります。"</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"緊急速報メールの転送"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"受信した緊急速報メールを転送するために、緊急速報メール モジュールにバインドすることをこのアプリに許可します。緊急速報メールは、緊急事態を警告する目的で一部の地域に配信されます。緊急速報メールの受信時に、悪意のあるアプリによってデバイスの動作や処理が妨害される恐れがあります。"</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"通話の管理"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"デバイスでの通話に関する詳細の参照と、通話の操作をアプリに許可します。"</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"緊急速報メール SMS の読み取り"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"デバイスで受信した緊急速報メール SMS の読み取りをアプリに許可します。緊急速報メールは、緊急事態を警告する目的で一部の地域に配信されます。緊急速報メールの受信時に、悪意のあるアプリによってデバイスの動作や処理が妨害される恐れがあります。"</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"登録したフィードの読み取り"</string> @@ -2190,12 +2192,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"新機能: Window Magnifier"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"画面の一部または全体を拡大できるようになりました"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"[設定] で ON にする"</string> + <string name="dismiss_action" msgid="1728820550388704784">"閉じる"</string> </resources> diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml index 1653cb91c3fb..912930fa2854 100644 --- a/core/res/res/values-ka/strings.xml +++ b/core/res/res/values-ka/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS სერვისი"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"სენსორის შეტყობინების სერვისი"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight სერვისი"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"სასაათო სარტყლის დეტექტორი (კავშირის გარეშე)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"თქვენი მოწყობილობა წაიშლება"</string> <string name="factory_reset_message" msgid="2657049595153992213">"ადმინისტრატორის აპის გამოყენება ვერ მოხერხდება. თქვენი მოწყობილობა ახლა ამოიშლება.\n\nთუ შეკითხვები გაქვთ, დაუკავშირდით თქვენი ორგანიზაციის ადმინისტრატორს."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"ბეჭდვა გათიშულია <xliff:g id="OWNER_APP">%s</xliff:g>-ის მიერ."</string> @@ -352,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"აპს შეეძლება MMS შეტყობინებების მიღება და დამუშავება. ეს ნიშნავს, რომ აპს შეეძლება შეტყობინებების მონიტორინგი და მათი წაშლა თქვენთვის ჩვენების გარეშე."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Cell broadcast შეტყობინებების გადამისამართება"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"საშუალებას აძლევს აპს, დაუკავშირდეს cell broadcast მოდულს იმისთვის, რომ გადაამისამართოს cell broadcast შეტყობინებები მათი მიღებისთანავე. Cell broadcast გაფრთხილებები მიეწოდება ზოგიერთ მდებარეობაზე საგანგებო სიტუაციების შესახებ გაფრთხილების მიზნით. საგანგებო cell broadcast-ის მიღების დროს, მავნე აპებმა შეიძლება ხელი შეუშალონ თქვენი მოწყობილობის ფუნქციონირებას ან ოპერაციებს."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"მიმდინარე ზარების მართვა"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"საშუალებას აძლევს აპს, ნახოს თქვენს მოწყობილობაზე მიმდინარე ზარების დეტალები და აკონტროლოს ეს ზარები."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"მასიური დაგზავნის შეტყობინებების წაკითხვა"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"აპს შეეძლება, წაიკითხოს თქვენს მოწყობილობაზე გამოგზავნილი ქსელის სამაუწყებლო შეტყობინებები. სამაუწყებლო გაფრთხილებები მოგეწოდებათ ზოგიერთ ადგილზე ექსტრემალური სიტუაციების შესახებ გასაფრთხილებლად. ქსელის გადაუდებელი შეტყონიბენის მიღების დროს მავნე აპებმა შეიძლება ხელი შეუშალონ თქვენი მოწყობილობის ფუნქციონირებას ან ოპერაციებს."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"გამოწერილი არხების წაკითხვა"</string> diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml index 635fed7f6bf1..d61553862e92 100644 --- a/core/res/res/values-kk/strings.xml +++ b/core/res/res/values-kk/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS қызметі"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Датчик хабарландыруы қызметі"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight қызметі"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Уақыт белдеуін анықтағыш (қосылу мүмкіндігі жоқ)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Құрылғыңыздағы деректер өшіріледі"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Әкімші қолданбасын пайдалану мүмкін емес. Қазір құрылғыдағы деректер өшіріледі\n\nСұрақтарыңыз болса, ұйым әкімшісіне хабарласыңыз."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Басып шығаруды <xliff:g id="OWNER_APP">%s</xliff:g> өшірді."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB байланысы"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Қолданба қосулы"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Батареяны пайдаланып жатқан қолданбалар"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ұлғайту"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> батареяны пайдалануда"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> қолданба батареяны пайдалануда"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Батарея мен деректер трафигі туралы білу үшін түртіңіз"</string> @@ -353,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Қолданбаға MMS хабарларын алу және өңдеу мүмкіндігін береді. Бұл қолданба құрылғыңызға жіберілген хабарларды сізге көрсетпестен қабылдай және жоя алады дегенді білдіреді."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Ұялы таратылым хабарларының бағытын өзгерту"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Ұялы таратылым хабарлары алынғаннан кейін, олардың бағытын өзгерту үшін қолданбаға ұялы таратылым модулімен байланыстыруға мүмкіндік береді. Ұялы таратылым ескертулері кей аймақтарда төтенше жағдайлар туралы хабарлау үшін беріледі. Төтенше жағдай туралы ұялы таратылым хабары алынғаннан кейін, зиянды қолданбалар құрылғы жұмысына кедергі келтіруі мүмкін."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Қазіргі қоңырауларды басқару"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Қолданбаға құрылғыдағы қазіргі қоңыраулар туралы мәліметтерді көруге және басқаруға мүмкіндік береді."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"ұялы хабар тарату хабарларын оқу"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Қолданбаға ұялы таратылым хабарларын оқу мүмкіндігін береді. Ұялы таратылым дабылдары кейбір аймақтарда төтенше жағдай туралы ескерту үшін қолданылады. Төтенше ұялы хабарлар келгенде залалды қолданбалар құрылғының жұмысына кедергі жасауы мүмкін."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"жазылған ағындарды оқу"</string> @@ -2190,12 +2192,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Жаңа: Window Magnifier"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Енді экранның бір бөлігін не барлығын ұлғайта аласыз."</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Параметрлер бөлімінен қосу"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Қабылдамау"</string> </resources> diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml index 1160a40bb899..075a6524fcd5 100644 --- a/core/res/res/values-km/strings.xml +++ b/core/res/res/values-km/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"សេវាកម្ម GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"សេវាកម្មជូនដំណឹងឧបករណ៍ចាប់សញ្ញា"</string> <string name="twilight_service" msgid="8964898045693187224">"សេវាកម្មព្រលប់"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"ឧបករណ៍សម្គាល់ល្វែងម៉ោង (គ្មានការតភ្ជាប់ទេ)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"ឧបករណ៍របស់អ្នកនឹងត្រូវបានលុប"</string> <string name="factory_reset_message" msgid="2657049595153992213">"មិនអាចប្រើកម្មវិធីអ្នកគ្រប់គ្រងបានទេ។ ឧបករណ៍របស់អ្នកនឹងលុបឥឡូវនេះ។\n\nប្រសិនបើអ្នកមានសំណួរផ្សេងៗ សូមទាក់ទងទៅអ្នកគ្រប់គ្រងស្ថាប័នរបស់អ្នក។"</string> <string name="printing_disabled_by" msgid="3517499806528864633">"ការបោះពុម្ពត្រូវបានបិទដោយ <xliff:g id="OWNER_APP">%s</xliff:g> ។"</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"ការតភ្ជាប់ USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"កម្មវិធីដែលកំពុងដំណើរការ"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"កម្មវិធីដែលកំពុងប្រើថ្ម"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ការពង្រីក"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> កំពុងប្រើថ្ម"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"កម្មវិធីចំនួន <xliff:g id="NUMBER">%1$d</xliff:g> កំពុងប្រើថ្ម"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ចុចដើម្បីមើលព័ត៌មានលម្អិតអំពីការប្រើប្រាស់ទិន្នន័យ និងថ្ម"</string> @@ -353,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"ឲ្យកម្មវិធីទទួល និងដំណើរការសារ MMS ។ វាមានន័យថា កម្មវិធីអាចតាមដាន ឬលុបសារដែលបានផ្ញើទៅឧបករណ៍របស់អ្នកដោយមិនបង្ហាញពួកវា។"</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"បញ្ជូនសារផ្សាយចល័តបន្ត"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"អនុញ្ញាតឱ្យកម្មវិធីភ្ជាប់ទៅម៉ូឌុលការផ្សាយចល័ត ដើម្បីបញ្ជូនសារផ្សាយចល័តបន្ត នៅពេលទទួលបានសារទាំងនោះ។ ការជូនដំណឹងអំពីការផ្សាយចល័តត្រូវបានបញ្ជូនទៅទីតាំងមួយចំនួន ដើម្បីព្រមានអ្នកអំពីស្ថានភាពអាសន្ន។ កម្មវិធីគ្រោះថ្នាក់អាចរំខានដល់ដំណើរការ ឬប្រតិបត្តិការឧបករណ៍របស់អ្នក នៅពេលទទួលបានការផ្សាយចល័តពេលមានអាសន្ន។"</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"គ្រប់គ្រងការហៅទូរសព្ទដែលកំពុងដំណើរការ"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"អនុញ្ញាតឱ្យកម្មវិធីមើលព័ត៌មានលម្អិតអំពីការហៅទូរសព្ទដែលកំពុងដំណើរការនៅលើឧបករណ៍របស់អ្នក និងគ្រប់គ្រងការហៅទូរសព្ទទាំងនេះ។"</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"អានសារប្រកាសចល័ត"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"ឲ្យកម្មវិធីអានសារប្រកាសការហៅដែលឧបករណ៍របស់អ្នកបានទទួល។ ការជូនដំណឹងប្រកាសចល័តត្រូវបានបញ្ជូនទៅទីតាំងមួយចំនួន ដើម្បីព្រមានអ្នកអំពីស្ថានភាពអាសន្ន។ កម្មវិធីព្យាបាទអាចជ្រៀតជ្រែកការអនុវត្ត ឬប្រតិបត្តិការឧបករណ៍របស់អ្នកពេលទទួលការប្រកាសចល័តពេលអាសន្ន។"</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"អានអត្ថបទព័ត៌មានបានជាវ"</string> @@ -2190,12 +2192,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"ថ្មី៖ កម្មវិធីពង្រីកវិនដូ"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"ឥឡូវនេះ អ្នកអាចពង្រីកផ្នែកខ្លះ ឬទាំងអស់នៃអេក្រង់របស់អ្នក"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"បើកនៅក្នុងការកំណត់"</string> + <string name="dismiss_action" msgid="1728820550388704784">"ច្រានចោល"</string> </resources> diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml index 8eb3467dd32e..61ed9b37cbdc 100644 --- a/core/res/res/values-kn/strings.xml +++ b/core/res/res/values-kn/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS ಸೇವೆ"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"ಸೆನ್ಸರ್ ಅಧಿಸೂಚನೆ ಸೇವೆ"</string> <string name="twilight_service" msgid="8964898045693187224">"ಟ್ವಿಲೈಟ್ ಸೇವೆ"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"ಸಮಯವಲಯ ಡಿಟೆಕ್ಟರ್ (ಯಾವುದೇ ಸಂಪರ್ಕ ಕಲ್ಪಿಸುವಿಕೆ ಇಲ್ಲ)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"ನಿಮ್ಮ ಸಾಧನವನ್ನು ಅಳಿಸಲಾಗುತ್ತದೆ"</string> <string name="factory_reset_message" msgid="2657049595153992213">"ನಿರ್ವಹಣೆ ಅಪ್ಲಿಕೇಶನ್ ಬಳಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ನಿಮ್ಮ ಸಾಧನವನ್ನು ಇದೀಗ ಅಳಿಸಲಾಗುತ್ತದೆ.\n\nನಿಮ್ಮಲ್ಲಿ ಪ್ರಶ್ನೆಗಳಿದ್ದರೆ, ನಿಮ್ಮ ಸಂಸ್ಥೆಯ ನಿರ್ವಾಹಕರನ್ನು ಸಂಪರ್ಕಿಸಿ."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ಮೂಲಕ ಪ್ರಿಂಟಿಂಗ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB ಸಂಪರ್ಕ"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App ರನ್ ಆಗುತ್ತಿದೆ"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ಅಪ್ಲಿಕೇಶನ್ಗಳು ಬ್ಯಾಟರಿಯನ್ನು ಉಪಯೋಗಿಸುತ್ತಿವೆ"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ಹಿಗ್ಗಿಸುವಿಕೆ"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ಆ್ಯಪ್, ಬ್ಯಾಟರಿಯನ್ನು ಬಳಸುತ್ತಿದೆ"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ಅಪ್ಲಿಕೇಶನ್ಗಳು ಬ್ಯಾಟರಿ ಬಳಸುತ್ತಿವೆ"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ಬ್ಯಾಟರಿ,ಡೇಟಾ ಬಳಕೆಯ ವಿವರಗಳಿಗಾಗಿ ಟ್ಯಾಪ್ ಮಾಡಿ"</string> @@ -353,6 +353,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"MMS ಸಂದೇಶಗಳನ್ನು ಸ್ವೀಕರಿಸಲು ಮತ್ತು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅವಕಾಶ ಮಾಡಿಕೊಡುತ್ತದೆ. ಇದರರ್ಥ, ನಿಮ್ಮ ಸಾಧನಕ್ಕೆ ಕಳುಹಿಸಲಾಗಿರುವ ಸಂದೇಶಗಳನ್ನು ನಿಮಗೆ ತೋರಿಸದೆಯೇ, ಅಪ್ಲಿಕೇಶನ್ ಅವುಗಳನ್ನು ಮಾನಿಟರ್ ಮಾಡಬಹುದು ಅಥವಾ ಅಳಿಸಬಹುದು."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"ಸೆಲ್ ಪ್ರಸಾರ ಸಂದೇಶಗಳನ್ನು ಫಾರ್ವರ್ಡ್ ಮಾಡಿ"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"ಸೆಲ್ ಪ್ರಸಾರವು ಸಂದೇಶಗಳನ್ನು ಸ್ವೀಕರಿಸಿದ ರೀತಿಯಲ್ಲಿಯೇ ಫಾರ್ವರ್ಡ್ ಮಾಡಲು, ಸೆಲ್ ಪ್ರಸಾರ ಮಾಡ್ಯುಲ್ ಅನ್ನು ಪ್ರತಿಬಂಧಿಸಲು ಆ್ಯಪ್ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಕೆಲವು ಸ್ಥಳಗಳಲ್ಲಿ ತುರ್ತು ಸ್ಥಿತಿಗಳ ಕುರಿತು ನಿಮಗೆ ಎಚ್ಚರಿಸಲು ಸೆಲ್ ಪ್ರಸಾರದ ಎಚ್ಚರಿಕೆಗಳನ್ನು ಕಳುಹಿಸಲಾಗುತ್ತದೆ. ತುರ್ತು ಸೆಲ್ ಪ್ರಸಾರವನ್ನು ಸ್ವೀಕರಿಸಿದಾಗ ನಿಮ್ಮ ಸಾಧನದ ಕಾರ್ಯಾಚರಣೆ ಅಥವಾ ಕಾರ್ಯಕ್ಷಮತೆಗೆ ದುರುದ್ದೇಶಪೂರಿತ ಆ್ಯಪ್ಗಳು ಹಸ್ತಕ್ಷೇಪ ಮಾಡಬಹುದು."</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"ಸೆಲ್ ಪ್ರಸಾರದ ಸಂದೇಶಗಳನ್ನು ಓದಿರಿ"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"ನಿಮ್ಮ ಸಾಧನದಿಂದ ಸ್ವೀಕರಿಸಿದ ಸೆಲ್ ಪ್ರಸಾರ ಸಂದೇಶಗಳನ್ನು ರೀಡ್ ಮಾಡಲು ಅಪ್ಲಿಕೇಶನ್ಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಸೆಲ್ ಪ್ರಸಾರ ಎಚ್ಚರಿಕೆಗಳನ್ನು ತುರ್ತು ಸಂದರ್ಭಗಳಲ್ಲಿ ನಿಮಗೆ ಎಚ್ಚರಿಸುವ ಸಲುವಾಗಿ ಕೆಲವು ಸ್ಥಳಗಳಲ್ಲಿ ವಿತರಿಸಲಾಗುತ್ತದೆ. ದುರುದ್ದೇಶಪೂರಿತ ಅಪ್ಲಿಕೇಶನ್ಗಳು ತುರ್ತು ಸೆಲ್ ಪ್ರಸಾರವನ್ನು ಸ್ವೀಕರಿಸುವಾಗ, ನಿಮ್ಮ ಸಾಧನದ ಕಾರ್ಯಕ್ಷಮತೆ ಇಲ್ಲವೇ ಕಾರ್ಯಾಚರಣೆಯಲ್ಲಿ ಹಸ್ತಕ್ಷೇಪ ಮಾಡಬಹುದು."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"ಚಂದಾದಾರ ಫೀಡ್ಗಳನ್ನು ಓದಿ"</string> @@ -2190,12 +2194,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"ಹೊಸದು: ವಿಂಡೋ ಮ್ಯಾಗ್ನಿಫೈಯರ್"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"ಈಗ ಕೆಲವು ಅಥವಾ ಎಲ್ಲಾ ಸ್ಕ್ರೀನ್ ಅನ್ನು ಹಿಗ್ಗಿಸಬಹುದು"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ಸೆಟ್ಟಿಂಗ್ಗಳಲ್ಲಿ ಆನ್ ಮಾಡಿ"</string> + <string name="dismiss_action" msgid="1728820550388704784">"ವಜಾಗೊಳಿಸಿ"</string> </resources> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index 46b4a1b3ed1c..dfa377074e1d 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS 서비스"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"센서 알림 서비스"</string> <string name="twilight_service" msgid="8964898045693187224">"새벽 서비스"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"시간대 감지(연결되지 않음)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"기기가 삭제됩니다."</string> <string name="factory_reset_message" msgid="2657049595153992213">"관리자 앱을 사용할 수 없습니다. 곧 기기가 삭제됩니다.\n\n궁금한 점이 있으면 조직의 관리자에게 문의하세요."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g>에 의해 사용 중지되었습니다."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB 연결"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"실행 중인 앱"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"배터리를 소모하는 앱"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"확대"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 배터리 사용 중"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"앱 <xliff:g id="NUMBER">%1$d</xliff:g>개에서 배터리 사용 중"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"탭하여 배터리 및 데이터 사용량 확인"</string> @@ -353,6 +353,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"앱이 MMS 메시지를 수신하고 처리할 수 있도록 허용합니다. 앱이 사용자에게 표시하지 않고 기기로 전송된 메시지를 확인 또는 삭제할 수도 있습니다."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"셀 브로드캐스트 메시지 전달"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"셀 브로드캐스트 메시지를 수신하자마자 전달하기 위해 앱이 셀 브로드캐스트 모듈에 연결하도록 허용합니다. 비상 상황임을 알리기 위해 일부 지역에서 셀 브로드캐스트 경고가 전달됩니다. 비상 셀 브로드캐스트를 수신할 때 악성 앱이 기기의 성능이나 작동을 방해할 수 있습니다."</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"셀 브로드캐스트 메시지 읽기"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"앱이 기기가 수신한 셀 브로드캐스트 메시지를 읽을 수 있도록 합니다. 비상 상황임을 알리기 위해 일부 지역에서 셀 브로드캐스트 경고가 전달됩니다. 비상 셀 브로드캐스트를 수신할 때 악성 앱이 기기의 성능이나 작동을 방해할 수 있습니다."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"가입된 피드 읽기"</string> @@ -2190,12 +2194,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"새로운 기능: 창 돋보기"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"이제 화면 일부 또는 전체를 확대할 수 있습니다."</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"설정에서 사용 설정"</string> + <string name="dismiss_action" msgid="1728820550388704784">"닫기"</string> </resources> diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml index bb005f3281fc..bd6ecef63b24 100644 --- a/core/res/res/values-ky/strings.xml +++ b/core/res/res/values-ky/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS кызматы"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Сенсордун билдирмелеринин кызматы"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight кызматы"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Убакыт алкагын аныктагыч (байланыш жок)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Түзмөгүңүз тазаланат"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Түзмөктү башкаруучу колдонмо жараксыз. Түзмөгүңүз азыр тазаланат.\n\nСуроолоруңуз болсо, ишканаңыздын администраторуна кайрылыңыз."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Басып чыгаруу <xliff:g id="OWNER_APP">%s</xliff:g> тарабынан өчүрүлдү."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB аркылуу туташуу"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Колдонмо иштеп жатат"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Колдонмолор батареяңызды коротууда"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Чоңойтуу"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосу батареяны пайдаланып жатат"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> колдонмо батареяны пайдаланып жатат"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Батареянын кубаты жана трафиктин көлөмү жөнүндө билүү үчүн таптап коюңуз"</string> @@ -353,6 +353,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Колдонмого MMS билдирүүлөрүн кабыл алууга жана аларды иштетип чыгууга уруксат берет. Бул, колдонмо сизге билгизбестен түзмөгүңүзгө жөнөтүлгөн билдирүүлөрдү мониторлой же жок кыла алат дегенди билдирет."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Уюк жөнөтүүлөрүнүн билдирүүлөрүн башка номерге багыттоо"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Уюк жөнөтүүлөрүнүн билдирүүлөрү келген сайын башка номерге багыттап туруу үчүн колдонмого уюк жөнөтүүлөрүнүн модулу менен байланышууга уруксат берет. Шашылыш уюк жөнөтүүлөрү кээ бир жерлердеги өзгөчө кырдаалдар тууралуу сизге эскертүү үчүн жөнөтүлөт. Зыянкеч колдонмолор шашылыш уюк жөнөтүүлөрү кабыл алынганда түзмөктүн майнаптуулугуна же иштешине жолтоо болушу мүмкүн."</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"уюктук берүү билдирүүлөрүн окуу"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Колдонмого түзмөгүңүз кабыл алган уюк берүүнүн билдирүүлөрүн окууга жол берет. Шашылыш эскертүү билдирүүлөрү кээ бир жерлердеги өзгөчө кырдаалдар тууралу сизди эскертүү үчүн жөнөтүлөт. Зыяндуу колдономолор шашылыш эскертүүлөр берилип жатканда, сиздин түзмөктүн иштешине жолтоо болушу мүмкүн."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"жазылган түрмөктөрдү окуу"</string> @@ -1800,8 +1804,8 @@ <string name="package_updated_device_owner" msgid="7560272363805506941">"Администраторуңуз жаңыртып койгон"</string> <string name="package_deleted_device_owner" msgid="2292335928930293023">"Администраторуңуз жок кылып салган"</string> <string name="confirm_battery_saver" msgid="5247976246208245754">"ЖАРАЙТ"</string> - <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Батареянын мөөнөтүн узартуу үчүн Батареяны үнөмдөгүч режими төмөнкүлөрдү аткарат:\n\n• Караңгы теманы күйгүзөт\n• Фондогу аракеттерди, айрым визуалдык эффекттерди жана \"Окей Google\" сыяктуу башка функцияларды өчүрөт же чектейт\n\n"<annotation id="url">"Кеңири маалымат"</annotation></string> - <string name="battery_saver_description" msgid="6794188153647295212">"Батареянын мөөнөтүн узартуу үчүн Батареяны үнөмдөгүч режими:\n\n• Караңгы теманы күйгүзөт\n• Фондогу аракеттерди, айрым визуалдык эффекттерди жана \"Окей Google\" сыяктуу башка функцияларды өчүрөт же чектейт"</string> + <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Батареяны көбүрөөк убакытка жеткирүү үчүн Батареяны үнөмдөгүч режиминде:\n\n• Караңгы тема күйгүзүлөт\n• Фондогу аракеттерди, айрым визуалдык эффекттерди жана \"Окей Google\" сыяктуу башка функцияларды өчүрөт же чектейт\n\n"<annotation id="url">"Кеңири маалымат"</annotation></string> + <string name="battery_saver_description" msgid="6794188153647295212">"Батареяны көбүрөөк убакытка жеткирүү үчүн Батареяны үнөмдөгүч режими:\n\n• Караңгы тема күйгүзүлөт\n• Фондогу аракеттерди, айрым визуалдык эффекттерди жана \"Окей Google\" сыяктуу башка функцияларды өчүрөт же чектейт"</string> <string name="data_saver_description" msgid="4995164271550590517">"Трафикти үнөмдөө режиминде айрым колдонмолор дайын-даректерди фондо өткөрө алышпайт. Учурда сиз пайдаланып жаткан колдонмо дайын-даректерди жөнөтүп/ала алат, бирок адаттагыдан азыраак өткөргөндүктөн, анын айрым функциялары талаптагыдай иштебей коюшу мүмкүн. Мисалы, сүрөттөр басылмайынча жүктөлбөйт."</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"Трафикти үнөмдөө режимин иштетесизби?"</string> <string name="data_saver_enable_button" msgid="4399405762586419726">"Күйгүзүү"</string> @@ -2190,12 +2194,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Жаңы функция: Терезе чоңойткуч"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Эми толук экранды же анын бөлүгүн чоңойто аласыз"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Жөндөөлөрдөн күйгүзүү"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Жабуу"</string> </resources> diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml index 8e4e467fdd50..c60d594a4bd2 100644 --- a/core/res/res/values-lo/strings.xml +++ b/core/res/res/values-lo/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"ບໍລິການ GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"ບໍລິການການແຈ້ງເຕືອນເຊັນເຊີ"</string> <string name="twilight_service" msgid="8964898045693187224">"ບໍລິການ Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"ຕົວກວດຫາເຂດເວລາ (ບໍ່ມີການເຊື່ອມຕໍ່)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"ອຸປະກອນຂອງທ່ານຈະຖືກລຶບ"</string> <string name="factory_reset_message" msgid="2657049595153992213">"ບໍ່ສາມາດໃຊ້ແອັບຜູ້ເບິ່ງແຍງລະບົບໄດ້. ອຸປະກອນຂອງທ່ານຈະຖືກລຶບຂໍ້ມູນໃນຕອນນີ້.\n\nຫາກທ່ານມີຄຳຖາມ, ໃຫ້ຕິດຕໍ່ຜູ້ເບິ່ງແຍງລະບົບອົງກອນຂອງທ່ານ."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"ການພິມຖືກປິດໄວ້ໂດຍ <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"ການເຊື່ອມຕໍ່ USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ແອັບກຳລັງເຮັດວຽກ"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ແອັບທີ່ກຳລັງໃຊ້ແບັດເຕີຣີ"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ການຂະຫຍາຍ"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ກຳລັງໃຊ້ແບັດເຕີຣີຢູ່"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ແອັບກຳລັງໃຊ້ແບັດເຕີຣີຢູ່"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ແຕະເພື່ອເບິ່ງລາຍລະອຽດການນຳໃຊ້ແບັດເຕີຣີ ແລະ ອິນເຕີເນັດ"</string> @@ -353,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"ອະນຸຍາດໃຫ້ແອັບຯ ຮັບແລະປະມວນຜົນຂໍ້ຄວາມ MMS. ນີ້ໝາຍຄວາມວ່າແອັບຯສາມາດຕິດຕາມ ຫຼືລຶບຂໍ້ຄວາມທີ່ສົ່ງເຂົ້າອຸປະກອນຂອງທ່ານ ໂດຍທີ່ບໍ່ສະແດງພວກມັນໃຫ້ທ່ານເຫັນ."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"ສົ່ງຕໍ່ຂໍ້ຄວາມການກະຈາຍສັນຍານໂທລະສັບ"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"ອະນຸຍາດໃຫ້ແອັບຜູກມັດກັບໂມດູນການກະຈາຍສັນຍານໂທລະສັບເພື່ອສົ່ງຕໍ່ຂໍ້ຄວາມການກະຈາຍສັນຍານໂທລະສັບເມື່ອໄດ້ຮັບມາ. ການເຕືອນການກະຈາຍສັນຍານໂທລະສັບແມ່ນຖືກຈັດສົ່ງໃນບາງສະຖານທີ່ເພື່ອເຕືອນທ່ານໃນກໍລະນີມີເຫດການສຸກເສີນເກີດຂຶ້ນ. ແອັບທີ່ເປັນອັນຕະລາຍອາດລົບກວນປະສິດທິພາບ ຫຼື ການເຮັດວຽກຂອງອຸປະກອນທ່ານເມື່ອໄດ້ຮັບການກະຈາຍສັນຍານໂທລະສັບສຸກເສີນ."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"ຈັດການສາຍໂທອອກ"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"ອະນຸຍາດໃຫ້ແອັບໃດໜຶ່ງເບິ່ງເຫັນລາຍລະອຽດກ່ຽວກັບສາຍໂທອອກຢູ່ອຸປະກອນຂອງທ່ານ ແລະ ເພື່ອຄວບຄຸມການໂທເຫຼົ່ານີ້."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"ອ່ານຂໍ້ຄວາມກະຈາຍສັນຍານຂອງເສົາສັນຍານ"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"ອະນຸຍາດໃຫ້ແອັບຯ ສາມາດອ່ານຂໍ້ຄວາມແຈ້ງເຕືອນເຫດສຸກເສີນ ທີ່ໄດ້ຮັບໂດຍອຸປະກອນຂອງທ່ານ. ການແຈ້ງເຕືອນສຸກເສີນທີ່ມີໃຫ້ບໍລິການໃນບາງພື້ນທີ່ ເພື່ອແຈ້ງເຕືອນໃຫ້ທ່ານຮູ້ເຖິງສະຖານະການສຸກເສີນ. ແອັບພລິເຄຊັນທີ່ເປັນອັນຕະລາຍອາດລົບກວນປະສິດທິພາບ ຫຼືການດຳເນີນງານຂອງອຸປະກອນຂອງທ່ານ ເມື່ອໄດ້ການຮັບແຈ້ງເຕືອນສຸກເສີນຈາກສະຖານີມືຖື."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"ອ່ານຂໍ້ມູນຟີດທີ່ສະໝັກໄວ້"</string> @@ -2190,12 +2192,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"ໃໝ່: ຕົວຂະຫຍາຍໜ້າຈໍ"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"ຕອນນີ້ທ່ານສາມາດຂະຫຍາຍບາງສ່ວນ ຫຼື ທັງໝົດຂອງໜ້າຈໍໄດ້"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ເປີດໃຊ້ໃນການຕັ້ງຄ່າ"</string> + <string name="dismiss_action" msgid="1728820550388704784">"ປິດໄວ້"</string> </resources> diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml index a9227163bf6b..39cbbe1d075f 100644 --- a/core/res/res/values-lt/strings.xml +++ b/core/res/res/values-lt/strings.xml @@ -203,6 +203,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS paslauga"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Jutiklių pranešimų paslauga"</string> <string name="twilight_service" msgid="8964898045693187224">"Paslauga „Twilight“"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Laiko juostos aptikimo priemonė (nėra ryšio)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Įrenginys bus ištrintas"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Administratoriaus programos negalima naudoti. Dabar įrenginio duomenys bus ištrinti.\n\nJei turite klausimų, susisiekite su organizacijos administratoriumi."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Neleidžiama spausdinti (<xliff:g id="OWNER_APP">%s</xliff:g>)."</string> @@ -293,8 +294,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB jungtis"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Programa paleista"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Programos, naudojančios akumuliatoriaus energiją"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Didinimas"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"„<xliff:g id="APP_NAME">%1$s</xliff:g>“ naudoja akumuliatoriaus energiją"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Programų, naudojančių akumuliatoriaus energiją: <xliff:g id="NUMBER">%1$d</xliff:g>"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Palieskite ir sužinokite išsamios informacijos apie akumuliatoriaus bei duomenų naudojimą"</string> @@ -359,6 +359,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Leidžiama programai gauti ir apdoroti MMS pranešimus. Tai reiškia, kad programa gali stebėti ir ištrinti į jūsų įrenginį siunčiamus pranešimus jums jų neparodžiusi."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Persiųsti mobiliuoju transliuojamus pranešimus"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Programai leidžiama susaistyti transliacijos mobiliuoju modulį, kad būtų galima persiųsti mobiliuoju transliuojamus pranešimus, kai jie gaunami. Transliacijos mobiliuoju įspėjimai pristatomi kai kuriose vietovėse, kad būtų galima įspėti apie kritines situacijas. Kai gaunamas mobiliuoju transliuojamas pranešimas apie kritinę situaciją, kenkėjiškos programos gali trukdyti įrenginiui veikti ar jį naudoti."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Tvarkyti vykstančius skambučius"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Programai leidžiama peržiūrėti išsamią informaciją apie vykstančius skambučius įrenginyje ir valdyti šiuos skambučius."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"skaityti mobiliuoju transliuojamus pranešimus"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Programai leidžiama skaityti mobiliuoju transliuojamus pranešimus, gaunamus jūsų įrenginyje. Mobiliuoju transliuojami įspėjimai pristatomi kai kuriose vietose, kad įspėtų apie kritines situacijas. Kai gaunamas mobiliuoju transliuojamas pranešimas apie kritinę situaciją, kenkėjiškos programos gali trukdyti įrenginiui veikti ar jį naudoti."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"skaityti prenumeruojamus tiekimus"</string> @@ -2258,12 +2260,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nauja: „Window Magnifier“"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Dabar galite padidinti dalį ekrano ar jį visą"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Įjungti nustatymuose"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Atmesti"</string> </resources> diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml index 2fec712d0cd0..49d3f44488b2 100644 --- a/core/res/res/values-lv/strings.xml +++ b/core/res/res/values-lv/strings.xml @@ -201,6 +201,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS pakalpojums"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Sensoru paziņojumu pakalpojums"</string> <string name="twilight_service" msgid="8964898045693187224">"Krēslas noteikšanas pakalpojums"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Laika joslas noteikšanas rīks (nav savienojuma)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Jūsu ierīces dati tiks dzēsti"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Administratora lietotni nevar izmantot. Ierīcē saglabātie dati tiks dzēsti.\n\nJa jums ir kādi jautājumi, sazinieties ar savas organizācijas administratoru."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Drukāšanu atspējoja <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -290,8 +291,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB savienojums"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Lietotne darbojas"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Lietotnes, kas patērē akumulatora jaudu"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Palielinājums"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Lietotne <xliff:g id="APP_NAME">%1$s</xliff:g> izmanto akumulatoru"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> lietotne(-es) izmanto akumulatoru"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Pieskarieties, lai skatītu detalizētu informāciju par akumulatora un datu lietojumu"</string> @@ -356,6 +356,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Ļauj lietotnei saņemt un apstrādāt multiziņas. Tas nozīmē, ka lietotne var pārraudzīt vai dzēst uz jūsu ierīci nosūtītos ziņojumus, neparādot tos jums."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Pārsūtīt šūnu apraides ziņojumus"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Ļauj piesaistīt lietotni šūnu apraides modulim, lai pārsūtītu šūnu apraides ziņojumus, tiklīdz tie tiek saņemti. Šūnu apraides brīdinājumi tiek piegādāti noteiktās atrašanās vietās, lai brīdinātu jūs par ārkārtas situācijām. Ļaunprātīgas lietotnes var traucēt ierīces veiktspēju vai darbības, kad ir saņemts ārkārtas šūnas apraides ziņojums."</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"šūnu apraides ziņojumu lasīšana"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Ļauj lietotnei lasīt ierīcē saņemtos šūnu apraides ziņojumus. Šūnu apraides brīdinājumi tiek piegādāti dažās atrašanās vietās, lai brīdinātu jūs par ārkārtas situācijām. Ļaunprātīgas lietotnes var traucēt ierīces veiktspēju vai darbības, kad ir saņemts ārkārtas šūnas apraides ziņojums."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lasīt abonētās plūsmas"</string> @@ -2224,12 +2228,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Jaunums: funkcija Window Magnifier"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Tagad varat palielināt ekrāna daļu vai visu ekrānu"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Ieslēgt sadaļā Iestatījumi"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Nerādīt"</string> </resources> diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml index 3d02757d8ed9..63375f51899e 100644 --- a/core/res/res/values-mk/strings.xml +++ b/core/res/res/values-mk/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Услуга GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Услуга за известување од сензорот"</string> <string name="twilight_service" msgid="8964898045693187224">"Услуга за самрак"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Откривач на временска зона (не може да се поврзе)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Уредот ќе се избрише"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Апликацијата на администраторот не може да се користи. Уредот ќе се избрише сега.\n\nАко имате прашања, контактирајте со администраторот на организацијата."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Печатењето е оневозможено од <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB-врска"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Апликацијата работи"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Апликации што ја трошат батеријата"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Зголемување"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> користи батерија"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> апликации користат батерија"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Допрете за детали за батеријата и потрошениот сообраќај"</string> @@ -353,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Овозможува апликацијата да прима и да обработува MMS пораки. Тоа значи дека апликацијата може да следи или да брише пораки испратени до вашиот уред без да ви ги прикаже вам."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Проследување пораки за мобилен пренос"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Дозволува апликацијата да се врзе со модулот за мобилен пренос за да проследува пораки за мобилен пренос штом ќе се примат. Предупредувањата за мобилно емитување се доставуваат на некои локации за да ве предупредат на итни ситуации. Злонамерните апликации може да пречат во ефикасноста или работењето на вашиот уред кога се прима емитување за итен случај."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Управување со тековни повици"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Дозволува апликацијата да гледа детали за тековните повици на уредот и да ги контролира овие повици."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"прочитај пораки за мобилно емитување"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Овозможува апликациите да ги читаат пораките за мобилно емитување што ги прима вашиот уред. Предупредувањата за мобилно емитување се доставуваат на некои локации, за да ве предупредат на итни ситуации. Злонамерните апликации може да пречат во ефикасноста или работењето на вашиот уред кога се прима емитување за итен случај."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"читај претплатени навестувања на содржина"</string> @@ -2190,12 +2192,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Ново: „Лупа за прозорци“"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Сега може се зголеми целиот екран или само дел"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Вклучи во „Поставки“"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Отфрли"</string> </resources> diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml index 583c46e325a3..3eca56c29e25 100644 --- a/core/res/res/values-ml/strings.xml +++ b/core/res/res/values-ml/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS സേവനം"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"സെൻസർ അറിയിപ്പ് സേവനം"</string> <string name="twilight_service" msgid="8964898045693187224">"സന്ധ്യാസമയത്തെ സേവനം"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"സമയമേഖല കണ്ടെത്താനുള്ള സംവിധാനം (കണക്റ്റിവിറ്റി ഇല്ല)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"നിങ്ങളുടെ ഉപകരണം മായ്ക്കും"</string> <string name="factory_reset_message" msgid="2657049595153992213">"അഡ്മിൻ ആപ്പ് ഉപയോഗിക്കാനാകില്ല. നിങ്ങളുടെ ഉപകരണം ഇപ്പോൾ മായ്ക്കപ്പെടും.\n\nനിങ്ങൾക്ക് ചോദ്യങ്ങൾ ഉണ്ടെങ്കിൽ, നിങ്ങളുടെ സ്ഥാപനത്തിന്റെ അഡ്മിനെ ബന്ധപ്പെടുക."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> പ്രിന്റിംഗ് പ്രവർത്തനരഹിതമാക്കി."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB കണക്ഷൻ"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ആപ്പ് പ്രവർത്തിക്കുന്നു"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ആപ്പുകൾ ബാറ്ററി ഉപയോഗിക്കുന്നു"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"മാഗ്നിഫിക്കേഷൻ"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ബാറ്ററി ഉപയോഗിക്കുന്നു"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ആപ്പുകൾ ബാറ്ററി ഉപയോഗിക്കുന്നു"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ബാറ്ററി, ഡാറ്റ ഉപയോഗം എന്നിവയുടെ വിശദാംശങ്ങളറിയാൻ ടാപ്പുചെയ്യുക"</string> @@ -353,6 +353,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"MMS സന്ദേശങ്ങൾ നേടാനും പ്രോസസ്സുചെയ്യാനും അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. നിങ്ങളുടെ ഉപകരണത്തിലേക്ക് അയയ്ക്കുന്ന സന്ദേശങ്ങൾ നിങ്ങൾക്ക് ദൃശ്യമാക്കാതെ തന്നെ അപ്ലിക്കേഷന് നിരീക്ഷിക്കാനോ ഇല്ലാതാക്കാനോ കഴിയുമെന്നാണ് ഇതിനർത്ഥം."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"ബ്രോഡ്കാസ്റ്റ് സന്ദേശങ്ങൾ കൈമാറുക"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"സ്വീകരിക്കുന്ന മുറയ്ക്ക് ബ്രോഡ്കാസ്റ്റ് സന്ദേശങ്ങൾ കൈമാറുന്നതിന് സെൽ ബ്രോഡ്കാസ്റ്റ് മോഡ്യൂളിലേക്ക് ബൈൻഡ് ചെയ്യാൻ ആപ്പിനെ അനുവദിക്കുന്നു. അടിയന്തര സാഹചര്യങ്ങളെ കുറിച്ച് നിങ്ങൾക്ക് മുന്നറിയിപ്പ് നൽകുന്നതിന് ചില ലൊക്കേഷനുകളിൽ സെൽ ബ്രോഡ്കാസ്റ്റ് അലേർട്ടുകൾ ഡെലിവറി ചെയ്യപ്പെടുന്നു. ഒരു അടിയന്തര സെൽ ബ്രോഡ്കാസ്റ്റ് ലഭിക്കുമ്പോൾ ക്ഷുദ്രകരമായ അപ്ലിക്കേഷനുകൾ നിങ്ങളുടെ ഉപകരണത്തിന്റെ പ്രകടനത്തെയോ പ്രവർത്തനത്തെയോ തടസപ്പെടുത്താനിടയുണ്ട്."</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"സെൽ പ്രക്ഷേപണ സന്ദേശങ്ങൾ റീഡുചെയ്യുക"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"നിങ്ങളുടെ ഉപകരണത്തിൽ ലഭിച്ച സെൽ പ്രക്ഷേപണ സന്ദേശങ്ങൾ റീഡുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു. അടിയന്തര സാഹചര്യങ്ങളെക്കുറിച്ച് നിങ്ങൾക്ക് മുന്നറിയിപ്പ് നൽകാനായി ചില ലൊക്കേഷനുകളിൽ നൽകപ്പെടുന്നവയാണ് സെൽ പ്രക്ഷേപണ അലേർട്ടുകൾ. ഒരു അടിയന്തര സെൽ പ്രക്ഷേപണം ലഭിക്കുമ്പോൾ, ക്ഷുദ്രകരമായ അപ്ലിക്കേഷനുകൾ നിങ്ങളുടെ ഉപകരണത്തിന്റെ പ്രകടനമോ പ്രവർത്തനമോ തടസ്സപ്പെടുത്താനിടയുണ്ട്."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"സബ്സ്ക്രൈബ് ചെയ്ത ഫീഡുകൾ വായിക്കുക"</string> @@ -2190,12 +2194,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"പുതിയത്: വിൻഡോ മാഗ്നിഫൈയർ"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"സ്ക്രീനിന്റെ ഭാഗങ്ങളോ മുഴുവനുമോ മാഗ്നിഫൈ ചെയ്യാം"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ക്രമീകരണത്തിൽ ഓണാക്കുക"</string> + <string name="dismiss_action" msgid="1728820550388704784">"ഡിസ്മിസ് ചെയ്യുക"</string> </resources> diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml index 081e17065b56..366a5b7a7c9a 100644 --- a/core/res/res/values-mn/strings.xml +++ b/core/res/res/values-mn/strings.xml @@ -48,7 +48,7 @@ <string name="invalidPin" msgid="7542498253319440408">"4-8 тооноос бүтэх PIN-г бичнэ үү."</string> <string name="invalidPuk" msgid="8831151490931907083">"8-с цөөнгүй тооноос бүтэх PUK-г бичнэ үү."</string> <string name="needPuk" msgid="7321876090152422918">"SIM картны PUK-түгжигдсэн. Тайлах бол PUK кодыг бичнэ үү."</string> - <string name="needPuk2" msgid="7032612093451537186">"SIM картын хаалтыг болиулах бол PUK2-г бичнэ үү."</string> + <string name="needPuk2" msgid="7032612093451537186">"SIM картыг блокоос гаргах бол PUK2-г бичнэ үү."</string> <string name="enablePin" msgid="2543771964137091212">"Амжилтгүй боллоо, СИМ/РҮИМ түгжээг идэвхжүүлнэ үү."</string> <plurals name="pinpuk_attempts" formatted="false" msgid="1619867269012213584"> <item quantity="other">Таны СИМ түгжигдэхээс өмнө танд <xliff:g id="NUMBER_1">%d</xliff:g> оролдлого хийх боломж үлдлээ. </item> @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS үйлчилгээ"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Мэдрэгчийн мэдэгдлийн үйлчилгээ"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight үйлчилгээ"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Цагийн бүс илрүүлэгч (Холболт байхгүй)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Таны төхөөрөмж устах болно."</string> <string name="factory_reset_message" msgid="2657049595153992213">"Админ аппыг ашиглах боломжгүй. Таны төхөөрөмжийг одоо устгана.\n\nХэрэв танд асуулт байгаа бол байгууллагынхаа админтай холбогдоно уу."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> хэвлэх үйлдлийг идэвхгүй болгосон."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB холболт"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Апп ажиллаж байна"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Апп батарей ашиглаж байна"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Томруулах"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> батерей ашиглаж байна"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> апп батерей ашиглаж байна"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Батерей, дата ашиглалтын талаар дэлгэрэнгүйг харахын тулд товшино уу"</string> @@ -353,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Апп нь MMS мессежийг хүлээн авах болон гүйцэтгэх боломжтой. Ингэснээр апп нь таны төхөөрөмжрүү илгээсэн мессежийг танд үзүүлэхгүйгээр хянах болон устгаж чадна."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Гар утсанд масс мессеж түгээх онцлогийн мессежийг шилжүүлэх"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Гар утсанд масс мессеж түгээх онцлогийн мессежийг хүлээн авах үед түүнийг шилжүүлэх зорилгоор аппад гар утсанд масс мессеж түгээх модультай холбогдохыг зөвшөөрөх Гар утсанд масс мессеж түгээх онцлогийн сэрэмжлүүлэг нь онцгой нөхцөл байдлын тухай танд анхааруулахын тулд зарим байршилд хүрдэг. Гар утсанд масс мессеж түгээх онцлогийн илгээх онцгой нөхцөл байдлын тухай мессежийг хүлээн авах үед хортой апп таны төхөөрөмжийн гүйцэтгэл эсвэл ажиллагаанд саад учруулж болзошгүй."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Үргэлжилж буй дуудлагыг удирдах"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Аппад таны төхөөрөмж дээрх үргэлжилж буй дуудлагын талаарх дэлгэрэнгүйг харах болон эдгээр дуудлагыг хянахыг зөвшөөрнө."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"үүрэн өргөн дамжууллын мессеж унших"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Апп нь таны төхөөрөмжийн хүлээн авсан үүрэн өргөн дамжуулах мессежийг унших боломжтой. Үүрэн өргөн дамжууллын мэдэгдэл нь яаралтай нөхцөл байдлыг анхааруулах зорилгоор зарим байршлуудад хүрдэг. Хортой апп нь яаралтай үүрэн өргөн дамжууллыг хүлээн авсан үед таны төхөөрөмжийн ажиллагаа болон чадамжид нөлөөлөх боломжтой."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"бүртгүүлсэн хангамжийг унших"</string> @@ -480,10 +482,10 @@ <string name="permdesc_transmitIr" product="tablet" msgid="5884738958581810253">"Апп-д таблетын хэт улаан дамжуулагчийг ашиглахыг зөвшөөрнө."</string> <string name="permdesc_transmitIr" product="tv" msgid="3278506969529173281">"Аппад таны Android TV төхөөрөмжийн хэт улаан туяаны дамжуулагчийг ашиглахыг зөвшөөрнө."</string> <string name="permdesc_transmitIr" product="default" msgid="8484193849295581808">"Апп-д утасны хэт улаан дамжуулагчийг ашиглахыг зөвшөөрнө."</string> - <string name="permlab_setWallpaper" msgid="6959514622698794511">"ханын зургийг тохируулах"</string> - <string name="permdesc_setWallpaper" msgid="2973996714129021397">"Апп нь системийн ханын зургийг тохируулах боломжтой."</string> - <string name="permlab_setWallpaperHints" msgid="1153485176642032714">"Таны ханын зурагны хэмжээг тохируулах"</string> - <string name="permdesc_setWallpaperHints" msgid="6257053376990044668">"Апп нь системийн ханын зургийн хэмжээний саналыг тохируулах боломжтой"</string> + <string name="permlab_setWallpaper" msgid="6959514622698794511">"дэлгэцийн зургийг тохируулах"</string> + <string name="permdesc_setWallpaper" msgid="2973996714129021397">"Апп нь системийн дэлгэцийн зургийг тохируулах боломжтой."</string> + <string name="permlab_setWallpaperHints" msgid="1153485176642032714">"Таны дэлгэцийн зургийн хэмжээг тохируулах"</string> + <string name="permdesc_setWallpaperHints" msgid="6257053376990044668">"Апп нь системийн дэлгэцийн зургийн хэмжээний саналыг тохируулах боломжтой"</string> <string name="permlab_setTimeZone" msgid="7922618798611542432">"цагийн бүсийн тохиргоо"</string> <string name="permdesc_setTimeZone" product="tablet" msgid="1788868809638682503">"Апп нь таблетын цагийн бүсийг солих боломжтой."</string> <string name="permdesc_setTimeZone" product="tv" msgid="9069045914174455938">"Аппад таны Android TV төхөөрөмжийн цагийн бүсийг өөрчлөхийг зөвшөөрнө."</string> @@ -1429,8 +1431,8 @@ <string name="input_method_binding_label" msgid="1166731601721983656">"Оруулах арга"</string> <string name="sync_binding_label" msgid="469249309424662147">"Синк"</string> <string name="accessibility_binding_label" msgid="1974602776545801715">"Хандалт"</string> - <string name="wallpaper_binding_label" msgid="1197440498000786738">"Ханын зураг"</string> - <string name="chooser_wallpaper" msgid="3082405680079923708">"Ханын зураг солих"</string> + <string name="wallpaper_binding_label" msgid="1197440498000786738">"Дэлгэцийн зураг"</string> + <string name="chooser_wallpaper" msgid="3082405680079923708">"Дэлгэцийн зураг солих"</string> <string name="notification_listener_binding_label" msgid="2702165274471499713">"Мэдэгдэл сонсогч"</string> <string name="vr_listener_binding_label" msgid="8013112996671206429">"VR сонсогч"</string> <string name="condition_provider_service_binding_label" msgid="8490641013951857673">"Нөхцөл нийлүүлэгч"</string> @@ -1510,7 +1512,7 @@ <string name="shareactionprovider_share_with_application" msgid="4902832247173666973">"<xliff:g id="APPLICATION_NAME">%s</xliff:g>-тай хуваалцана уу"</string> <string name="content_description_sliding_handle" msgid="982510275422590757">"Бариулыг гулсуулна. Хүрээд хүлээнэ."</string> <string name="description_target_unlock_tablet" msgid="7431571180065859551">"Түгжээг тайлах бол татна уу"</string> - <string name="action_bar_home_description" msgid="1501655419158631974">"Нүүр хуудасруу шилжих"</string> + <string name="action_bar_home_description" msgid="1501655419158631974">"Нүүр хуудас руу шилжих"</string> <string name="action_bar_up_description" msgid="6611579697195026932">"Дээш шилжих"</string> <string name="action_menu_overflow_description" msgid="4579536843510088170">"Нэмэлт сонголтууд"</string> <string name="action_bar_home_description_format" msgid="5087107531331621803">"%1$s, %2$s"</string> @@ -2190,12 +2192,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Шинэ: Цонх томруулагч"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Та одоо зарим эсвэл бүх дэлгэцээ томруулж болно"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Тохиргоонд асаана уу"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Үл хэрэгсэх"</string> </resources> diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml index 058863389c75..197797f9a0eb 100644 --- a/core/res/res/values-mr/strings.xml +++ b/core/res/res/values-mr/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS सेवा"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"सेन्सर सूचना सेवा"</string> <string name="twilight_service" msgid="8964898045693187224">"ट्वायलाइट सेवा"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"टाइम झोन डिटेक्टर (कनेक्टिव्हिटी नाही)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"तुमचे डिव्हाइस मिटविले जाईल"</string> <string name="factory_reset_message" msgid="2657049595153992213">"प्रशासक अॅप वापरता येणार नाही. तुमचे डिव्हाइस आता साफ केले जाईल.\n\nतुम्हाला कुठलेही प्रश्न असल्यास, तुमच्या संस्थेच्या प्रशासकाशी संपर्क साधा."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> नी प्रिंट करणे बंद केले आहे."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB कनेक्शन"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"APP चालत आहे"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"बॅटरी लवकर संपवणारी अॅप्स"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"मॅग्निफिकेशन"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> बॅटरी वापरत आहे"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> अॅप्स बॅटरी वापरत आहेत"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"बॅटरी आणि डेटा वापराच्या तपशीलांसाठी टॅप करा"</string> @@ -353,6 +353,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"MMS मेसेज प्राप्त करण्यास आणि त्यावर प्रक्रिया करण्यास अॅप ला अनुमती देते. म्हणजेच अॅप आपल्या डिव्हाइसवर पाठविलेले मेसेज तुम्हाला न दर्शवता त्यांचे परीक्षण करू किंवा ते हटवू शकतो."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"सेल प्रसारण मेसेज फॉरवर्ड करा"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"सेल प्रसारण मेसेज मिळाल्यानंतर ते फॉरवर्ड करण्यासाठी ॲपला सेल प्रसारण मॉड्यूलमध्ये प्रतिबद्ध करण्याची अनुमती देते. काही स्थानांमध्ये तुम्हाला आणीबाणीच्या परिस्थीतींची चेतावणी देण्यासाठी सेल प्रसारण सूचना वितरित केल्या जातात. दुर्भावनापूर्ण अॅप्स आणीबाणी सेल प्रसारण मिळवतात तेव्हा ती तुमच्या डिव्हाइसच्या परफॉर्मन्समध्ये किंवा कामामध्ये कदाचित व्यत्यय आणू शकतात."</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"सेल प्रसारण मेसेज वाचा"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"आपल्या डिव्हाइसद्वारे प्राप्त केलेले सेल प्रसारण मेसेज वाचण्यासाठी अॅप ला अनुमती देते. काही स्थानांमध्ये तुम्हाला आणीबाणीच्या परिस्थितीची चेतावणी देण्यासाठी सेल प्रसारण सूचना वितरीत केल्या जातात. आणीबाणी सेल प्रसारण प्राप्त होते तेव्हा आपल्या डिव्हाइसच्या कार्यप्रदर्शनात किंवा कार्यात दुर्भावनापूर्ण अॅप्स व्यत्यय आणू शकतात."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"सदस्यता घेतलेली फीड वाचा"</string> @@ -2190,12 +2194,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"नवीन: विंडो मॅग्निफायर"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"आता स्क्रीन अंशतः किंवा पूर्ण मॅग्निफाय करू शकता"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"सेटिंग्ज मध्ये सुरू करा"</string> + <string name="dismiss_action" msgid="1728820550388704784">"डिसमिस करा"</string> </resources> diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml index 1d70f76f3cd7..635c5b7f95fc 100644 --- a/core/res/res/values-ms/strings.xml +++ b/core/res/res/values-ms/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Perkhidmatan GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Perkhidmatan Pemberitahuan Penderia"</string> <string name="twilight_service" msgid="8964898045693187224">"Perkhidmatan Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Pengesan Zon Waktu (Tiada kesambungan)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Peranti anda akan dipadam"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Apl pentadbir tidak dapat digunakan. Peranti anda akan dipadamkan sekarang.\n\nJika anda ingin mengemukakan soalan, hubungi pentadbir organisasi anda."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Pencetakan dilumpuhkan oleh <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Sambungan USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Apl berjalan"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apl yang menggunakan bateri"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Pembesaran"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> sedang menggunakan bateri"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apl sedang menggunakan bateri"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Ketik untuk mendapatkan butiran tentang penggunaan kuasa bateri dan data"</string> @@ -353,6 +353,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Membenarkan apl menerima dan memproses mesej MMS. Ini bermakna apl boleh memantau atau memadam mesej yang dihantar ke peranti anda tanpa menunjukkannya kepada anda."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Kirim semula mesej siaran sel"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Membenarkan apl terikat pada modul siaran sel untuk mengirim semula mesej siaran sel apabila diterima. Makluman siaran sel dihantar di sesetengah lokasi untuk memberi amaran kepada anda tentang situasi kecemasan. Apl hasad boleh mengganggu prestasi atau operasi peranti anda apabila siaran sel kecemasan diterima."</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"baca mesej siaran sel"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Membolehkan apl membaca mesej siaran sel yang diterima oleh peranti anda. Isyarat siaran sel dihantar di beberapa lokasi untuk memberi amaran kepada anda tentang situasi kecemasan. Apl hasad boleh mengganggu prestasi atau operasi peranti anda apabila siaran sel kecemasan diterima."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"baca suapan langganan"</string> @@ -2190,12 +2194,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Baharu: Pembesar Tetingkap"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Besarkan sebahagian atau keseluruhan skrin anda"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Hidupkan dalam Tetapan"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Tolak"</string> </resources> diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml index 097c6c599e2b..96d4417f917d 100644 --- a/core/res/res/values-my/strings.xml +++ b/core/res/res/values-my/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS ဝန်ဆောင်မှု"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"အာရုံခံကိရိယာ အကြောင်းကြားချက် ဝန်ဆောင်မှု"</string> <string name="twilight_service" msgid="8964898045693187224">"နေဝင်ဆည်းဆာ ဝန်ဆောင်မှု"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"ဒေသစံတော်ချိန် ရှာဖွေစနစ် (ချိတ်ဆက်နိုင်မှု မလိုပါ)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"သင့်ကိရိယာအား ပယ်ဖျက်လိမ့်မည်"</string> <string name="factory_reset_message" msgid="2657049595153992213">"စီမံခန့်ခွဲမှု အက်ပ်ကို သုံး၍မရပါ။ သင်၏ စက်ပစ္စည်းအတွင်းရှိ အရာများကို ဖျက်လိုက်ပါမည်\n\nမေးစရာများရှိပါက သင့်အဖွဲ့အစည်း၏ စီမံခန့်ခွဲသူကို ဆက်သွယ်ပါ။"</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> က ပုံနှိပ်ထုတ်ယူခြင်းကို ပိတ်ထားသည်။"</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB ချိတ်ဆက်မှု"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"APP လုပ်ဆောင်နေသည်"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"အက်ပ်များက ဘက်ထရီကုန်စေသည်"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ချဲ့ခြင်း"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> က ဘက်ထရီကို အသုံးပြုနေသည်"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"အက်ပ် <xliff:g id="NUMBER">%1$d</xliff:g> ခုက ဘက်ထရီကို အသုံးပြုနေသည်"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ဘက်ထရီနှင့် ဒေတာအသုံးပြုမှု အသေးစိတ်ကို ကြည့်ရန် တို့ပါ"</string> @@ -353,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"အပလီကေးရှင်းအား ရုပ်သံစာများ လက်ခံခြင်း၊ ဆောင်ရွက်ခြင်း ခွင့်ပြုပါ။ ဤခွင့်ပြုချက်တွင် အပလီကေးရှင်းအနေဖြင့် သင် လက်ခံရရှိသော စာများအား သင့်အား မပြပဲစောင့်ကြည့်ခွင့်နှင့် ဖျက်ပစ်ခွင့်များ ပါဝင်ပါသည်။"</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"စာတို ဖြန့်ဝေခြင်းစနစ်သုံး မက်ဆေ့ဂျ်များကို ထပ်ဆင့်ပို့ခြင်း"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"စာတို ဖြန့်ဝေခြင်းစနစ် မော်ဂျူးကိုပေါင်းရန် အက်ပ်များအား ခွင့်ပြုသည်။ ၎င်းမှာ စာတို ဖြန့်ဝေခြင်းစနစ်သုံး မက်ဆေ့ဂျ်များကို လက်ခံရရှိသည့်အတိုင်း ထပ်ဆင့်ပို့ရန် ဖြစ်သည်။ အချို့တည်နေရာများတွင် သင့်အား အရေးပေါ်အခြေအနေများကို သတိပေးရန် စာတို ဖြန့်ဝေခြင်းစနစ်သုံး သတိပေးချက်များကို ပေးပို့သည်။ အရေးပေါ် စာတို ဖြန့်ဝေခြင်းကို ရရှိသည့်အခါ သံသယဖြစ်နိုင်ဖွယ်ရှိသည့် အက်ပ်များက သင့်စက်၏ စွမ်းဆောင်ရည်နှင့် အော်ပရေးရှင်းတို့ကို အနှောင့်အယှက်ပေးနိုင်သည်။"</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"လက်ရှိခေါ်ဆိုမှုများကို စီမံခြင်း"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"သင့်စက်ပစ္စည်းပေါ်ရှိ လက်ရှိခေါ်ဆိုမှုများအကြောင်း အသေးစိတ်များကို ကြည့်ရှုရန်နှင့် ဤခေါ်ဆိုမှုများကို ထိန်းချုပ်ရန် အက်ပ်အား ခွင့်ပြုသည်။"</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"စာတိုများ ဖြန့်ဝေခြင်းစနစ်အား ဖတ်ခြင်း"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"အပလီကေးရှင်းကို သင်၏ စက်ပစ္စည်းမှ လက်ခံရရှိသော အများလွှင့်ထုတ်ချက်များကို ဖတ်ရန် ခွင့်ပြုသည်။ အများလွှင့်ထုတ်ချက်များသည် အရေးပေါ်အခြေအနေများကို သင့်အား သတိပေးရန် အချို့ နေရာများတွင် ပို့ပေးသည်။ အရေးပေါ်သတိပေးချက် ထုတ်လွှင့်ချက်ကို လက်ခံရရှိချိန်တွင်အန္တရာယ် ဖြစ်စေနိုင်သော အပလီကေးရှင်းများသည် သင့်စက်ပစ္စည်း၏ လုပ်ငန်းလည်ပတ်မှုနှင့် စွမ်းဆောင်မှုကို ဝင်စွက်ဖက်နိုင်သည်။"</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"အမည်သွင်းထားသောဖိဖ့်များကို ဖတ်ခြင်း"</string> @@ -2190,12 +2192,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"အသစ်- ဝင်းဒိုးမှန်ဘီလူး"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"ဖန်သားပြင် တစ်စိတ်တစ်ပိုင်း (သို့) တစ်ခုလုံး ချဲ့နိုင်ပါပြီ"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"\'ဆက်တင်များ\' တွင် ဖွင့်ရန်"</string> + <string name="dismiss_action" msgid="1728820550388704784">"ပယ်ရန်"</string> </resources> diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index 6fa80dd10722..c85626fdd2a4 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS-tjeneste"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Sensor Notification Service"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight Service"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Tidssoneoppdagelse (ingen tilkobling)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Enheten blir slettet"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Administratorappen kan ikke brukes. Enheten din blir nå tømt.\n\nTa kontakt med administratoren for organisasjonen din hvis du har spørsmål."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> har slått av utskrift."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB-tilkobling"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App kjører"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apper bruker batteri"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Forstørring"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> bruker batteri"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apper bruker batteri"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Trykk for detaljer om batteri- og databruk"</string> @@ -353,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Lar appen motta og behandle multimediemeldinger. Dette betyr at appen kan overvåke eller slette meldinger som er sendt til enheten din uten at du har sett dem."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Videresend kringkastede meldinger"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Tillat at denne appen binder seg til modulen for kringkastede meldinger for å videresende kringkastede meldinger når de mottas. Kringkastede varsler leveres noen steder for å advare deg om nødssituasjoner. Skadelige apper kan forstyrre ytelsen eller funksjonen til enheten din når en kringkastet nødmelding mottas."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Administrer pågående anrop"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Gir en app tillatelse til å se informasjon om pågående anrop på enheten og til å kontrollere disse anropene."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"lese kringkastede meldinger"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Tillater at appen kan lese kringkastede meldinger enheten din mottar. Kringkastede varsler leveres noen steder for å advare deg om nødssituasjoner. Skadelige apper kan forstyrre ytelsen eller funksjonen til enheten din når en kringkastet nødmelding mottas."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lese abonnement på nyhetskilder"</string> @@ -1800,8 +1802,8 @@ <string name="package_updated_device_owner" msgid="7560272363805506941">"Oppdatert av administratoren din"</string> <string name="package_deleted_device_owner" msgid="2292335928930293023">"Slettet av administratoren din"</string> <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string> - <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"For å forlenge batterilevetiden gjør Batterisparing dette:\n\n• Slår på mørkt tema\n• Slår av eller begrenser bakgrunnsaktivitet, enkelte visuelle effekter og andre funksjoner, for eksempel «Hey Google»\n\n"<annotation id="url">"Finn ut mer"</annotation></string> - <string name="battery_saver_description" msgid="6794188153647295212">"For å forlenge batterilevetiden gjør Batterisparing dette:\n\n• Slår på mørkt tema\n• Slår av eller begrenser bakgrunnsaktivitet, enkelte visuelle effekter og andre funksjoner, for eksempel «Hey Google»"</string> + <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"For å forlenge batterilevetiden gjør Batterisparing dette:\n\n• slår på mørkt tema\n• slår av eller begrenser bakgrunnsaktivitet, enkelte visuelle effekter og andre funksjoner, for eksempel «Hey Google»\n\n"<annotation id="url">"Finn ut mer"</annotation></string> + <string name="battery_saver_description" msgid="6794188153647295212">"For å forlenge batterilevetiden gjør Batterisparing dette:\n\n• slår på mørkt tema\n• slår av eller begrenser bakgrunnsaktivitet, enkelte visuelle effekter og andre funksjoner, for eksempel «Hey Google»"</string> <string name="data_saver_description" msgid="4995164271550590517">"Datasparing hindrer noen apper fra å sende og motta data i bakgrunnen, for å redusere dataforbruket. Aktive apper kan bruke data, men kanskje ikke så mye som ellers – for eksempel vises ikke bilder før du trykker på dem."</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"Vil du slå på Datasparing?"</string> <string name="data_saver_enable_button" msgid="4399405762586419726">"Slå på"</string> @@ -2190,12 +2192,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nytt: vindusforstørrer"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Nå kan du forstørre deler av eller hele skjermen"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Slå på i innstillingene"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Avvis"</string> </resources> diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml index 28c35254c5db..d1ae9ab01868 100644 --- a/core/res/res/values-ne/strings.xml +++ b/core/res/res/values-ne/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS सेवा"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"सेन्सरको सूचनासम्बन्धी सेवा"</string> <string name="twilight_service" msgid="8964898045693187224">"ट्वाइलाइट सेवा"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"समय क्षेत्र पत्ता लगाउने सुविधा (नेटवर्क कनेक्सन नहुँदा)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"तपाईंको यन्त्र मेटिनेछ"</string> <string name="factory_reset_message" msgid="2657049595153992213">"प्रशासकको एप प्रयोग गर्न मिल्दैन। तपाईंको यन्त्रको डेटा अब मेटाइने छ।\n\nतपाईंसँग प्रश्नहरू भएका खण्डमा आफ्नो संगठनका प्रशासकसँग सम्पर्क गर्नुहोस्।"</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ले छाप्ने कार्यलाई असक्षम पार्यो।"</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB जडान"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"एप चलिरहेको छ"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"एपहरूले ब्याट्री खपत गर्दै छन्"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"जुम इन गर्ने सुविधा"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ले ब्याट्री प्रयोग गर्दै छ"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> एपहरूले ब्याट्री प्रयोग गर्दै छन्"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ब्याट्री र डेटाका प्रयोग सम्बन्धी विवरणहरूका लागि ट्याप गर्नुहोस्"</string> @@ -353,6 +353,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"एपलाई MMS सन्देशहरू प्राप्त गर्न र प्रकृया गर्न अनुमति दिन्छ। यसको मतलब अनुप्रयोगले तपाईंको उपकरणमा पठाइएको सन्देशहरू तपाईंलाई नदेखाईनै मोनिटर गर्न वा मेटाउन सक्दछ।"</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"मोबाइल प्रसारणसम्बन्धी सन्देशहरू फर्वार्ड गर्नुहोस्"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"मोबाइल प्रसारणसम्बन्धी सन्देशहरू प्राप्त हुनासाथै तिनीहरूलाई फर्वार्ड गर्नका लागि यसले एपलाई मोबाइल प्रसारण मोड्युलमा जोडिने अनुमति दिन्छ। तपाईंलाई कतिपय स्थानमा आपत्कालीन अवस्थाका बारेमा जानकारी दिनका लागि मोबाइल प्रसारणसम्बन्धी अलर्टहरू पठाइन्छ। हानिकारक एपहरूले आपत्कालीन मोबाइल प्रसारण प्राप्त हुँदा तपाईंको यन्त्रलाई कार्य सम्पादन गर्ने वा सञ्चालित हुने क्रममा हस्तक्षेप गर्न सक्छन्।"</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"सेल प्रसारित सन्देशहरू पढ्नुहोस्"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"तपाईंको उपकरणद्वारा प्राप्त सेल प्रसारण सन्देशहरू एपलाई पढ्न अनुमति दिन्छ। सेल प्रसारण चेतावनीहरू केही स्थानहरूमा तपाईंलाई आपत्कालीन गतिविधिहरूको बारेमा सचेत गराउन गरिएका छन्। खराब एपहरूले एउटा आपत्कालीन सेल प्रसारण प्राप्त गर्दछ जब तपाईंको उपकरणको प्रदर्शन वा अपरेशनको साथ हस्तक्षेप गर्न सक्दछन्।"</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"सदस्य बनाइका फिडहरू पढ्नुहोस्"</string> @@ -1965,7 +1969,7 @@ <string name="autofill_save_type_debit_card" msgid="3169397504133097468">"डेबिट कार्ड"</string> <string name="autofill_save_type_payment_card" msgid="6555012156728690856">"भुक्तानी कार्ड"</string> <string name="autofill_save_type_generic_card" msgid="1019367283921448608">"कार्ड"</string> - <string name="autofill_save_type_username" msgid="1018816929884640882">"प्रयोगकर्ताको नाम"</string> + <string name="autofill_save_type_username" msgid="1018816929884640882">"युजरनेम"</string> <string name="autofill_save_type_email_address" msgid="1303262336895591924">"इमेल ठेगाना"</string> <string name="etws_primary_default_message_earthquake" msgid="8401079517718280669">"शान्त रहनुहोस् र नजिकै आश्रयस्थल खोज्नुहोस्।"</string> <string name="etws_primary_default_message_tsunami" msgid="5828171463387976279">"तटीय क्षेत्र र नदीछेउका ठाउँहरू छाडी उच्च सतहमा अवस्थित कुनै अझ सुरक्षित ठाउँमा जानुहोस्।"</string> @@ -2190,12 +2194,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"नयाँ सुविधा: विन्डो म्याग्निफायर"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"तपाईं अब स्क्रिनको केही वा सबै भाग जुम इन गर्न सक्नुहुन्छ"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"सेटिङमा गई यो सुविधा अन गर्नुहोस्"</string> + <string name="dismiss_action" msgid="1728820550388704784">"हटाउनुहोस्"</string> </resources> diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index 8b571e82dea8..9d470b8a9f52 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS-service"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Service voor sensormeldingen"</string> <string name="twilight_service" msgid="8964898045693187224">"Service voor schemering"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Tijdzonedetector (Geen verbinding)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Je apparaat wordt gewist"</string> <string name="factory_reset_message" msgid="2657049595153992213">"De beheer-app kan niet worden gebruikt. Je apparaat wordt nu gewist.\n\nNeem contact op met de beheerder van je organisatie als je vragen hebt."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Afdrukken uitgeschakeld door <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB-verbinding"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App actief"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Apps die de batterij gebruiken"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Vergroting"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> gebruikt de batterij"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> apps gebruiken de batterij"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tik voor batterij- en datagebruik"</string> @@ -353,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Hiermee kan de app MMS-berichten ontvangen en verwerken. Dit betekent dat de app berichten die naar je apparaat zijn verzonden, kan bijhouden of verwijderen zonder deze aan u weer te geven."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Cell broadcast-berichten doorsturen"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Hiermee kan de app de module voor cell broadcasts binden om cell broadcast-berichten door te sturen als die worden ontvangen. Cell broadcast-waarschuwingen worden op bepaalde locaties verzonden om je te waarschuwen voor noodsituaties. Schadelijke apps kunnen de prestaties of verwerking van je apparaat verstoren als een bericht met een noodmelding wordt ontvangen."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Actieve gesprekken beheren"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Hiermee kan een app informatie over actieve gesprekken op je apparaat bekijken en deze gesprekken beheren."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"infodienstberichten lezen"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Toestaan dat de app infodienstberichten leest die worden ontvangen op je apparaat. Infodienstberichten worden verzonden naar bepaalde locaties om u te waarschjeen voor noodsituaties. Schadelijke apps kunnen de prestaties of verwerking van je apparaat verstoren wanneer een infodienstbericht wordt ontvangen."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"Geabonneerde feeds lezen"</string> @@ -2190,12 +2192,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nieuw: Venstervergroting"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Je kunt je scherm nu (gedeeltelijk) vergroten"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Inschakelen in Instellingen"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Sluiten"</string> </resources> diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml index 4b5c9b0be420..df721729a298 100644 --- a/core/res/res/values-or/strings.xml +++ b/core/res/res/values-or/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS ସର୍ଭିସ୍"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"ସେନ୍ସର୍ ନୋଟିଫିକେସନ୍ ସର୍ଭିସ୍"</string> <string name="twilight_service" msgid="8964898045693187224">"ଟ୍ୱିଲାଇଟ୍ ସର୍ଭିସ୍"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"ଟାଇମ୍ ଜୋନ୍ ଡିଟେକ୍ଟର୍ (କୌଣସି ସଂଯୋଗ ନାହିଁ)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"ଆପଣଙ୍କ ଡିଭାଇସ୍ ବର୍ତ୍ତମାନ ଲିଭାଯିବ"</string> <string name="factory_reset_message" msgid="2657049595153992213">"ଆଡମିନ୍ ଆପ୍ ବ୍ୟବହାର କରାଯାଇପାରିବ ନାହିଁ। ଆପଣଙ୍କ ଡିଭାଇସ୍ର ସମସ୍ତ ଡାଟାକୁ ବର୍ତ୍ତମାନ ଲିଭାଇଦିଆଯିବ। \n\nଯଦି ଆପଣଙ୍କର କୌଣସି ପ୍ରଶ୍ନ ରହିଥାଏ, ଆପଣଙ୍କ ସଂସ୍ଥାର ଆଡମିନ୍ଙ୍କ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।"</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ଦ୍ଵାରା ପ୍ରିଣ୍ଟିଙ୍ଗ ଅକ୍ଷମ କରାଯାଇଛି"</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB ସଂଯୋଗ"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ଆପ୍ ଚାଲୁଛି"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ଆପ୍ଗୁଡ଼ିକ ବ୍ୟାଟେରୀ ଖର୍ଚ୍ଚ କରିଥା\'ନ୍ତି"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ମ୍ୟାଗ୍ନିଫିକେସନ୍"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ବ୍ୟାଟେରୀ ବ୍ୟବହାର କରୁଛି"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g>ଟି ଆପ୍ ବ୍ୟାଟେରୀ ବ୍ୟବହାର କରୁଛନ୍ତି"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ବ୍ୟାଟେରୀ ଏବଂ ଡାଟା ବ୍ୟବହାର ଉପରେ ବିବରଣୀ ପାଇଁ ଟାପ୍ କରନ୍ତୁ"</string> @@ -353,6 +353,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"MMS ମେସେଜ୍ ପ୍ରାପ୍ତ କରିବାକୁ ତଥା ପ୍ରକ୍ରିୟା କରାଇବାକୁ ଆପ୍ଟିକୁ ଅନୁମତି ଦିଏ। ଏହାର ଅର୍ଥ, ଆପଣଙ୍କ ଡିଭାଇସ୍କୁ ପଠାଯାଇଥିବା ମେସେଜ୍ ଆପଣଙ୍କୁ ନଦେଖାଇ ଆପ୍ଟି ମନିଟର୍ କିମ୍ବା ଡିଲିଟ୍ କରିପାରେ।"</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"ସେଲ୍ ପ୍ରସାରଣ ମେସେଜ୍ ଫର୍ୱାର୍ଡ କରନ୍ତୁ"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"ସେଲ୍ ପ୍ରସାରଣ ମେସେଜ୍ ପ୍ରାପ୍ତ ହେବା ପରେ ସେଗୁଡ଼ିକୁ ଫର୍ୱାର୍ଡ କରିବା ପାଇଁ ଆପ୍କୁ ସେଲ୍ ପ୍ରସାରଣ ମଡ୍ୟୁଲ୍ ସହିତ ସଂଯୁକ୍ତ କରିବାକୁ ଅନୁମତି ଦିଏ। ଜରୁରୀକାଳୀନ ପରିସ୍ଥିତିରେ ଆପଣଙ୍କୁ ଚେତାବନୀ ଦେବା ପାଇଁ କିଛି ଲୋକେସନ୍ରେ ସେଲ୍ ପ୍ରସାରଣ ଆଲର୍ଟ ବିତରଣ କରାଯାଇଥାଏ। ଏକ ଜରୁରୀକାଳୀନ ସେଲ୍ ପ୍ରସାରଣ ପ୍ରାପ୍ତ ହେବା ସମୟରେ କିଛି କ୍ଷତିକାରକ ଆପ୍ସ ହୁଏତ ଆପଣଙ୍କର ଡିଭାଇସ୍ର କାର୍ଯ୍ୟଦକ୍ଷତା କିମ୍ବା କାର୍ଯ୍ୟ ପ୍ରକ୍ରିୟାରେ ହସ୍ତକ୍ଷେପ କରିପାରେ।"</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"ସେଲ୍ ବ୍ରଡ୍କାଷ୍ଟ ମେସେଜ୍ ପଢ଼ନ୍ତୁ"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"ଆପଣଙ୍କ ଡିଭାଇସ୍ରେ ପ୍ରାପ୍ତ ହୋଇଥିବା ସେଲ୍ ବ୍ରଡ୍କାଷ୍ଟ ମେସେଜ୍ ପଢିବାକୁ ଆପ୍କୁ ଅନୁମତି ଦିଏ। ଜରୁରୀକାଳୀନ ଅବସ୍ଥା ବିଷୟରେ ଆପଣଙ୍କୁ ସତର୍କ କରାଇବାକୁ କିଛି ଲୋକେଶନ୍ରେ ସେଲ୍ ବ୍ରଡ୍କାଷ୍ଟ ସତର୍କ ଡେଲିଭର୍ କରାଯାଇଥାଏ। ଏକ ଜରୁରୀକାଳୀନ ସେଲ୍ ବ୍ରଡ୍କାଷ୍ଟ ପ୍ରାପ୍ତ ହେବାପରେ ହାନୀକାରକ ଆପ୍ ଆପଣଙ୍କ ଡିଭାଇସ୍ର କାର୍ଯ୍ୟକ୍ଷମତା କିମ୍ବା ସଞ୍ଚାଳନାରେ ବାଧା ପହଞ୍ଚାଇପାରନ୍ତି।"</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"ସବସ୍କ୍ରାଇବ୍ ହୋଇଥିବା ଫୀଡ୍କୁ ପଢ଼ନ୍ତୁ"</string> @@ -2190,12 +2194,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"ନୂଆ: ୱିଣ୍ଡୋ ମ୍ୟାଗ୍ନିଫାୟର୍"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"ଆପଣ ଏବେ ଆଂଶିକ ବା ସମ୍ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନ୍ ବଡ଼ କରିପାରିବେ"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ସେଟିଂସରେ ଚାଲୁ କରନ୍ତୁ"</string> + <string name="dismiss_action" msgid="1728820550388704784">"ଖାରଜ କରନ୍ତୁ"</string> </resources> diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml index 5de08850a3ee..9736e579c0f6 100644 --- a/core/res/res/values-pa/strings.xml +++ b/core/res/res/values-pa/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS ਸੇਵਾ"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"ਸੈਂਸਰ ਸੂਚਨਾ ਸੇਵਾ"</string> <string name="twilight_service" msgid="8964898045693187224">"ਟਵੀਲਾਈਟ ਸੇਵਾ"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"ਸਮਾਂ ਖੇਤਰ ਦਾ ਪਤਾ ਲਗਾਉਣ ਦੀ ਸੁਵਿਧਾ (ਕੋਈ ਕਨੈਕਟੀਵਿਟੀ ਨਹੀਂ)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"ਤੁਹਾਡਾ ਡੀਵਾਈਸ ਮਿਟਾਇਆ ਜਾਏਗਾ"</string> <string name="factory_reset_message" msgid="2657049595153992213">"ਪ੍ਰਸ਼ਾਸਕ ਐਪ ਵਰਤੀ ਨਹੀਂ ਜਾ ਸਕਦੀ। ਹੁਣ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦਾ ਡਾਟਾ ਮਿਟਾਇਆ ਜਾਵੇਗਾ।\n\nਜੇਕਰ ਤੁਹਾਡੇ ਕੋਲ ਕੋਈ ਸਵਾਲ ਹਨ, ਤਾਂ ਆਪਣੀ ਸੰਸਥਾ ਦੇ ਪ੍ਰਸ਼ਾਸਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ਵੱਲੋਂ ਪ੍ਰਿੰਟ ਕਰਨਾ ਬੰਦ ਕੀਤਾ ਗਿਆ।"</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB ਕਨੈਕਸ਼ਨ"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ਚੱਲ ਰਹੀ ਐਪ"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ਬੈਟਰੀ ਦੀ ਖਪਤ ਕਰਨ ਵਾਲੀਆਂ ਐਪਾਂ"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"ਵੱਡਦਰਸ਼ੀਕਰਨ"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਵੱਲੋਂ ਬੈਟਰੀ ਦੀ ਵਰਤੋਂ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ਐਪਾਂ ਬੈਟਰੀ ਦੀ ਵਰਤੋਂ ਕਰ ਰਹੀਆਂ ਹਨ"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"ਬੈਟਰੀ ਅਤੇ ਡਾਟਾ ਵਰਤੋਂ ਸਬੰਧੀ ਵੇਰਵਿਆਂ ਲਈ ਟੈਪ ਕਰੋ"</string> @@ -353,6 +353,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"ਐਪ ਨੂੰ MMS ਸੁਨੇਹੇ ਪ੍ਰਾਪਤ ਕਰਨ ਅਤੇ ਉਹਨਾਂ ਦੀ ਪ੍ਰਕਿਰਿਆ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਇਸਦਾ ਮਤਲਬ ਹੈ ਕਿ ਐਪ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਤੇ ਭੇਜੇ ਗਏ ਸੁਨੇਹਿਆਂ ਨੂੰ ਤੁਹਾਨੂੰ ਦਿਖਾਏ ਬਿਨਾਂ ਨਿਰੀਖਣ ਕਰ ਸਕਦੀ ਹੈ ਜਾਂ ਮਿਟਾ ਸਕਦੀ ਹੈ।"</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"ਸੈੱਲ ਪ੍ਰਸਾਰਨ ਸੁਨੇਹਿਆਂ ਨੂੰ ਅੱਗੇ ਭੇਜੋ"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"ਐਪ ਨੂੰ ਸੈੱਲ ਪ੍ਰਸਾਰਨ ਸੁਨੇਹਿਆਂ ਦੇ ਪ੍ਰਾਪਤ ਹੁੰਦੇ ਹੀ ਉਹਨਾਂ ਨੂੰ ਅੱਗੇ ਭੇਜਣ ਲਈ ਸੈੱਲ ਪ੍ਰਸਾਰਨ ਮਾਡਿਊਲ ਨਾਲ ਜੋੜਨ ਦੀ ਇਜਾਜ਼ਤ ਦਿੱਤੀ ਜਾਂਦੀ ਹੈ। ਸੈੱਲ ਪ੍ਰਸਾਰਨ ਸੁਚੇਤਨਾਵਾਂ ਤੁਹਾਨੂੰ ਸੰਕਟਕਾਲੀ ਸਥਿਤੀਆਂ ਦੀ ਚਿਤਾਵਨੀ ਦੇਣ ਲਈ ਕੁਝ ਟਿਕਾਣਿਆਂ \'ਤੇ ਪ੍ਰਦਾਨ ਕੀਤੀਆਂ ਜਾਂਦੀਆਂ ਹਨ। ਭੈੜੀਆਂ ਐਪਾਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੀ ਕਾਰਗੁਜ਼ਾਰੀ ਜਾਂ ਓਪਰੇਸ਼ਨ ਵਿੱਚ ਵਿਘਨ ਪਾ ਸਕਦੀਆਂ ਹਨ ਜਦੋਂ ਇੱਕ ਸੰਕਟਕਾਲੀ ਸੈੱਲ ਪ੍ਰਸਾਰਨ ਪ੍ਰਾਪਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।"</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"ਸੈਲ ਪ੍ਰਸਾਰਨ ਸੁਨੇਹੇ ਪੜ੍ਹੋ"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"ਐਪ ਨੂੰ ਤੁਹਾਡੀ ਡੀਵਾਈਸ ਵੱਲੋਂ ਪ੍ਰਾਪਤ ਕੀਤੇ ਸੈੱਲ ਪ੍ਰਸਾਰਣ ਸੁਨੇਹੇ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਸੈੱਲ ਪ੍ਰਸਾਰਣ ਚਿਤਾਵਨੀਆਂ ਤੁਹਾਨੂੰ ਸੰਕਟਕਾਲੀਨ ਸਥਿਤੀਆਂ ਦੀ ਚਿਤਾਵਨੀ ਦੇਣ ਲਈ ਕੁਝ ਨਿਰਧਾਰਤ ਟਿਕਾਣਿਆਂ ਤੇ ਪ੍ਰਦਾਨ ਕੀਤੀਆਂ ਜਾਂਦੀਆਂ ਹਨ। ਖਰਾਬ ਐਪਾਂ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੇ ਪ੍ਰਦਰਸ਼ਨ ਜਾਂ ਓਪਰੇਸ਼ਨ ਵਿੱਚ ਵਿਘਨ ਪਾ ਸਕਦੀਆਂ ਹਨ ਜਦੋਂ ਇੱਕ ਸੰਕਟਕਾਲੀਨ ਸੈੱਲ ਪ੍ਰਸਾਰਣ ਪ੍ਰਾਪਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।"</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"ਸਬਸਕ੍ਰਾਈਬ ਕੀਤੇ ਫੀਡਸ ਪੜ੍ਹੋ"</string> @@ -2190,12 +2194,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"ਨਵਾਂ: Window ਵੱਡਦਰਸ਼ੀ"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"ਹੁਣ ਤੁਸੀਂ ਕੁਝ ਜਾਂ ਪੂਰੀ ਸਕ੍ਰੀਨ ਵੱਡਦਰਸ਼ੀ ਕਰ ਸਕਦੇ ਹੋ"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਚਾਲੂ ਕਰੋ"</string> + <string name="dismiss_action" msgid="1728820550388704784">"ਖਾਰਜ ਕਰੋ"</string> </resources> diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index 427beb508366..295a54ec72ca 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -203,6 +203,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Usługa GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Usługa powiadomień czujnika"</string> <string name="twilight_service" msgid="8964898045693187224">"Usługa Zmierzch"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Wykrywanie strefy czasowej (brak połączenia)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Twoje urządzenie zostanie wyczyszczone"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Nie można użyć aplikacji administratora. Dane z urządzenia zostaną wykasowane.\n\nJeśli masz pytania, skontaktuj się z administratorem organizacji."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Drukowanie wyłączone przez: <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -293,8 +294,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Połączenie USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Działa aplikacja"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacje zużywające baterię"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Powiększenie"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> zużywa baterię"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Liczba aplikacji zużywających baterię: <xliff:g id="NUMBER">%1$d</xliff:g>"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Kliknij, by wyświetlić szczegóły wykorzystania baterii i użycia danych"</string> @@ -359,6 +359,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Pozwala aplikacji na odbieranie i przetwarzanie MMS-ów. To oznacza, że aplikacja będzie mogła bez Twojej wiedzy monitorować i usuwać wiadomości wysyłane do Twojego urządzenia."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Przekaż komunikaty z sieci komórkowej"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Zezwala aplikacji powiązać się z modułem komunikatów z sieci komórkowej, aby przekazywać je w momencie, w którym są otrzymywane. W niektórych lokalizacjach komunikaty alarmowe z sieci komórkowej są dostarczane, aby ostrzec Cię o sytuacjach zagrożenia. Złośliwe aplikacje mogą wpływać na działanie urządzenia lub zakłócać je po nadejściu komunikatu alarmowego z sieci komórkowej."</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"odczyt komunikatów z sieci komórkowej"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Zezwala aplikacji na odczyt komunikatów z sieci komórkowej odebranych na urządzeniu. Komunikaty alarmowe z sieci komórkowej są dostarczane w niektórych lokalizacjach w celu ostrzeżenia Cię o sytuacjach zagrożenia. Złośliwe aplikacje mogą wpływać na wydajność lub zakłócać działanie urządzenia po odebraniu komunikatu alarmowego z sieci komórkowej."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"czytanie subskrybowanych źródeł"</string> @@ -1846,7 +1850,7 @@ <string name="package_updated_device_owner" msgid="7560272363805506941">"Zaktualizowany przez administratora"</string> <string name="package_deleted_device_owner" msgid="2292335928930293023">"Usunięty przez administratora"</string> <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string> - <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Aby wydłużyć czas pracy na baterii, funkcja Oszczędzanie baterii:\n\n•włącza tryb ciemny,\n• wyłącza lub ogranicza aktywność w tle, niektóre efekty wizualne oraz inne funkcje, np. „OK Google”.\n\n"<annotation id="url">"Więcej informacji"</annotation></string> + <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Aby wydłużyć czas pracy na baterii, funkcja Oszczędzanie baterii:\n\n• włącza tryb ciemny,\n• wyłącza lub ogranicza aktywność w tle, niektóre efekty wizualne oraz inne funkcje, np. „OK Google”.\n\n"<annotation id="url">"Więcej informacji"</annotation></string> <string name="battery_saver_description" msgid="6794188153647295212">"Aby wydłużyć czas pracy na baterii, Oszczędzanie baterii:\n\n• włącza tryb ciemny,\n• wyłącza lub ogranicza aktywność w tle, niektóre efekty wizualne oraz inne funkcje, np. „OK Google”."</string> <string name="data_saver_description" msgid="4995164271550590517">"Oszczędzanie danych uniemożliwia niektórym aplikacjom wysyłanie i odbieranie danych w tle, zmniejszając w ten sposób ich użycie. Aplikacja, z której w tej chwili korzystasz, może uzyskiwać dostęp do danych, ale rzadziej. Może to powodować, że obrazy będą się wyświetlać dopiero po kliknięciu."</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"Włączyć Oszczędzanie danych?"</string> @@ -2258,12 +2262,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nowość: powiększanie okna"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Możesz teraz powiększyć część lub całość ekranu"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Włącz w Ustawieniach"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Odrzuć"</string> </resources> diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml index 3fed0287bc1e..d9050bfdf784 100644 --- a/core/res/res/values-pt-rBR/strings.xml +++ b/core/res/res/values-pt-rBR/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Serviço de GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Serviço de notificações do sensor"</string> <string name="twilight_service" msgid="8964898045693187224">"Serviço de crepúsculo"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detector de fuso horário (sem conectividade)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Seu dispositivo será limpo"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Não é possível usar o aplicativo para administrador. Seu dispositivo passará por uma limpeza agora.\n\nEm caso de dúvidas, entre em contato com o administrador da sua organização."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Impressão desativada por <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -352,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Permite que o app receba e processe mensagens MMS. Isso significa que o app pode monitorar ou excluir as mensagens enviadas para o dispositivo sem mostrá-las para você."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Encaminhar mensagens de transmissão celular"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Permite que o app se vincule ao módulo de transmissão celular para encaminhar mensagens de transmissão celular assim que elas forem recebidas. Alertas de transmissão celular são recebidos em alguns locais para avisar sobre situações de emergência. Apps maliciosos podem interferir no desempenho ou funcionamento do dispositivo quando uma transmissão celular de emergência é recebida."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Gerenciar chamadas em andamento"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Permite que um app veja detalhes sobre chamadas em andamento no seu dispositivo e as controle."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"ler mensagens de difusão celular"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Permite que o app leia mensagens de difusão celular recebidas por seu dispositivo. Alertas de difusão celular são recebidos em alguns locais para avisar você de situações de emergência. Apps maliciosos podem interferir no desempenho ou funcionamento de seu dispositivo quando uma difusão celular de emergência é recebida."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"ler feeds inscritos"</string> diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index 1c890dd4b651..3de02ab436c0 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Serviço GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Serviço de notificações do sensor"</string> <string name="twilight_service" msgid="8964898045693187224">"Serviço de crepúsculo"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detetor do fuso horário (sem conetividade)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"O seu dispositivo será apagado"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Não é possível utilizar a app de administrador. O seu dispositivo será agora apagado.\n\nSe tiver questões, contacte o administrador da entidade."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Impressão desativada por <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -352,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Permite que a app receba e processe mensagens MMS. Isto significa que a app poderá monitorizar ou eliminar mensagens enviadas para o seu dispositivo sem as apresentar."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Encaminhar mensagens de difusão celular"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Permite que a app se vincule ao módulo de difusão celular para encaminhar mensagens de difusão celular à medida que são recebidas. Os alertas de difusão celular são fornecidos em algumas localizações para avisar sobre situações de emergência. As aplicações maliciosas podem interferir com o desempenho ou funcionamento do seu dispositivo quando for recebida uma difusão celular de emergência."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Gerir chamadas em curso"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Permite que uma app veja detalhes acerca das chamadas em curso no seu dispositivo e controle essas chamadas."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"ler mensagens de transmissão celular"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Permite que a app leia mensagens de transmissão celular recebidas pelo seu dispositivo. Os alertas de transmissão celular são fornecidos em algumas localizações para avisá-lo sobre situações de emergência. As aplicações maliciosas podem interferir com o desempenho ou funcionamento do seu dispositivo quando for recebida uma transmissão celular de emergência."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"ler feeds subscritos"</string> diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index 3fed0287bc1e..d9050bfdf784 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Serviço de GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Serviço de notificações do sensor"</string> <string name="twilight_service" msgid="8964898045693187224">"Serviço de crepúsculo"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detector de fuso horário (sem conectividade)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Seu dispositivo será limpo"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Não é possível usar o aplicativo para administrador. Seu dispositivo passará por uma limpeza agora.\n\nEm caso de dúvidas, entre em contato com o administrador da sua organização."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Impressão desativada por <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -352,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Permite que o app receba e processe mensagens MMS. Isso significa que o app pode monitorar ou excluir as mensagens enviadas para o dispositivo sem mostrá-las para você."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Encaminhar mensagens de transmissão celular"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Permite que o app se vincule ao módulo de transmissão celular para encaminhar mensagens de transmissão celular assim que elas forem recebidas. Alertas de transmissão celular são recebidos em alguns locais para avisar sobre situações de emergência. Apps maliciosos podem interferir no desempenho ou funcionamento do dispositivo quando uma transmissão celular de emergência é recebida."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Gerenciar chamadas em andamento"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Permite que um app veja detalhes sobre chamadas em andamento no seu dispositivo e as controle."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"ler mensagens de difusão celular"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Permite que o app leia mensagens de difusão celular recebidas por seu dispositivo. Alertas de difusão celular são recebidos em alguns locais para avisar você de situações de emergência. Apps maliciosos podem interferir no desempenho ou funcionamento de seu dispositivo quando uma difusão celular de emergência é recebida."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"ler feeds inscritos"</string> diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml index 5cf30763d8f0..340b752441ba 100644 --- a/core/res/res/values-ro/strings.xml +++ b/core/res/res/values-ro/strings.xml @@ -201,6 +201,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Serviciul GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Serviciu pentru notificări de la senzori"</string> <string name="twilight_service" msgid="8964898045693187224">"Serviciul Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detector de fus orar (fără conexiune)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Datele de pe dispozitiv vor fi șterse"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Aplicația de administrare nu poate fi utilizată. Dispozitivul va fi șters.\n\nDacă aveți întrebări, contactați administratorul organizației dvs."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Printare dezactivată de <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -290,8 +291,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Conexiune USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplicația rulează"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplicațiile consumă bateria"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Mărire"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> folosește bateria"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplicații folosesc bateria"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Atingeți pentru mai multe detalii privind bateria și utilizarea datelor"</string> @@ -356,6 +356,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Permite aplicației să primească și să proceseze mesaje MMS. Acest lucru înseamnă că aplicația ar putea monitoriza sau șterge mesajele trimise pe dispozitivul dvs. fără a vi le arăta."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Redirecționează mesajele cu transmisie celulară"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Permite aplicației să se conecteze la modulul de transmisie celulară pentru a redirecționa mesajele cu transmisie celulară pe măsură ce le primește. Alertele cu transmisie celulară sunt difuzate în unele locații pentru a vă avertiza cu privire la situațiile de urgență. Aplicațiile rău intenționate pot afecta performanța sau funcționarea dispozitivului dvs. când este primită o transmisie celulară de urgență."</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"citește mesajele cu transmisie celulară"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Permite aplicației să citească mesajele primite prin transmisie celulară de dispozitivul dvs. Alertele cu transmisie celulară sunt difuzate în unele locații pentru a vă avertiza cu privire la situațiile de urgență. Aplicațiile rău intenționate pot afecta performanța sau funcționarea dispozitivului dvs. când este primită o transmisie celulară de urgență."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"citire feeduri abonat"</string> @@ -2224,12 +2228,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nou: lupă fereastră"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Acum puteți mări o parte sau tot ecranul"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Activați din Setări"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Respingeți"</string> </resources> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index efd3c6c5ad96..74d5bf9b8627 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -203,6 +203,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Служба GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Сервис для обработки уведомлений от датчиков"</string> <string name="twilight_service" msgid="8964898045693187224">"Сервис для определения наступления сумерек"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Определитель часового пояса (работает без Интернета)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Все данные с устройства будут удалены"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Невозможно использовать приложение для администрирования. С устройства будут удалены все данные.\n\nЕсли у вас возникли вопросы, обратитесь к администратору."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Функция печати отключена приложением \"<xliff:g id="OWNER_APP">%s</xliff:g>\""</string> @@ -293,8 +294,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB-подключение"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Приложение активно"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Приложения, расходующие заряд"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Увеличение"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" расходует заряд"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Несколько приложений (<xliff:g id="NUMBER">%1$d</xliff:g>) расходуют заряд"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Нажмите, чтобы проверить энергопотребление и трафик"</string> @@ -359,6 +359,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Приложение сможет получать и обрабатывать MMS. Это значит, что оно сможет отслеживать и удалять отправленные на ваше устройство сообщения, не показывая их."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Пересылка сообщений для оповещения населения"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Приложение сможет выполнить привязку к модулю оповещения населения, чтобы пересылать сообщения широковещательных SMS-служб сразу после их получения. В некоторых странах эти сообщения используются для информирования об экстренных ситуациях. Вредоносное ПО может помешать работе устройства, на которое поступают такие сообщения."</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"Читать сообщения массовой рассылки"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Приложение получит доступ к сообщениям широковещательных SMS-служб, которые в некоторых странах используются для информирования населения об экстренных ситуациях. Вредоносные программы могут помешать работе устройства, на которое поступают такие сообщения."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"Просмотр фидов пользователя"</string> @@ -2258,12 +2262,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Новинка: экранная лупа"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Теперь можно увеличивать весь экран или его часть."</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Включить в настройках"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Закрыть"</string> </resources> diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml index 100aed1c3c66..6c1c777b1e94 100644 --- a/core/res/res/values-si/strings.xml +++ b/core/res/res/values-si/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS සේවාව"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"සංවේදක දැනුම් දීමේ සේවාව"</string> <string name="twilight_service" msgid="8964898045693187224">"ඇඳිරි සේවාව"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"වේලා කලාප අනාවරකය (සම්බන්ධතාවක් නොමැත)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"ඔබගේ උපාංගය මකා දැමෙනු ඇත"</string> <string name="factory_reset_message" msgid="2657049595153992213">"පරිපාලක යෙදුම භාවිතා කළ නොහැකිය. ඔබේ උපාංගය දැන් මකා දමනු ඇත.\n\nඔබට ප්රශ්න තිබේ නම්, ඔබේ සංවිධානයේ පරිපාලකට අමතන්න."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> විසින් මුද්රණය කිරීම අබල කර ඇත."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB සම්බන්ධතාවය"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"යෙදුම ධාවනය කරමින්"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"බැටරිය භාවිත කරන යෙදුම්"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"විශාලනය"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> බැටරිය භාවිත කරයි"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"යෙදුම් <xliff:g id="NUMBER">%1$d</xliff:g>ක් බැටරිය භාවිත කරයි"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"බැටරි හා දත්ත භාවිතය පිළිබඳව විස්තර සඳහා තට්ටු කරන්න"</string> @@ -353,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"MMS පණිවිඩ සොයා ලබාගැනීමට සහ ක්රියාත්මක කිරීමට යෙදුමට අවසර දෙන්න. යෙදුම නිරීක්ෂණය කරනු ලබන අතර ඔබට ලැබුන පණිවිඩ පෙන්වීමෙන් තොරවම මකා දැමිය හැකි බව මෙමඟින් අදහස් කරයි."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"සෙල් විකාශන පණිවිඩ යොමු කිරීම"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"සෙල් විකාශන පණිවිඩ ලැබුණු විට ඒවා යොමු කිරීම සඳහා සෙල් විකාශන මොඩියුලයට බැඳීමට යෙදුමට ඉඩ දෙයි. හදිසි අවස්ථා පිළිබඳව ඔබට අනතුරු ඇඟවීම සඳහා සෙල් විකාශන ඇඟවීම් සමහර ස්ථානවල ලබා දෙනු ලැබේ. හදිසි සෙල් විකාශනයක් ලැබෙන අවස්ථාවකදී, අනිෂ්ට යෙදුම්වලින් ඔබගේ උපාංග කාර්ය සාධනයට හෝ මෙහෙයුමට බාධා සිදු විය හැකිය."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"සිදු වෙමින් පවතින ඇමතුම් කළමනාකරණය කරන්න"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"ඔබගේ උපාංගයේ සිදු වෙමින් පවතින ඇමතුම් පිළිබඳ විස්තර බැලීමට සහ මෙම ඇමතුම් පාලනය කිරීමට යෙදුමකට ඉඩ දෙයි."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"සෙල් ප්රචාරණ පණිවිඩ කියවීම"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"ඔබගේ උපාංගයට ලැබුණු සෙල් විකාශන පණිවිඩ කියවීමට යෙදුමට අවසර දෙන්න. ඔබට හදිසි අවස්ථාවන් පිළිබඳ අනතුරු ඇඟවීමට සෙල් විකාශන පණිවිඩ ඇතැම් ස්ථානවල සිට යවනු ලබයි. හදිසි සෙල් විකාශන ලැබෙන අවස්ථාවකදී, අනිෂ්ට යෙදුම් මඟින් ඔබගේ උපාංගයට කාර්ය සාධනයට හෝ ක්රියකරණයට බාධා සිදුවිය හැක."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"දායක වූ සංග්රහ කියවීම"</string> @@ -2190,12 +2192,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"නව: කවුළු විශාලකය"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"ඔබට දැන් තිරයේ සමහර හෝ සියලු දේ විශාලනය කළ හැකිය"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"සැකසීම් තුළ ක්රියාත්මක කරන්න"</string> + <string name="dismiss_action" msgid="1728820550388704784">"ඉවත ලන්න"</string> </resources> diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml index f7756e5959ce..cfffb86ac10e 100644 --- a/core/res/res/values-sk/strings.xml +++ b/core/res/res/values-sk/strings.xml @@ -162,7 +162,7 @@ <string name="httpErrorAuth" msgid="469553140922938968">"Nepodarilo sa overiť totožnosť."</string> <string name="httpErrorProxyAuth" msgid="7229662162030113406">"Overenie pomocou servera proxy bolo neúspešné."</string> <string name="httpErrorConnect" msgid="3295081579893205617">"K serveru sa nepodarilo pripojiť."</string> - <string name="httpErrorIO" msgid="3860318696166314490">"Nepodarilo sa nadviazať komunikáciu so serverom. Skúste to znova neskôr."</string> + <string name="httpErrorIO" msgid="3860318696166314490">"Nepodarilo sa nadviazať komunikáciu so serverom. Skúste to neskôr."</string> <string name="httpErrorTimeout" msgid="7446272815190334204">"Časový limit pripojenia na server vypršal."</string> <string name="httpErrorRedirectLoop" msgid="8455757777509512098">"Stránka obsahuje príliš veľa presmerovaní servera."</string> <string name="httpErrorUnsupportedScheme" msgid="2664108769858966374">"Protokol nie je podporovaný."</string> @@ -203,6 +203,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Služba GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Služba upozornení senzora"</string> <string name="twilight_service" msgid="8964898045693187224">"Služba stmievania"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detektor časového pásma (bez pripojenia)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Vaše zariadenie bude vymazané"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Daná aplikácia na správu sa nedá použiť. Vaše zariadenie bude vymazané.\n\nV prípade otázok kontaktujte správcu organizácie."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Tlač zakázala aplikácia <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -293,8 +294,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Pripojenie USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplikácia je spustená"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikácie spotrebúvajúce batériu"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Zväčšenie"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> používa batériu"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Aplikácie (<xliff:g id="NUMBER">%1$d</xliff:g>) používajú batériu"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Klepnutím zobrazíte podrobnosti o batérii a spotrebe dát"</string> @@ -359,6 +359,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Umožňuje aplikácii prijímať a spracovávať správy MMS. Znamená to, že aplikácia môže sledovať správy odoslané na vaše zariadenie alebo ich odstrániť bez toho, aby sa vám zobrazili."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Preposielanie správ informačných služieb"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Umožňuje aplikácii spojiť sa s modulom správ informačných služieb s cieľom preposielať prichádzajúce správy informačných služieb. Správy informačných služieb sa doručujú na určitých miestach a upozorňujú na tiesňové situácie. Škodlivé aplikácie môžu pri prijatí správy informačnej služby narušiť výkonnosť alebo prevádzku vášho zariadenia."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Správa prebiehajúcich hovorov"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Povolí aplikácii čítať podrobnosti o prebiehajúcich hovoroch v zariadení a ovládať ich."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"čítať správy informačných služieb"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Umožňuje aplikácii čítať správy informačných služieb prijaté vaším zariadením. Správy informačných služieb sa doručujú na určitých miestach a upozorňujú na tiesňové situácie. Škodlivé aplikácie môžu pri prijatí správy informačnej služby narušiť výkonnosť alebo prevádzku vášho zariadenia."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"čítať odoberané informačné kanály"</string> @@ -572,7 +574,7 @@ <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Časový limit rozpoznania odtlačku prsta vypršal. Skúste to znova."</string> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Operácia týkajúca sa odtlačku prsta bola zrušená"</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Overenie odtlačku prsta zrušil používateľ."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Príliš veľa pokusov. Skúste to znova neskôr."</string> + <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Príliš veľa pokusov. Skúste to neskôr."</string> <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Príliš veľa pokusov. Senzor odtlačkov prstov bol deaktivovaný."</string> <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Skúste to znova"</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Neregistrovali ste žiadne odtlačky prstov."</string> @@ -616,7 +618,7 @@ <string name="face_error_no_space" msgid="5649264057026021723">"Nové údaje o tvári sa nedajú uložiť. Najprv odstráňte jeden zo starých záznamov."</string> <string name="face_error_canceled" msgid="2164434737103802131">"Operácia týkajúca sa tváre bola zrušená"</string> <string name="face_error_user_canceled" msgid="8553045452825849843">"Odomknutie tvárou zrušil používateľ."</string> - <string name="face_error_lockout" msgid="7864408714994529437">"Príliš veľa pokusov. Skúste to znova neskôr."</string> + <string name="face_error_lockout" msgid="7864408714994529437">"Príliš veľa pokusov. Skúste to neskôr."</string> <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Príliš veľa pokusov. Odomknutie tvárou bolo zakázané."</string> <string name="face_error_unable_to_process" msgid="5723292697366130070">"Nedá sa overiť tvár. Skúste to znova."</string> <string name="face_error_not_enrolled" msgid="7369928733504691611">"Nenastavili ste odomknutie tvárou."</string> @@ -1824,7 +1826,7 @@ <item quantity="other">Skúste to znova o <xliff:g id="COUNT">%d</xliff:g> sekúnd</item> <item quantity="one">Skúste to znova o 1 sekundu</item> </plurals> - <string name="restr_pin_try_later" msgid="5897719962541636727">"Skúste to znova neskôr"</string> + <string name="restr_pin_try_later" msgid="5897719962541636727">"Skúste to neskôr"</string> <string name="immersive_cling_title" msgid="2307034298721541791">"Zobrazenie na celú obrazovku"</string> <string name="immersive_cling_description" msgid="7092737175345204832">"Ukončíte potiahnutím zhora nadol."</string> <string name="immersive_cling_positive" msgid="7047498036346489883">"Dobre"</string> @@ -2258,12 +2260,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Novinka: Lupa pre okná"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Teraz môžete zväčšiť celú obrazovku alebo jej časť"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Zapnúť v Nastaveniach"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Zavrieť"</string> </resources> diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml index df7e0ee1a856..2a027b2a4488 100644 --- a/core/res/res/values-sl/strings.xml +++ b/core/res/res/values-sl/strings.xml @@ -203,6 +203,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Storitev GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Storitev obvestil tipal"</string> <string name="twilight_service" msgid="8964898045693187224">"Storitev Somrak"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Zaznavanje časovnega pasu (brez povezave)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Podatki v napravi bodo izbrisani"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Skrbniške aplikacije ni mogoče uporabljati. Podatki v napravi bodo izbrisani.\n\nČe imate vprašanja, se obrnite na skrbnika organizacije."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Tiskanje je onemogočil pravilnik <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -293,8 +294,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Povezava USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplikacija se izvaja"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacije, ki porabljajo energijo baterije"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Povečava"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Aplikacija <xliff:g id="APP_NAME">%1$s</xliff:g> porablja energijo baterije"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Toliko aplikacij porablja energijo baterije: <xliff:g id="NUMBER">%1$d</xliff:g>"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Dotaknite se za prikaz podrobnosti porabe baterije in prenosa podatkov"</string> @@ -359,6 +359,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Aplikaciji omogoča prejemanje in obdelavo MMS-ov. S tem lahko aplikacija nadzoruje ali izbriše sporočila, poslana v napravo, ne da bi vam jih pokazala."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Posredovanje sporočil oddaj v celici"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Aplikaciji omogoča povezovanje z modulom za oddaje v celici, da posreduje sporočila oddaj v celici, takoj ko jih prejme. Na nekaterih lokacijah so opozorila oddaj v celici dostavljena, da vas opozorijo na izredne razmere. Zlonamerne aplikacije lahko vplivajo na delovanje naprave, ko prejme sporočilo oddaje v celici."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Upravljanje aktivnih klicev"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Aplikaciji dovoljuje ogled podrobnosti o aktivnih klicih v napravi in upravljanje s temi klici."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"branje sporočil oddaje v celici"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Omogoča aplikaciji branje sporočil oddaje v celici, ki jih prejme naprava. Opozorila oddaje v celici so dostavljena na nekaterih lokacijah, da vas opozorijo na izredne razmere. Zlonamerne aplikacije lahko vplivajo na delovanje naprave, ko dobi sporočilo oddaje v celici."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"branje naročenih virov"</string> @@ -1846,7 +1848,7 @@ <string name="package_updated_device_owner" msgid="7560272363805506941">"Posodobil skrbnik"</string> <string name="package_deleted_device_owner" msgid="2292335928930293023">"Izbrisal skrbnik"</string> <string name="confirm_battery_saver" msgid="5247976246208245754">"V redu"</string> - <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Funkcija varčevanja z energijo baterije podaljša čas delovanja baterije tako:\n\n•vklopi temno temo,\n•izklopi ali omeji dejavnost v ozadju, nekatere vizualne učinke in druge funkcije, kot je »Hey Google«.\n\n"<annotation id="url">"Več o tem"</annotation></string> + <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Funkcija varčevanja z energijo baterije podaljša čas delovanja baterije tako:\n\n• vklopi temno temo,\n• izklopi ali omeji dejavnost v ozadju, nekatere vizualne učinke in druge funkcije, kot je »Hey Google«.\n\n"<annotation id="url">"Več o tem"</annotation></string> <string name="battery_saver_description" msgid="6794188153647295212">"Funkcija varčevanja z energijo baterije podaljša čas delovanja baterije tako:\n\n• vklopi temno temo;\n• izklopi ali omeji dejavnost v ozadju, nekatere vizualne učinke in druge funkcije, kot je »Hey Google«."</string> <string name="data_saver_description" msgid="4995164271550590517">"Zaradi zmanjševanja prenesene količine podatkov funkcija varčevanja s podatki nekaterim aplikacijam preprečuje, da bi v ozadju pošiljale ali prejemale podatke. Aplikacija, ki jo trenutno uporabljate, lahko prenaša podatke, vendar to morda počne manj pogosto. To na primer pomeni, da se slike ne prikažejo, dokler se jih ne dotaknete."</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"Vklop varčevanja s podatki?"</string> @@ -2258,12 +2260,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Novo: Lupa v oknu"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Zdaj lahko povečate del zaslona ali celotni zaslon"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Vklopite v nastavitvah"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Opusti"</string> </resources> diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml index 8de3f8ca4f80..25989bd9adfa 100644 --- a/core/res/res/values-sq/strings.xml +++ b/core/res/res/values-sq/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Shërbimi GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Shërbimi i njoftimeve të sensorit"</string> <string name="twilight_service" msgid="8964898045693187224">"Shërbimi i muzgut"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Zbuluesi i brezit orar (nuk nevojitet lidhja)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Pajisja do të spastrohet"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Aplikacioni i administratorit nuk mund të përdoret. Pajisja jote tani do të fshihet.\n\nNëse ke pyetje, kontakto me administratorin e organizatës."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Printimi është çaktivizuar nga <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Lidhja USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Aplikacioni është në ekzekutim"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Aplikacionet që konsumojnë baterinë"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Zmadhimi"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> po përdor baterinë"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> aplikacione po përdorin baterinë"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Trokit për detaje mbi baterinë dhe përdorimin e të dhënave"</string> @@ -353,6 +353,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Lejon aplikacionin të marrë dhe përpunojë mesazhe MMS. Kjo do të thotë se aplikacioni mund të monitorojë ose fshijë mesazhe të dërguara në pajisjen tënde, pa t\'i treguar ato."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Transmeto mesazhet e transmetimit celular"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Lejon që aplikacioni të lidhet me modulin e transmetimit celular për t\'i transferuar mesazhet e transmetimit celular menjëherë kur merren. Sinjalizimet e transmetimit celular dërgohen në disa vendndodhje për të të paralajmëruar për situata urgjente. Aplikacionet keqdashëse mund të ndërhyjnë në cilësinë e funksionimit ose në veprimin e pajisjes sate kur merret një transmetim celular urgjent."</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"lexo mesazhet e transmetimit të qelizës"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Lejon aplikacionin të lexojë mesazhet e transmetimit të qelizës, të marra nga pajisja jote. Alarmet e transmetimit të qelizës dërgohen në disa vendndodhje për të të paralajmëruar në situata urgjente. Aplikacionet keqdashëse mund të ndërhyjnë në veprimtarinë ose operacionin e pajisjes tënde kur merret një transmetim urgjent i qelizës."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"lexo informacione të abonuara"</string> @@ -2190,12 +2194,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Risi: Zmadhuesi i dritareve"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Tani mund t\'i zmadhosh një pjesë apo të gjithë ekranin tënd"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Aktivizo te \"Cilësimet\""</string> + <string name="dismiss_action" msgid="1728820550388704784">"Hiq"</string> </resources> diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml index e4031189f26e..fe1201358f5e 100644 --- a/core/res/res/values-sr/strings.xml +++ b/core/res/res/values-sr/strings.xml @@ -201,6 +201,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS услуга"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Услуга обавештења сензора"</string> <string name="twilight_service" msgid="8964898045693187224">"Услуга Сумрак"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Детектор временске зоне (нема интернет везе)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Уређај ће бити обрисан"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Не можете да користите ову апликацију за администраторе. Уређај ће сада бити обрисан.\n\nАко имате питања, контактирајте администратора организације."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Штампање је онемогућила апликација <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -290,8 +291,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB веза"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Активна апликација"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Апликације које троше батерију"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Увећање"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> користи батерију"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Апликације (<xliff:g id="NUMBER">%1$d</xliff:g>) користе батерију"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Додирните за детаље о батерији и потрошњи података"</string> @@ -356,6 +356,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Дозвољава апликацији да прима и обрађује MMS поруке. То значи да апликација може да надгледа или брише поруке које се шаљу уређају, а да вам их не прикаже."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Прослеђивање порука за мобилне уређаје на локалитету"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Дозвољава апликацији да се везује за модул порука за мобилне уређаје на локалитету да би прослеђивала поруке за мобилне уређаје на локалитету онако како су примљене. Обавештења порука за мобилне уређаје на локалитету се на неким локацијама примају као упозорења на хитне случајеве. Злонамерне апликације могу да утичу на учинак или ометају рад уређаја када се прими порука о хитном случају за мобилне уређаје на локалитету."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Управљање одлазним позивима"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Омогућава апликацији да види детаље о одлазним позивима на уређају и да контролише те позиве."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"читање порука инфо сервиса"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Омогућава апликацији да чита поруке инфо сервиса које уређај прима. Упозорења инфо сервиса се на неким локацијама примају као упозорења на хитне случајеве. Злонамерне апликације могу да утичу на учинак или ометају функционисање уређаја када се прими порука инфо сервиса о хитном случају."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"читање пријављених фидова"</string> @@ -932,7 +934,7 @@ <string name="granularity_label_link" msgid="9007852307112046526">"линк"</string> <string name="granularity_label_line" msgid="376204904280620221">"ред"</string> <string name="factorytest_failed" msgid="3190979160945298006">"Фабричко тестирање није успело"</string> - <string name="factorytest_not_system" msgid="5658160199925519869">"Радња FACTORY_TEST је подржана само за пакете инсталиране у директоријуму /system/app."</string> + <string name="factorytest_not_system" msgid="5658160199925519869">"Радња FACTORY_TEST је подржана само за пакете инсталиране у фолдеру /system/app."</string> <string name="factorytest_no_action" msgid="339252838115675515">"Није пронађен ниједан пакет који обезбеђује радњу FACTORY_TEST."</string> <string name="factorytest_reboot" msgid="2050147445567257365">"Рестартуј"</string> <string name="js_dialog_title" msgid="7464775045615023241">"На страници на адреси „<xliff:g id="TITLE">%s</xliff:g>“ пише:"</string> @@ -2048,7 +2050,7 @@ <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Батерија телефона је довољно напуњена. Функције више нису ограничене."</string> <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Батерија таблета је довољно напуњена. Функције више нису ограничене."</string> <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"Батерија уређаја је довољно напуњена. Функције више нису ограничене."</string> - <string name="mime_type_folder" msgid="2203536499348787650">"Директоријум"</string> + <string name="mime_type_folder" msgid="2203536499348787650">"Фолдер"</string> <string name="mime_type_apk" msgid="3168784749499623902">"Android апликација"</string> <string name="mime_type_generic" msgid="4606589110116560228">"Датотека"</string> <string name="mime_type_generic_ext" msgid="9220220924380909486">"<xliff:g id="EXTENSION">%1$s</xliff:g> датотека"</string> @@ -2224,12 +2226,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Ново: Лупа за прозор"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Можете да увећате део екрана или цео екран"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Укључите у Подешавањима"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Одбаци"</string> </resources> diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml index cc21f3929356..60b14ffb75b8 100644 --- a/core/res/res/values-sv/strings.xml +++ b/core/res/res/values-sv/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS-tjänst"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Sensor Notification Service"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight Service"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Tidszondetektering (ingen anslutning)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Enheten kommer att rensas"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Det går inte att använda administratörsappen. Enheten rensas.\n\nKontakta organisationens administratör om du har några frågor."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Utskrift har inaktiverats av <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB-anslutning"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"App körs"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Appar som drar batteri"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Förstoring"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> drar batteri"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> appar drar batteri"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Tryck för information om batteri- och dataanvändning"</string> @@ -353,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Tillåter att appen tar emot och hanterar MMS-meddelanden. Detta innebär att appen kan övervaka eller ta bort meddelanden som skickats till enheten utan att visa dem för dig."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Vidarebefordra massutskick via sms"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Tillåter att appen binds till cellsändningsmodulen så att massutskick via sms kan vidarebefordras vid mottagandet. I vissa områden används massutskick via sms för att varna om nödsituationer. Skadliga appar kan påverka enhetens prestanda eller funktioner när ett massutskick via sms tas emot."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Hantera pågående samtal"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Tillåter att en app får åtkomst till information om pågående samtal på enheten och kan kontrollera dessa samtal."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"läsa SMS-meddelanden"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Appen tillåts läsa SMS som skickas till din enhet. På vissa platser skickas SMS för att varna för nödsituationer. Skadliga appar kan påverka enhetens prestanda eller funktionalitet när du får ett meddelande om en nödsituation via SMS."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"läsa flöden som du prenumererar på"</string> @@ -2190,12 +2192,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Nyhet: Fönsterförstoring"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Nu kan du förstora delar av eller hela skärmen"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Aktivera i inställningarna"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Stäng"</string> </resources> diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml index 9478b0b50832..0818d80c9742 100644 --- a/core/res/res/values-sw/strings.xml +++ b/core/res/res/values-sw/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Huduma ya GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Huduma ya Arifa ya Kitambuzi"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight Service"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Kitambua Saa za Eneo (Hakuna muunganisho)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Data iliyomo kwenye kifaa chako itafutwa"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Huwezi kutumia programu ya msimamizi. Sasa data iliyo kwenye kifaa chako itafutwa.\n\nIkiwa una maswali yoyote, wasiliana na msimamizi wa shirika lako."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Kipengele cha kuchapisha kimezimwa na <xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Muunganisho wa USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Programu inaendelea kutekelezwa"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Programu zinazotumia betri"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ukuzaji"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> inatumia betri"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Programu <xliff:g id="NUMBER">%1$d</xliff:g> zinatumia betri"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Gusa ili upate maelezo kuhusu betri na matumizi ya data"</string> @@ -353,6 +353,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Inaruhusu programu kupokea na kuchakata ujumbe medianwai (MMS). Hii inamaanisha uwezo wa kuchunguza na kufuta ujumbe uliotumwa kwa kifaa chako bila ya kukuonyesha."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Sambaza ujumbe wa matangazo ya simu"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Huruhusu programu ipachikwe katika sehemu ya matangazo ya simu ili isambaze ujumbe wa matangazo ya simu unapopokewa. Arifa za matangazo ya simu huwasilishwa katika maeneo mengine ili kukuonya juu ya hali za dharura. Huenda programu hasidi zikatatiza utendaji au shughuli ya kifaa chako matangazo ya simu ya dharura yanapopokewa."</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"soma mawasiliano ya matangazo ya simu"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Huruhusu programu kusoma mawasiliano ya matangazo ya simu yaliyoingia kwenye kifaa chako. Arifa za matangazo ya simu huwasilishwa katika maeneo mengine ili kukuonya juu ya hali za dharura. Huenda programu hasidi zikatatiza utendajikazi au shughuli ya kifaa chako wakati matangazo ya simu ya dharura yameingia."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"kusoma mipasho kutoka vyanzo unavyofuatilia"</string> @@ -2190,12 +2194,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Mpya: Kikuza Dirisha"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Sasa unaweza kukuza sehemu ya au skrini yako yote"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Washa katika Mipangilio"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Ondoa"</string> </resources> diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml index ebaeaddfd86f..0fe5962a3f3d 100644 --- a/core/res/res/values-ta/strings.xml +++ b/core/res/res/values-ta/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS சேவை"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"சென்சார் அறிவிப்புச் சேவை"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight சேவை"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"நேர மண்டல டிடெக்டர் (இணைப்பு இல்லை)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"சாதனத் தரவு அழிக்கப்படும்"</string> <string name="factory_reset_message" msgid="2657049595153992213">"நிர்வாகி ஆப்ஸை உபயோகிக்க முடியாது. இப்போது, உங்கள் சாதனம் ஆரம்ப நிலைக்கு மீட்டமைக்கப்படும்.\n\nஏதேனும் கேள்விகள் இருப்பின், உங்கள் நிறுவனத்தின் நிர்வாகியைத் தொடர்புகொள்ளவும்."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"பிரிண்ட் செய்வதை <xliff:g id="OWNER_APP">%s</xliff:g> தடுத்துள்ளது."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB இணைப்பு"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ஆப்ஸ் இயங்குகிறது"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"பேட்டரியைப் பயன்படுத்தும் ஆப்ஸ்"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"பெரிதாக்கல்"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ஆப்ஸ் பேட்டரியைப் பயன்படுத்துகிறது"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ஆப்ஸ் பேட்டரியைப் பயன்படுத்துகின்றன"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"பேட்டரி மற்றும் டேட்டா உபயோக விவரங்களைக் காண, தட்டவும்"</string> @@ -353,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"MMS செய்திகளைப் பெற, செயற்படுத்தப் ஆப்ஸை அனுமதிக்கிறது. இதற்கு அர்த்தம் உங்கள் சாதனத்திற்கு அனுப்பப்படும் செய்திகளை உங்களுக்குக் காட்டாமல் கண்காணிக்கவோ, நீக்கவோ ஆப்ஸால் முடியும் என்பதாகும்."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"செல் பிராட்காஸ்ட் மெசேஜ்களை முன்னனுப்பு"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"செல் பிராட்காஸ்ட் மெசேஜ்களைப் பெறும்போதெல்லாம் அவற்றை முன்னனுப்பும் பொருட்டு, ஆப்ஸை செல் பிராட்காஸ்ட் மாடியூலோடு இணைக்கும். சில இடங்களில் அவசர சூழ்நிலைகளின் போது உங்களை எச்சரிக்க செல் பிராட்காஸ்ட் விழிப்பூட்டல்கள் அனுப்பப்படும். அவசரநிலை செல் பிராட்காஸ்ட்டைப் பெறும்போது, தீங்கிழைக்கும் ஆப்ஸ் உங்கள் சாதனத்தின் செயல்திறனுக்கோ செயல்பாட்டிற்கோ இடையூறு விளைவிக்கக்கூடும்."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"செயலில் உள்ள அழைப்புகளை நிர்வகித்தல்"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"உங்கள் சாதனத்தில், செயலில் உள்ள அழைப்புகள் குறித்த விவரங்களைப் பார்க்கவும் அந்த அழைப்புகளை நிர்வகிக்கவும் ஆப்ஸை அனுமதிக்கும்."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"செல் அலைபரப்புச் செய்திகளைப் படித்தல்"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"உங்கள் சாதனத்தில் பெறப்படும் செல் அலைபரப்புச் செய்திகளைப் படிப்பதற்குப் ஆப்ஸை அனுமதிக்கிறது. அவசரநிலை சூழ்நிலைகளை உங்களுக்கு எச்சரிக்கைச் செய்வதற்கு சில இடங்களில் செல் அலைபரப்பு விழிப்பூட்டல்கள் வழங்கப்படும். அவசரநிலை மொபைல் அலைபரப்புப் பெறப்படும்போது உங்கள் சாதனத்தின் செயல்திறன் அல்லது செயல்பாட்டுடன் தீங்கிழைக்கும் ஆப்ஸ் அதைத் தடுக்கலாம்."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"குழுசேர்ந்த ஊட்டங்களைப் படித்தல்"</string> @@ -2190,12 +2192,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"புதிது: சாளரம் பெரிதாக்கும் கருவி"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"திரை முழுவதையுமோ ஒரு பகுதியையோ பெரிதாக்கலாம்"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"அமைப்புகளில் ஆன் செய்க"</string> + <string name="dismiss_action" msgid="1728820550388704784">"மூடுக"</string> </resources> diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml index c63d175002ea..b4d338096bb8 100644 --- a/core/res/res/values-te/strings.xml +++ b/core/res/res/values-te/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS సర్వీస్"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"సెన్సార్ నోటిఫికేషన్ సర్వీస్"</string> <string name="twilight_service" msgid="8964898045693187224">"ట్విలైట్ సర్వీస్"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"టైమ్ జోన్ డిటెక్టర్ (కనెక్టివిటీ లేదు)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"మీ పరికరంలోని డేటా తొలగించబడుతుంది"</string> <string name="factory_reset_message" msgid="2657049595153992213">"నిర్వాహక యాప్ ఉపయోగించడం సాధ్యపడదు. మీ పరికరంలోని డేటా ఇప్పుడు తొలగించబడుతుంది.\n\nమీకు ప్రశ్నలు ఉంటే, మీ సంస్థ యొక్క నిర్వాహకులను సంప్రదించండి."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"ముద్రణ <xliff:g id="OWNER_APP">%s</xliff:g> ద్వారా నిలిపివేయబడింది."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB కనెక్షన్"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"యాప్ అమలవుతోంది"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"బ్యాటరీని ఉపయోగిస్తున్న యాప్లు"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"మాగ్నిఫికేషన్"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> బ్యాటరీని ఉపయోగిస్తోంది"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> యాప్లు బ్యాటరీని ఉపయోగిస్తున్నాయి"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"బ్యాటరీ మరియు డేటా వినియోగ వివరాల కోసం నొక్కండి"</string> @@ -353,6 +353,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"MMS సందేశాలను స్వీకరించడానికి మరియు ప్రాసెస్ చేయడానికి యాప్ను అనుమతిస్తుంది. యాప్ మీ డివైజ్కు పంపబడిన సందేశాలను మీకు చూపకుండానే పర్యవేక్షించగలదని లేదా తొలగించగలదని దీని అర్థం."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"సెల్ ప్రసార సందేశాలను ఫార్వర్డ్ చేయడం"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"సెల్ ప్రసార సందేశాలను అందుకుంటే, వాటిని ఫార్వర్డ్ చేసే విధంగా సెల్ ప్రసార మాడ్యూల్కు కట్టుబడి ఉండటానికి యాప్ను అనుమతిస్తుంది. సెల్ ప్రసార హెచ్చరికలు అత్యవసర పరిస్థితుల గురించి మిమ్మల్ని హెచ్చరించడానికి కొన్ని స్థానాల్లో అందించబడతాయి. అత్యవసర సెల్ ప్రసారం అందుకున్నప్పుడు హానికరమైన యాప్లు మీ పరికరం యొక్క పనితీరు లేదా నిర్వహణకు అంతరాయం కలిగించవచ్చు."</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"సెల్ ప్రసార సందేశాలను చదవడం"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"మీ పరికరం స్వీకరించిన సెల్ ప్రసార సందేశాలను చదవడానికి యాప్ను అనుమతిస్తుంది. సెల్ ప్రసార హెచ్చరికలు అత్యవసర పరిస్థితుల గురించి మిమ్మల్ని హెచ్చరించడానికి కొన్ని స్థానాల్లో అందించబడతాయి. అత్యవసర సెల్ ప్రసారం స్వీకరించినప్పుడు హానికరమైన యాప్లు మీ పరికరం యొక్క పనితీరు లేదా నిర్వహణకు అంతరాయం కలిగించవచ్చు."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"చందా చేయబడిన ఫీడ్లను చదవడం"</string> @@ -2190,12 +2194,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"కొత్తది: విండో మాగ్నిఫయర్"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"స్క్రీన్ మొత్తం లేదా కొంత భాగాన్ని జూమ్ చేయవచ్చు"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"సెట్టింగ్లలో ఆన్ చేయండి"</string> + <string name="dismiss_action" msgid="1728820550388704784">"విస్మరించు"</string> </resources> diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml index b0acb1217b8b..abda062110bb 100644 --- a/core/res/res/values-th/strings.xml +++ b/core/res/res/values-th/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"บริการ GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"บริการแจ้งเตือนเกี่ยวกับเซ็นเซอร์"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight Service"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"ตัวตรวจจับเขตเวลา (ไม่มีการเชื่อมต่อ)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"ระบบจะลบข้อมูลในอุปกรณ์ของคุณ"</string> <string name="factory_reset_message" msgid="2657049595153992213">"ใช้แอปผู้ดูแลระบบนี้ไม่ได้ ขณะนี้ระบบจะลบข้อมูลในอุปกรณ์ของคุณ\n\nโปรดติดต่อผู้ดูแลระบบขององค์กรหากมีคำถาม"</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> ปิดใช้การพิมพ์แล้ว"</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"การเชื่อมต่อ USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"แอปที่ทำงานอยู่"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"แอปหลายแอปกำลังใช้แบตเตอรี่"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"การขยาย"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> กำลังใช้แบตเตอรี่"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"แอป <xliff:g id="NUMBER">%1$d</xliff:g> แอปกำลังใช้แบตเตอรี่"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"แตะเพื่อดูรายละเอียดเกี่ยวกับแบตเตอรี่และปริมาณการใช้อินเทอร์เน็ต"</string> @@ -353,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"อนุญาตให้แอปพลิเคชันรับและประมวลผลข้อความ MMS ซึ่งหมายความว่าแอปพลิเคชันจะสามารถตรวจสอบหรือลบข้อความที่ส่งมายังอุปกรณ์ของคุณได้โดยไม่ต้องแสดงให้คุณเห็น"</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"ส่งต่อข้อความจากการส่งข้อมูลเตือนภัยทางมือถือ (CB)"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"อนุญาตให้แอปเชื่อมโยงกับโมดูลการส่งข้อมูลเตือนภัยทางมือถือ (CB) เพื่อส่งต่อข้อความจากการส่งข้อมูลเตือนภัยทางมือถือ (CB) ทันทีที่ได้รับ ระบบจะส่งการแจ้งเตือนจากการส่งข้อมูลเตือนภัยทางมือถือ (CB) ในบางตำแหน่งเพื่อแจ้งเตือนคุณเกี่ยวกับสถานการณ์ฉุกเฉิน แอปที่เป็นอันตรายอาจรบกวนประสิทธิภาพหรือการทำงานของอุปกรณ์เมื่อได้รับการส่งข้อมูลเตือนภัยทางมือถือ (CB) ในกรณีฉุกเฉิน"</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"จัดการสายที่สนทนา"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"อนุญาตแอปเพื่อดูรายละเอียดเกี่ยวกับสายที่สนทนาอยู่บนโทรศัพท์และเพื่อควบคุมสายสนทนาเหล่านี้"</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"อ่านข้อความที่ได้รับจากสถานีมือถือ"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"อนุญาตให้แอปอ่านข้อความจากสถานีมือถือที่อุปกรณ์ได้รับ การแจ้งเตือนทางมือถือมีให้บริการในบางพื้นที่ โดยจะแจ้งเตือนคุณเกี่ยวกับสถานการณ์ฉุกเฉิน แอปที่เป็นอันตรายอาจเข้าแทรกแซงการทำงานของอุปกรณ์เมื่อได้รับข้อความแจ้งเตือนฉุกเฉิน"</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"อ่านฟีดข้อมูลที่สมัครไว้"</string> @@ -1800,7 +1802,7 @@ <string name="package_updated_device_owner" msgid="7560272363805506941">"อัปเดตโดยผู้ดูแลระบบ"</string> <string name="package_deleted_device_owner" msgid="2292335928930293023">"ลบโดยผู้ดูแลระบบ"</string> <string name="confirm_battery_saver" msgid="5247976246208245754">"ตกลง"</string> - <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"โหมดประหยัดแบตเตอรี่จะดำเนินการดังต่อไปนี้เพื่อยืดอายุการใช้งานแบตเตอรี่\n\n• เปิดธีมมืด\n•ปิดหรือจำกัดกิจกรรมในเบื้องหลัง เอฟเฟกต์ภาพบางอย่าง และฟีเจอร์อื่นๆ อย่างเช่น “Ok Google”\n\n"<annotation id="url">"ดูข้อมูลเพิ่มเติม"</annotation></string> + <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"โหมดประหยัดแบตเตอรี่จะดำเนินการดังต่อไปนี้เพื่อยืดอายุการใช้งานแบตเตอรี่\n\n• เปิดธีมมืด\n• ปิดหรือจำกัดกิจกรรมในเบื้องหลัง เอฟเฟกต์ภาพบางอย่าง และฟีเจอร์อื่นๆ อย่างเช่น “Ok Google”\n\n"<annotation id="url">"ดูข้อมูลเพิ่มเติม"</annotation></string> <string name="battery_saver_description" msgid="6794188153647295212">"โหมดประหยัดแบตเตอรี่จะดำเนินการดังต่อไปนี้เพื่อยืดอายุการใช้งานแบตเตอรี่\n\n• เปิดธีมมืด\n• ปิดหรือจำกัดกิจกรรมในเบื้องหลัง เอฟเฟกต์ภาพบางอย่าง และฟีเจอร์อื่นๆ อย่างเช่น \"Ok Google\""</string> <string name="data_saver_description" msgid="4995164271550590517">"เพื่อช่วยลดปริมาณการใช้อินเทอร์เน็ต โปรแกรมประหยัดอินเทอร์เน็ตจะช่วยป้องกันไม่ให้บางแอปส่งหรือรับข้อมูลโดยการใช้อินเทอร์เน็ตอยู่เบื้องหลัง แอปที่คุณกำลังใช้งานสามารถเข้าถึงอินเทอร์เน็ตได้ แต่อาจไม่บ่อยเท่าเดิม ตัวอย่างเช่น ภาพต่างๆ จะไม่แสดงจนกว่าคุณจะแตะที่ภาพเหล่านั้น"</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"เปิดการประหยัดอินเทอร์เน็ตไหม"</string> @@ -2190,12 +2192,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"ใหม่: แว่นขยายหน้าต่าง"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"คุณสามารถขยายหน้าจอบางส่วนหรือทั้งหมดได้แล้วตอนนี้"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"เปิดในการตั้งค่า"</string> + <string name="dismiss_action" msgid="1728820550388704784">"ปิด"</string> </resources> diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml index f04e7e1f3d69..286d28d364d8 100644 --- a/core/res/res/values-tl/strings.xml +++ b/core/res/res/values-tl/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Serbisyo ng GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Serbisyo ng Notification ng Sensor"</string> <string name="twilight_service" msgid="8964898045693187224">"Serbisyo ng Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Detector ng Time Zone (Walang koneksyon)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Buburahin ang iyong device"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Hindi magamit ang admin app. Mabubura na ang iyong device.\n\nKung mayroon kang mga tanong, makipag-ugnayan sa admin ng iyong organisasyon."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Na-disable ng <xliff:g id="OWNER_APP">%s</xliff:g> ang pag-print."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Koneksyon ng USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Tumatakbo ang app"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Mga app na kumokonsumo ng baterya"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Pag-magnify"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Gumagamit ng baterya ang <xliff:g id="APP_NAME">%1$s</xliff:g>"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Gumagamit ng baterya ang <xliff:g id="NUMBER">%1$d</xliff:g> (na) app"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"I-tap para sa mga detalye tungkol sa paggamit ng baterya at data"</string> @@ -353,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Pinapayagan ang app na tumanggap at magproseso ng mga mensaheng MMS. Nangangahulugan ito na maaaring sumubaybay o magtanggal ang app ng mga mensaheng ipinapadala sa iyong device nang hindi ipinapakita ang mga ito sa iyo."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Magpasa ng mga mensahe ng cell broadcast"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Nagbibigay-daan sa app na mag-bind sa module ng cell broadcast para makapagpasa ng mga mensahe ng cell broadcast pagkatanggap sa mga ito. Inihahatid ang mga alerto ng cell broadcast sa ilang lokasyon para balaan ka tungkol sa mga emergency na sitwasyon. Posibleng makasagabal ang mga nakakahamak na app sa performance o pagpapatakbo ng iyong device kapag nakatanggap ito ng emergency na cell broadcast."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Pamahalaan ang mga kasalukuyang tawag"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Pinapayagan ang app na makita ang mga detalye tungkol sa mga kasalukuyang tawag sa iyong device at kontrolin ang mga tawag na ito."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"basahin ang mga mensahe ng cell broadcast"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Binibigyang-daan ang app na magbasa ng mga mensahe ng cell broadcast na natanggap ng iyong device. Inihahatid ang mga alerto ng cell broadcast sa ilang lokasyon upang balaan ka tungkol sa mga emergency na sitwasyon. Maaaring makaabala ang nakakahamak na apps sa performance o pagpapatakbo ng iyong device kapag nakatanggap ng emergency na cell broadcast."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"magbasa ng mga na-subscribe na feed"</string> @@ -2190,12 +2192,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Bago: Magnifier ng Window"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Mama-magnify na ang bahagi o kabuuan ng screen mo"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"I-on sa Mga Setting"</string> + <string name="dismiss_action" msgid="1728820550388704784">"I-dismiss"</string> </resources> diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml index 79cfe191d35f..96c15b19c69c 100644 --- a/core/res/res/values-tr/strings.xml +++ b/core/res/res/values-tr/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS Hizmeti"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Sensör Bildirim Hizmeti"</string> <string name="twilight_service" msgid="8964898045693187224">"Alacakaranlık Hizmeti"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Zaman Dilimi Algılayıcı (Bağlantı yok)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Cihazınız silinecek"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Yönetim uygulaması kullanılamıyor. Cihazınız şimdi silinecek.\n\nSorularınız varsa kuruluşunuzun yöneticisine başvurun."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Yazdırma işlemi <xliff:g id="OWNER_APP">%s</xliff:g> tarafından devre dışı bırakıldı."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB bağlantısı"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Uygulama çalışıyor"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Pil kullanan uygulamalar"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Büyütme"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> pil kullanıyor"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> uygulama pil kullanıyor"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Pil ve veri kullanımı ile ilgili ayrıntılar için dokunun"</string> @@ -353,6 +353,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Uygulamaya MMS iletilerini alma ve işleme izni verir. Bu izin, uygulamanın cihazınıza gönderilen iletileri takip edip size göstermeden silebileceği anlamına gelir."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Hücre yayını mesajlarını yönlendirme"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Uygulamanın hücre yayını mesajları geldiğinde bunları yönlendirmek için hücre yayını modülüne bağlanmasına izin verir. Hücre yayını uyarıları bazı konumlarda acil durumlar hakkında sizi uyarmak için kullanılır. Zararlı uygulamalar acil durum hücre yayını alındığında cihazınızın performansını ve çalışmasını olumsuz etkileyebilir."</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"hücre yayını mesajlarını oku"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Uygulamaya, cihazınız tarafından alınan hücre yayını mesajlarını okuma izni verir. Hücre yayını uyarıları bazı yerlerde acil durumlar konusunda sizi uyarmak için gönderilir. Kötü amaçlı uygulamalar acil hücre yayını alındığında cihazınızın performansına ya da çalışmasına engel olabilir."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"abone olunan yayınları okuma"</string> @@ -2190,12 +2194,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Yeni: Pencere Büyüteci"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Artık ekranınızın bir kısmını veya tamamını büyütebilirsiniz"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Ayarlar\'da aç"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Kapat"</string> </resources> diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml index a752010655a9..8511edc4bdaa 100644 --- a/core/res/res/values-uk/strings.xml +++ b/core/res/res/values-uk/strings.xml @@ -203,6 +203,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Сервіс GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Сервіс \"Сповіщення датчика\""</string> <string name="twilight_service" msgid="8964898045693187224">"Сервіс \"Сутінки\""</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Визначення часового поясу (без Інтернету)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"З вашого пристрою буде стерто всі дані"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Не можна запускати додаток для адміністраторів. Буде відновлено заводські налаштування пристрою.\n\nЯкщо у вас є запитання, зв’яжіться з адміністратором своєї організації."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Додаток <xliff:g id="OWNER_APP">%s</xliff:g> вимкнув друк."</string> @@ -293,8 +294,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"З’єднання USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Працює додаток"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Додатки, що використовують заряд акумулятора"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Збільшення"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"Додаток <xliff:g id="APP_NAME">%1$s</xliff:g> використовує заряд акумулятора"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"Додатків, що використовують заряд акумулятора: <xliff:g id="NUMBER">%1$d</xliff:g>"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Торкніться, щоб перевірити використання акумулятора й трафік"</string> @@ -359,6 +359,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Дозволяє програмі отримувати й обробляти MMS-повідомлення. Це означає, що програма може відстежувати чи видаляти повідомлення, надіслані на ваш пристрій, навіть не показуючи їх вам."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Переадресувати повідомлення Cell Broadcast"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Дозволяє додатку зв\'язуватися з модулем Cell Broadcast, щоб переадресувати відповідні вхідні повідомлення. У деяких місцеположеннях сповіщення Cell Broadcast надсилаються для попередження про надзвичайні ситуації. Після повідомлення Cell Broadcast шкідливі додатки можуть перешкоджати роботі вашого пристрою."</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"читати широкомовні повідомлення мережі"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Дозволяє програмі читати широкомовні повідомлення мережі, отримані пристроєм. Широкомовні сповіщення мережі надсилаються в деяких країнах для попередження про надзвичайні ситуації. Шкідливі програми можуть втручатися у швидкодію чи роботу пристрою під час отримання широкомовного повідомлення мережі про надзвичайну ситуацію."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"читати підписані канали"</string> @@ -2258,12 +2262,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Нове: збільшення вікон"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Тепер можна збільшити весь екран або його частину"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Увімкнути в налаштуваннях"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Закрити"</string> </resources> diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml index 4324e36c62b9..6eabc7b44c94 100644 --- a/core/res/res/values-ur/strings.xml +++ b/core/res/res/values-ur/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS سروس"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"سینسر نوٹیفکیشن سروس"</string> <string name="twilight_service" msgid="8964898045693187224">"شفقی سروس"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"ٹائم زون ڈیٹیکٹر (کوئی کنیکٹوٹی نہیں ہے)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"آپ کا آلہ صاف کر دیا جائے گا"</string> <string name="factory_reset_message" msgid="2657049595153992213">"منتظم کی ایپ استعمال نہیں کی جا سکتی۔ آپ کا آلہ اب مٹا دیا جائے گا۔\n\nاگر آپ کے سوالات ہیں تو اپنی تنظیم کے منتظم سے رابطہ کریں۔"</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> نے پرنٹنگ کو غیر فعال کر دیا ہے۔"</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB کنکشن"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"ایپ چل رہی ہے"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"ایپس بیٹری خرچ کر رہی ہیں"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"میگنیفکیشن"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> بیٹری کا استعمال کر رہی ہے"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ایپس بیٹری کا استعمال کر رہی ہیں"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"بیٹری اور ڈیٹا استعمال کے بارے میں تفصیلات کے لیے تھپتھپائیں"</string> @@ -353,6 +353,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"ایپ کو MMS پیغامات حاصل اور ان پر کارروائی کرنے کی اجازت دیتا ہے۔ اس کا مطلب ہے کہ ایپ آپ کے آلے پر مرسلہ پیغامات آپ کو دکھائے بغیر ان پر نگاہ رکھ یا انہیں حذف کرسکتی ہے۔"</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"سیل کے نشریاتی پیغامات فارورڈ کریں"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"سیل کی نشریاتی پیغامات کے موصول ہوتے ہی فارورڈ کرنے کے لیے ایپ کو سیل کے نشریاتی ماڈیول میں پابندی لگانے کی اجازت دیں۔ سیل کی نشریاتی الرٹس آپ کو ہنگامی حالات سے مطلع کرنے کیلئے کچھ مقامات میں مہیا کی جاتی ہیں۔ نقصان دہ ایپس کوئی ہنگامی سیل براڈ کاسٹ موصول ہونے پر آپ کے آلے کی کارکردگی یا عمل میں مداخلت کر سکتی ہیں۔"</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"سیل کے نشریاتی پیغامات پڑھیں"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"ایپ کو آپ کے آلے کو موصولہ سیل کے نشریاتی پیغامات پڑھنے کی اجازت دیتا ہے۔ سیل کی نشریاتی الرٹس آپ کو ہنگامی حالات سے مطلع کرنے کیلئے کچھ مقامات میں مہیا کی جاتی ہیں۔ نقصان دہ ایپس کوئی ہنگامی سیل کا نشریہ موصول ہونے پر آپ کے آلے کی کارکردگی یا عمل میں خلل ڈال سکتی ہیں۔"</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"سبسکرائب کردہ فیڈز پڑھیں"</string> @@ -2190,12 +2194,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"نیا: ونڈو میگنیفائر"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"اب آپ اپنی تمام یا کچھ اسکرین کو بڑا کر سکتے ہیں"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"ترتیبات میں آن کریں"</string> + <string name="dismiss_action" msgid="1728820550388704784">"برخاست کریں"</string> </resources> diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml index 923831c00b88..00f2215b7769 100644 --- a/core/res/res/values-uz/strings.xml +++ b/core/res/res/values-uz/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS xizmati"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Sensorli bildirishnoma xizmati"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight xizmati"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Vaqt mintaqasini aniqlagich (Oflayn)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Qurilmangizdagi ma’lumotlar o‘chirib tashlanadi"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Administrator ilovasini ishlatib bo‘lmaydi. Qurilmada barcha ma’lumotlar o‘chirib tashlanadi.\n\nSavollaringiz bo‘lsa, administrator bilan bog‘laning."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Chop etish funksiyasi <xliff:g id="OWNER_APP">%s</xliff:g> tomonidan faolsizlantirilgan."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB orqali ulanish"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Ilova faol"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Batareya quvvatini sarflayotgan ilovalar"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Kattalashtirish"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> ilovasi batareya quvvatini sarflamoqda"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ta ilova batareya quvvatini sarflamoqda"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Batareya va trafik sarfi tafsilotlari uchun ustiga bosing"</string> @@ -353,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Ilovaga MMS xabarlarini qabul qilish va ularni qayta ishlash uchun ruxsat beradi. Bu sizga yuborilgan xabarlarni ilova sizga ko‘rsatmasdan kuzatishi va o‘chirishi mumkinligini bildiradi."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Aholini ogohlantirish xabarlarini uzatish"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Qabul qilingan aholini ogohlantirish xabarlarini shu holicha uzatish uchun ilovani aholini ogohlantirish moduliga bogʻlash imkonini beradi. Ilovaga ayrim mamlakatlarda aholini favqulodda vaziyatlarda ogohlantirish uchun yuboriladigan tarqatma xabarlarni oʻqish uchun ruxsat beradi. Zararli dasturlar bunday xabarlar kelayotgan qurilmaning ishlashiga xalaqit qilishi mumkin."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Amaldagi chaqiruvlarni boshqarish"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Ilovaga qurilmangizdagi amaldagi chaqiruv tafsilotlarini koʻrish va uni boshqarish huquqini beradi."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"uyali tarmoq operatori xabarlarini o‘qish"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Ilovaga qurilmangiz tomonidan qabul qilingan uyali tarmoq operatori xabarlarini o‘qish uchun ruxsat beradi. Uyali tarmoq operatorining ogohlantiruvchi xabarlari ba’zi manzillarga favqulodda holatlar haqida ogohlantirish uchun jo‘natiladi. Zararli ilovalar uyali tarmoq orqali favqulodda xabar qabul qilinganda qurilmangizning ish faoliyati yoki amallariga xalaqit qilishi mumkin"</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"obunalarni o‘qish"</string> @@ -593,7 +595,7 @@ <string name="face_acquired_too_right" msgid="2513391513020932655">"Telefonni chapga suring."</string> <string name="face_acquired_too_left" msgid="8882499346502714350">"Telefonni oʻngga suring."</string> <string name="face_acquired_poor_gaze" msgid="4427153558773628020">"Qurilmaga tik qarang."</string> - <string name="face_acquired_not_detected" msgid="2945945257956443257">"Telefoningizga yuzingizni tik tuting."</string> + <string name="face_acquired_not_detected" msgid="2945945257956443257">"Telefonni yuzingizga tik qarating."</string> <string name="face_acquired_too_much_motion" msgid="8199691445085189528">"Ortiqcha harakatlanmoqda. Qimirlatmasdan ushlang."</string> <string name="face_acquired_recalibrate" msgid="8724013080976469746">"Yuzingizni qaytadan qayd qildiring."</string> <string name="face_acquired_too_different" msgid="4699657338753282542">"Yuz tanilmadi. Qaytadan urining."</string> @@ -1773,7 +1775,7 @@ <string name="restr_pin_confirm_pin" msgid="7143161971614944989">"Yangi PIN kodni tasdiqlash"</string> <string name="restr_pin_create_pin" msgid="917067613896366033">"Cheklovlarni o‘zgartirish uchun PIN-kod yaratish"</string> <string name="restr_pin_error_doesnt_match" msgid="7063392698489280556">"PIN-kod mos kelmadi. Qayta urinib ko‘ring."</string> - <string name="restr_pin_error_too_short" msgid="1547007808237941065">"PIN kod kamida 4 ta raqamdan iborat bo‘lishi shart."</string> + <string name="restr_pin_error_too_short" msgid="1547007808237941065">"PIN kod juda qisqa, kamida 4 ta raqam kiriting."</string> <plurals name="restr_pin_countdown" formatted="false" msgid="4427486903285216153"> <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> soniyadan so‘ng qayta urinib ko‘ring</item> <item quantity="one">1 soniyadan so‘ng qayta urinib ko‘ring</item> @@ -1800,7 +1802,7 @@ <string name="package_updated_device_owner" msgid="7560272363805506941">"Administrator tomonidan yangilangan"</string> <string name="package_deleted_device_owner" msgid="2292335928930293023">"Administrator tomonidan o‘chirilgan"</string> <string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string> - <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Batareya quvvatini uzaytirish uchun Quvvat tejash funksiyasi:\n\n• Tungi mavzuni yoqadi\n• Fondagi harakatlar, vizual effektlar va “Hey Google” kabi boshqa funksiyalarni faolsizlantiradi\n\n"<annotation id="url">"Batafsil"</annotation></string> + <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Batareya quvvatini uzaytirish uchun Quvvat tejash funksiyasi:\n\n• Tungi mavzuni yoqadi\n• Fondagi harakatlar, vizual effektlar va “Ok Google” kabi boshqa funksiyalarni faolsizlantiradi\n\n"<annotation id="url">"Batafsil"</annotation></string> <string name="battery_saver_description" msgid="6794188153647295212">"Batareya quvvatini uzaytirish uchun Quvvat tejash funksiyasi:\n\n• Tungi mavzuni yoqadi\n• Fondagi harakatlar, vizual effektlar va “Ok Google” kabi boshqa funksiyalarni faolsizlantiradi"</string> <string name="data_saver_description" msgid="4995164271550590517">"Trafik tejash rejimida ayrim ilovalar uchun orqa fonda internetdan foydalanish imkoniyati cheklanadi. Siz ishlatayotgan ilova zaruratga qarab internet-trafik sarflashi mumkin, biroq cheklangan miqdorda. Masalan, rasmlar ustiga bosmaguningizcha ular yuklanmaydi."</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"Trafik tejash yoqilsinmi?"</string> @@ -1894,7 +1896,7 @@ <string name="app_suspended_title" msgid="888873445010322650">"Ilova ishlamayapti"</string> <string name="app_suspended_default_message" msgid="6451215678552004172">"<xliff:g id="APP_NAME_0">%1$s</xliff:g> ishlamayapti. Uning ishlashini <xliff:g id="APP_NAME_1">%2$s</xliff:g> cheklamoqda."</string> <string name="app_suspended_more_details" msgid="211260942831587014">"Batafsil"</string> - <string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Ilovani ishga tushirish"</string> + <string name="app_suspended_unsuspend_message" msgid="1665438589450555459">"Ilovani pauzadan chiqarish"</string> <string name="work_mode_off_title" msgid="5503291976647976560">"Ish profili yoqilsinmi?"</string> <string name="work_mode_off_message" msgid="8417484421098563803">"Ishga oid ilovalar, bildirishnomalar, ma’lumotlar va boshqa ish profili imkoniyatlari yoqiladi"</string> <string name="work_mode_turn_on" msgid="3662561662475962285">"Yoqish"</string> @@ -2009,7 +2011,7 @@ <string name="notification_feedback_indicator" msgid="663476517711323016">"Fikr-mulohaza yuborish"</string> <string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Kun tartibi rejimi haqidagi bildirishnoma"</string> <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Batareya quvvati odatdagidan ertaroq tugashi mumkin"</string> - <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Batareya quvvati uzoqroq ishlashi uchun Tejamkor rejim yoqildi"</string> + <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Batareya quvvatini uzoqroq vaqtga yetkazish uchun quvvat tejash rejimi yoqildi"</string> <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Quvvat tejash"</string> <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Quvvat tejash rejimi faolsizlantirildi"</string> <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Telefon yetarli quvvatlandi. Funksiyalar endi cheklovlarsiz ishlaydi."</string> @@ -2190,12 +2192,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Yangi: Ekran lupasi"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Ekranni toʻliq yoki qisman kattalashtirish mumkin"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Sozlamalar orqali yoqish"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Yopish"</string> </resources> diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml index 296261f850e8..8b27cd0f3897 100644 --- a/core/res/res/values-vi/strings.xml +++ b/core/res/res/values-vi/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Dịch vụ GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Dịch vụ Thông báo của cảm biến"</string> <string name="twilight_service" msgid="8964898045693187224">"Dịch vụ Twilight"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Trình phát hiện múi giờ (Không có kết nối)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Thiết bị của bạn sẽ bị xóa"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Không thể sử dụng ứng dụng quản trị. Thiết bị của bạn sẽ bị xóa ngay bây giờ.\n\nHãy liên hệ với quản trị viên của tổ chức nếu bạn có thắc mắc."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"<xliff:g id="OWNER_APP">%s</xliff:g> đã tắt tính năng in."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Kết nối USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Ứng dụng đang chạy"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Các ứng dụng tiêu thụ pin"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Phóng to"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> đang sử dụng pin"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> ứng dụng đang sử dụng pin"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Nhấn để biết chi tiết về mức sử dụng dữ liệu và pin"</string> @@ -353,6 +353,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Cho phép ứng dụng nhận và xử lý tin nhắn MMS. Điều này có nghĩa là ứng dụng có thể theo dõi hoặc xóa tin nhắn được gửi đến thiết bị của bạn mà không hiển thị chúng cho bạn."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Chuyển tiếp tin nhắn truyền phát trên di động"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Cho phép ứng dụng liên kết với mô-đun truyền phát trên di động để chuyển tiếp tin nhắn truyền phát trên di động ngay khi nhận được. Ở một số vị trí, thông báo truyền phát trên di động sẽ được gửi nhằm cảnh báo cho bạn về các tình huống khẩn cấp. Các ứng dụng độc hại có thể ảnh hưởng đến hiệu suất hoặc hoạt động của thiết bị khi nhận được tin nhắn truyền phát trên di động lúc khẩn cấp."</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"đọc tin nhắn quảng bá"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Cho phép ứng dụng đọc tin nhắn quảng bá mà thiết bị của bạn nhận được. Tin nhắn quảng bá cảnh báo được gửi ở một số địa điểm nhằm cảnh báo cho bạn về các tình huống khẩn cấp. Các ứng dụng độc hại có thể gây ảnh hưởng đến hiệu suất hoặc hoạt động của thiết bị của bạn khi nhận được tin nhắn quảng bá khẩn cấp."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"đọc nguồn cấp dữ liệu đã đăng ký"</string> @@ -2190,12 +2194,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Tính năng mới: Phóng to cửa sổ"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Giờ đây, bạn có thể phóng to một phần hoặc toàn màn hình"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Bật trong phần Cài đặt"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Đóng"</string> </resources> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index a27e7b1ba94c..9826dfb50bd9 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS 服务"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"传感器通知服务"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight 服务"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"时区检测器(无网络连接)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"系统将清空您的设备"</string> <string name="factory_reset_message" msgid="2657049595153992213">"无法使用管理应用,系统现在将清空您的设备。\n\n如有疑问,请与您所在单位的管理员联系。"</string> <string name="printing_disabled_by" msgid="3517499806528864633">"“<xliff:g id="OWNER_APP">%s</xliff:g>”已停用打印功能。"</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB 连接"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"应用正在运行中"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"消耗电量的应用"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"放大功能"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g>正在消耗电量"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> 个应用正在消耗电量"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"点按即可详细了解电量和流量消耗情况"</string> @@ -353,6 +353,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"允许该应用接收和处理彩信。这就意味着,该应用可能会监视发送到您设备的彩信,或删除发送到您设备的彩信而不向您显示。"</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"转发小区广播消息"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"允许应用绑定到小区广播模块,以便及时转发收到的小区广播消息。小区广播消息是在某些地区发送的、用于发布紧急情况警告的提醒信息。恶意应用可能会在您的设备收到紧急小区广播时干扰设备的性能或操作。"</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"读取小区广播消息"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"允许应用读取您的设备收到的小区广播消息。小区广播消息是在某些地区发送的、用于发布紧急情况警告的提醒信息。恶意应用可能会在您收到小区紧急广播时干扰您设备的性能或操作。"</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"读取订阅的供稿"</string> @@ -2190,12 +2194,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"新功能:窗口放大镜"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"您现在可以放大屏幕上的部分或所有内容"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"在“设置”中开启"</string> + <string name="dismiss_action" msgid="1728820550388704784">"关闭"</string> </resources> diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml index 5099ebfd463f..33196c829fc3 100644 --- a/core/res/res/values-zh-rHK/strings.xml +++ b/core/res/res/values-zh-rHK/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS 服務"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"感應器通知服務"</string> <string name="twilight_service" msgid="8964898045693187224">"暮光服務"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"時區偵測器 (沒有連線)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"您的裝置將被清除"</string> <string name="factory_reset_message" msgid="2657049595153992213">"無法使用管理員應用程式。系統會現在清除您的裝置。\n\n如有任何疑問,請聯絡您的機構管理員。"</string> <string name="printing_disabled_by" msgid="3517499806528864633">"「<xliff:g id="OWNER_APP">%s</xliff:g>」暫停了列印。"</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB 連線"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"應用程式正在執行"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"耗用電量的應用程式"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"放大"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在使用電量"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> 個應用程式正在使用電量"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"輕按即可查看電池和數據用量詳情"</string> @@ -353,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"允許應用程式接收和處理 MMS 訊息。這表示應用程式可監控傳送至您裝置的訊息,或在您閱讀訊息前擅自刪除訊息。"</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"轉寄區域廣播訊息"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"允許應用程式繫結至區域廣播模組,以在收到區域廣播訊息時轉寄訊息。在某些地點,系統會發出區域廣播通知,提示您有緊急狀況發生。惡意應用程式可能會在裝置收到緊急區域廣播時,干擾裝置的效能或運作。"</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"管理正在進行的通話"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"允許應用程式查看裝置上正在進行的通話詳情並控制通話。"</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"讀取區域廣播訊息"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"允許應用程式讀取您裝置接收的區域廣播訊息。某些地點會發出區域廣播警報,警告您發生緊急狀況。惡意應用程式可能會在裝置收到緊急區域廣播時,干擾裝置的性能或運作。"</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"讀取訂閱的資訊提供"</string> @@ -2190,12 +2192,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"新功能:視窗放大鏡"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"您現在可以放大部分或整個畫面"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"在「設定」中開啟"</string> + <string name="dismiss_action" msgid="1728820550388704784">"關閉"</string> </resources> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index 31bd99be57b1..a034f0bef015 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"GNSS 服務"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"感應器通知服務"</string> <string name="twilight_service" msgid="8964898045693187224">"Twilight 服務"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"時區偵測器 (不必連上網路)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"你的裝置資料將遭到清除"</string> <string name="factory_reset_message" msgid="2657049595153992213">"無法使用管理應用程式,系統現在將清除你裝置中的資料。\n\n如有任何問題,請與貴機構的管理員聯絡。"</string> <string name="printing_disabled_by" msgid="3517499806528864633">"「<xliff:g id="OWNER_APP">%s</xliff:g>」已停用列印功能。"</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"USB 連線"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"應用程式執行中"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"正在耗用電量的應用程式"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"放大"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」正在耗用電量"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> 個應用程式正在耗用電量"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"輕觸即可查看電池和數據用量詳情"</string> @@ -353,6 +353,10 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"允許應用程式接收和處理多媒體訊息。這項設定可讓應用程式監控傳送至你裝置的訊息,或在你閱讀訊息前擅自刪除訊息。"</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"轉送區域廣播訊息"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"允許應用程式繫結至區域廣播模組,以便轉送收到的區域廣播訊息。某些地點會發出區域廣播警示,警告你有緊急狀況發生。請注意,惡意應用程式可能會在裝置收到緊急區域廣播時,干擾裝置的效能或運作。"</string> + <!-- no translation found for permlab_manageOngoingCalls (281244770664231782) --> + <skip /> + <!-- no translation found for permdesc_manageOngoingCalls (7003138133829915265) --> + <skip /> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"讀取區域廣播訊息"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"允許應用程式讀取你裝置收到的區域廣播訊息。某些地點會發出區域廣播警示,警告你有緊急狀況發生。請注意,惡意應用程式可能會在裝置收到緊急區域廣播時,干擾裝置的效能或運作。"</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"讀取訂閱資訊提供"</string> @@ -2190,12 +2194,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"新功能:視窗放大鏡"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"你可以放大局部或整個畫面"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"在「設定」中開啟"</string> + <string name="dismiss_action" msgid="1728820550388704784">"關閉"</string> </resources> diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml index 28eed9b98efd..67eb874fc007 100644 --- a/core/res/res/values-zu/strings.xml +++ b/core/res/res/values-zu/strings.xml @@ -199,6 +199,7 @@ <string name="gnss_service" msgid="8907781262179951385">"Isevisi ye-GNSS"</string> <string name="sensor_notification_service" msgid="7474531979178682676">"Isevisi Yesaziso Senzwa"</string> <string name="twilight_service" msgid="8964898045693187224">"Isevisi Yangovivi"</string> + <string name="offline_location_time_zone_detection_service_attribution" msgid="303754195048744816">"Isitholi Sezoni Yesikhathi (Akukho ukuxhumana)"</string> <string name="factory_reset_warning" msgid="6858705527798047809">"Idivayisi yakho izosulwa"</string> <string name="factory_reset_message" msgid="2657049595153992213">"Uhlelo lokusebenza lomlawuli alikwazi ukusetshenziswa. Idivayisi yakho manje izosuswa.\n\nUma unemibuzo, xhumana nomlawuli wezinhlangano zakho."</string> <string name="printing_disabled_by" msgid="3517499806528864633">"Ukuphrinta kukhutshazwe nge-<xliff:g id="OWNER_APP">%s</xliff:g>."</string> @@ -287,8 +288,7 @@ <string name="notification_channel_usb" msgid="1528280969406244896">"Ukuxhumeka kwe-USB"</string> <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"Uhlelo loksuebenza olusebenzayo"</string> <string name="notification_channel_foreground_service" msgid="7102189948158885178">"Izinhlelo zokusebenza ezidla ibhethri"</string> - <!-- no translation found for notification_channel_accessibility_magnification (1707913872219798098) --> - <skip /> + <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"Ukukhuliswa"</string> <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g> isebenzisa ibhethri"</string> <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g> izinhlelo zokusebenza zisebenzisa ibhethri"</string> <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"Thepha ngemininingwane ekusetshenzisweni kwebhethri nedatha"</string> @@ -353,6 +353,8 @@ <string name="permdesc_receiveMms" msgid="958102423732219710">"Ivumela uhlelo lokusebenza ukuthola nokucubungula imilayezo ye-MMS. Loku kuchaza ukuthi uhlelo lokusebenza lungangamela noma lesuse imilayezo ethunyelwe kudivayisi yakho ngaphandle kokukubonisa yona."</string> <string name="permlab_bindCellBroadcastService" msgid="586746677002040651">"Dlulisela imilayezo yokusakaza kweselula"</string> <string name="permdesc_bindCellBroadcastService" msgid="6540910200973641606">"Ivumela uhlelo lokusebenza ukuthi luboshezelwe kumojuli yokusakaza kweselula ukuze kudluliselwe imilayezo yokusakaza yeselula njengoba itholwa. Izexwayiso zokusakaza kweselula zilethwa kwezinye izindawo ukuze zikuxwayise ngezimo zesimo esiphuthumayo. Izinhlelo zokusebenza ezinobungozi zingaphazamisa ngokusebenza noma ukusetshenziswa kwedivayisi yakho uma ukusakaza kweselula kwesimo esiphuthumayo kwamukelwa."</string> + <string name="permlab_manageOngoingCalls" msgid="281244770664231782">"Phatha amakholi aqhubekayo"</string> + <string name="permdesc_manageOngoingCalls" msgid="7003138133829915265">"Ivumela uhlelo lokusebenza ukubona imininingwane emayelana namakholi aqhubekayo kudivayisi yakho nokulawula lamakholi."</string> <string name="permlab_readCellBroadcasts" msgid="5869884450872137693">"funda imilayezo yokusakaza yeselula"</string> <string name="permdesc_readCellBroadcasts" msgid="672513437331980168">"Ivumela uhlelo lokusebenza ukufunda imilayezo yokusakaza yeselula etholwe idivayisi yakho. Izaziso zokusakaza zeselula zilethwa kwezinye izindawo ukukuxwayisa ngezimo ezisheshayo. Izinhlelo zokusebenza ezingalungile zingaphazamisana nokusebenza noma umsebenzi wedivayisi yakho uma ukusakaza kweselula kwesimo esisheshayo kutholwa."</string> <string name="permlab_subscribedFeedsRead" msgid="217624769238425461">"funda izifunzo ezikhokhelwayo"</string> @@ -817,7 +819,7 @@ <string name="relationTypeReferredBy" msgid="5285082289602849400">"Kusikiselwe ngu-"</string> <string name="relationTypeRelative" msgid="3396498519818009134">"Isihlobo"</string> <string name="relationTypeSister" msgid="3721676005094140671">"Usisi"</string> - <string name="relationTypeSpouse" msgid="6916682664436031703">"Umlingane"</string> + <string name="relationTypeSpouse" msgid="6916682664436031703">"Umlingani"</string> <string name="sipAddressTypeCustom" msgid="6283889809842649336">"Ngokwezifiso"</string> <string name="sipAddressTypeHome" msgid="5918441930656878367">"Ekhaya"</string> <string name="sipAddressTypeWork" msgid="7873967986701216770">"Umsebenzi"</string> @@ -2190,12 +2192,8 @@ <string name="config_pdp_reject_user_authentication_failed" msgid="4531693033885744689"></string> <string name="config_pdp_reject_service_not_subscribed" msgid="8190338397128671588"></string> <string name="config_pdp_reject_multi_conn_to_same_pdn_not_allowed" msgid="6024904218067254186"></string> - <!-- no translation found for window_magnification_prompt_title (8197528399699536320) --> - <skip /> - <!-- no translation found for window_magnification_prompt_content (4166711383253283838) --> - <skip /> - <!-- no translation found for turn_on_magnification_settings_action (8521433346684847700) --> - <skip /> - <!-- no translation found for dismiss_action (1728820550388704784) --> - <skip /> + <string name="window_magnification_prompt_title" msgid="8197528399699536320">"Okusha: Isikhulisi sewindi"</string> + <string name="window_magnification_prompt_content" msgid="4166711383253283838">"Manje usungakwazi ukukhulisa esinye noma sonke isikrini sakho"</string> + <string name="turn_on_magnification_settings_action" msgid="8521433346684847700">"Vula Kumasethingi"</string> + <string name="dismiss_action" msgid="1728820550388704784">"Cashisa"</string> </resources> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 40e11cb92d3e..fab65d05e69f 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -654,10 +654,9 @@ The default is false. --> <bool name="config_lidControlsSleep">false</bool> - <!-- Indicate whether closing the lid causes the device to enter the folded state which means - to get a smaller screen and opening the lid causes the device to enter the unfolded state - which means to get a larger screen. --> - <bool name="config_lidControlsDisplayFold">false</bool> + <!-- The device state (supplied by DeviceStateManager) that should be treated as folded by the + display fold controller. Default is DeviceStateManager.INVALID_DEVICE_STATE. --> + <integer name="config_foldedDeviceState">-1</integer> <!-- Indicate the display area rect for foldable devices in folded state. --> <string name="config_foldedArea"></string> @@ -3303,6 +3302,10 @@ is non-interactive. --> <bool name="config_cameraDoubleTapPowerGestureEnabled">true</bool> + <!-- Allow the gesture to quick tap the power button multiple times to start the emergency sos + experience while the device is non-interactive. --> + <bool name="config_emergencyGestureEnabled">true</bool> + <!-- Allow the gesture power + volume up to change the ringer mode while the device is interactive. --> <bool name="config_volumeHushGestureEnabled">true</bool> @@ -4570,6 +4573,6 @@ <!-- Indicates that default fitness tracker app needs to request sensor and location permissions. --> <bool name="config_trackerAppNeedsPermissions">false</bool> - <!-- Component with platform query permissions for AppSearch --> - <string name="config_defaultAppSearchPlatformQuerierComponent" translatable="false"></string> + <!-- Package with global data query permissions for AppSearch --> + <string name="config_globalAppSearchDataQuerierPackage" translatable="false"></string> </resources> diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 05db741643e8..4fd8ef6bfa24 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -480,7 +480,7 @@ <dimen name="notification_inbox_item_top_padding">5dp</dimen> <!-- Size of the feedback indicator for notifications --> - <dimen name="notification_feedback_size">14dp</dimen> + <dimen name="notification_feedback_size">16dp</dimen> <!-- Size of the profile badge for notifications --> <dimen name="notification_badge_size">12dp</dimen> diff --git a/core/res/res/values/dimens_car.xml b/core/res/res/values/dimens_car.xml index 2c4f4c89ab81..c3cd80b1edda 100644 --- a/core/res/res/values/dimens_car.xml +++ b/core/res/res/values/dimens_car.xml @@ -84,6 +84,14 @@ <dimen name="car_button_radius">@dimen/car_radius_1</dimen> <dimen name="car_pill_button_size">56dp</dimen> <dimen name="car_touch_target_size">76dp</dimen> + <dimen name="car_touch_target_size_minus_one">75dp</dimen> + + <!-- Switch. --> + <!-- Thumb size + 2*thumb margin size must equal car_touch_target_size --> + <!-- 2 * Thumb size + 2*track margin size must equal car_touch_target_size --> + <dimen name="car_switch_thumb_size">24dp</dimen> + <dimen name="car_switch_thumb_margin_size">26dp</dimen> + <dimen name="car_switch_track_margin_size">14dp</dimen> <!-- Seekbar --> <dimen name="car_seekbar_height">6dp</dimen> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 89b986b8fcb8..31aee4a2e8b4 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -928,6 +928,15 @@ interfere with the performance or operation of your device when an emergency cell broadcast is received.</string> + <!-- Title for an application which grants an app the ability to see and manage calls on + the user's device. Usually reserved for apps associated with wearable devices that + can show information about calls. --> + <string name="permlab_manageOngoingCalls">Manage ongoing calls</string> + <!-- Description of an application permission, listed so the user can choose whether they + want to allow the application to do this. --> + <string name="permdesc_manageOngoingCalls">Allows an app to see details about ongoing calls + on your device and to control these calls.</string> + <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_readCellBroadcasts">read cell broadcast messages</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index e50eee6afa91..88a78a8e6ac3 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1436,6 +1436,10 @@ <java-symbol type="drawable" name="ic_mic" /> <java-symbol type="drawable" name="ic_alert_window_layer" /> <java-symbol type="drawable" name="ic_feedback_indicator" /> + <java-symbol type="drawable" name="ic_feedback_alerted" /> + <java-symbol type="drawable" name="ic_feedback_silenced" /> + <java-symbol type="drawable" name="ic_feedback_uprank" /> + <java-symbol type="drawable" name="ic_feedback_downrank" /> <java-symbol type="drawable" name="ic_account_circle" /> <java-symbol type="color" name="user_icon_1" /> @@ -2823,6 +2827,7 @@ <java-symbol type="bool" name="config_cameraDoubleTapPowerGestureEnabled" /> <java-symbol type="integer" name="config_cameraLiftTriggerSensorType" /> <java-symbol type="string" name="config_cameraLiftTriggerSensorStringType" /> + <java-symbol type="bool" name="config_emergencyGestureEnabled" /> <java-symbol type="bool" name="config_volumeHushGestureEnabled" /> <java-symbol type="drawable" name="platlogo_m" /> @@ -3701,7 +3706,7 @@ <java-symbol type="string" name="config_customCountryDetector" /> <!-- For Foldables --> - <java-symbol type="bool" name="config_lidControlsDisplayFold" /> + <java-symbol type="integer" name="config_foldedDeviceState" /> <java-symbol type="string" name="config_foldedArea" /> <java-symbol type="array" name="config_disableApksUnlessMatchedSku_apk_list" /> @@ -4115,8 +4120,8 @@ <java-symbol type="bool" name="config_trackerAppNeedsPermissions"/> - <!-- Component with platform query permissions for AppSearch --> - <java-symbol type="string" name="config_defaultAppSearchPlatformQuerierComponent" /> + <!-- Package with global data query permissions for AppSearch --> + <java-symbol type="string" name="config_globalAppSearchDataQuerierPackage" /> <!-- Color used by the accessibility focus rectangle --> <java-symbol type="color" name="accessibility_focus_highlight_color" /> diff --git a/core/tests/powertests/PowerStatsLoadTests/Android.bp b/core/tests/batterystatstests/BatteryStatsLoadTests/Android.bp index 66c91adc6540..ade97b81e775 100644 --- a/core/tests/powertests/PowerStatsLoadTests/Android.bp +++ b/core/tests/batterystatstests/BatteryStatsLoadTests/Android.bp @@ -1,5 +1,5 @@ android_test { - name: "PowerStatsLoadTests", + name: "BatteryStatsLoadTests", srcs: ["src/**/*.java"], static_libs: [ "androidx.test.rules", diff --git a/core/tests/powertests/PowerStatsLoadTests/AndroidManifest.xml b/core/tests/batterystatstests/BatteryStatsLoadTests/AndroidManifest.xml index 9cecaedf1380..adc20c6ae496 100644 --- a/core/tests/powertests/PowerStatsLoadTests/AndroidManifest.xml +++ b/core/tests/batterystatstests/BatteryStatsLoadTests/AndroidManifest.xml @@ -16,7 +16,7 @@ --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.frameworks.core.powerstatsloadtests"> + package="com.android.frameworks.core.batterystatsloadtests"> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> @@ -27,7 +27,7 @@ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" - android:targetPackage="com.android.frameworks.core.powerstatsloadtests" + android:targetPackage="com.android.frameworks.core.batterystatsloadtests" android:label="Power Stats Load Tests" /> <queries> diff --git a/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/ConnectivitySetupRule.java b/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/ConnectivitySetupRule.java index ca2942647f08..1afc22b7406d 100644 --- a/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/ConnectivitySetupRule.java +++ b/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/ConnectivitySetupRule.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.frameworks.core.powerstatsloadtests; +package com.android.frameworks.core.batterystatsloadtests; import static org.junit.Assert.assertEquals; diff --git a/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/PowerMetrics.java b/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/PowerMetrics.java index 88cb719add60..dbe5773a3107 100644 --- a/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/PowerMetrics.java +++ b/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/PowerMetrics.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.frameworks.core.powerstatsloadtests; +package com.android.frameworks.core.batterystatsloadtests; import android.os.Process; diff --git a/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/PowerMetricsCollector.java b/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/PowerMetricsCollector.java index a71559b5ad6b..254458cc8935 100644 --- a/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/PowerMetricsCollector.java +++ b/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/PowerMetricsCollector.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.frameworks.core.powerstatsloadtests; +package com.android.frameworks.core.batterystatsloadtests; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -106,6 +106,7 @@ public class PowerMetricsCollector implements TestRule { mContext = instrumentation.getContext(); mUid = Process.myUid(); mUserManager = mContext.getSystemService(UserManager.class); + // TODO(b/175324611): Use BatteryUsageStats instead mStatsHelper = new BatteryStatsHelper(mContext, false /* collectBatteryBroadcast */); mStatsHelper.create((Bundle) null); } diff --git a/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/SystemServiceCallLoadTest.java b/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/SystemServiceCallLoadTest.java index 911ccba3ac78..488469d54f29 100644 --- a/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/SystemServiceCallLoadTest.java +++ b/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/SystemServiceCallLoadTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.frameworks.core.powerstatsloadtests; +package com.android.frameworks.core.batterystatsloadtests; import static org.junit.Assert.assertNotNull; diff --git a/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/WiFiLoadTest.java b/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/WiFiLoadTest.java index 90627192946d..27495da8d839 100644 --- a/core/tests/powertests/PowerStatsLoadTests/src/com/android/frameworks/core/powerstatsloadtests/WiFiLoadTest.java +++ b/core/tests/batterystatstests/BatteryStatsLoadTests/src/com/android/frameworks/core/batterystatsloadtests/WiFiLoadTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.frameworks.core.powerstatsloadtests; +package com.android.frameworks.core.batterystatsloadtests; import android.util.Log; diff --git a/core/tests/powertests/PowerStatsViewer/Android.bp b/core/tests/batterystatstests/BatteryStatsViewer/Android.bp index a3dc4fb4ff74..1e0498be5800 100644 --- a/core/tests/powertests/PowerStatsViewer/Android.bp +++ b/core/tests/batterystatstests/BatteryStatsViewer/Android.bp @@ -1,5 +1,5 @@ android_test { - name: "PowerStatsViewer", + name: "BatteryStatsViewer", srcs: ["src/**/*.java"], defaults: ["SettingsLibDefaults"], static_libs: [ diff --git a/core/tests/powertests/PowerStatsViewer/AndroidManifest.xml b/core/tests/batterystatstests/BatteryStatsViewer/AndroidManifest.xml index 28ea05fca61e..edb1b108b7bc 100644 --- a/core/tests/powertests/PowerStatsViewer/AndroidManifest.xml +++ b/core/tests/batterystatstests/BatteryStatsViewer/AndroidManifest.xml @@ -16,7 +16,7 @@ --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.frameworks.core.powerstatsviewer" + package="com.android.frameworks.core.batterystatsviewer" android:sharedUserId="android.uid.system"> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> @@ -24,9 +24,9 @@ <application android:theme="@style/Theme" - android:label="Power Stats Viewer"> - <activity android:name=".PowerStatsViewerActivity" - android:label="Power Stats Viewer" + android:label="Battery Stats Viewer"> + <activity android:name=".BatteryStatsViewerActivity" + android:label="Battery Stats Viewer" android:launchMode="singleTop" android:exported="true"> <intent-filter> @@ -35,7 +35,7 @@ </intent-filter> </activity> - <activity android:name=".PowerConsumerPickerActivity" - android:label="Select a power consumer"/> + <activity android:name=".BatteryConsumerPickerActivity" + android:label="Select a battery consumer"/> </application> </manifest> diff --git a/core/tests/powertests/PowerStatsViewer/res/layout/power_stats_entry_layout.xml b/core/tests/batterystatstests/BatteryStatsViewer/res/layout/battery_consumer_entry_layout.xml index 1ced825adf31..1ced825adf31 100644 --- a/core/tests/powertests/PowerStatsViewer/res/layout/power_stats_entry_layout.xml +++ b/core/tests/batterystatstests/BatteryStatsViewer/res/layout/battery_consumer_entry_layout.xml diff --git a/core/tests/powertests/PowerStatsViewer/res/layout/power_consumer_info_layout.xml b/core/tests/batterystatstests/BatteryStatsViewer/res/layout/battery_consumer_info_layout.xml index fbd0ebd61bc7..fbd0ebd61bc7 100644 --- a/core/tests/powertests/PowerStatsViewer/res/layout/power_consumer_info_layout.xml +++ b/core/tests/batterystatstests/BatteryStatsViewer/res/layout/battery_consumer_info_layout.xml diff --git a/core/tests/powertests/PowerStatsViewer/res/layout/power_consumer_picker_activity_layout.xml b/core/tests/batterystatstests/BatteryStatsViewer/res/layout/battery_consumer_picker_activity_layout.xml index ecc89f0cb33e..ecc89f0cb33e 100644 --- a/core/tests/powertests/PowerStatsViewer/res/layout/power_consumer_picker_activity_layout.xml +++ b/core/tests/batterystatstests/BatteryStatsViewer/res/layout/battery_consumer_picker_activity_layout.xml diff --git a/core/tests/powertests/PowerStatsViewer/res/layout/power_consumer_picker_layout.xml b/core/tests/batterystatstests/BatteryStatsViewer/res/layout/battery_consumer_picker_layout.xml index bea38c18c20b..bea38c18c20b 100644 --- a/core/tests/powertests/PowerStatsViewer/res/layout/power_consumer_picker_layout.xml +++ b/core/tests/batterystatstests/BatteryStatsViewer/res/layout/battery_consumer_picker_layout.xml diff --git a/core/tests/powertests/PowerStatsViewer/res/layout/power_stats_viewer_layout.xml b/core/tests/batterystatstests/BatteryStatsViewer/res/layout/battery_stats_viewer_layout.xml index 238e238deeaa..e58a08fd362c 100644 --- a/core/tests/powertests/PowerStatsViewer/res/layout/power_stats_viewer_layout.xml +++ b/core/tests/batterystatstests/BatteryStatsViewer/res/layout/battery_stats_viewer_layout.xml @@ -42,13 +42,13 @@ android:paddingStart="10dp" android:paddingEnd="10dp"> - <include layout="@layout/power_consumer_info_layout"/> + <include layout="@layout/battery_consumer_info_layout"/> </LinearLayout> </androidx.cardview.widget.CardView> <androidx.recyclerview.widget.RecyclerView - android:id="@+id/power_stats_data_view" + android:id="@+id/battery_consumer_data_view" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"/> @@ -59,7 +59,7 @@ android:layout_height="match_parent" android:gravity="center" android:visibility="gone" - android:text="No power stats available"/> + android:text="No battery stats available"/> </LinearLayout> <FrameLayout diff --git a/core/tests/powertests/PowerStatsViewer/res/values/styles.xml b/core/tests/batterystatstests/BatteryStatsViewer/res/values/styles.xml index 629d729e7b9a..629d729e7b9a 100644 --- a/core/tests/powertests/PowerStatsViewer/res/values/styles.xml +++ b/core/tests/batterystatstests/BatteryStatsViewer/res/values/styles.xml diff --git a/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerStatsData.java b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java index 7aeb86ae0cb1..1d9d9e86c218 100644 --- a/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerStatsData.java +++ b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java @@ -14,11 +14,16 @@ * limitations under the License. */ -package com.android.frameworks.core.powerstatsviewer; +package com.android.frameworks.core.batterystatsviewer; import android.content.Context; +import android.os.BatteryConsumer; import android.os.BatteryStats; +import android.os.BatteryUsageStats; import android.os.Process; +import android.os.SystemBatteryConsumer; +import android.os.UidBatteryConsumer; +import android.os.UserHandle; import com.android.internal.os.BatterySipper; import com.android.internal.os.BatteryStatsHelper; @@ -26,7 +31,7 @@ import com.android.internal.os.BatteryStatsHelper; import java.util.ArrayList; import java.util.List; -public class PowerStatsData { +public class BatteryConsumerData { private static final String PACKAGE_CALENDAR_PROVIDER = "com.android.providers.calendar"; private static final String PACKAGE_MEDIA_PROVIDER = "com.android.providers.media"; private static final String PACKAGE_SYSTEMUI = "com.android.systemui"; @@ -54,11 +59,11 @@ public class PowerStatsData { public double total; } - private final PowerConsumerInfoHelper.PowerConsumerInfo mPowerConsumerInfo; + private final BatteryConsumerInfoHelper.BatteryConsumerInfo mBatteryConsumerInfo; private final List<Entry> mEntries = new ArrayList<>(); - public PowerStatsData(Context context, BatteryStatsHelper batteryStatsHelper, - String powerConsumerId) { + public BatteryConsumerData(Context context, BatteryStatsHelper batteryStatsHelper, + BatteryUsageStats batteryUsageStats, String batteryConsumerId) { List<BatterySipper> usageList = batteryStatsHelper.getUsageList(); BatteryStats batteryStats = batteryStatsHelper.getStats(); @@ -92,14 +97,14 @@ public class PowerStatsData { long totalAudioTimeMs = 0; long totalVideoTimeMs = 0; - BatterySipper requestedPowerConsumer = null; + BatterySipper requestedBatterySipper = null; for (BatterySipper sipper : usageList) { if (sipper.drainType == BatterySipper.DrainType.SCREEN) { totalScreenPower = sipper.sumPower(); } - if (powerConsumerId(sipper).equals(powerConsumerId)) { - requestedPowerConsumer = sipper; + if (batteryConsumerId(sipper).equals(batteryConsumerId)) { + requestedBatterySipper = sipper; } totalPowerMah += sipper.sumPower(); @@ -136,81 +141,109 @@ public class PowerStatsData { totalVideoTimeMs += sipper.videoTimeMs; } - long totalScreenMeasuredEnergyUJ = batteryStats.getScreenOnEnergy(); + BatteryConsumer requestedBatteryConsumer = null; + + for (BatteryConsumer consumer : batteryUsageStats.getUidBatteryConsumers()) { + if (batteryConsumerId(consumer).equals(batteryConsumerId)) { + requestedBatteryConsumer = consumer; + break; + } + } - if (requestedPowerConsumer == null) { - mPowerConsumerInfo = null; + if (requestedBatterySipper == null) { + mBatteryConsumerInfo = null; return; } - mPowerConsumerInfo = PowerConsumerInfoHelper.makePowerConsumerInfo( - context.getPackageManager(), requestedPowerConsumer); + if (requestedBatteryConsumer == null) { + for (BatteryConsumer consumer : batteryUsageStats.getSystemBatteryConsumers()) { + if (batteryConsumerId(consumer).equals(batteryConsumerId)) { + requestedBatteryConsumer = consumer; + break; + } + } + } + + mBatteryConsumerInfo = BatteryConsumerInfoHelper.makeBatteryConsumerInfo( + context.getPackageManager(), requestedBatterySipper); + long totalScreenMeasuredEnergyUJ = batteryStats.getScreenOnEnergy(); addEntry("Total power", EntryType.POWER, - requestedPowerConsumer.totalSmearedPowerMah, totalSmearedPowerMah); - maybeAddMeasuredEnergyEntry(requestedPowerConsumer.drainType, batteryStats); + requestedBatterySipper.totalSmearedPowerMah, totalSmearedPowerMah); + maybeAddMeasuredEnergyEntry(requestedBatterySipper.drainType, batteryStats); addEntry("... excluding system", EntryType.POWER, - requestedPowerConsumer.totalSmearedPowerMah, totalPowerExcludeSystemMah); + requestedBatterySipper.totalSmearedPowerMah, totalPowerExcludeSystemMah); addEntry("Screen, smeared", EntryType.POWER, - requestedPowerConsumer.screenPowerMah, totalScreenPower); + requestedBatterySipper.screenPowerMah, totalScreenPower); if (totalScreenMeasuredEnergyUJ != BatteryStats.ENERGY_DATA_UNAVAILABLE) { final double measuredCharge = UJ_2_MAH * totalScreenMeasuredEnergyUJ; final double ratio = measuredCharge / totalScreenPower; addEntry("Screen, smeared (PowerStatsHal adjusted)", EntryType.POWER, - requestedPowerConsumer.screenPowerMah * ratio, measuredCharge); + requestedBatterySipper.screenPowerMah * ratio, measuredCharge); } addEntry("Other, smeared", EntryType.POWER, - requestedPowerConsumer.proportionalSmearMah, totalProportionalSmearMah); + requestedBatterySipper.proportionalSmearMah, totalProportionalSmearMah); addEntry("Excluding smeared", EntryType.POWER, - requestedPowerConsumer.totalPowerMah, totalPowerMah); - addEntry("CPU", EntryType.POWER, - requestedPowerConsumer.cpuPowerMah, totalCpuPowerMah); + requestedBatterySipper.totalPowerMah, totalPowerMah); + if (requestedBatteryConsumer != null) { + addEntry("CPU", EntryType.POWER, + requestedBatteryConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_CPU), + totalCpuPowerMah); + } + addEntry("CPU (sipper)", EntryType.POWER, + requestedBatterySipper.cpuPowerMah, totalCpuPowerMah); addEntry("System services", EntryType.POWER, - requestedPowerConsumer.systemServiceCpuPowerMah, totalSystemServiceCpuPowerMah); - addEntry("Usage", EntryType.POWER, - requestedPowerConsumer.usagePowerMah, totalUsagePowerMah); + requestedBatterySipper.systemServiceCpuPowerMah, totalSystemServiceCpuPowerMah); + if (requestedBatteryConsumer != null) { + addEntry("Usage", EntryType.POWER, + requestedBatteryConsumer.getConsumedPower( + BatteryConsumer.POWER_COMPONENT_USAGE), totalUsagePowerMah); + } else { + addEntry("Usage (sipper)", EntryType.POWER, + requestedBatterySipper.usagePowerMah, totalUsagePowerMah); + } addEntry("Wake lock", EntryType.POWER, - requestedPowerConsumer.wakeLockPowerMah, totalWakeLockPowerMah); + requestedBatterySipper.wakeLockPowerMah, totalWakeLockPowerMah); addEntry("Mobile radio", EntryType.POWER, - requestedPowerConsumer.mobileRadioPowerMah, totalMobileRadioPowerMah); + requestedBatterySipper.mobileRadioPowerMah, totalMobileRadioPowerMah); addEntry("WiFi", EntryType.POWER, - requestedPowerConsumer.wifiPowerMah, totalWifiPowerMah); + requestedBatterySipper.wifiPowerMah, totalWifiPowerMah); addEntry("Bluetooth", EntryType.POWER, - requestedPowerConsumer.bluetoothPowerMah, totalBluetoothPowerMah); + requestedBatterySipper.bluetoothPowerMah, totalBluetoothPowerMah); addEntry("GPS", EntryType.POWER, - requestedPowerConsumer.gpsPowerMah, totalGpsPowerMah); + requestedBatterySipper.gpsPowerMah, totalGpsPowerMah); addEntry("Camera", EntryType.POWER, - requestedPowerConsumer.cameraPowerMah, totalCameraPowerMah); + requestedBatterySipper.cameraPowerMah, totalCameraPowerMah); addEntry("Flashlight", EntryType.POWER, - requestedPowerConsumer.flashlightPowerMah, totalFlashlightPowerMah); + requestedBatterySipper.flashlightPowerMah, totalFlashlightPowerMah); addEntry("Sensors", EntryType.POWER, - requestedPowerConsumer.sensorPowerMah, totalSensorPowerMah); + requestedBatterySipper.sensorPowerMah, totalSensorPowerMah); addEntry("Audio", EntryType.POWER, - requestedPowerConsumer.audioPowerMah, totalAudioPowerMah); + requestedBatterySipper.audioPowerMah, totalAudioPowerMah); addEntry("Video", EntryType.POWER, - requestedPowerConsumer.videoPowerMah, totalVideoPowerMah); + requestedBatterySipper.videoPowerMah, totalVideoPowerMah); addEntry("CPU time", EntryType.DURATION, - requestedPowerConsumer.cpuTimeMs, totalCpuTimeMs); + requestedBatterySipper.cpuTimeMs, totalCpuTimeMs); addEntry("CPU foreground time", EntryType.DURATION, - requestedPowerConsumer.cpuFgTimeMs, totalCpuFgTimeMs); + requestedBatterySipper.cpuFgTimeMs, totalCpuFgTimeMs); addEntry("Wake lock time", EntryType.DURATION, - requestedPowerConsumer.wakeLockTimeMs, totalWakeLockTimeMs); + requestedBatterySipper.wakeLockTimeMs, totalWakeLockTimeMs); addEntry("WiFi running time", EntryType.DURATION, - requestedPowerConsumer.wifiRunningTimeMs, totalWifiRunningTimeMs); + requestedBatterySipper.wifiRunningTimeMs, totalWifiRunningTimeMs); addEntry("Bluetooth time", EntryType.DURATION, - requestedPowerConsumer.bluetoothRunningTimeMs, totalBluetoothRunningTimeMs); + requestedBatterySipper.bluetoothRunningTimeMs, totalBluetoothRunningTimeMs); addEntry("GPS time", EntryType.DURATION, - requestedPowerConsumer.gpsTimeMs, totalGpsTimeMs); + requestedBatterySipper.gpsTimeMs, totalGpsTimeMs); addEntry("Camera time", EntryType.DURATION, - requestedPowerConsumer.cameraTimeMs, totalCameraTimeMs); + requestedBatterySipper.cameraTimeMs, totalCameraTimeMs); addEntry("Flashlight time", EntryType.DURATION, - requestedPowerConsumer.flashlightTimeMs, totalFlashlightTimeMs); + requestedBatterySipper.flashlightTimeMs, totalFlashlightTimeMs); addEntry("Audio time", EntryType.DURATION, - requestedPowerConsumer.audioTimeMs, totalAudioTimeMs); + requestedBatterySipper.audioTimeMs, totalAudioTimeMs); addEntry("Video time", EntryType.DURATION, - requestedPowerConsumer.videoTimeMs, totalVideoTimeMs); + requestedBatterySipper.videoTimeMs, totalVideoTimeMs); } private boolean isSystemSipper(BatterySipper sipper) { @@ -261,15 +294,27 @@ public class PowerStatsData { } } - public PowerConsumerInfoHelper.PowerConsumerInfo getPowerConsumerInfo() { - return mPowerConsumerInfo; + public BatteryConsumerInfoHelper.BatteryConsumerInfo getBatteryConsumerInfo() { + return mBatteryConsumerInfo; } public List<Entry> getEntries() { return mEntries; } - public static String powerConsumerId(BatterySipper sipper) { + public static String batteryConsumerId(BatterySipper sipper) { return sipper.drainType + "|" + sipper.userId + "|" + sipper.getUid(); } + + public static String batteryConsumerId(BatteryConsumer consumer) { + if (consumer instanceof UidBatteryConsumer) { + return BatterySipper.DrainType.APP + "|" + + UserHandle.getUserId(((UidBatteryConsumer) consumer).getUid()) + "|" + + ((UidBatteryConsumer) consumer).getUid(); + } else if (consumer instanceof SystemBatteryConsumer) { + return ((SystemBatteryConsumer) consumer).getDrainType() + "|0|0"; + } else { + return ""; + } + } } diff --git a/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerConsumerInfoHelper.java b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerInfoHelper.java index 6fec2405b0c6..8ee6c604cb3e 100644 --- a/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerConsumerInfoHelper.java +++ b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerInfoHelper.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.frameworks.core.powerstatsviewer; +package com.android.frameworks.core.batterystatsviewer; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; @@ -26,11 +26,11 @@ import com.android.internal.os.BatterySipper; import java.util.Locale; -class PowerConsumerInfoHelper { +class BatteryConsumerInfoHelper { private static final String SYSTEM_SERVER_PACKAGE_NAME = "android"; - public static class PowerConsumerInfo { + public static class BatteryConsumerInfo { public String id; public CharSequence label; public double powerMah; @@ -40,10 +40,10 @@ class PowerConsumerInfoHelper { } @NonNull - public static PowerConsumerInfo makePowerConsumerInfo(PackageManager packageManager, + public static BatteryConsumerInfo makeBatteryConsumerInfo(PackageManager packageManager, @NonNull BatterySipper sipper) { - PowerConsumerInfo info = new PowerConsumerInfo(); - info.id = PowerStatsData.powerConsumerId(sipper); + BatteryConsumerInfo info = new BatteryConsumerInfo(); + info.id = BatteryConsumerData.batteryConsumerId(sipper); sipper.sumPower(); info.powerMah = sipper.totalSmearedPowerMah; switch (sipper.drainType) { diff --git a/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerConsumerPickerActivity.java b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerPickerActivity.java index f56d113980c8..2db848b084a6 100644 --- a/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerConsumerPickerActivity.java +++ b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerPickerActivity.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.frameworks.core.powerstatsviewer; +package com.android.frameworks.core.batterystatsviewer; import android.content.Context; import android.content.Intent; @@ -34,14 +34,14 @@ import com.google.android.material.tabs.TabLayout; * Picker, showing a sorted lists of applications and other types of entities consuming power. * Returns the selected entity ID or null. */ -public class PowerConsumerPickerActivity extends FragmentActivity { +public class BatteryConsumerPickerActivity extends FragmentActivity { public static final ActivityResultContract<Void, String> CONTRACT = new ActivityResultContract<Void, String>() { @NonNull @Override public Intent createIntent(@NonNull Context context, Void aVoid) { - return new Intent(context, PowerConsumerPickerActivity.class); + return new Intent(context, BatteryConsumerPickerActivity.class); } @Override @@ -58,7 +58,7 @@ public class PowerConsumerPickerActivity extends FragmentActivity { super.onCreate(icicle); getActionBar().setDisplayHomeAsUpEnabled(true); - setContentView(R.layout.power_consumer_picker_activity_layout); + setContentView(R.layout.battery_consumer_picker_activity_layout); ViewPager viewPager = findViewById(R.id.pager); @@ -75,12 +75,12 @@ public class PowerConsumerPickerActivity extends FragmentActivity { public Fragment getItem(int position) { switch (position) { case 0: - return new PowerConsumerPickerFragment( - PowerConsumerPickerFragment.PICKER_TYPE_APP); + return new BatteryConsumerPickerFragment( + BatteryConsumerPickerFragment.PICKER_TYPE_APP); case 1: default: - return new PowerConsumerPickerFragment( - PowerConsumerPickerFragment.PICKER_TYPE_DRAIN); + return new BatteryConsumerPickerFragment( + BatteryConsumerPickerFragment.PICKER_TYPE_DRAIN); } } @@ -101,9 +101,9 @@ public class PowerConsumerPickerActivity extends FragmentActivity { tabLayout.setupWithViewPager(viewPager); } - public void setSelectedPowerConsumer(String id) { + public void setSelectedBatteryConsumer(String batteryConsumerId) { Intent intent = new Intent(); - intent.putExtra(Intent.EXTRA_RETURN_RESULT, id); + intent.putExtra(Intent.EXTRA_RETURN_RESULT, batteryConsumerId); setResult(RESULT_OK, intent); finish(); } diff --git a/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerConsumerPickerFragment.java b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerPickerFragment.java index 25225b87f602..bb11fd598511 100644 --- a/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerConsumerPickerFragment.java +++ b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerPickerFragment.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.frameworks.core.powerstatsviewer; +package com.android.frameworks.core.batterystatsviewer; import android.content.Context; import android.content.pm.PackageManager; @@ -36,7 +36,7 @@ import androidx.loader.content.Loader; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; -import com.android.frameworks.core.powerstatsviewer.PowerConsumerInfoHelper.PowerConsumerInfo; +import com.android.frameworks.core.batterystatsviewer.BatteryConsumerInfoHelper.BatteryConsumerInfo; import com.android.internal.os.BatterySipper; import com.android.internal.os.BatteryStatsHelper; import com.android.settingslib.utils.AsyncLoaderCompat; @@ -50,7 +50,7 @@ import java.util.Locale; * Picker, showing a sorted lists of applications or other types of entities consuming power. * Returns the selected entity ID or null. */ -public class PowerConsumerPickerFragment extends Fragment { +public class BatteryConsumerPickerFragment extends Fragment { private static final String TAG = "AppPicker"; public static final String PICKER_TYPE = "pickertype"; @@ -58,53 +58,53 @@ public class PowerConsumerPickerFragment extends Fragment { public static final int PICKER_TYPE_APP = 0; public static final int PICKER_TYPE_DRAIN = 1; - private PowerConsumerListAdapter mPowerConsumerListAdapter; + private BatteryConsumerListAdapter mBatteryConsumerListAdapter; private RecyclerView mAppList; private View mLoadingView; - private interface OnPowerConsumerSelectedListener { - void onPowerConsumerSelected(String uid); + private interface OnBatteryConsumerSelectedListener { + void onBatteryConsumerSelected(String batteryConsumerId); } - public PowerConsumerPickerFragment(int pickerType) { + public BatteryConsumerPickerFragment(int pickerType) { Bundle args = new Bundle(); args.putInt(PICKER_TYPE, pickerType); setArguments(args); } - public PowerConsumerPickerFragment() { + public BatteryConsumerPickerFragment() { } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.power_consumer_picker_layout, container, false); + View view = inflater.inflate(R.layout.battery_consumer_picker_layout, container, false); mLoadingView = view.findViewById(R.id.loading_view); mAppList = view.findViewById(R.id.list_view); mAppList.setLayoutManager(new LinearLayoutManager(getContext())); - mPowerConsumerListAdapter = new PowerConsumerListAdapter( - PowerConsumerPickerFragment.this::setSelectedPowerConsumer); - mAppList.setAdapter(mPowerConsumerListAdapter); + mBatteryConsumerListAdapter = new BatteryConsumerListAdapter( + BatteryConsumerPickerFragment.this::setSelectedBatteryConsumer); + mAppList.setAdapter(mBatteryConsumerListAdapter); LoaderManager.getInstance(this).initLoader(0, getArguments(), - new PowerConsumerListLoaderCallbacks()); + new BatteryConsumerListLoaderCallbacks()); return view; } - public void setSelectedPowerConsumer(String id) { - ((PowerConsumerPickerActivity) getActivity()).setSelectedPowerConsumer(id); + public void setSelectedBatteryConsumer(String id) { + ((BatteryConsumerPickerActivity) getActivity()).setSelectedBatteryConsumer(id); } - private static class PowerConsumerListLoader extends - AsyncLoaderCompat<List<PowerConsumerInfo>> { + private static class BatteryConsumerListLoader extends + AsyncLoaderCompat<List<BatteryConsumerInfo>> { private final BatteryStatsHelper mStatsHelper; private final int mPickerType; private final UserManager mUserManager; private final PackageManager mPackageManager; - PowerConsumerListLoader(Context context, int pickerType) { + BatteryConsumerListLoader(Context context, int pickerType) { super(context); mUserManager = context.getSystemService(UserManager.class); mStatsHelper = new BatteryStatsHelper(context, false /* collectBatteryBroadcast */); @@ -115,8 +115,8 @@ public class PowerConsumerPickerFragment extends Fragment { } @Override - public List<PowerConsumerInfo> loadInBackground() { - List<PowerConsumerInfoHelper.PowerConsumerInfo> powerConsumerList = new ArrayList<>(); + public List<BatteryConsumerInfo> loadInBackground() { + List<BatteryConsumerInfo> batteryConsumerList = new ArrayList<>(); mStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, UserHandle.myUserId()); @@ -135,74 +135,75 @@ public class PowerConsumerPickerFragment extends Fragment { } } - powerConsumerList.add( - PowerConsumerInfoHelper.makePowerConsumerInfo(mPackageManager, sipper)); + batteryConsumerList.add( + BatteryConsumerInfoHelper.makeBatteryConsumerInfo(mPackageManager, sipper)); } - powerConsumerList.sort( - Comparator.comparing((PowerConsumerInfo a) -> a.powerMah).reversed()); - return powerConsumerList; + batteryConsumerList.sort( + Comparator.comparing((BatteryConsumerInfo a) -> a.powerMah).reversed()); + return batteryConsumerList; } @Override - protected void onDiscardResult(List<PowerConsumerInfo> result) { + protected void onDiscardResult(List<BatteryConsumerInfo> result) { } } - private class PowerConsumerListLoaderCallbacks implements - LoaderManager.LoaderCallbacks<List<PowerConsumerInfo>> { + private class BatteryConsumerListLoaderCallbacks implements + LoaderManager.LoaderCallbacks<List<BatteryConsumerInfo>> { @NonNull @Override - public Loader<List<PowerConsumerInfo>> onCreateLoader(int id, Bundle args) { - return new PowerConsumerListLoader(getContext(), args.getInt(PICKER_TYPE)); + public Loader<List<BatteryConsumerInfo>> onCreateLoader(int id, Bundle args) { + return new BatteryConsumerListLoader(getContext(), args.getInt(PICKER_TYPE)); } @Override - public void onLoadFinished(@NonNull Loader<List<PowerConsumerInfo>> loader, - List<PowerConsumerInfoHelper.PowerConsumerInfo> powerConsumerList) { - mPowerConsumerListAdapter.setPowerConsumerList(powerConsumerList); + public void onLoadFinished(@NonNull Loader<List<BatteryConsumerInfo>> loader, + List<BatteryConsumerInfo> batteryConsumerList) { + mBatteryConsumerListAdapter.setBatteryConsumerList(batteryConsumerList); mAppList.setVisibility(View.VISIBLE); mLoadingView.setVisibility(View.GONE); } @Override public void onLoaderReset( - @NonNull Loader<List<PowerConsumerInfoHelper.PowerConsumerInfo>> loader) { + @NonNull Loader<List<BatteryConsumerInfo>> loader) { } } - public class PowerConsumerListAdapter extends RecyclerView.Adapter<PowerConsumerViewHolder> { - private final OnPowerConsumerSelectedListener mListener; - private List<PowerConsumerInfo> mPowerConsumerList; + public class BatteryConsumerListAdapter extends + RecyclerView.Adapter<BatteryConsumerViewHolder> { + private final OnBatteryConsumerSelectedListener mListener; + private List<BatteryConsumerInfo> mBatteryConsumerList; - public PowerConsumerListAdapter(OnPowerConsumerSelectedListener listener) { + public BatteryConsumerListAdapter(OnBatteryConsumerSelectedListener listener) { mListener = listener; } - void setPowerConsumerList(List<PowerConsumerInfo> powerConsumerList) { - mPowerConsumerList = powerConsumerList; + void setBatteryConsumerList(List<BatteryConsumerInfo> batteryConsumerList) { + mBatteryConsumerList = batteryConsumerList; notifyDataSetChanged(); } @Override public int getItemCount() { - return mPowerConsumerList.size(); + return mBatteryConsumerList.size(); } @NonNull @Override - public PowerConsumerViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, + public BatteryConsumerViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int position) { LayoutInflater layoutInflater = LayoutInflater.from(viewGroup.getContext()); - View view = layoutInflater.inflate(R.layout.power_consumer_info_layout, viewGroup, + View view = layoutInflater.inflate(R.layout.battery_consumer_info_layout, viewGroup, false); - return new PowerConsumerViewHolder(view, mListener); + return new BatteryConsumerViewHolder(view, mListener); } @Override - public void onBindViewHolder(@NonNull PowerConsumerViewHolder viewHolder, int position) { - PowerConsumerInfoHelper.PowerConsumerInfo item = mPowerConsumerList.get(position); + public void onBindViewHolder(@NonNull BatteryConsumerViewHolder viewHolder, int position) { + BatteryConsumerInfo item = mBatteryConsumerList.get(position); viewHolder.id = item.id; viewHolder.titleView.setText(item.label); if (item.details != null) { @@ -225,9 +226,9 @@ public class PowerConsumerPickerFragment extends Fragment { } // View Holder used when displaying apps - public static class PowerConsumerViewHolder extends RecyclerView.ViewHolder + public static class BatteryConsumerViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { - private final OnPowerConsumerSelectedListener mListener; + private final OnBatteryConsumerSelectedListener mListener; public String id; public TextView titleView; @@ -236,7 +237,7 @@ public class PowerConsumerPickerFragment extends Fragment { public TextView packagesView; public TextView powerView; - PowerConsumerViewHolder(View view, OnPowerConsumerSelectedListener listener) { + BatteryConsumerViewHolder(View view, OnBatteryConsumerSelectedListener listener) { super(view); mListener = listener; view.setOnClickListener(this); @@ -250,7 +251,7 @@ public class PowerConsumerPickerFragment extends Fragment { @Override public void onClick(View v) { - mListener.onPowerConsumerSelected(id); + mListener.onBatteryConsumerSelected(id); } } } 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 new file mode 100644 index 000000000000..4978010f8591 --- /dev/null +++ b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryStatsViewerActivity.java @@ -0,0 +1,338 @@ +/* + * 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.frameworks.core.batterystatsviewer; + +import android.content.Context; +import android.content.SharedPreferences; +import android.os.BatteryStats; +import android.os.BatteryStatsManager; +import android.os.BatteryUsageStats; +import android.os.Bundle; +import android.os.UserHandle; +import android.os.UserManager; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.activity.ComponentActivity; +import androidx.activity.result.ActivityResultLauncher; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.loader.app.LoaderManager; +import androidx.loader.app.LoaderManager.LoaderCallbacks; +import androidx.loader.content.Loader; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.android.internal.os.BatteryStatsHelper; +import com.android.settingslib.utils.AsyncLoaderCompat; + +import java.util.Collections; +import java.util.List; +import java.util.Locale; + +public class BatteryStatsViewerActivity extends ComponentActivity { + private static final int BATTERY_STATS_REFRESH_RATE_MILLIS = 60 * 1000; + public static final String PREF_SELECTED_BATTERY_CONSUMER = "batteryConsumerId"; + public static final int LOADER_BATTERY_STATS_HELPER = 0; + public static final int LOADER_BATTERY_USAGE_STATS = 1; + + private BatteryStatsDataAdapter mBatteryStatsDataAdapter; + private Runnable mBatteryStatsRefresh = this::periodicBatteryStatsRefresh; + private SharedPreferences mSharedPref; + private String mBatteryConsumerId; + private TextView mTitleView; + private TextView mDetailsView; + private ImageView mIconView; + private TextView mPackagesView; + private RecyclerView mBatteryConsumerDataView; + private View mLoadingView; + private View mEmptyView; + private ActivityResultLauncher<Void> mStartAppPicker = registerForActivityResult( + BatteryConsumerPickerActivity.CONTRACT, this::onApplicationSelected); + private BatteryStatsHelper mBatteryStatsHelper; + private BatteryUsageStats mBatteryUsageStats; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mSharedPref = getPreferences(Context.MODE_PRIVATE); + + setContentView(R.layout.battery_stats_viewer_layout); + + View appCard = findViewById(R.id.app_card); + appCard.setOnClickListener((e) -> startAppPicker()); + + mTitleView = findViewById(android.R.id.title); + mDetailsView = findViewById(R.id.details); + mIconView = findViewById(android.R.id.icon); + mPackagesView = findViewById(R.id.packages); + + mBatteryConsumerDataView = findViewById(R.id.battery_consumer_data_view); + mBatteryConsumerDataView.setLayoutManager(new LinearLayoutManager(this)); + mBatteryStatsDataAdapter = new BatteryStatsDataAdapter(); + mBatteryConsumerDataView.setAdapter(mBatteryStatsDataAdapter); + + mLoadingView = findViewById(R.id.loading_view); + mEmptyView = findViewById(R.id.empty_view); + + mBatteryConsumerId = mSharedPref.getString(PREF_SELECTED_BATTERY_CONSUMER, null); + loadBatteryStats(); + if (mBatteryConsumerId == null) { + startAppPicker(); + } + } + + @Override + protected void onResume() { + super.onResume(); + periodicBatteryStatsRefresh(); + } + + @Override + protected void onPause() { + super.onPause(); + getMainThreadHandler().removeCallbacks(mBatteryStatsRefresh); + } + + private void startAppPicker() { + mStartAppPicker.launch(null); + } + + private void onApplicationSelected(String batteryConsumerId) { + if (batteryConsumerId == null) { + if (mBatteryConsumerId == null) { + finish(); + } + } else { + mBatteryConsumerId = batteryConsumerId; + mSharedPref.edit() + .putString(PREF_SELECTED_BATTERY_CONSUMER, mBatteryConsumerId) + .apply(); + mLoadingView.setVisibility(View.VISIBLE); + loadBatteryStats(); + } + } + + private void periodicBatteryStatsRefresh() { + loadBatteryStats(); + getMainThreadHandler().postDelayed(mBatteryStatsRefresh, BATTERY_STATS_REFRESH_RATE_MILLIS); + } + + private void loadBatteryStats() { + LoaderManager loaderManager = LoaderManager.getInstance(this); + loaderManager.restartLoader(LOADER_BATTERY_STATS_HELPER, null, + new BatteryStatsHelperLoaderCallbacks()); + loaderManager.restartLoader(LOADER_BATTERY_USAGE_STATS, null, + new BatteryUsageStatsLoaderCallbacks()); + } + + private static class BatteryStatsHelperLoader extends AsyncLoaderCompat<BatteryStatsHelper> { + private final BatteryStatsHelper mBatteryStatsHelper; + private final UserManager mUserManager; + + BatteryStatsHelperLoader(Context context) { + super(context); + mUserManager = context.getSystemService(UserManager.class); + mBatteryStatsHelper = new BatteryStatsHelper(context, + false /* collectBatteryBroadcast */); + mBatteryStatsHelper.create((Bundle) null); + mBatteryStatsHelper.clearStats(); + } + + @Override + public BatteryStatsHelper loadInBackground() { + mBatteryStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, + UserHandle.myUserId()); + return mBatteryStatsHelper; + } + + @Override + protected void onDiscardResult(BatteryStatsHelper result) { + } + } + + private class BatteryStatsHelperLoaderCallbacks implements LoaderCallbacks<BatteryStatsHelper> { + @NonNull + @Override + public Loader<BatteryStatsHelper> onCreateLoader(int id, Bundle args) { + return new BatteryStatsHelperLoader(BatteryStatsViewerActivity.this); + } + + @Override + public void onLoadFinished(@NonNull Loader<BatteryStatsHelper> loader, + BatteryStatsHelper batteryStatsHelper) { + onBatteryStatsHelperLoaded(batteryStatsHelper); + } + + @Override + public void onLoaderReset(@NonNull Loader<BatteryStatsHelper> loader) { + } + } + + private static class BatteryUsageStatsLoader extends AsyncLoaderCompat<BatteryUsageStats> { + private final BatteryStatsManager mBatteryStatsManager; + + BatteryUsageStatsLoader(Context context) { + super(context); + mBatteryStatsManager = context.getSystemService(BatteryStatsManager.class); + } + + @Override + public BatteryUsageStats loadInBackground() { + return mBatteryStatsManager.getBatteryUsageStats(); + } + + @Override + protected void onDiscardResult(BatteryUsageStats result) { + } + } + + private class BatteryUsageStatsLoaderCallbacks implements LoaderCallbacks<BatteryUsageStats> { + @NonNull + @Override + public Loader<BatteryUsageStats> onCreateLoader(int id, Bundle args) { + return new BatteryUsageStatsLoader(BatteryStatsViewerActivity.this); + } + + @Override + public void onLoadFinished(@NonNull Loader<BatteryUsageStats> loader, + BatteryUsageStats batteryUsageStats) { + onBatteryUsageStatsLoaded(batteryUsageStats); + } + + @Override + public void onLoaderReset(@NonNull Loader<BatteryUsageStats> loader) { + } + } + + public void onBatteryStatsHelperLoaded(BatteryStatsHelper batteryStatsHelper) { + mBatteryStatsHelper = batteryStatsHelper; + onBatteryStatsDataLoaded(); + } + + private void onBatteryUsageStatsLoaded(BatteryUsageStats batteryUsageStats) { + mBatteryUsageStats = batteryUsageStats; + onBatteryStatsDataLoaded(); + } + + public void onBatteryStatsDataLoaded() { + if (mBatteryStatsHelper == null || mBatteryUsageStats == null) { + return; + } + + BatteryConsumerData batteryConsumerData = new BatteryConsumerData(this, mBatteryStatsHelper, + mBatteryUsageStats, mBatteryConsumerId); + + BatteryConsumerInfoHelper.BatteryConsumerInfo + batteryConsumerInfo = batteryConsumerData.getBatteryConsumerInfo(); + if (batteryConsumerInfo == null) { + mTitleView.setText("Battery consumer not found"); + mPackagesView.setVisibility(View.GONE); + } else { + mTitleView.setText(batteryConsumerInfo.label); + if (batteryConsumerInfo.details != null) { + mDetailsView.setText(batteryConsumerInfo.details); + mDetailsView.setVisibility(View.VISIBLE); + } else { + mDetailsView.setVisibility(View.GONE); + } + mIconView.setImageDrawable( + batteryConsumerInfo.iconInfo.loadIcon(getPackageManager())); + + if (batteryConsumerInfo.packages != null) { + mPackagesView.setText(batteryConsumerInfo.packages); + mPackagesView.setVisibility(View.VISIBLE); + } else { + mPackagesView.setVisibility(View.GONE); + } + } + + mBatteryStatsDataAdapter.setEntries(batteryConsumerData.getEntries()); + if (batteryConsumerData.getEntries().isEmpty()) { + mEmptyView.setVisibility(View.VISIBLE); + mBatteryConsumerDataView.setVisibility(View.GONE); + } else { + mEmptyView.setVisibility(View.GONE); + mBatteryConsumerDataView.setVisibility(View.VISIBLE); + } + + mLoadingView.setVisibility(View.GONE); + } + + private static class BatteryStatsDataAdapter extends + RecyclerView.Adapter<BatteryStatsDataAdapter.ViewHolder> { + public static class ViewHolder extends RecyclerView.ViewHolder { + public TextView titleTextView; + public TextView amountTextView; + public TextView percentTextView; + + ViewHolder(View itemView) { + super(itemView); + + titleTextView = itemView.findViewById(R.id.title); + amountTextView = itemView.findViewById(R.id.amount); + percentTextView = itemView.findViewById(R.id.percent); + } + } + + private List<BatteryConsumerData.Entry> mEntries = Collections.emptyList(); + + public void setEntries(List<BatteryConsumerData.Entry> entries) { + mEntries = entries; + notifyDataSetChanged(); + } + + @Override + public int getItemCount() { + return mEntries.size(); + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int position) { + LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext()); + View itemView = layoutInflater.inflate(R.layout.battery_consumer_entry_layout, parent, + false); + return new ViewHolder(itemView); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder viewHolder, int position) { + BatteryConsumerData.Entry entry = mEntries.get(position); + switch (entry.entryType) { + case POWER: + viewHolder.titleTextView.setText(entry.title); + viewHolder.amountTextView.setText( + String.format(Locale.getDefault(), "%.1f mAh", entry.value)); + break; + case DURATION: + viewHolder.titleTextView.setText(entry.title); + viewHolder.amountTextView.setText( + String.format(Locale.getDefault(), "%,d ms", (long) entry.value)); + break; + } + + double proportion = entry.total != 0 ? entry.value * 100 / entry.total : 0; + viewHolder.percentTextView.setText(String.format(Locale.getDefault(), "%.1f%%", + proportion)); + } + } +} diff --git a/core/tests/powertests/OWNERS b/core/tests/batterystatstests/OWNERS index d68066bb8c40..c22f6a4bbbf6 100644 --- a/core/tests/powertests/OWNERS +++ b/core/tests/batterystatstests/OWNERS @@ -1 +1,2 @@ +include /BATTERY_STATS_OWNERS include /services/core/java/com/android/server/power/OWNERS diff --git a/core/tests/coretests/src/android/app/ApplicationPackageManagerTest.java b/core/tests/coretests/src/android/app/ApplicationPackageManagerTest.java index 95da532045ac..4b0ed65e5fde 100644 --- a/core/tests/coretests/src/android/app/ApplicationPackageManagerTest.java +++ b/core/tests/coretests/src/android/app/ApplicationPackageManagerTest.java @@ -90,7 +90,7 @@ public class ApplicationPackageManagerTest extends TestCase { private boolean mAllow3rdPartyOnInternal = true; public MockedApplicationPackageManager() { - super(null, null, null); + super(null, null); } public void setForceAllowOnExternal(boolean forceAllowOnExternal) { diff --git a/core/tests/coretests/src/android/app/OWNERS b/core/tests/coretests/src/android/app/OWNERS new file mode 100644 index 000000000000..bd7da0c3f209 --- /dev/null +++ b/core/tests/coretests/src/android/app/OWNERS @@ -0,0 +1 @@ +per-file Window*.java = file:/services/core/java/com/android/server/wm/OWNERS diff --git a/core/tests/coretests/src/android/app/activity/OWNERS b/core/tests/coretests/src/android/app/activity/OWNERS new file mode 100644 index 000000000000..0862c05e0ee4 --- /dev/null +++ b/core/tests/coretests/src/android/app/activity/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/wm/OWNERS diff --git a/core/tests/coretests/src/android/app/appsearch/OWNERS b/core/tests/coretests/src/android/app/appsearch/OWNERS new file mode 100644 index 000000000000..24f6b0b6b2b6 --- /dev/null +++ b/core/tests/coretests/src/android/app/appsearch/OWNERS @@ -0,0 +1 @@ +include /apex/appsearch/OWNERS
\ No newline at end of file diff --git a/core/tests/coretests/src/android/app/servertransaction/OWNERS b/core/tests/coretests/src/android/app/servertransaction/OWNERS new file mode 100644 index 000000000000..0862c05e0ee4 --- /dev/null +++ b/core/tests/coretests/src/android/app/servertransaction/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/wm/OWNERS diff --git a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java index 4654f63a2a91..b2b34d64b12c 100644 --- a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java +++ b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java @@ -26,6 +26,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertSame; +import android.app.servertransaction.TestUtils.LaunchActivityItemBuilder; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; @@ -43,6 +44,8 @@ import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.function.Supplier; + /** * Tests for {@link ObjectPool}. * @@ -144,24 +147,22 @@ public class ObjectPoolTests { persistableBundle.putInt("k", 4); IBinder assistToken = new Binder(); - LaunchActivityItem emptyItem = LaunchActivityItem.obtain(null, 0, null, null, null, null, - null, null, 0, null, null, null, null, false, null, null, null); - LaunchActivityItem item = LaunchActivityItem.obtain(intent, ident, activityInfo, - config(), overrideConfig, compat, referrer, null /* voiceInteractor */, - procState, bundle, persistableBundle, resultInfoList(), referrerIntentList(), - true /* isForward */, null /* profilerInfo */, assistToken, - null /* fixedRotationAdjustments */); + Supplier<LaunchActivityItem> itemSupplier = () -> new LaunchActivityItemBuilder() + .setIntent(intent).setIdent(ident).setInfo(activityInfo).setCurConfig(config()) + .setOverrideConfig(overrideConfig).setCompatInfo(compat).setReferrer(referrer) + .setProcState(procState).setState(bundle).setPersistentState(persistableBundle) + .setPendingResults(resultInfoList()).setPendingNewIntents(referrerIntentList()) + .setIsForward(true).setAssistToken(assistToken).build(); + + LaunchActivityItem emptyItem = new LaunchActivityItemBuilder().build(); + LaunchActivityItem item = itemSupplier.get(); assertNotSame(item, emptyItem); assertFalse(item.equals(emptyItem)); item.recycle(); assertEquals(item, emptyItem); - LaunchActivityItem item2 = LaunchActivityItem.obtain(intent, ident, activityInfo, - config(), overrideConfig, compat, referrer, null /* voiceInteractor */, - procState, bundle, persistableBundle, resultInfoList(), referrerIntentList(), - true /* isForward */, null /* profilerInfo */, assistToken, - null /* fixedRotationAdjustments */); + LaunchActivityItem item2 = itemSupplier.get(); assertSame(item, item2); assertFalse(item2.equals(emptyItem)); } diff --git a/core/tests/coretests/src/android/app/servertransaction/TestUtils.java b/core/tests/coretests/src/android/app/servertransaction/TestUtils.java index d125fe790eba..7e9933c8d9df 100644 --- a/core/tests/coretests/src/android/app/servertransaction/TestUtils.java +++ b/core/tests/coretests/src/android/app/servertransaction/TestUtils.java @@ -18,11 +18,19 @@ package android.app.servertransaction; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; +import android.app.ProfilerInfo; import android.app.ResultInfo; import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.res.CompatibilityInfo; import android.content.res.Configuration; +import android.os.Bundle; +import android.os.IBinder; +import android.os.PersistableBundle; import android.util.MergedConfiguration; +import android.view.DisplayAdjustments.FixedRotationAdjustments; +import com.android.internal.app.IVoiceInteractor; import com.android.internal.content.ReferrerIntent; import java.util.ArrayList; @@ -81,4 +89,117 @@ class TestUtils { return referrerIntents; } + + static class LaunchActivityItemBuilder { + private Intent mIntent; + private int mIdent; + private ActivityInfo mInfo; + private Configuration mCurConfig; + private Configuration mOverrideConfig; + private CompatibilityInfo mCompatInfo; + private String mReferrer; + private IVoiceInteractor mVoiceInteractor; + private int mProcState; + private Bundle mState; + private PersistableBundle mPersistentState; + private List<ResultInfo> mPendingResults; + private List<ReferrerIntent> mPendingNewIntents; + private boolean mIsForward; + private ProfilerInfo mProfilerInfo; + private IBinder mAssistToken; + private FixedRotationAdjustments mFixedRotationAdjustments; + + LaunchActivityItemBuilder setIntent(Intent intent) { + mIntent = intent; + return this; + } + + LaunchActivityItemBuilder setIdent(int ident) { + mIdent = ident; + return this; + } + + LaunchActivityItemBuilder setInfo(ActivityInfo info) { + mInfo = info; + return this; + } + + LaunchActivityItemBuilder setCurConfig(Configuration curConfig) { + mCurConfig = curConfig; + return this; + } + + LaunchActivityItemBuilder setOverrideConfig(Configuration overrideConfig) { + mOverrideConfig = overrideConfig; + return this; + } + + LaunchActivityItemBuilder setCompatInfo(CompatibilityInfo compatInfo) { + mCompatInfo = compatInfo; + return this; + } + + LaunchActivityItemBuilder setReferrer(String referrer) { + mReferrer = referrer; + return this; + } + + LaunchActivityItemBuilder setVoiceInteractor(IVoiceInteractor voiceInteractor) { + mVoiceInteractor = voiceInteractor; + return this; + } + + LaunchActivityItemBuilder setProcState(int procState) { + mProcState = procState; + return this; + } + + LaunchActivityItemBuilder setState(Bundle state) { + mState = state; + return this; + } + + LaunchActivityItemBuilder setPersistentState(PersistableBundle persistentState) { + mPersistentState = persistentState; + return this; + } + + LaunchActivityItemBuilder setPendingResults(List<ResultInfo> pendingResults) { + mPendingResults = pendingResults; + return this; + } + + LaunchActivityItemBuilder setPendingNewIntents(List<ReferrerIntent> pendingNewIntents) { + mPendingNewIntents = pendingNewIntents; + return this; + } + + LaunchActivityItemBuilder setIsForward(boolean isForward) { + mIsForward = isForward; + return this; + } + + LaunchActivityItemBuilder setProfilerInfo(ProfilerInfo profilerInfo) { + mProfilerInfo = profilerInfo; + return this; + } + + LaunchActivityItemBuilder setAssistToken(IBinder assistToken) { + mAssistToken = assistToken; + return this; + } + + LaunchActivityItemBuilder setFixedRotationAdjustments(FixedRotationAdjustments fra) { + mFixedRotationAdjustments = fra; + return this; + } + + LaunchActivityItem build() { + return LaunchActivityItem.obtain(mIntent, mIdent, mInfo, + mCurConfig, mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, + mProcState, mState, mPersistentState, mPendingResults, mPendingNewIntents, + mIsForward, mProfilerInfo, mAssistToken, null /* activityClientController */, + mFixedRotationAdjustments); + } + } } diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java index 0ae789af477c..32f892924ac5 100644 --- a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java +++ b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java @@ -41,6 +41,7 @@ import android.app.Activity; import android.app.ActivityThread.ActivityClientRecord; import android.app.ClientTransactionHandler; import android.app.servertransaction.ActivityLifecycleItem.LifecycleState; +import android.app.servertransaction.TestUtils.LaunchActivityItemBuilder; import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; @@ -263,13 +264,7 @@ public class TransactionExecutorTests { // A previous queued launch transaction runs on main thread (execute). final ClientTransaction launchTransaction = ClientTransaction.obtain(null /* client */, token /* activityToken */); - final LaunchActivityItem launchItem = spy(LaunchActivityItem.obtain( - null /* intent */, 0 /* ident */, null /* info */, null /* curConfig */, - null, /* overrideConfig */ null /* compatInfo */, null /* referrer */ , - null /* voiceInteractor */, 0 /* procState */, null /* state */, - null /* persistentState */, null /* pendingResults */, - null /* pendingNewIntents */, false /* isForward */, null /* profilerInfo */, - null /* assistToken */, null /* fixedRotationAdjustments */)); + final LaunchActivityItem launchItem = spy(new LaunchActivityItemBuilder().build()); launchTransaction.addCallback(launchItem); mExecutor.execute(launchTransaction); diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java index 7e992989426d..e1c7146908d6 100644 --- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java +++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java @@ -29,6 +29,7 @@ import android.app.IApplicationThread; import android.app.IInstrumentationWatcher; import android.app.IUiAutomationConnection; import android.app.ProfilerInfo; +import android.app.servertransaction.TestUtils.LaunchActivityItemBuilder; import android.content.AutofillOptions; import android.content.ComponentName; import android.content.ContentCaptureOptions; @@ -195,11 +196,14 @@ public class TransactionParcelTests { FixedRotationAdjustments fixedRotationAdjustments = new FixedRotationAdjustments( Surface.ROTATION_90, 1920, 1080, DisplayCutout.NO_CUTOUT); - LaunchActivityItem item = LaunchActivityItem.obtain(intent, ident, activityInfo, - config(), overrideConfig, compat, referrer, null /* voiceInteractor */, - procState, bundle, persistableBundle, resultInfoList(), referrerIntentList(), - true /* isForward */, null /* profilerInfo */, new Binder(), - fixedRotationAdjustments); + LaunchActivityItem item = new LaunchActivityItemBuilder() + .setIntent(intent).setIdent(ident).setInfo(activityInfo).setCurConfig(config()) + .setOverrideConfig(overrideConfig).setCompatInfo(compat).setReferrer(referrer) + .setProcState(procState).setState(bundle).setPersistentState(persistableBundle) + .setPendingResults(resultInfoList()).setPendingNewIntents(referrerIntentList()) + .setIsForward(true).setAssistToken(new Binder()) + .setFixedRotationAdjustments(fixedRotationAdjustments).build(); + writeAndPrepareForReading(item); // Read from parcel and assert diff --git a/core/tests/coretests/src/android/app/time/OWNERS b/core/tests/coretests/src/android/app/time/OWNERS new file mode 100644 index 000000000000..8f8089717e3b --- /dev/null +++ b/core/tests/coretests/src/android/app/time/OWNERS @@ -0,0 +1,3 @@ +# Bug component: 847766 +mingaleev@google.com +include /core/java/android/app/timedetector/OWNERS diff --git a/core/tests/coretests/src/android/app/timedetector/GnssTimeSuggestionTest.java b/core/tests/coretests/src/android/app/timedetector/GnssTimeSuggestionTest.java new file mode 100644 index 000000000000..e248010319e1 --- /dev/null +++ b/core/tests/coretests/src/android/app/timedetector/GnssTimeSuggestionTest.java @@ -0,0 +1,66 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app.timedetector; + +import static android.app.timezonedetector.ParcelableTestSupport.assertRoundTripParcelable; +import static android.app.timezonedetector.ParcelableTestSupport.roundTripParcelable; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +import android.os.TimestampedValue; + +import org.junit.Test; + +public class GnssTimeSuggestionTest { + + private static final TimestampedValue<Long> ARBITRARY_TIME = + new TimestampedValue<>(1111L, 2222L); + + @Test + public void testEquals() { + GnssTimeSuggestion one = new GnssTimeSuggestion(ARBITRARY_TIME); + assertEquals(one, one); + + GnssTimeSuggestion two = new GnssTimeSuggestion(ARBITRARY_TIME); + assertEquals(one, two); + assertEquals(two, one); + + TimestampedValue<Long> differentTime = new TimestampedValue<>( + ARBITRARY_TIME.getReferenceTimeMillis() + 1, + ARBITRARY_TIME.getValue()); + GnssTimeSuggestion three = new GnssTimeSuggestion(differentTime); + assertNotEquals(one, three); + assertNotEquals(three, one); + + // DebugInfo must not be considered in equals(). + one.addDebugInfo("Debug info 1"); + two.addDebugInfo("Debug info 2"); + assertEquals(one, two); + } + + @Test + public void testParcelable() { + GnssTimeSuggestion suggestion = new GnssTimeSuggestion(ARBITRARY_TIME); + assertRoundTripParcelable(suggestion); + + // DebugInfo should also be stored (but is not checked by equals() + suggestion.addDebugInfo("This is debug info"); + GnssTimeSuggestion rtSuggestion = roundTripParcelable(suggestion); + assertEquals(suggestion.getDebugInfo(), rtSuggestion.getDebugInfo()); + } +} diff --git a/core/tests/coretests/src/android/app/timedetector/OWNERS b/core/tests/coretests/src/android/app/timedetector/OWNERS new file mode 100644 index 000000000000..8f8089717e3b --- /dev/null +++ b/core/tests/coretests/src/android/app/timedetector/OWNERS @@ -0,0 +1,3 @@ +# Bug component: 847766 +mingaleev@google.com +include /core/java/android/app/timedetector/OWNERS diff --git a/core/tests/coretests/src/android/app/timezone/OWNERS b/core/tests/coretests/src/android/app/timezone/OWNERS new file mode 100644 index 000000000000..8f8089717e3b --- /dev/null +++ b/core/tests/coretests/src/android/app/timezone/OWNERS @@ -0,0 +1,3 @@ +# Bug component: 847766 +mingaleev@google.com +include /core/java/android/app/timedetector/OWNERS diff --git a/core/tests/coretests/src/android/app/timezonedetector/OWNERS b/core/tests/coretests/src/android/app/timezonedetector/OWNERS new file mode 100644 index 000000000000..8f8089717e3b --- /dev/null +++ b/core/tests/coretests/src/android/app/timezonedetector/OWNERS @@ -0,0 +1,3 @@ +# Bug component: 847766 +mingaleev@google.com +include /core/java/android/app/timedetector/OWNERS diff --git a/core/tests/coretests/src/android/content/OWNERS b/core/tests/coretests/src/android/content/OWNERS new file mode 100644 index 000000000000..911efb2562e7 --- /dev/null +++ b/core/tests/coretests/src/android/content/OWNERS @@ -0,0 +1 @@ +per-file ContextTest.java = file:/services/core/java/com/android/server/wm/OWNERS diff --git a/core/tests/coretests/src/android/os/VibratorInfoTest.java b/core/tests/coretests/src/android/os/VibratorInfoTest.java new file mode 100644 index 000000000000..89411902bb6b --- /dev/null +++ b/core/tests/coretests/src/android/os/VibratorInfoTest.java @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.os; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; + +import android.platform.test.annotations.Presubmit; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@Presubmit +@RunWith(JUnit4.class) +public class VibratorInfoTest { + + @Test + public void testHasAmplitudeControl() { + assertFalse(createInfo(/* capabilities= */ 0).hasAmplitudeControl()); + assertTrue(createInfo(VibratorInfo.CAPABILITY_COMPOSE_EFFECTS + | VibratorInfo.CAPABILITY_AMPLITUDE_CONTROL).hasAmplitudeControl()); + } + + @Test + public void testHasCapabilities() { + assertTrue(createInfo(VibratorInfo.CAPABILITY_COMPOSE_EFFECTS) + .hasCapability(VibratorInfo.CAPABILITY_COMPOSE_EFFECTS)); + assertFalse(createInfo(VibratorInfo.CAPABILITY_COMPOSE_EFFECTS) + .hasCapability(VibratorInfo.CAPABILITY_AMPLITUDE_CONTROL)); + } + + @Test + public void testIsEffectSupported() { + VibratorInfo info = new VibratorInfo(/* id= */ 0, /* capabilities= */0, + new int[]{VibrationEffect.EFFECT_CLICK}, null); + assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN, + createInfo(/* capabilities= */ 0).isEffectSupported(VibrationEffect.EFFECT_CLICK)); + assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_YES, + info.isEffectSupported(VibrationEffect.EFFECT_CLICK)); + assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_NO, + info.isEffectSupported(VibrationEffect.EFFECT_TICK)); + } + + @Test + public void testIsPrimitiveSupported() { + VibratorInfo info = new VibratorInfo(/* id= */ 0, VibratorInfo.CAPABILITY_COMPOSE_EFFECTS, + null, new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK}); + assertTrue(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_CLICK)); + assertFalse(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_TICK)); + + // Returns false when there is no compose capability. + info = new VibratorInfo(/* id= */ 0, /* capabilities= */ 0, + null, new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK}); + assertFalse(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_CLICK)); + } + + @Test + public void testEquals() { + VibratorInfo empty = new VibratorInfo(1, 0, null, null); + VibratorInfo complete = new VibratorInfo(1, VibratorInfo.CAPABILITY_AMPLITUDE_CONTROL, + new int[]{VibrationEffect.EFFECT_CLICK}, + new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK}); + + assertEquals(complete, complete); + assertEquals(complete, new VibratorInfo(1, VibratorInfo.CAPABILITY_AMPLITUDE_CONTROL, + new int[]{VibrationEffect.EFFECT_CLICK}, + new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK})); + + assertFalse(empty.equals(new VibratorInfo(1, 0, new int[]{}, new int[]{}))); + assertFalse(complete.equals(new VibratorInfo(1, VibratorInfo.CAPABILITY_COMPOSE_EFFECTS, + new int[]{VibrationEffect.EFFECT_CLICK}, + new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK}))); + assertFalse(complete.equals(new VibratorInfo(1, VibratorInfo.CAPABILITY_AMPLITUDE_CONTROL, + new int[]{}, new int[]{}))); + assertFalse(complete.equals(new VibratorInfo(1, VibratorInfo.CAPABILITY_AMPLITUDE_CONTROL, + null, new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK}))); + assertFalse(complete.equals(new VibratorInfo(1, VibratorInfo.CAPABILITY_AMPLITUDE_CONTROL, + new int[]{VibrationEffect.EFFECT_CLICK}, null))); + } + + @Test + public void testSerialization() { + VibratorInfo original = new VibratorInfo(1, VibratorInfo.CAPABILITY_COMPOSE_EFFECTS, + new int[]{VibrationEffect.EFFECT_CLICK}, null); + + Parcel parcel = Parcel.obtain(); + original.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + VibratorInfo restored = VibratorInfo.CREATOR.createFromParcel(parcel); + assertEquals(original, restored); + } + + private static VibratorInfo createInfo(long capabilities) { + return new VibratorInfo(/* id= */ 0, capabilities, null, null); + } +} diff --git a/core/tests/coretests/src/android/os/VibratorTest.java b/core/tests/coretests/src/android/os/VibratorTest.java index c3d84ecc2abf..575a1be905f2 100644 --- a/core/tests/coretests/src/android/os/VibratorTest.java +++ b/core/tests/coretests/src/android/os/VibratorTest.java @@ -55,6 +55,26 @@ public class VibratorTest { } @Test + public void areEffectsSupported_returnsArrayOfSameSize() { + assertEquals(0, mVibratorSpy.areEffectsSupported(new int[0]).length); + assertEquals(1, + mVibratorSpy.areEffectsSupported(new int[]{VibrationEffect.EFFECT_CLICK}).length); + assertEquals(2, + mVibratorSpy.areEffectsSupported(new int[]{VibrationEffect.EFFECT_CLICK, + VibrationEffect.EFFECT_TICK}).length); + } + + @Test + public void arePrimitivesSupported_returnsArrayOfSameSize() { + assertEquals(0, mVibratorSpy.arePrimitivesSupported(new int[0]).length); + assertEquals(1, mVibratorSpy.arePrimitivesSupported( + new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK}).length); + assertEquals(2, mVibratorSpy.arePrimitivesSupported( + new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK, + VibrationEffect.Composition.PRIMITIVE_QUICK_RISE}).length); + } + + @Test public void vibrate_withAudioAttributes_createsVibrationAttributesWithSameUsage() { VibrationEffect effect = VibrationEffect.get(VibrationEffect.EFFECT_CLICK); AudioAttributes audioAttributes = new AudioAttributes.Builder().setUsage( diff --git a/core/tests/coretests/src/com/android/internal/jank/OWNERS b/core/tests/coretests/src/com/android/internal/jank/OWNERS new file mode 100644 index 000000000000..faece0818a09 --- /dev/null +++ b/core/tests/coretests/src/com/android/internal/jank/OWNERS @@ -0,0 +1 @@ +include /core/java/com/android/internal/jank/OWNERS
\ No newline at end of file diff --git a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiDeviceInfoTest.java b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiDeviceInfoTest.java index 4c0de629c464..4ce072ccc894 100755 --- a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiDeviceInfoTest.java +++ b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiDeviceInfoTest.java @@ -37,6 +37,7 @@ public class HdmiDeviceInfoTest { int deviceType = 0; int vendorId = 0x123456; String displayName = "test device"; + int cecVersion = HdmiControlManager.HDMI_CEC_VERSION_2_0; int powerStatus = HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY; int deviceId = 3; int adopterId = 2; @@ -70,6 +71,16 @@ public class HdmiDeviceInfoTest { vendorId, displayName, powerStatus)) + .addEqualityGroup( + new HdmiDeviceInfo( + logicalAddr, + phyAddr, + portId, + deviceType, + vendorId, + displayName, + powerStatus, + cecVersion)) .testEquals(); } } diff --git a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiPortInfoTest.java b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiPortInfoTest.java new file mode 100755 index 000000000000..d8dc1eabe045 --- /dev/null +++ b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiPortInfoTest.java @@ -0,0 +1,62 @@ +/* + * 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.hdmi; + +import androidx.test.filters.SmallTest; + +import com.google.common.testing.EqualsTester; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Tests for {@link HdmiPortInfo} */ +@RunWith(JUnit4.class) +@SmallTest +public class HdmiPortInfoTest { + + @Test + public void testEquals() { + int portId = 1; + int portType = 0; + int address = 0x123456; + boolean isCec = true; + boolean isMhl = false; + boolean isArcSupported = false; + + new EqualsTester() + .addEqualityGroup( + new HdmiPortInfo(portId, portType, address, isCec, isMhl, isArcSupported), + new HdmiPortInfo(portId, portType, address, isCec, isMhl, isArcSupported)) + .addEqualityGroup( + new HdmiPortInfo( + portId + 1, portType, address, isCec, isMhl, isArcSupported)) + .addEqualityGroup( + new HdmiPortInfo( + portId, portType + 1, address, isCec, isMhl, isArcSupported)) + .addEqualityGroup( + new HdmiPortInfo( + portId, portType, address + 1, isCec, isMhl, isArcSupported)) + .addEqualityGroup( + new HdmiPortInfo(portId, portType, address, !isCec, isMhl, isArcSupported)) + .addEqualityGroup( + new HdmiPortInfo(portId, portType, address, isCec, !isMhl, isArcSupported)) + .addEqualityGroup( + new HdmiPortInfo(portId, portType, address, isCec, isMhl, !isArcSupported)) + .testEquals(); + } +} diff --git a/core/tests/mockingcoretests/src/android/app/activity/OWNERS b/core/tests/mockingcoretests/src/android/app/activity/OWNERS new file mode 100644 index 000000000000..0862c05e0ee4 --- /dev/null +++ b/core/tests/mockingcoretests/src/android/app/activity/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/wm/OWNERS diff --git a/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerStatsViewerActivity.java b/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerStatsViewerActivity.java deleted file mode 100644 index 05679101f86a..000000000000 --- a/core/tests/powertests/PowerStatsViewer/src/com/android/frameworks/core/powerstatsviewer/PowerStatsViewerActivity.java +++ /dev/null @@ -1,276 +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.frameworks.core.powerstatsviewer; - -import android.content.Context; -import android.content.SharedPreferences; -import android.os.BatteryStats; -import android.os.Bundle; -import android.os.UserHandle; -import android.os.UserManager; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.TextView; - -import androidx.activity.ComponentActivity; -import androidx.activity.result.ActivityResultLauncher; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.loader.app.LoaderManager; -import androidx.loader.app.LoaderManager.LoaderCallbacks; -import androidx.loader.content.Loader; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - -import com.android.internal.os.BatteryStatsHelper; -import com.android.settingslib.utils.AsyncLoaderCompat; - -import java.util.Collections; -import java.util.List; -import java.util.Locale; - -public class PowerStatsViewerActivity extends ComponentActivity { - private static final int POWER_STATS_REFRESH_RATE_MILLIS = 60 * 1000; - public static final String PREF_SELECTED_POWER_CONSUMER = "powerConsumerId"; - private static final String LOADER_ARG_POWER_CONSUMER_ID = "powerConsumerId"; - - private PowerStatsDataAdapter mPowerStatsDataAdapter; - private Runnable mPowerStatsRefresh = this::periodicPowerStatsRefresh; - private SharedPreferences mSharedPref; - private String mPowerConsumerId; - private TextView mTitleView; - private TextView mDetailsView; - private ImageView mIconView; - private TextView mPackagesView; - private RecyclerView mPowerStatsDataView; - private View mLoadingView; - private View mEmptyView; - private ActivityResultLauncher<Void> mStartAppPicker = registerForActivityResult( - PowerConsumerPickerActivity.CONTRACT, this::onApplicationSelected); - - @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - mSharedPref = getPreferences(Context.MODE_PRIVATE); - - setContentView(R.layout.power_stats_viewer_layout); - - View appCard = findViewById(R.id.app_card); - appCard.setOnClickListener((e) -> startAppPicker()); - - mTitleView = findViewById(android.R.id.title); - mDetailsView = findViewById(R.id.details); - mIconView = findViewById(android.R.id.icon); - mPackagesView = findViewById(R.id.packages); - - mPowerStatsDataView = findViewById(R.id.power_stats_data_view); - mPowerStatsDataView.setLayoutManager(new LinearLayoutManager(this)); - mPowerStatsDataAdapter = new PowerStatsDataAdapter(); - mPowerStatsDataView.setAdapter(mPowerStatsDataAdapter); - - mLoadingView = findViewById(R.id.loading_view); - mEmptyView = findViewById(R.id.empty_view); - - mPowerConsumerId = mSharedPref.getString(PREF_SELECTED_POWER_CONSUMER, null); - loadPowerStats(); - if (mPowerConsumerId == null) { - startAppPicker(); - } - } - - @Override - protected void onResume() { - super.onResume(); - periodicPowerStatsRefresh(); - } - - @Override - protected void onPause() { - super.onPause(); - getMainThreadHandler().removeCallbacks(mPowerStatsRefresh); - } - - private void startAppPicker() { - mStartAppPicker.launch(null); - } - - private void onApplicationSelected(String powerConsumerId) { - if (powerConsumerId == null) { - if (mPowerConsumerId == null) { - finish(); - } - } else { - mPowerConsumerId = powerConsumerId; - mSharedPref.edit().putString(PREF_SELECTED_POWER_CONSUMER, mPowerConsumerId).apply(); - mLoadingView.setVisibility(View.VISIBLE); - loadPowerStats(); - } - } - - private void periodicPowerStatsRefresh() { - loadPowerStats(); - getMainThreadHandler().postDelayed(mPowerStatsRefresh, POWER_STATS_REFRESH_RATE_MILLIS); - } - - private void loadPowerStats() { - Bundle args = new Bundle(); - args.putString(LOADER_ARG_POWER_CONSUMER_ID, mPowerConsumerId); - LoaderManager.getInstance(this).restartLoader(0, args, new PowerStatsDataLoaderCallbacks()); - } - - private static class PowerStatsDataLoader extends AsyncLoaderCompat<PowerStatsData> { - private final String mPowerConsumerId; - private final BatteryStatsHelper mBatteryStatsHelper; - private final UserManager mUserManager; - - PowerStatsDataLoader(Context context, String powerConsumerId) { - super(context); - mPowerConsumerId = powerConsumerId; - mUserManager = context.getSystemService(UserManager.class); - mBatteryStatsHelper = new BatteryStatsHelper(context, - false /* collectBatteryBroadcast */); - mBatteryStatsHelper.create((Bundle) null); - mBatteryStatsHelper.clearStats(); - } - - @Override - public PowerStatsData loadInBackground() { - mBatteryStatsHelper.refreshStats(BatteryStats.STATS_SINCE_CHARGED, - UserHandle.myUserId()); - return new PowerStatsData(getContext(), mBatteryStatsHelper, mPowerConsumerId); - } - - @Override - protected void onDiscardResult(PowerStatsData result) { - } - } - - private class PowerStatsDataLoaderCallbacks implements LoaderCallbacks<PowerStatsData> { - @NonNull - @Override - public Loader<PowerStatsData> onCreateLoader(int id, Bundle args) { - return new PowerStatsDataLoader(PowerStatsViewerActivity.this, - args.getString(LOADER_ARG_POWER_CONSUMER_ID)); - } - - @Override - public void onLoadFinished(@NonNull Loader<PowerStatsData> loader, - PowerStatsData powerStatsData) { - - PowerConsumerInfoHelper.PowerConsumerInfo - powerConsumerInfo = powerStatsData.getPowerConsumerInfo(); - if (powerConsumerInfo == null) { - mTitleView.setText("Power consumer not found"); - mPackagesView.setVisibility(View.GONE); - } else { - mTitleView.setText(powerConsumerInfo.label); - if (powerConsumerInfo.details != null) { - mDetailsView.setText(powerConsumerInfo.details); - mDetailsView.setVisibility(View.VISIBLE); - } else { - mDetailsView.setVisibility(View.GONE); - } - mIconView.setImageDrawable( - powerConsumerInfo.iconInfo.loadIcon(getPackageManager())); - - if (powerConsumerInfo.packages != null) { - mPackagesView.setText(powerConsumerInfo.packages); - mPackagesView.setVisibility(View.VISIBLE); - } else { - mPackagesView.setVisibility(View.GONE); - } - } - - mPowerStatsDataAdapter.setEntries(powerStatsData.getEntries()); - if (powerStatsData.getEntries().isEmpty()) { - mEmptyView.setVisibility(View.VISIBLE); - mPowerStatsDataView.setVisibility(View.GONE); - } else { - mEmptyView.setVisibility(View.GONE); - mPowerStatsDataView.setVisibility(View.VISIBLE); - } - - mLoadingView.setVisibility(View.GONE); - } - - @Override - public void onLoaderReset(@NonNull Loader<PowerStatsData> loader) { - } - } - - private static class PowerStatsDataAdapter extends - RecyclerView.Adapter<PowerStatsDataAdapter.ViewHolder> { - public static class ViewHolder extends RecyclerView.ViewHolder { - public TextView titleTextView; - public TextView amountTextView; - public TextView percentTextView; - - ViewHolder(View itemView) { - super(itemView); - - titleTextView = itemView.findViewById(R.id.title); - amountTextView = itemView.findViewById(R.id.amount); - percentTextView = itemView.findViewById(R.id.percent); - } - } - - private List<PowerStatsData.Entry> mEntries = Collections.emptyList(); - - public void setEntries(List<PowerStatsData.Entry> entries) { - mEntries = entries; - notifyDataSetChanged(); - } - - @Override - public int getItemCount() { - return mEntries.size(); - } - - @NonNull - @Override - public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int position) { - LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext()); - View itemView = layoutInflater.inflate(R.layout.power_stats_entry_layout, parent, - false); - return new ViewHolder(itemView); - } - - @Override - public void onBindViewHolder(@NonNull ViewHolder viewHolder, int position) { - PowerStatsData.Entry entry = mEntries.get(position); - switch (entry.entryType) { - case POWER: - viewHolder.titleTextView.setText(entry.title); - viewHolder.amountTextView.setText( - String.format(Locale.getDefault(), "%.1f mAh", entry.value)); - break; - case DURATION: - viewHolder.titleTextView.setText(entry.title); - viewHolder.amountTextView.setText( - String.format(Locale.getDefault(), "%,d ms", (long) entry.value)); - break; - } - - double proportion = entry.total != 0 ? entry.value * 100 / entry.total : 0; - viewHolder.percentTextView.setText(String.format(Locale.getDefault(), "%.1f%%", - proportion)); - } - } -} diff --git a/data/etc/car/Android.bp b/data/etc/car/Android.bp index 3e3aefc6f51d..7f20b3bf2c40 100644 --- a/data/etc/car/Android.bp +++ b/data/etc/car/Android.bp @@ -159,6 +159,13 @@ prebuilt_etc { } prebuilt_etc { + name: "privapp_allowlist_com.google.android.car.networking.preferenceupdater", + sub_dir: "permissions", + src: "com.google.android.car.networking.preferenceupdater.xml", + filename_from_src: true, +} + +prebuilt_etc { name: "allowed_privapp_com.android.carshell", sub_dir: "permissions", src: "com.android.car.shell.xml", diff --git a/data/etc/car/com.android.car.provision.xml b/data/etc/car/com.android.car.provision.xml index 474cd543d593..4fd9cae53bd7 100644 --- a/data/etc/car/com.android.car.provision.xml +++ b/data/etc/car/com.android.car.provision.xml @@ -18,6 +18,8 @@ <privapp-permissions package="com.android.car.provision"> <permission name="android.car.permission.CAR_POWERTRAIN"/> <permission name="android.permission.INTERACT_ACROSS_USERS"/> + <permission name="android.permission.INTERACT_ACROSS_USERS_FULL"/> + <permission name="android.permission.MANAGE_USERS"/> <permission name="android.permission.MASTER_CLEAR"/> <permission name="android.permission.QUERY_ALL_PACKAGES"/> <permission name="android.permission.SEND_CATEGORY_CAR_NOTIFICATIONS"/> diff --git a/data/etc/car/com.google.android.car.networking.preferenceupdater.xml b/data/etc/car/com.google.android.car.networking.preferenceupdater.xml new file mode 100644 index 000000000000..489ce1b47ffa --- /dev/null +++ b/data/etc/car/com.google.android.car.networking.preferenceupdater.xml @@ -0,0 +1,27 @@ +<?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 + --> +<permissions> + <privapp-permissions package="com.google.android.car.networking.preferenceupdater"> + <permission name="android.permission.ACCESS_NETWORK_STATE"/> + <permission name="android.permission.ACCESS_WIFI_STATE"/> + <permission name="android.permission.ACTIVITY_EMBEDDING"/> + <permission name="android.permission.INTERACT_ACROSS_USERS"/> + <permission name="android.permission.INTERACT_ACROSS_USERS_FULL"/> + <permission name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"/> + <permission name="android.permission.LOCATION_HARDWARE"/> + </privapp-permissions> +</permissions> diff --git a/data/etc/com.android.documentsui.xml b/data/etc/com.android.documentsui.xml index 1e570ba9ac1c..d32cbecb16ec 100644 --- a/data/etc/com.android.documentsui.xml +++ b/data/etc/com.android.documentsui.xml @@ -22,5 +22,6 @@ <permission name="android.permission.LOG_COMPAT_CHANGE"/> <permission name="android.permission.MODIFY_QUIET_MODE"/> <permission name="android.permission.READ_COMPAT_CHANGE_CONFIG"/> + <permission name="android.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND"/> </privapp-permissions> </permissions> diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index 5f129fe03b61..0a77be967ace 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -210,6 +210,7 @@ applications that come with the platform <privapp-permissions package="com.android.providers.contacts"> <permission name="android.permission.BIND_DIRECTORY_SEARCH"/> + <permission name="android.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST"/> <permission name="android.permission.GET_ACCOUNTS_PRIVILEGED"/> <permission name="android.permission.INTERACT_ACROSS_USERS"/> <permission name="android.permission.MANAGE_USERS"/> @@ -245,6 +246,7 @@ applications that come with the platform <permission name="android.permission.REGISTER_STATS_PULL_ATOM" /> <!-- Permissions required for reading DeviceConfig --> <permission name="android.permission.READ_DEVICE_CONFIG" /> + <permission name="android.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND"/> </privapp-permissions> <privapp-permissions package="com.android.providers.telephony"> diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index a5667b2f0a8a..d8a735c78ca3 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -1021,12 +1021,6 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "-903853754": { - "message": "pauseBackStacks: stack=%s mResumedActivity=%s", - "level": "DEBUG", - "group": "WM_DEBUG_STATES", - "at": "com\/android\/server\/wm\/TaskDisplayArea.java" - }, "-883738232": { "message": "Adding more than one toast window for UID at a time.", "level": "WARN", @@ -1069,6 +1063,12 @@ "group": "WM_DEBUG_TASKS", "at": "com\/android\/server\/wm\/ActivityTaskSupervisor.java" }, + "-856590985": { + "message": "dcTarget: %s mImeRequester: %s", + "level": "DEBUG", + "group": "WM_DEBUG_IME", + "at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java" + }, "-856025122": { "message": "SURFACE transparentRegionHint=%s: %s", "level": "INFO", @@ -1717,12 +1717,6 @@ "group": "WM_SHOW_TRANSACTIONS", "at": "com\/android\/server\/wm\/Session.java" }, - "-49129622": { - "message": "performLayout: Activity exiting now removed %s", - "level": "VERBOSE", - "group": "WM_DEBUG_ADD_REMOVE", - "at": "com\/android\/server\/wm\/TaskDisplayArea.java" - }, "-33096143": { "message": "applyAnimation: transition animation is disabled or skipped. container=%s", "level": "VERBOSE", @@ -1777,6 +1771,12 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, + "44438983": { + "message": "performLayout: Activity exiting now removed %s", + "level": "VERBOSE", + "group": "WM_DEBUG_ADD_REMOVE", + "at": "com\/android\/server\/wm\/DisplayContent.java" + }, "45285419": { "message": "startingWindow was set but startingSurface==null, couldn't remove", "level": "VERBOSE", @@ -1837,12 +1837,6 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowContextListenerController.java" }, - "91350919": { - "message": "Attempted to set IME flag to a display that does not exist: %d", - "level": "WARN", - "group": "WM_ERROR", - "at": "com\/android\/server\/wm\/WindowManagerService.java" - }, "94402792": { "message": "Moving to RESUMED: %s (in existing)", "level": "VERBOSE", @@ -2125,6 +2119,12 @@ "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", @@ -2383,12 +2383,6 @@ "group": "WM_ERROR", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, - "632168013": { - "message": "dcTarget: %s mImeTargetFromIme: %s", - "level": "DEBUG", - "group": "WM_DEBUG_IME", - "at": "com\/android\/server\/wm\/ImeInsetsSourceProvider.java" - }, "633654009": { "message": "SURFACE POS (setPositionInTransaction) @ (%f,%f): %s", "level": "INFO", diff --git a/graphics/java/android/graphics/OWNERS b/graphics/java/android/graphics/OWNERS index 61968890b837..c3fb6f8eba7c 100644 --- a/graphics/java/android/graphics/OWNERS +++ b/graphics/java/android/graphics/OWNERS @@ -4,3 +4,5 @@ romainguy@google.com jreck@google.com njawad@google.com sumir@google.com + +per-file BLASTBufferQueue.java = file:/services/core/java/com/android/server/wm/OWNERS diff --git a/graphics/java/android/graphics/ParcelableColorSpace.java b/graphics/java/android/graphics/ParcelableColorSpace.java index 326084924450..748d66cb5f6c 100644 --- a/graphics/java/android/graphics/ParcelableColorSpace.java +++ b/graphics/java/android/graphics/ParcelableColorSpace.java @@ -22,18 +22,19 @@ import android.os.Parcel; import android.os.Parcelable; /** - * A {@link Parcelable} {@link ColorSpace}. In order to enable parceling, the ColorSpace - * must be either a {@link ColorSpace.Named Named} ColorSpace or a {@link ColorSpace.Rgb} instance - * that has an ICC parametric transfer function as returned by {@link Rgb#getTransferParameters()}. + * A {@link Parcelable} wrapper for a {@link ColorSpace}. In order to enable parceling, the + * ColorSpace must be either a {@link ColorSpace.Named Named} ColorSpace or a + * {@link ColorSpace.Rgb} instance that has an ICC parametric transfer function as returned by + * {@link ColorSpace.Rgb#getTransferParameters()}. */ -public final class ParcelableColorSpace extends ColorSpace implements Parcelable { +public final class ParcelableColorSpace implements Parcelable { private final ColorSpace mColorSpace; /** * Checks if the given ColorSpace is able to be parceled. A ColorSpace can only be * parceled if it is a {@link ColorSpace.Named Named} ColorSpace or a {@link ColorSpace.Rgb} * instance that has an ICC parametric transfer function as returned by - * {@link Rgb#getTransferParameters()} + * {@link ColorSpace.Rgb#getTransferParameters()} */ public static boolean isParcelable(@NonNull ColorSpace colorSpace) { if (colorSpace.getId() == ColorSpace.MIN_ID) { @@ -57,7 +58,6 @@ public final class ParcelableColorSpace extends ColorSpace implements Parcelable * to be parceled. See {@link #isParcelable(ColorSpace)}. */ public ParcelableColorSpace(@NonNull ColorSpace colorSpace) { - super(colorSpace.getName(), colorSpace.getModel(), colorSpace.getId()); mColorSpace = colorSpace; if (mColorSpace.getId() == ColorSpace.MIN_ID) { @@ -139,31 +139,6 @@ public final class ParcelableColorSpace extends ColorSpace implements Parcelable }; @Override - public boolean isWideGamut() { - return mColorSpace.isWideGamut(); - } - - @Override - public float getMinValue(int component) { - return mColorSpace.getMinValue(component); - } - - @Override - public float getMaxValue(int component) { - return mColorSpace.getMaxValue(component); - } - - @Override - public @NonNull float[] toXyz(@NonNull float[] v) { - return mColorSpace.toXyz(v); - } - - @Override - public @NonNull float[] fromXyz(@NonNull float[] v) { - return mColorSpace.fromXyz(v); - } - - @Override public boolean equals(@Nullable Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; @@ -175,10 +150,4 @@ public final class ParcelableColorSpace extends ColorSpace implements Parcelable public int hashCode() { return mColorSpace.hashCode(); } - - /** @hide */ - @Override - long getNativeInstance() { - return mColorSpace.getNativeInstance(); - } } diff --git a/keystore/java/android/security/KeyStoreOperation.java b/keystore/java/android/security/KeyStoreOperation.java index 49a48871fd30..7ea9e1438845 100644 --- a/keystore/java/android/security/KeyStoreOperation.java +++ b/keystore/java/android/security/KeyStoreOperation.java @@ -17,7 +17,7 @@ package android.security; import android.annotation.NonNull; -import android.hardware.keymint.KeyParameter; +import android.hardware.security.keymint.KeyParameter; import android.os.RemoteException; import android.os.ServiceSpecificException; import android.security.keymaster.KeymasterDefs; diff --git a/keystore/java/android/security/KeyStoreSecurityLevel.java b/keystore/java/android/security/KeyStoreSecurityLevel.java index 7c3de8bee475..3ef4aa5b7ec3 100644 --- a/keystore/java/android/security/KeyStoreSecurityLevel.java +++ b/keystore/java/android/security/KeyStoreSecurityLevel.java @@ -18,7 +18,7 @@ package android.security; import android.annotation.NonNull; import android.app.compat.CompatChanges; -import android.hardware.keymint.KeyParameter; +import android.hardware.security.keymint.KeyParameter; import android.os.RemoteException; import android.os.ServiceSpecificException; import android.security.keystore.BackendBusyException; diff --git a/keystore/java/android/security/keystore2/AndroidKeyStore3DESCipherSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStore3DESCipherSpi.java index 69c7a2589d6f..0775a1a99886 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStore3DESCipherSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStore3DESCipherSpi.java @@ -17,7 +17,7 @@ package android.security.keystore2; import android.annotation.NonNull; -import android.hardware.keymint.KeyParameter; +import android.hardware.security.keymint.KeyParameter; import android.security.keymaster.KeymasterDefs; import android.security.keystore.ArrayUtils; import android.security.keystore.KeyProperties; diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreAuthenticatedAESCipherSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreAuthenticatedAESCipherSpi.java index 2b5f6c31607b..bc56f015f3bd 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreAuthenticatedAESCipherSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreAuthenticatedAESCipherSpi.java @@ -18,7 +18,7 @@ package android.security.keystore2; import android.annotation.NonNull; import android.annotation.Nullable; -import android.hardware.keymint.KeyParameter; +import android.hardware.security.keymint.KeyParameter; import android.security.KeyStoreException; import android.security.KeyStoreOperation; import android.security.keymaster.KeymasterDefs; diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java b/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java index 18d26922f1ae..a3b04abfba3f 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java @@ -19,7 +19,7 @@ package android.security.keystore2; import android.annotation.CallSuper; import android.annotation.NonNull; import android.annotation.Nullable; -import android.hardware.keymint.KeyParameter; +import android.hardware.security.keymint.KeyParameter; import android.security.KeyStoreException; import android.security.KeyStoreOperation; import android.security.keymaster.KeymasterDefs; diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java index 2250c89aac41..d1ef1df817e6 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java @@ -17,7 +17,7 @@ package android.security.keystore2; import android.annotation.NonNull; -import android.hardware.keymint.KeyParameter; +import android.hardware.security.keymint.KeyParameter; import android.security.KeyStoreException; import android.security.KeyStoreOperation; import android.security.keymaster.KeymasterDefs; diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreHmacSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreHmacSpi.java index eea45c287622..8475ad9fd57b 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreHmacSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreHmacSpi.java @@ -16,7 +16,7 @@ package android.security.keystore2; -import android.hardware.keymint.KeyParameter; +import android.hardware.security.keymint.KeyParameter; import android.security.KeyStoreException; import android.security.KeyStoreOperation; import android.security.keymaster.KeymasterDefs; diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyGeneratorSpi.java index 479fd8a6a73a..233f352989ab 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyGeneratorSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyGeneratorSpi.java @@ -16,8 +16,8 @@ package android.security.keystore2; -import android.hardware.keymint.KeyParameter; -import android.hardware.keymint.SecurityLevel; +import android.hardware.security.keymint.KeyParameter; +import android.hardware.security.keymint.SecurityLevel; import android.security.KeyStore2; import android.security.KeyStoreSecurityLevel; import android.security.keymaster.KeymasterArguments; diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java index 61725e3e8c24..df0e1462a492 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java @@ -18,8 +18,8 @@ package android.security.keystore2; import android.annotation.NonNull; import android.annotation.Nullable; -import android.hardware.keymint.KeyParameter; -import android.hardware.keymint.SecurityLevel; +import android.hardware.security.keymint.KeyParameter; +import android.hardware.security.keymint.SecurityLevel; import android.os.Build; import android.security.KeyPairGeneratorSpec; import android.security.KeyStore2; diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java index 2686ddc20c1d..951f91887894 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java @@ -18,7 +18,7 @@ package android.security.keystore2; import android.annotation.NonNull; import android.annotation.Nullable; -import android.hardware.keymint.KeyParameter; +import android.hardware.security.keymint.KeyParameter; import android.security.keymaster.KeymasterDefs; import android.security.keystore.KeyProperties; import android.security.keystore.KeymasterUtils; diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreRSASignatureSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreRSASignatureSpi.java index 444dad4cffbe..ab7559116a41 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreRSASignatureSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreRSASignatureSpi.java @@ -17,7 +17,7 @@ package android.security.keystore2; import android.annotation.NonNull; -import android.hardware.keymint.KeyParameter; +import android.hardware.security.keymint.KeyParameter; import android.security.keymaster.KeymasterDefs; import android.security.keystore.KeyProperties; diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSignatureSpiBase.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSignatureSpiBase.java index a168f8feb3db..9b4f01e744f7 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreSignatureSpiBase.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSignatureSpiBase.java @@ -18,7 +18,7 @@ package android.security.keystore2; import android.annotation.CallSuper; import android.annotation.NonNull; -import android.hardware.keymint.KeyParameter; +import android.hardware.security.keymint.KeyParameter; import android.security.KeyStoreException; import android.security.KeyStoreOperation; import android.security.keymaster.KeymasterDefs; diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java index 9790a4ae5b65..aca531458382 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java @@ -18,9 +18,9 @@ package android.security.keystore2; import android.annotation.NonNull; import android.hardware.biometrics.BiometricManager; -import android.hardware.keymint.HardwareAuthenticatorType; -import android.hardware.keymint.KeyParameter; -import android.hardware.keymint.SecurityLevel; +import android.hardware.security.keymint.HardwareAuthenticatorType; +import android.hardware.security.keymint.KeyParameter; +import android.hardware.security.keymint.SecurityLevel; import android.security.GateKeeper; import android.security.KeyStore2; import android.security.KeyStoreParameter; diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreUnauthenticatedAESCipherSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreUnauthenticatedAESCipherSpi.java index a2d4528b99fd..4d4b0d8f183b 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreUnauthenticatedAESCipherSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreUnauthenticatedAESCipherSpi.java @@ -18,7 +18,7 @@ package android.security.keystore2; import android.annotation.NonNull; import android.annotation.Nullable; -import android.hardware.keymint.KeyParameter; +import android.hardware.security.keymint.KeyParameter; import android.security.keymaster.KeymasterDefs; import android.security.keystore.ArrayUtils; import android.security.keystore.KeyProperties; diff --git a/keystore/java/android/security/keystore2/KeyStore2ParameterUtils.java b/keystore/java/android/security/keystore2/KeyStore2ParameterUtils.java index 8fa532b6e188..18c786aa3093 100644 --- a/keystore/java/android/security/keystore2/KeyStore2ParameterUtils.java +++ b/keystore/java/android/security/keystore2/KeyStore2ParameterUtils.java @@ -18,8 +18,8 @@ package android.security.keystore2; import android.annotation.NonNull; import android.hardware.biometrics.BiometricManager; -import android.hardware.keymint.KeyParameter; -import android.hardware.keymint.SecurityLevel; +import android.hardware.security.keymint.KeyParameter; +import android.hardware.security.keymint.SecurityLevel; import android.security.GateKeeper; import android.security.keymaster.KeymasterDefs; import android.security.keystore.KeyProperties; diff --git a/libs/WindowManager/Shell/res/layout/docked_stack_divider.xml b/libs/WindowManager/Shell/res/layout/docked_stack_divider.xml index ad870252d819..ea21eb97df57 100644 --- a/libs/WindowManager/Shell/res/layout/docked_stack_divider.xml +++ b/libs/WindowManager/Shell/res/layout/docked_stack_divider.xml @@ -14,7 +14,7 @@ limitations under the License. --> -<com.android.wm.shell.splitscreen.DividerView +<com.android.wm.shell.legacysplitscreen.DividerView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="match_parent" android:layout_width="match_parent"> @@ -24,15 +24,15 @@ android:id="@+id/docked_divider_background" android:background="@color/docked_divider_background"/> - <com.android.wm.shell.splitscreen.MinimizedDockShadow + <com.android.wm.shell.legacysplitscreen.MinimizedDockShadow style="@style/DockedDividerMinimizedShadow" android:id="@+id/minimized_dock_shadow" android:alpha="0"/>"> - <com.android.wm.shell.splitscreen.DividerHandleView + <com.android.wm.shell.legacysplitscreen.DividerHandleView style="@style/DockedDividerHandle" android:id="@+id/docked_divider_handle" android:contentDescription="@string/accessibility_divider" android:background="@null"/> -</com.android.wm.shell.splitscreen.DividerView> +</com.android.wm.shell.legacysplitscreen.DividerView> diff --git a/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json b/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json index db9e1af9ec1e..4070829fcfbe 100644 --- a/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json +++ b/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json @@ -1,12 +1,6 @@ { "version": "1.0.0", "messages": { - "-1993693214": { - "message": "Letterbox Task Changed: #%d", - "level": "VERBOSE", - "group": "WM_SHELL_TASK_ORG", - "at": "com\/android\/wm\/shell\/letterbox\/LetterboxTaskListener.java" - }, "-1683614271": { "message": "Existing task: id=%d component=%s", "level": "VERBOSE", @@ -37,6 +31,12 @@ "group": "WM_SHELL_DRAG_AND_DROP", "at": "com\/android\/wm\/shell\/draganddrop\/DragAndDropController.java" }, + "-1362429294": { + "message": "%s onTaskAppeared Primary taskId=%d", + "level": "VERBOSE", + "group": "WM_SHELL_TASK_ORG", + "at": "com\/android\/wm\/shell\/legacysplitscreen\/LegacySplitScreenTaskListener.java" + }, "-1340279385": { "message": "Remove listener=%s", "level": "VERBOSE", @@ -73,12 +73,6 @@ "group": "WM_SHELL_TASK_ORG", "at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java" }, - "-842742255": { - "message": "%s onTaskAppeared unknown taskId=%d winMode=%d", - "level": "VERBOSE", - "group": "WM_SHELL_TASK_ORG", - "at": "com\/android\/wm\/shell\/splitscreen\/SplitScreenTaskListener.java" - }, "-742394458": { "message": "pair task1=%d task2=%d in AppPair=%s", "level": "VERBOSE", @@ -91,17 +85,11 @@ "group": "WM_SHELL_DRAG_AND_DROP", "at": "com\/android\/wm\/shell\/draganddrop\/DragLayout.java" }, - "-679492476": { - "message": "%s onTaskAppeared Primary taskId=%d", - "level": "VERBOSE", - "group": "WM_SHELL_TASK_ORG", - "at": "com\/android\/wm\/shell\/splitscreen\/SplitScreenTaskListener.java" - }, - "-342975160": { - "message": "Letterbox Task Vanished: #%d", + "-298656957": { + "message": "%s onTaskAppeared unknown taskId=%d winMode=%d", "level": "VERBOSE", "group": "WM_SHELL_TASK_ORG", - "at": "com\/android\/wm\/shell\/letterbox\/LetterboxTaskListener.java" + "at": "com\/android\/wm\/shell\/legacysplitscreen\/LegacySplitScreenTaskListener.java" }, "-234284913": { "message": "unpair taskId=%d pair=%s", @@ -115,12 +103,6 @@ "group": "WM_SHELL_TRANSITIONS", "at": "com\/android\/wm\/shell\/Transitions.java" }, - "154313206": { - "message": "%s onTaskAppeared Secondary taskId=%d", - "level": "VERBOSE", - "group": "WM_SHELL_TASK_ORG", - "at": "com\/android\/wm\/shell\/splitscreen\/SplitScreenTaskListener.java" - }, "157713005": { "message": "Task info changed taskId=%d", "level": "VERBOSE", @@ -139,6 +121,12 @@ "group": "WM_SHELL_DRAG_AND_DROP", "at": "com\/android\/wm\/shell\/draganddrop\/DragAndDropController.java" }, + "473543554": { + "message": "%s onTaskAppeared Supported", + "level": "VERBOSE", + "group": "WM_SHELL_TASK_ORG", + "at": "com\/android\/wm\/shell\/legacysplitscreen\/LegacySplitScreenTaskListener.java" + }, "481673835": { "message": "addListenerForTaskId taskId=%s", "level": "VERBOSE", @@ -175,6 +163,12 @@ "group": "WM_SHELL_TASK_ORG", "at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java" }, + "982027396": { + "message": "%s onTaskAppeared Secondary taskId=%d", + "level": "VERBOSE", + "group": "WM_SHELL_TASK_ORG", + "at": "com\/android\/wm\/shell\/legacysplitscreen\/LegacySplitScreenTaskListener.java" + }, "1079041527": { "message": "incrementPool size=%d", "level": "VERBOSE", @@ -199,12 +193,6 @@ "group": "WM_SHELL_DRAG_AND_DROP", "at": "com\/android\/wm\/shell\/draganddrop\/DragAndDropController.java" }, - "1885882094": { - "message": "Letterbox Task Appeared: #%d", - "level": "VERBOSE", - "group": "WM_SHELL_TASK_ORG", - "at": "com\/android\/wm\/shell\/letterbox\/LetterboxTaskListener.java" - }, "1891981945": { "message": "release entry.taskId=%s listener=%s size=%d", "level": "VERBOSE", @@ -228,12 +216,6 @@ "level": "VERBOSE", "group": "WM_SHELL_DRAG_AND_DROP", "at": "com\/android\/wm\/shell\/draganddrop\/DragAndDropController.java" - }, - "2135461748": { - "message": "%s onTaskAppeared Supported", - "level": "VERBOSE", - "group": "WM_SHELL_TASK_ORG", - "at": "com\/android\/wm\/shell\/splitscreen\/SplitScreenTaskListener.java" } }, "groups": { diff --git a/libs/WindowManager/Shell/res/values/config.xml b/libs/WindowManager/Shell/res/values/config.xml index f0eae97b107e..807e5afae890 100644 --- a/libs/WindowManager/Shell/res/values/config.xml +++ b/libs/WindowManager/Shell/res/values/config.xml @@ -42,16 +42,4 @@ <!-- Bounds [left top right bottom] on screen for picture-in-picture (PIP) windows, when the PIP menu is shown in center. --> <string translatable="false" name="pip_menu_bounds">"596 280 1324 690"</string> - - <!-- Gravity of letterboxed apps in portrait screen orientation. - Can be Gravity.TOP, Gravity.CENTER or Gravity.BOTTOM. - Any other value will result in runtime exception for a letterboxed activity. - Default is Gravity.TOP. --> - <integer name="config_letterboxPortraitGravity">0x00000030</integer> - - <!-- Gravity of letterboxed apps in landscape screen orientation. - Can be Gravity.LEFT, Gravity.CENTER or Gravity.RIGHT. - Any other value will result in runtime exception for a letterboxed activity. - Default is Gravity.CENTER. --> - <integer name="config_letterboxLandscapeGravity">0x00000011</integer> </resources> diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java index 4f13b83bc29d..63d31182a748 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java @@ -20,8 +20,9 @@ import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_FULLSCR import static com.android.wm.shell.ShellTaskOrganizer.taskListenerTypeToString; import android.app.ActivityManager; -import android.util.ArraySet; +import android.graphics.Point; import android.util.Slog; +import android.util.SparseArray; import android.view.SurfaceControl; import androidx.annotation.NonNull; @@ -40,7 +41,7 @@ public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener { private final SyncTransactionQueue mSyncQueue; - private final ArraySet<Integer> mTasks = new ArraySet<>(); + private final SparseArray<SurfaceControl> mLeashByTaskId = new SparseArray<>(); public FullscreenTaskListener(SyncTransactionQueue syncQueue) { mSyncQueue = syncQueue; @@ -48,39 +49,44 @@ public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener { @Override public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) { - synchronized (mTasks) { - if (mTasks.contains(taskInfo.taskId)) { - throw new RuntimeException("Task appeared more than once: #" + taskInfo.taskId); - } - ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Appeared: #%d", - taskInfo.taskId); - mTasks.add(taskInfo.taskId); - mSyncQueue.runInSync(t -> { - // Reset several properties back to fullscreen (PiP, for example, leaves all these - // properties in a bad state). - t.setWindowCrop(leash, null); - t.setPosition(leash, 0, 0); - // TODO(shell-transitions): Eventually set everything in transition so there's no - // SF Transaction here. - if (!Transitions.ENABLE_SHELL_TRANSITIONS) { - t.setAlpha(leash, 1f); - t.setMatrix(leash, 1, 0, 0, 1); - t.show(leash); - } - }); + if (mLeashByTaskId.get(taskInfo.taskId) != null) { + throw new IllegalStateException("Task appeared more than once: #" + taskInfo.taskId); } + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Appeared: #%d", + taskInfo.taskId); + mLeashByTaskId.put(taskInfo.taskId, leash); + final Point positionInParent = taskInfo.positionInParent; + mSyncQueue.runInSync(t -> { + // Reset several properties back to fullscreen (PiP, for example, leaves all these + // properties in a bad state). + t.setWindowCrop(leash, null); + t.setPosition(leash, positionInParent.x, positionInParent.y); + // TODO(shell-transitions): Eventually set everything in transition so there's no + // SF Transaction here. + if (!Transitions.ENABLE_SHELL_TRANSITIONS) { + t.setAlpha(leash, 1f); + t.setMatrix(leash, 1, 0, 0, 1); + t.show(leash); + } + }); + } + + @Override + public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) { + final SurfaceControl leash = mLeashByTaskId.get(taskInfo.taskId); + final Point positionInParent = taskInfo.positionInParent; + mSyncQueue.runInSync(t -> t.setPosition(leash, positionInParent.x, positionInParent.y)); } @Override public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) { - synchronized (mTasks) { - if (!mTasks.remove(taskInfo.taskId)) { - Slog.e(TAG, "Task already vanished: #" + taskInfo.taskId); - return; - } - ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Vanished: #%d", - taskInfo.taskId); + if (mLeashByTaskId.get(taskInfo.taskId) == null) { + Slog.e(TAG, "Task already vanished: #" + taskInfo.taskId); + return; } + mLeashByTaskId.remove(taskInfo.taskId); + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Vanished: #%d", + taskInfo.taskId); } @Override @@ -88,7 +94,7 @@ public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener { final String innerPrefix = prefix + " "; final String childPrefix = innerPrefix + " "; pw.println(prefix + this); - pw.println(innerPrefix + mTasks.size() + " Tasks"); + pw.println(innerPrefix + mLeashByTaskId.size() + " Tasks"); } @Override diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandler.java index 45948dd9e800..2f2168f53553 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandler.java @@ -16,15 +16,12 @@ package com.android.wm.shell; -import android.view.Gravity; - import com.android.wm.shell.apppairs.AppPairs; import com.android.wm.shell.common.annotations.ExternalThread; import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout; -import com.android.wm.shell.letterbox.LetterboxConfigController; import com.android.wm.shell.onehanded.OneHanded; import com.android.wm.shell.pip.Pip; -import com.android.wm.shell.splitscreen.SplitScreen; +import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import java.io.PrintWriter; import java.util.Optional; @@ -36,29 +33,26 @@ import java.util.Optional; */ public final class ShellCommandHandler { - private final Optional<SplitScreen> mSplitScreenOptional; + private final Optional<LegacySplitScreen> mLegacySplitScreenOptional; private final Optional<Pip> mPipOptional; private final Optional<OneHanded> mOneHandedOptional; private final Optional<HideDisplayCutout> mHideDisplayCutout; private final ShellTaskOrganizer mShellTaskOrganizer; private final Optional<AppPairs> mAppPairsOptional; - private final LetterboxConfigController mLetterboxConfigController; public ShellCommandHandler( ShellTaskOrganizer shellTaskOrganizer, - Optional<SplitScreen> splitScreenOptional, + Optional<LegacySplitScreen> legacySplitScreenOptional, Optional<Pip> pipOptional, Optional<OneHanded> oneHandedOptional, Optional<HideDisplayCutout> hideDisplayCutout, - Optional<AppPairs> appPairsOptional, - LetterboxConfigController letterboxConfigController) { + Optional<AppPairs> appPairsOptional) { mShellTaskOrganizer = shellTaskOrganizer; - mSplitScreenOptional = splitScreenOptional; + mLegacySplitScreenOptional = legacySplitScreenOptional; mPipOptional = pipOptional; mOneHandedOptional = oneHandedOptional; mHideDisplayCutout = hideDisplayCutout; mAppPairsOptional = appPairsOptional; - mLetterboxConfigController = letterboxConfigController; } /** Dumps WM Shell internal state. */ @@ -68,7 +62,7 @@ public final class ShellCommandHandler { pw.println(); pw.println(); mPipOptional.ifPresent(pip -> pip.dump(pw)); - mSplitScreenOptional.ifPresent(splitScreen -> splitScreen.dump(pw)); + mLegacySplitScreenOptional.ifPresent(splitScreen -> splitScreen.dump(pw)); mOneHandedOptional.ifPresent(oneHanded -> oneHanded.dump(pw)); mHideDisplayCutout.ifPresent(hideDisplayCutout -> hideDisplayCutout.dump(pw)); pw.println(); @@ -85,14 +79,6 @@ public final class ShellCommandHandler { return false; } switch (args[1]) { - case "set-letterbox-portrait-gravity": - return runSetLetterboxPortraitGravity(args, pw); - case "get-letterbox-portrait-gravity": - return runGetLetterboxPortraitGravity(pw); - case "set-letterbox-landscape-gravity": - return runSetLetterboxLandscapeGravity(args, pw); - case "get-letterbox-landscape-gravity": - return runGetLetterboxLandscapeGravity(pw); case "pair": return runPair(args, pw); case "unpair": @@ -104,92 +90,6 @@ public final class ShellCommandHandler { } } - private boolean runSetLetterboxPortraitGravity(String[] args, PrintWriter pw) { - if (args.length < 3) { - // First two arguments are "WMShell" and command name. - pw.println("Error: reset, TOP, CENTER or BOTTOM should be provided as an argument"); - return true; - } - switch (args[2]) { - case "reset": - mLetterboxConfigController.resetPortraitGravity(); - break; - case "TOP": - mLetterboxConfigController.setPortraitGravity(Gravity.TOP); - break; - case "CENTER": - mLetterboxConfigController.setPortraitGravity(Gravity.CENTER); - break; - case "BOTTOM": - mLetterboxConfigController.setPortraitGravity(Gravity.BOTTOM); - break; - default: - pw.println("Error: expected reset, TOP, CENTER or BOTTOM but got " + args[2]); - } - return true; - } - - private boolean runGetLetterboxPortraitGravity(PrintWriter pw) { - final int gravity = mLetterboxConfigController.getPortraitGravity(); - switch (gravity) { - case Gravity.TOP: - pw.println("TOP"); - break; - case Gravity.CENTER: - pw.println("CENTER"); - break; - case Gravity.BOTTOM: - pw.println("BOTTOM"); - break; - default: - throw new AssertionError("Unexpected gravity: " + gravity); - } - return true; - } - - private boolean runSetLetterboxLandscapeGravity(String[] args, PrintWriter pw) { - if (args.length < 3) { - // First two arguments are "WMShell" and command name. - pw.println("Error: reset, LEFT, CENTER or RIGHT should be provided as an argument"); - return false; - } - switch (args[2]) { - case "reset": - mLetterboxConfigController.resetLandscapeGravity(); - break; - case "LEFT": - mLetterboxConfigController.setLandscapeGravity(Gravity.LEFT); - break; - case "CENTER": - mLetterboxConfigController.setLandscapeGravity(Gravity.CENTER); - break; - case "RIGHT": - mLetterboxConfigController.setLandscapeGravity(Gravity.RIGHT); - break; - default: - pw.println( - "Error: expected reset, LEFT, CENTER or RIGHT but got " + args[2]); - } - return true; - } - - private boolean runGetLetterboxLandscapeGravity(PrintWriter pw) { - final int gravity = mLetterboxConfigController.getLandscapeGravity(); - switch (gravity) { - case Gravity.LEFT: - pw.println("LEFT"); - break; - case Gravity.CENTER: - pw.println("CENTER"); - break; - case Gravity.RIGHT: - pw.println("RIGHT"); - break; - default: - throw new AssertionError("Unexpected gravity: " + gravity); - } - return true; - } private boolean runPair(String[] args, PrintWriter pw) { if (args.length < 4) { @@ -220,12 +120,6 @@ public final class ShellCommandHandler { pw.println(" Print this help text."); pw.println(" <no arguments provided>"); pw.println(" Dump Window Manager Shell internal state"); - pw.println(" set-letterbox-portrait-gravity [reset|TOP|CENTER|BOTTOM]"); - pw.println(" get-letterbox-portrait-gravity"); - pw.println(" Set, reset or print letterbox gravity for portrait screen mode."); - pw.println(" set-letterbox-landscape-gravity [reset|LEFT|CENTER|RIGHT]"); - pw.println(" get-letterbox-landscape-gravity"); - pw.println(" Set, reset or print letterbox gravity for landscape screen mode."); pw.println(" pair <taskId1> <taskId2>"); pw.println(" unpair <taskId>"); pw.println(" Pairs/unpairs tasks with given ids."); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInit.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInit.java index 94555de4f05c..f4c617e601fc 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInit.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInit.java @@ -17,14 +17,12 @@ package com.android.wm.shell; import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_FULLSCREEN; -import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_LETTERBOX; import com.android.wm.shell.apppairs.AppPairs; import com.android.wm.shell.common.DisplayImeController; import com.android.wm.shell.common.annotations.ExternalThread; import com.android.wm.shell.draganddrop.DragAndDropController; -import com.android.wm.shell.letterbox.LetterboxTaskListener; -import com.android.wm.shell.splitscreen.SplitScreen; +import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import java.util.Optional; @@ -36,25 +34,25 @@ public class ShellInit { private final DisplayImeController mDisplayImeController; private final DragAndDropController mDragAndDropController; private final ShellTaskOrganizer mShellTaskOrganizer; - private final Optional<SplitScreen> mSplitScreenOptional; + private final Optional<LegacySplitScreen> mLegacySplitScreenOptional; private final Optional<AppPairs> mAppPairsOptional; - private final LetterboxTaskListener mLetterboxTaskListener; private final FullscreenTaskListener mFullscreenTaskListener; + private final Transitions mTransitions; public ShellInit(DisplayImeController displayImeController, DragAndDropController dragAndDropController, ShellTaskOrganizer shellTaskOrganizer, - Optional<SplitScreen> splitScreenOptional, + Optional<LegacySplitScreen> legacySplitScreenOptional, Optional<AppPairs> appPairsOptional, - LetterboxTaskListener letterboxTaskListener, - FullscreenTaskListener fullscreenTaskListener) { + FullscreenTaskListener fullscreenTaskListener, + Transitions transitions) { mDisplayImeController = displayImeController; mDragAndDropController = dragAndDropController; mShellTaskOrganizer = shellTaskOrganizer; - mSplitScreenOptional = splitScreenOptional; + mLegacySplitScreenOptional = legacySplitScreenOptional; mAppPairsOptional = appPairsOptional; - mLetterboxTaskListener = letterboxTaskListener; mFullscreenTaskListener = fullscreenTaskListener; + mTransitions = transitions; } @ExternalThread @@ -63,14 +61,16 @@ public class ShellInit { mDisplayImeController.startMonitorDisplays(); mShellTaskOrganizer.addListenerForType( - mLetterboxTaskListener, TASK_LISTENER_TYPE_LETTERBOX); - mShellTaskOrganizer.addListenerForType( mFullscreenTaskListener, TASK_LISTENER_TYPE_FULLSCREEN); // Register the shell organizer mShellTaskOrganizer.registerOrganizer(); mAppPairsOptional.ifPresent(AppPairs::onOrganizerRegistered); // Bind the splitscreen impl to the drag drop controller - mDragAndDropController.setSplitScreenController(mSplitScreenOptional); + mDragAndDropController.setSplitScreenController(mLegacySplitScreenOptional); + + if (Transitions.ENABLE_SHELL_TRANSITIONS) { + mTransitions.register(mShellTaskOrganizer); + } } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java index e68a7471fdaf..10cec6d59cbe 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java @@ -43,8 +43,6 @@ import androidx.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.common.ShellExecutor; -import com.android.wm.shell.common.SyncTransactionQueue; -import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.startingsurface.StartingSurfaceDrawer; import java.io.PrintWriter; @@ -64,14 +62,12 @@ public class ShellTaskOrganizer extends TaskOrganizer { public static final int TASK_LISTENER_TYPE_FULLSCREEN = -2; public static final int TASK_LISTENER_TYPE_MULTI_WINDOW = -3; public static final int TASK_LISTENER_TYPE_PIP = -4; - public static final int TASK_LISTENER_TYPE_LETTERBOX = -5; @IntDef(prefix = {"TASK_LISTENER_TYPE_"}, value = { TASK_LISTENER_TYPE_UNDEFINED, TASK_LISTENER_TYPE_FULLSCREEN, TASK_LISTENER_TYPE_MULTI_WINDOW, TASK_LISTENER_TYPE_PIP, - TASK_LISTENER_TYPE_LETTERBOX, }) public @interface TaskListenerType {} @@ -102,24 +98,17 @@ public class ShellTaskOrganizer extends TaskOrganizer { /** @see #setPendingLaunchCookieListener */ private final ArrayMap<IBinder, TaskListener> mLaunchCookieToListener = new ArrayMap<>(); - // TODO(shell-transitions): move to a more "global" Shell location as this isn't only for Tasks - private final Transitions mTransitions; - private final Object mLock = new Object(); private final StartingSurfaceDrawer mStartingSurfaceDrawer; - public ShellTaskOrganizer(SyncTransactionQueue syncQueue, TransactionPool transactionPool, - ShellExecutor mainExecutor, ShellExecutor animExecutor, Context context) { - this(null, syncQueue, transactionPool, mainExecutor, animExecutor, context); + public ShellTaskOrganizer(ShellExecutor mainExecutor, Context context) { + this(null, mainExecutor, context); } @VisibleForTesting - ShellTaskOrganizer(ITaskOrganizerController taskOrganizerController, - SyncTransactionQueue syncQueue, TransactionPool transactionPool, - ShellExecutor mainExecutor, ShellExecutor animExecutor, Context context) { + ShellTaskOrganizer(ITaskOrganizerController taskOrganizerController, ShellExecutor mainExecutor, + Context context) { super(taskOrganizerController, mainExecutor); - mTransitions = new Transitions(this, transactionPool, mainExecutor, animExecutor); - if (Transitions.ENABLE_SHELL_TRANSITIONS) mTransitions.register(this); // 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. @@ -380,9 +369,7 @@ public class ShellTaskOrganizer extends TaskOrganizer { static @TaskListenerType int taskInfoToTaskListenerType(RunningTaskInfo runningTaskInfo) { switch (runningTaskInfo.getWindowingMode()) { case WINDOWING_MODE_FULLSCREEN: - return runningTaskInfo.letterboxActivityBounds != null - ? TASK_LISTENER_TYPE_LETTERBOX - : TASK_LISTENER_TYPE_FULLSCREEN; + return TASK_LISTENER_TYPE_FULLSCREEN; case WINDOWING_MODE_MULTI_WINDOW: return TASK_LISTENER_TYPE_MULTI_WINDOW; case WINDOWING_MODE_PINNED: @@ -398,8 +385,6 @@ public class ShellTaskOrganizer extends TaskOrganizer { switch (type) { case TASK_LISTENER_TYPE_FULLSCREEN: return "TASK_LISTENER_TYPE_FULLSCREEN"; - case TASK_LISTENER_TYPE_LETTERBOX: - return "TASK_LISTENER_TYPE_LETTERBOX"; case TASK_LISTENER_TYPE_MULTI_WINDOW: return "TASK_LISTENER_TYPE_MULTI_WINDOW"; case TASK_LISTENER_TYPE_PIP: 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 59a765d49a14..7440f19a6e7c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java @@ -87,16 +87,12 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback, super(context, null, 0, 0, true /* disableBackgroundLayer */); mTaskOrganizer = organizer; + mExecutor = organizer.getExecutor(); setUseAlpha(); getHolder().addCallback(this); mGuard.open("release"); } - // TODO: Use TaskOrganizer executor when part of wmshell proper - public void setExecutor(Executor executor) { - mExecutor = executor; - } - /** * Only one listener may be set on the view, throws an exception otherwise. */ diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/Transitions.java index 10195b6a26b2..a779531f8b91 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/Transitions.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/Transitions.java @@ -16,10 +16,10 @@ package com.android.wm.shell; -import static android.window.TransitionInfo.TRANSIT_CLOSE; -import static android.window.TransitionInfo.TRANSIT_HIDE; -import static android.window.TransitionInfo.TRANSIT_OPEN; -import static android.window.TransitionInfo.TRANSIT_SHOW; +import static android.view.WindowManager.TRANSIT_CLOSE; +import static android.view.WindowManager.TRANSIT_OPEN; +import static android.view.WindowManager.TRANSIT_TO_BACK; +import static android.view.WindowManager.TRANSIT_TO_FRONT; import android.animation.Animator; import android.animation.ValueAnimator; @@ -40,7 +40,6 @@ import androidx.annotation.BinderThread; import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.TransactionPool; -import com.android.wm.shell.common.annotations.ShellMainThread; import com.android.wm.shell.protolog.ShellProtoLogGroup; import java.util.ArrayList; @@ -62,7 +61,7 @@ public class Transitions { /** Keeps track of currently tracked transitions and all the animations associated with each */ private final ArrayMap<IBinder, ArrayList<Animator>> mActiveTransitions = new ArrayMap<>(); - Transitions(@NonNull WindowOrganizer organizer, @NonNull TransactionPool pool, + public Transitions(@NonNull WindowOrganizer organizer, @NonNull TransactionPool pool, @NonNull ShellExecutor mainExecutor, @NonNull ShellExecutor animExecutor) { mOrganizer = organizer; mTransactionPool = pool; @@ -119,8 +118,8 @@ public class Transitions { } private static boolean isOpeningType(@WindowManager.TransitionType int type) { - return type == WindowManager.TRANSIT_OPEN - || type == WindowManager.TRANSIT_TO_FRONT + return type == TRANSIT_OPEN + || type == TRANSIT_TO_FRONT || type == WindowManager.TRANSIT_KEYGUARD_GOING_AWAY; } @@ -150,7 +149,7 @@ public class Transitions { // Don't animate anything with an animating parent if (change.getParent() != null) { - if (mode == TRANSIT_OPEN || mode == TRANSIT_SHOW) { + if (mode == TRANSIT_OPEN || mode == TRANSIT_TO_FRONT) { t.show(leash); t.setMatrix(leash, 1, 0, 0, 1); } @@ -161,7 +160,7 @@ public class Transitions { t.setPosition(leash, change.getEndAbsBounds().left - info.getRootOffset().x, change.getEndAbsBounds().top - info.getRootOffset().y); // Put all the OPEN/SHOW on top - if (mode == TRANSIT_OPEN || mode == TRANSIT_SHOW) { + if (mode == TRANSIT_OPEN || mode == TRANSIT_TO_FRONT) { t.show(leash); t.setMatrix(leash, 1, 0, 0, 1); if (isOpening) { @@ -174,7 +173,7 @@ public class Transitions { t.setLayer(leash, -i); t.setAlpha(leash, 1.f); } - } else if (mode == TRANSIT_CLOSE || mode == TRANSIT_HIDE) { + } else if (mode == TRANSIT_CLOSE || mode == TRANSIT_TO_BACK) { if (isOpening) { // put on bottom and leave visible without fade t.setLayer(leash, -i); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java index 318a0bd42940..4bf01f7cffac 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java @@ -59,7 +59,6 @@ import com.android.internal.policy.ScreenDecorationsUtils; import com.android.wm.shell.R; import com.android.wm.shell.TaskView; import com.android.wm.shell.common.AlphaOptimizedButton; -import com.android.wm.shell.common.HandlerExecutor; import com.android.wm.shell.common.TriangleShape; import java.io.FileDescriptor; @@ -304,11 +303,6 @@ public class BubbleExpandedView extends LinearLayout { setLayoutDirection(LAYOUT_DIRECTION_LOCALE); } - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - mTaskView.setExecutor(new HandlerExecutor(getHandler())); - } /** * Initialize {@link BubbleController} and {@link BubbleStackView} here, this method must need * to be called after view inflate. 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 50d9fe8629ac..e97fe0a9111c 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 @@ -112,7 +112,7 @@ public class DividerView extends FrameLayout implements View.OnTouchListener { } if (mMoving) { final int position = mSplitLayout.getDividePosition() + touchPos - mStartPos; - mSplitLayout.updateDividePosition(position); + mSplitLayout.updateDivideBounds(position); } break; case MotionEvent.ACTION_UP: @@ -131,7 +131,7 @@ public class DividerView extends FrameLayout implements View.OnTouchListener { final int position = mSplitLayout.getDividePosition() + touchPos - mStartPos; final DividerSnapAlgorithm.SnapTarget snapTarget = mSplitLayout.findSnapTarget(position, velocity); - mSplitLayout.setSnapTarget(snapTarget); + mSplitLayout.snapToTarget(position, snapTarget); break; } return true; 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 e11037f55cfa..e1a94b071bf4 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 @@ -22,6 +22,9 @@ import static android.view.WindowManager.DOCKED_TOP; import static com.android.internal.policy.DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_END; import static com.android.internal.policy.DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_START; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; @@ -31,6 +34,7 @@ import android.view.SurfaceControl; import androidx.annotation.Nullable; import com.android.internal.policy.DividerSnapAlgorithm; +import com.android.wm.shell.animation.Interpolators; /** * Records and handles layout of splits. Helps to calculate proper bounds when configuration or @@ -119,14 +123,16 @@ public class SplitLayout { mBounds1.set(mRootBounds); mBounds2.set(mRootBounds); if (isLandscape(mRootBounds)) { + position += mRootBounds.left; mDividerBounds.left = position - mDividerInsets; mDividerBounds.right = mDividerBounds.left + mDividerWindowWidth; - mBounds1.right = mBounds1.left + position; + mBounds1.right = position; mBounds2.left = mBounds1.right + mDividerSize; } else { + position += mRootBounds.top; mDividerBounds.top = position - mDividerInsets; mDividerBounds.bottom = mDividerBounds.top + mDividerWindowWidth; - mBounds1.bottom = mBounds1.top + position; + mBounds1.bottom = position; mBounds2.top = mBounds1.bottom + mDividerSize; } } @@ -145,17 +151,23 @@ public class SplitLayout { * Updates bounds with the passing position. Usually used to update recording bounds while * performing animation or dragging divider bar to resize the splits. */ - public void updateDividePosition(int position) { + void updateDivideBounds(int position) { updateBounds(position); mLayoutChangeListener.onBoundsChanging(this); } + void setDividePosition(int position) { + mDividePosition = position; + updateBounds(mDividePosition); + mLayoutChangeListener.onBoundsChanged(this); + } + /** * Sets new divide position and updates bounds correspondingly. Notifies listener if the new * target indicates dismissing split. */ - public void setSnapTarget(DividerSnapAlgorithm.SnapTarget snapTarget) { - switch(snapTarget.flag) { + public void snapToTarget(int currentPosition, DividerSnapAlgorithm.SnapTarget snapTarget) { + switch (snapTarget.flag) { case FLAG_DISMISS_START: mLayoutChangeListener.onSnappedToDismiss(false /* snappedToEnd */); break; @@ -163,9 +175,7 @@ public class SplitLayout { mLayoutChangeListener.onSnappedToDismiss(true /* snappedToEnd */); break; default: - mDividePosition = snapTarget.position; - updateBounds(mDividePosition); - mLayoutChangeListener.onBoundsChanged(this); + flingDividePosition(currentPosition, snapTarget.position); break; } } @@ -189,6 +199,27 @@ public class SplitLayout { isLandscape ? DOCKED_LEFT : DOCKED_TOP /* dockSide */); } + private void flingDividePosition(int from, int to) { + ValueAnimator animator = ValueAnimator + .ofInt(from, to) + .setDuration(250); + animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN); + animator.addUpdateListener( + animation -> updateDivideBounds((int) animation.getAnimatedValue())); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + setDividePosition(to); + } + + @Override + public void onAnimationCancel(Animator animation) { + setDividePosition(to); + } + }); + animator.start(); + } + private static boolean isLandscape(Rect bounds) { return bounds.width() > bounds.height(); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java index a89c8bb29c1b..8ae66790eb3b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java @@ -52,7 +52,7 @@ import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.R; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.protolog.ShellProtoLogGroup; -import com.android.wm.shell.splitscreen.SplitScreen; +import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import java.util.Optional; @@ -66,7 +66,7 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange private final Context mContext; private final DisplayController mDisplayController; - private SplitScreen mSplitScreen; + private LegacySplitScreen mLegacySplitScreen; private final SparseArray<PerDisplay> mDisplayDropTargets = new SparseArray<>(); private final SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction(); @@ -77,8 +77,8 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange mDisplayController.addDisplayWindowListener(this); } - public void setSplitScreenController(Optional<SplitScreen> splitscreen) { - mSplitScreen = splitscreen.orElse(null); + public void setSplitScreenController(Optional<LegacySplitScreen> splitscreen) { + mLegacySplitScreen = splitscreen.orElse(null); } @Override @@ -104,7 +104,7 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange R.layout.global_drop_target, null); rootView.setOnDragListener(this); rootView.setVisibility(View.INVISIBLE); - DragLayout dragLayout = new DragLayout(context, mSplitScreen); + DragLayout dragLayout = new DragLayout(context, mLegacySplitScreen); rootView.addView(dragLayout, new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)); try { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java index 7b3b5dbfa51c..4043d0bd3173 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java @@ -37,7 +37,6 @@ import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPL import android.app.ActivityManager; import android.app.ActivityTaskManager; -import android.app.IActivityTaskManager; import android.app.PendingIntent; import android.app.WindowConfiguration; import android.content.ActivityNotFoundException; @@ -60,7 +59,7 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import com.android.wm.shell.common.DisplayLayout; -import com.android.wm.shell.splitscreen.SplitScreen; +import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -78,22 +77,22 @@ public class DragAndDropPolicy { private final Context mContext; private final ActivityTaskManager mActivityTaskManager; private final Starter mStarter; - private final SplitScreen mSplitScreen; + private final LegacySplitScreen mLegacySplitScreen; private final ArrayList<DragAndDropPolicy.Target> mTargets = new ArrayList<>(); private DragSession mSession; - public DragAndDropPolicy(Context context, SplitScreen splitScreen) { - this(context, ActivityTaskManager.getInstance(), splitScreen, - new DefaultStarter(context, splitScreen)); + public DragAndDropPolicy(Context context, LegacySplitScreen legacySplitScreen) { + this(context, ActivityTaskManager.getInstance(), legacySplitScreen, + new DefaultStarter(context, legacySplitScreen)); } @VisibleForTesting DragAndDropPolicy(Context context, ActivityTaskManager activityTaskManager, - SplitScreen splitScreen, Starter starter) { + LegacySplitScreen legacySplitScreen, Starter starter) { mContext = context; mActivityTaskManager = activityTaskManager; - mSplitScreen = splitScreen; + mLegacySplitScreen = legacySplitScreen; mStarter = starter; } @@ -151,13 +150,13 @@ public class DragAndDropPolicy { new Rect(w / 2, 0, w, h))); } } else if (mSession.dragItemSupportsSplitscreen - && mSplitScreen != null - && mSplitScreen.isDividerVisible()) { + && mLegacySplitScreen != null + && mLegacySplitScreen.isDividerVisible()) { // Already split, allow replacing existing split task // TODO(b/169894807): For now, only allow replacing the non-primary task until we have // split pairs final Rect secondarySplitRawBounds = - mSplitScreen.getDividerView().getNonMinimizedSplitScreenSecondaryBounds(); + mLegacySplitScreen.getDividerView().getNonMinimizedSplitScreenSecondaryBounds(); final Rect secondarySplitBounds = new Rect(secondarySplitRawBounds); secondarySplitBounds.intersect(new Rect(l, t, l + iw, t + ih)); if (isVerticalSplit) { @@ -212,14 +211,14 @@ public class DragAndDropPolicy { boolean deferAppLaunchUntilSplit = false; if (target.type == TYPE_FULLSCREEN) { - if (mSplitScreen != null && mSplitScreen.isDividerVisible()) { + if (mLegacySplitScreen != null && mLegacySplitScreen.isDividerVisible()) { // If in split, remove split and launch fullscreen mStarter.exitSplitScreen(mSession.runningTaskId); } else { // Not in split, fall through to launch } } else { - if (mSplitScreen != null && mSplitScreen.isDividerVisible()) { + if (mLegacySplitScreen != null && mLegacySplitScreen.isDividerVisible()) { // Split is already visible, just replace the task // TODO(b/169894807): Since we only allow replacing the non-primary target above // just fall through and start the activity @@ -250,12 +249,12 @@ public class DragAndDropPolicy { // into split, and we should wait for home and other tasks to be moved to // split-secondary before trying to launch the new secondary task. This can be removed // once we have app-pairs. - mSplitScreen.registerInSplitScreenListener(new Consumer<Boolean>() { + mLegacySplitScreen.registerInSplitScreenListener(new Consumer<Boolean>() { @Override public void accept(Boolean inSplit) { if (inSplit) { startAppRunnable.run(); - mSplitScreen.unregisterInSplitScreenListener(this); + mLegacySplitScreen.unregisterInSplitScreenListener(this); } } }); @@ -333,11 +332,11 @@ public class DragAndDropPolicy { */ private static class DefaultStarter implements Starter { private final Context mContext; - private final SplitScreen mSplitScreen; + private final LegacySplitScreen mLegacySplitScreen; - public DefaultStarter(Context context, SplitScreen splitScreen) { + public DefaultStarter(Context context, LegacySplitScreen legacySplitScreen) { mContext = context; - mSplitScreen = splitScreen; + mLegacySplitScreen = legacySplitScreen; } @Override @@ -373,12 +372,12 @@ public class DragAndDropPolicy { @Override public void enterSplitScreen(int taskId, boolean leftOrTop) { - mSplitScreen.splitPrimaryTask(); + mLegacySplitScreen.splitPrimaryTask(); } @Override public void exitSplitScreen(int taskId) { - mSplitScreen.dismissSplitToPrimaryTask(); + mLegacySplitScreen.dismissSplitToPrimaryTask(); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java index 5b7531c09a7b..a56fe8ded2e3 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java @@ -35,7 +35,6 @@ import android.view.SurfaceControl; import android.view.View; import android.view.WindowInsets; import android.view.WindowInsets.Type; -import android.view.animation.Interpolator; import androidx.annotation.NonNull; @@ -43,10 +42,9 @@ import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.R; import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.protolog.ShellProtoLogGroup; -import com.android.wm.shell.splitscreen.SplitScreen; +import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import java.util.ArrayList; -import java.util.function.Consumer; /** * Coordinates the visible drop targets for the current drag. @@ -63,7 +61,7 @@ public class DragLayout extends View { private boolean mIsShowing; private boolean mHasDropped; - public DragLayout(Context context, SplitScreen splitscreen) { + public DragLayout(Context context, LegacySplitScreen splitscreen) { super(context); mPolicy = new DragAndDropPolicy(context, splitscreen); mDisplayMargin = context.getResources().getDimensionPixelSize( diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerHandleView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerHandleView.java index 2cb1fff4cde6..17ca110285bf 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerHandleView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerHandleView.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.wm.shell.splitscreen; +package com.android.wm.shell.legacysplitscreen; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerImeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerImeController.java index eb82357f2dea..2c0cf5938474 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerImeController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerImeController.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.wm.shell.splitscreen; +package com.android.wm.shell.legacysplitscreen; import static android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED; import static android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED; @@ -26,6 +26,7 @@ import android.annotation.Nullable; import android.graphics.Rect; import android.os.Handler; import android.util.Slog; +import android.view.Choreographer; import android.view.SurfaceControl; import android.window.TaskOrganizer; import android.window.WindowContainerToken; @@ -36,11 +37,11 @@ import com.android.wm.shell.common.TransactionPool; class DividerImeController implements DisplayImeController.ImePositionProcessor { private static final String TAG = "DividerImeController"; - private static final boolean DEBUG = SplitScreenController.DEBUG; + private static final boolean DEBUG = LegacySplitScreenController.DEBUG; private static final float ADJUSTED_NONFOCUS_DIM = 0.3f; - private final SplitScreenTaskListener mSplits; + private final LegacySplitScreenTaskListener mSplits; private final TransactionPool mTransactionPool; private final Handler mHandler; private final TaskOrganizer mTaskOrganizer; @@ -92,8 +93,8 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor private boolean mPausedTargetAdjusted = false; private boolean mAdjustedWhileHidden = false; - DividerImeController(SplitScreenTaskListener splits, TransactionPool pool, Handler handler, - TaskOrganizer taskOrganizer) { + DividerImeController(LegacySplitScreenTaskListener splits, TransactionPool pool, + Handler handler, TaskOrganizer taskOrganizer) { mSplits = splits; mTransactionPool = pool; mHandler = handler; @@ -104,7 +105,7 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor return mSplits.mSplitScreenController.getDividerView(); } - private SplitDisplayLayout getLayout() { + private LegacySplitDisplayLayout getLayout() { return mSplits.mSplitScreenController.getSplitLayout(); } @@ -201,7 +202,7 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor // Reposition the server's secondary split position so that it evaluates // insets properly. WindowContainerTransaction wct = new WindowContainerTransaction(); - final SplitDisplayLayout splitLayout = getLayout(); + final LegacySplitDisplayLayout splitLayout = getLayout(); if (mTargetAdjusted) { splitLayout.updateAdjustedBounds(mShownTop, mHiddenTop, mShownTop); wct.setBounds(mSplits.mSecondary.token, splitLayout.mAdjustedSecondary); @@ -284,7 +285,7 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor private void onProgress(float progress, SurfaceControl.Transaction t) { final DividerView view = getView(); if (mTargetAdjusted != mAdjusted && !mPaused) { - final SplitDisplayLayout splitLayout = getLayout(); + final LegacySplitDisplayLayout splitLayout = getLayout(); final float fraction = mTargetAdjusted ? progress : 1.f - progress; mLastAdjustTop = (int) (fraction * mShownTop + (1.f - fraction) * mHiddenTop); splitLayout.updateAdjustedBounds(mLastAdjustTop, mHiddenTop, mShownTop); @@ -338,6 +339,7 @@ class DividerImeController implements DisplayImeController.ImePositionProcessor SurfaceControl.Transaction t = mTransactionPool.acquire(); float value = (float) animation.getAnimatedValue(); onProgress(value, t); + t.setFrameTimelineVsync(Choreographer.getSfInstance().getVsyncId()); t.apply(); mTransactionPool.release(t); }); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerState.java index 23d86a00d4bf..af2ab158ab46 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerState.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerState.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.wm.shell.splitscreen; +package com.android.wm.shell.legacysplitscreen; /** * Class to hold state of divider that needs to persist across configuration changes. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java index c6496ad6246f..16c966fccbf4 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerView.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.wm.shell.splitscreen; +package com.android.wm.shell.legacysplitscreen; import static android.view.PointerIcon.TYPE_HORIZONTAL_DOUBLE_ARROW; import static android.view.PointerIcon.TYPE_VERTICAL_DOUBLE_ARROW; @@ -37,6 +37,7 @@ import android.os.Handler; import android.os.RemoteException; import android.util.AttributeSet; import android.util.Slog; +import android.view.Choreographer; import android.view.Display; import android.view.MotionEvent; import android.view.PointerIcon; @@ -74,7 +75,7 @@ import java.util.function.Consumer; public class DividerView extends FrameLayout implements OnTouchListener, OnComputeInternalInsetsListener { private static final String TAG = "DividerView"; - private static final boolean DEBUG = SplitScreenController.DEBUG; + private static final boolean DEBUG = LegacySplitScreenController.DEBUG; interface DividerCallbacks { void onDraggingStart(); @@ -136,12 +137,12 @@ public class DividerView extends FrameLayout implements OnTouchListener, private final Rect mOtherInsetRect = new Rect(); private final Rect mLastResizeRect = new Rect(); private final Rect mTmpRect = new Rect(); - private SplitScreenController mSplitScreenController; + private LegacySplitScreenController mSplitScreenController; private WindowManagerProxy mWindowManagerProxy; private DividerWindowManager mWindowManager; private VelocityTracker mVelocityTracker; private FlingAnimationUtils mFlingAnimationUtils; - private SplitDisplayLayout mSplitLayout; + private LegacySplitDisplayLayout mSplitLayout; private DividerImeController mImeController; private DividerCallbacks mCallback; private final AnimationHandler mAnimationHandler = new AnimationHandler(); @@ -155,7 +156,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, private boolean mAdjustedForIme; private DividerState mState; - private SplitScreenTaskListener mTiles; + private LegacySplitScreenTaskListener mTiles; boolean mFirstLayout = true; int mDividerPositionX; int mDividerPositionY; @@ -352,10 +353,11 @@ public class DividerView extends FrameLayout implements OnTouchListener, } } - void injectDependencies(SplitScreenController splitScreenController, + void injectDependencies(LegacySplitScreenController splitScreenController, DividerWindowManager windowManager, DividerState dividerState, - DividerCallbacks callback, SplitScreenTaskListener tiles, SplitDisplayLayout sdl, - DividerImeController imeController, WindowManagerProxy wmProxy) { + DividerCallbacks callback, LegacySplitScreenTaskListener tiles, + LegacySplitDisplayLayout sdl, DividerImeController imeController, + WindowManagerProxy wmProxy) { mSplitScreenController = splitScreenController; mWindowManager = windowManager; mState = dividerState; @@ -1108,6 +1110,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, } resizeSplitSurfaces(t, mDockedRect, mDockedTaskRect, mOtherRect, mOtherTaskRect); if (ownTransaction) { + t.setFrameTimelineVsync(Choreographer.getSfInstance().getVsyncId()); t.apply(); mTiles.releaseTransaction(t); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerWindowManager.java index 5078371dab64..2c3ae68e4749 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerWindowManager.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/DividerWindowManager.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.wm.shell.splitscreen; +package com.android.wm.shell.legacysplitscreen; import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ForcedResizableInfoActivity.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/ForcedResizableInfoActivity.java index 7a1633530148..abff69c9ecbb 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ForcedResizableInfoActivity.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/ForcedResizableInfoActivity.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.wm.shell.splitscreen; +package com.android.wm.shell.legacysplitscreen; import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY; import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SPLIT_SCREEN; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ForcedResizableInfoActivityController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/ForcedResizableInfoActivityController.java index 1ef142dacb9e..ee5c9bce1289 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ForcedResizableInfoActivityController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/ForcedResizableInfoActivityController.java @@ -14,10 +14,10 @@ * limitations under the License. */ -package com.android.wm.shell.splitscreen; +package com.android.wm.shell.legacysplitscreen; -import static com.android.wm.shell.splitscreen.ForcedResizableInfoActivity.EXTRA_FORCED_RESIZEABLE_REASON; +import static com.android.wm.shell.legacysplitscreen.ForcedResizableInfoActivity.EXTRA_FORCED_RESIZEABLE_REASON; import android.app.ActivityOptions; import android.content.Context; @@ -69,7 +69,7 @@ final class ForcedResizableInfoActivityController implements DividerView.Divider } ForcedResizableInfoActivityController(Context context, - SplitScreenController splitScreenController) { + LegacySplitScreenController splitScreenController) { mContext = context; splitScreenController.registerInSplitScreenListener(mDockedStackExistsListener); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitDisplayLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitDisplayLayout.java index 7d5e1a84a38d..477ec339f1db 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitDisplayLayout.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitDisplayLayout.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.wm.shell.splitscreen; +package com.android.wm.shell.legacysplitscreen; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; @@ -40,14 +40,14 @@ import com.android.wm.shell.common.DisplayLayout; * Handles split-screen related internal display layout. In general, this represents the * WM-facing understanding of the splits. */ -public class SplitDisplayLayout { +public class LegacySplitDisplayLayout { /** Minimum size of an adjusted stack bounds relative to original stack bounds. Used to * restrict IME adjustment so that a min portion of top stack remains visible.*/ private static final float ADJUSTED_STACK_FRACTION_MIN = 0.3f; private static final int DIVIDER_WIDTH_INACTIVE_DP = 4; - SplitScreenTaskListener mTiles; + LegacySplitScreenTaskListener mTiles; DisplayLayout mDisplayLayout; Context mContext; @@ -62,7 +62,8 @@ public class SplitDisplayLayout { Rect mAdjustedPrimary = null; Rect mAdjustedSecondary = null; - public SplitDisplayLayout(Context ctx, DisplayLayout dl, SplitScreenTaskListener taskTiles) { + public LegacySplitDisplayLayout(Context ctx, DisplayLayout dl, + LegacySplitScreenTaskListener taskTiles) { mTiles = taskTiles; mDisplayLayout = dl; mContext = ctx; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreen.java index 7c70a4efad91..499a9c5fa631 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreen.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.wm.shell.splitscreen; +package com.android.wm.shell.legacysplitscreen; import android.graphics.Rect; import android.window.WindowContainerToken; @@ -29,7 +29,7 @@ import java.util.function.Consumer; * Interface to engage split screen feature. */ @ExternalThread -public interface SplitScreen { +public interface LegacySplitScreen { /** Called when keyguard showing state changed. */ void onKeyguardVisibilityChanged(boolean isShowing); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java index 6d6c76139c87..d88696db7c1f 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.wm.shell.splitscreen; +package com.android.wm.shell.legacysplitscreen; import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; @@ -65,7 +65,7 @@ import java.util.function.Consumer; /** * Controls split screen feature. */ -public class SplitScreenController implements SplitScreen, +public class LegacySplitScreenController implements LegacySplitScreen, DisplayController.OnDisplaysChangedListener { static final boolean DEBUG = false; @@ -80,7 +80,7 @@ public class SplitScreenController implements SplitScreen, private final DividerState mDividerState = new DividerState(); private final ForcedResizableInfoActivityController mForcedResizableController; private final Handler mHandler; - private final SplitScreenTaskListener mSplits; + private final LegacySplitScreenTaskListener mSplits; private final SystemWindows mSystemWindows; final TransactionPool mTransactionPool; private final WindowManagerProxy mWindowManagerProxy; @@ -96,12 +96,12 @@ public class SplitScreenController implements SplitScreen, private DividerView mView; // Keeps track of real-time split geometry including snap positions and ime adjustments - private SplitDisplayLayout mSplitLayout; + private LegacySplitDisplayLayout mSplitLayout; // Transient: this contains the layout calculated for a new rotation requested by WM. This is // kept around so that we can wait for a matching configuration change and then use the exact // layout that we sent back to WM. - private SplitDisplayLayout mRotateSplitLayout; + private LegacySplitDisplayLayout mRotateSplitLayout; private boolean mIsKeyguardShowing; private boolean mVisible = false; @@ -109,7 +109,7 @@ public class SplitScreenController implements SplitScreen, private boolean mAdjustedForIme = false; private boolean mHomeStackResizable = false; - public SplitScreenController(Context context, + public LegacySplitScreenController(Context context, DisplayController displayController, SystemWindows systemWindows, DisplayImeController imeController, Handler handler, TransactionPool transactionPool, ShellTaskOrganizer shellTaskOrganizer, SyncTransactionQueue syncQueue, @@ -123,7 +123,7 @@ public class SplitScreenController implements SplitScreen, mTransactionPool = transactionPool; mWindowManagerProxy = new WindowManagerProxy(syncQueue, shellTaskOrganizer); mTaskOrganizer = shellTaskOrganizer; - mSplits = new SplitScreenTaskListener(this, shellTaskOrganizer, syncQueue); + mSplits = new LegacySplitScreenTaskListener(this, shellTaskOrganizer, syncQueue); mImePositionProcessor = new DividerImeController(mSplits, mTransactionPool, mHandler, shellTaskOrganizer); mRotationController = @@ -134,8 +134,8 @@ public class SplitScreenController implements SplitScreen, WindowContainerTransaction t = new WindowContainerTransaction(); DisplayLayout displayLayout = new DisplayLayout(mDisplayController.getDisplayLayout(display)); - SplitDisplayLayout sdl = - new SplitDisplayLayout(mContext, displayLayout, mSplits); + LegacySplitDisplayLayout sdl = + new LegacySplitDisplayLayout(mContext, displayLayout, mSplits); sdl.rotateTo(toRotation); mRotateSplitLayout = sdl; final int position = isDividerVisible() @@ -229,7 +229,7 @@ public class SplitScreenController implements SplitScreen, if (displayId != DEFAULT_DISPLAY) { return; } - mSplitLayout = new SplitDisplayLayout(mDisplayController.getDisplayContext(displayId), + mSplitLayout = new LegacySplitDisplayLayout(mDisplayController.getDisplayContext(displayId), mDisplayController.getDisplayLayout(displayId), mSplits); mImeController.addPositionProcessor(mImePositionProcessor); mDisplayController.addDisplayChangingController(mRotationController); @@ -251,7 +251,7 @@ public class SplitScreenController implements SplitScreen, if (displayId != DEFAULT_DISPLAY || !mSplits.isSplitScreenSupported()) { return; } - mSplitLayout = new SplitDisplayLayout(mDisplayController.getDisplayContext(displayId), + mSplitLayout = new LegacySplitDisplayLayout(mDisplayController.getDisplayContext(displayId), mDisplayController.getDisplayLayout(displayId), mSplits); if (mRotateSplitLayout == null) { int midPos = mSplitLayout.getSnapAlgorithm().getMiddleTarget().position; @@ -586,7 +586,7 @@ public class SplitScreenController implements SplitScreen, } } - SplitDisplayLayout getSplitLayout() { + LegacySplitDisplayLayout getSplitLayout() { return mSplitLayout; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenTaskListener.java index 5b2b38ba8189..02c82dee8ca4 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenTaskListener.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.wm.shell.splitscreen; +package com.android.wm.shell.legacysplitscreen; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; @@ -43,9 +43,9 @@ import com.android.wm.shell.common.SyncTransactionQueue; import java.io.PrintWriter; import java.util.ArrayList; -class SplitScreenTaskListener implements ShellTaskOrganizer.TaskListener { - private static final String TAG = "SplitScreenTaskListener"; - private static final boolean DEBUG = SplitScreenController.DEBUG; +class LegacySplitScreenTaskListener implements ShellTaskOrganizer.TaskListener { + private static final String TAG = LegacySplitScreenTaskListener.class.getSimpleName(); + private static final boolean DEBUG = LegacySplitScreenController.DEBUG; private final ShellTaskOrganizer mTaskOrganizer; private final SyncTransactionQueue mSyncQueue; @@ -58,12 +58,12 @@ class SplitScreenTaskListener implements ShellTaskOrganizer.TaskListener { SurfaceControl mPrimaryDim; SurfaceControl mSecondaryDim; Rect mHomeBounds = new Rect(); - final SplitScreenController mSplitScreenController; + final LegacySplitScreenController mSplitScreenController; private boolean mSplitScreenSupported = false; final SurfaceSession mSurfaceSession = new SurfaceSession(); - SplitScreenTaskListener(SplitScreenController splitScreenController, + LegacySplitScreenTaskListener(LegacySplitScreenController splitScreenController, ShellTaskOrganizer shellTaskOrganizer, SyncTransactionQueue syncQueue) { mSplitScreenController = splitScreenController; @@ -205,12 +205,9 @@ class SplitScreenTaskListener implements ShellTaskOrganizer.TaskListener { private void updateChildTaskSurface( RunningTaskInfo taskInfo, SurfaceControl leash, boolean firstAppeared) { - final Rect taskBounds = taskInfo.getConfiguration().windowConfiguration.getBounds(); final Point taskPositionInParent = taskInfo.positionInParent; - final Rect corp = new Rect(taskBounds); - corp.offset(-taskBounds.left, -taskBounds.top); mSyncQueue.runInSync(t -> { - t.setWindowCrop(leash, corp); + t.setWindowCrop(leash, null); t.setPosition(leash, taskPositionInParent.x, taskPositionInParent.y); if (firstAppeared && !Transitions.ENABLE_SHELL_TRANSITIONS) { t.setAlpha(leash, 1f); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MinimizedDockShadow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/MinimizedDockShadow.java index 06f4ef109193..1e9223cbe3e2 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MinimizedDockShadow.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/MinimizedDockShadow.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.wm.shell.splitscreen; +package com.android.wm.shell.legacysplitscreen; import android.annotation.Nullable; import android.content.Context; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/WindowManagerProxy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/WindowManagerProxy.java index 0307206e2def..68da35d9c4b1 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/WindowManagerProxy.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/WindowManagerProxy.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.wm.shell.splitscreen; +package com.android.wm.shell.legacysplitscreen; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; @@ -88,8 +88,8 @@ class WindowManagerProxy { mTaskOrganizer = taskOrganizer; } - void dismissOrMaximizeDocked(final SplitScreenTaskListener tiles, SplitDisplayLayout layout, - final boolean dismissOrMaximize) { + void dismissOrMaximizeDocked(final LegacySplitScreenTaskListener tiles, + LegacySplitDisplayLayout layout, final boolean dismissOrMaximize) { mExecutor.execute(() -> applyDismissSplit(tiles, layout, dismissOrMaximize)); } @@ -114,7 +114,7 @@ class WindowManagerProxy { mExecutor.execute(mSetTouchableRegionRunnable); } - void applyResizeSplits(int position, SplitDisplayLayout splitLayout) { + void applyResizeSplits(int position, LegacySplitDisplayLayout splitLayout) { WindowContainerTransaction t = new WindowContainerTransaction(); splitLayout.resizeSplits(position, t); new WindowOrganizer().applyTransaction(t); @@ -141,7 +141,7 @@ class WindowManagerProxy { * split is minimized. This actually "sticks out" of the secondary split area, but when in * minimized mode, the secondary split gets a 'negative' crop to expose it. */ - boolean applyHomeTasksMinimized(SplitDisplayLayout layout, WindowContainerToken parent, + boolean applyHomeTasksMinimized(LegacySplitDisplayLayout layout, WindowContainerToken parent, @NonNull WindowContainerTransaction wct) { // Resize the home/recents stacks to the larger minimized-state size final Rect homeBounds; @@ -189,7 +189,7 @@ class WindowManagerProxy { * * @return whether the home stack is resizable */ - boolean applyEnterSplit(SplitScreenTaskListener tiles, SplitDisplayLayout layout) { + boolean applyEnterSplit(LegacySplitScreenTaskListener tiles, LegacySplitDisplayLayout layout) { // Set launchtile first so that any stack created after // getAllRootTaskInfos and before reparent (even if unlikely) are placed // correctly. @@ -241,7 +241,7 @@ class WindowManagerProxy { * split (thus resulting in the top of the secondary split becoming * fullscreen. {@code false} resolves the other way. */ - void applyDismissSplit(SplitScreenTaskListener tiles, SplitDisplayLayout layout, + void applyDismissSplit(LegacySplitScreenTaskListener tiles, LegacySplitDisplayLayout layout, boolean dismissOrMaximize) { // Set launch root first so that any task created after getChildContainers and // before reparent (pretty unlikely) are put into fullscreen. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/letterbox/LetterboxConfigController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/letterbox/LetterboxConfigController.java deleted file mode 100644 index 0a549c6aa7d9..000000000000 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/letterbox/LetterboxConfigController.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.wm.shell.letterbox; - -import android.content.Context; -import android.view.Gravity; - -import com.android.wm.shell.R; - -/** - * Controls access to and overrides of resource config values used by {@link - * LetterboxTaskOrganizer}. - */ -public final class LetterboxConfigController { - - private final Context mContext; - - /** {@link Gravity} of letterboxed apps in portrait screen orientation. */ - private int mLetterboxPortraitGravity; - - /** {@link Gravity} of letterboxed apps in landscape screen orientation. */ - private int mLetterboxLandscapeGravity; - - public LetterboxConfigController(Context context) { - mContext = context; - mLetterboxPortraitGravity = - mContext.getResources().getInteger(R.integer.config_letterboxPortraitGravity); - mLetterboxLandscapeGravity = - mContext.getResources().getInteger(R.integer.config_letterboxLandscapeGravity); - } - - /** - * Overrides {@link Gravity} of letterboxed apps in portrait screen orientation. - * - * @throws IllegalArgumentException if gravity isn't equal to {@link Gravity#TOP}, {@link - * Gravity#CENTER} or {@link Gravity#BOTTOM}. - */ - public void setPortraitGravity(int gravity) { - if (gravity != Gravity.TOP && gravity != Gravity.CENTER && gravity != Gravity.BOTTOM) { - throw new IllegalArgumentException( - "Expected Gravity#TOP, Gravity#CENTER or Gravity#BOTTOM but got" - + gravity); - } - mLetterboxPortraitGravity = gravity; - } - - /** - * Resets {@link Gravity} of letterboxed apps in portrait screen orientation to {@link - * R.integer.config_letterboxPortraitGravity}. - */ - public void resetPortraitGravity() { - mLetterboxPortraitGravity = - mContext.getResources().getInteger(R.integer.config_letterboxPortraitGravity); - } - - /** - * Gets {@link Gravity} of letterboxed apps in portrait screen orientation. - */ - public int getPortraitGravity() { - return mLetterboxPortraitGravity; - } - - /** - * Overrides {@link Gravity} of letterboxed apps in landscape screen orientation. - * - * @throws IllegalArgumentException if gravity isn't equal to {@link Gravity#RIGHT}, {@link - * Gravity#CENTER} or {@link Gravity#LEFT}. - */ - public void setLandscapeGravity(int gravity) { - if (gravity != Gravity.LEFT && gravity != Gravity.CENTER && gravity != Gravity.RIGHT) { - throw new IllegalArgumentException( - "Expected Gravity#LEFT, Gravity#CENTER or Gravity#RIGHT but got" - + gravity); - } - mLetterboxLandscapeGravity = gravity; - } - - /** - * Resets {@link Gravity} of letterboxed apps in landscape screen orientation to {@link - * R.integer.config_letterboxLandscapeGravity}. - */ - public void resetLandscapeGravity() { - mLetterboxLandscapeGravity = - mContext.getResources().getInteger(R.integer.config_letterboxLandscapeGravity); - } - - /** - * Gets {@link Gravity} of letterboxed apps in landscape screen orientation. - */ - public int getLandscapeGravity() { - return mLetterboxLandscapeGravity; - } - -} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/letterbox/LetterboxTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/letterbox/LetterboxTaskListener.java deleted file mode 100644 index 490ef3296be6..000000000000 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/letterbox/LetterboxTaskListener.java +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.wm.shell.letterbox; - -import android.app.ActivityManager; -import android.graphics.Insets; -import android.graphics.Point; -import android.graphics.Rect; -import android.util.Slog; -import android.util.SparseArray; -import android.view.Gravity; -import android.view.SurfaceControl; -import android.view.WindowInsets; -import android.view.WindowManager; - -import com.android.internal.protolog.common.ProtoLog; -import com.android.wm.shell.ShellTaskOrganizer; -import com.android.wm.shell.Transitions; -import com.android.wm.shell.common.SyncTransactionQueue; -import com.android.wm.shell.protolog.ShellProtoLogGroup; - -/** - * Organizes a task in {@link android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN} when - * it's presented in the letterbox mode either because orientations of a top activity and a device - * don't match or because a top activity is in a size compat mode. - */ -public class LetterboxTaskListener implements ShellTaskOrganizer.TaskListener { - private static final String TAG = "LetterboxTaskListener"; - - private final SyncTransactionQueue mSyncQueue; - private final LetterboxConfigController mLetterboxConfigController; - private final WindowManager mWindowManager; - private final SparseArray<SurfaceControl> mLeashByTaskId = new SparseArray<>(); - - public LetterboxTaskListener( - SyncTransactionQueue syncQueue, - LetterboxConfigController letterboxConfigController, - WindowManager windowManager) { - mSyncQueue = syncQueue; - mLetterboxConfigController = letterboxConfigController; - mWindowManager = windowManager; - } - - @Override - public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) { - if (mLeashByTaskId.get(taskInfo.taskId) != null) { - throw new IllegalStateException("Task appeared more than once: #" + taskInfo.taskId); - } - ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Letterbox Task Appeared: #%d", - taskInfo.taskId); - mLeashByTaskId.put(taskInfo.taskId, leash); - Point positionInParent = new Point(); - Rect crop = new Rect(); - resolveTaskPositionAndCrop(taskInfo, positionInParent, crop); - mSyncQueue.runInSync(t -> { - setPositionAndWindowCrop(t, leash, positionInParent, crop); - if (!Transitions.ENABLE_SHELL_TRANSITIONS) { - t.setAlpha(leash, 1f); - t.setMatrix(leash, 1, 0, 0, 1); - t.show(leash); - } - }); - } - - @Override - public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) { - if (mLeashByTaskId.get(taskInfo.taskId) == null) { - Slog.e(TAG, "Task already vanished: #" + taskInfo.taskId); - return; - } - mLeashByTaskId.remove(taskInfo.taskId); - ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Letterbox Task Vanished: #%d", - taskInfo.taskId); - } - - @Override - public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) { - ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Letterbox Task Changed: #%d", - taskInfo.taskId); - final SurfaceControl leash = mLeashByTaskId.get(taskInfo.taskId); - Point positionInParent = new Point(); - Rect crop = new Rect(); - resolveTaskPositionAndCrop(taskInfo, positionInParent, crop); - mSyncQueue.runInSync(t -> setPositionAndWindowCrop(t, leash, positionInParent, crop)); - } - - private static void setPositionAndWindowCrop( - SurfaceControl.Transaction transaction, - SurfaceControl leash, - final Point positionInParent, - final Rect crop) { - transaction.setPosition(leash, positionInParent.x, positionInParent.y); - transaction.setWindowCrop(leash, crop); - } - - // TODO(b/173440321): Correct presentation of letterboxed activities in One-handed mode. - private void resolveTaskPositionAndCrop( - ActivityManager.RunningTaskInfo taskInfo, - Point positionInParent, - Rect crop) { - // In screen coordinates - Rect parentBounds = new Rect(taskInfo.parentBounds); - // Intersect parent and max bounds. This is required for situations when parent bounds - // go beyond display bounds, for example, in One-handed mode. - final Rect maxBounds = taskInfo.getConfiguration().windowConfiguration.getMaxBounds(); - if (!parentBounds.intersect(maxBounds)) { - Slog.w(TAG, "Task parent and max bounds don't intersect: #" + taskInfo.taskId); - } - - // In screen coordinates - final Rect taskBounds = taskInfo.getConfiguration().windowConfiguration.getBounds(); - final Rect activityBounds = taskInfo.letterboxActivityBounds; - - Insets insets = getInsets(); - Rect displayBoundsWithInsets = - new Rect(mWindowManager.getMaximumWindowMetrics().getBounds()); - displayBoundsWithInsets.inset(insets); - - Rect taskBoundsWithInsets = new Rect(taskBounds); - taskBoundsWithInsets.intersect(displayBoundsWithInsets); - - Rect activityBoundsWithInsets = new Rect(activityBounds); - activityBoundsWithInsets.intersect(displayBoundsWithInsets); - - Rect parentBoundsWithInsets = new Rect(parentBounds); - parentBoundsWithInsets.intersect(displayBoundsWithInsets); - - // Crop need to be in the task coordinates. - crop.set(activityBoundsWithInsets); - crop.offset(-taskBounds.left, -taskBounds.top); - - // Account for insets since coordinates calculations below are done with them. - positionInParent.x = parentBoundsWithInsets.left - parentBounds.left - - (taskBoundsWithInsets.left - taskBounds.left); - positionInParent.y = parentBoundsWithInsets.top - parentBounds.top - - (taskBoundsWithInsets.top - taskBounds.top); - - // Calculating a position of task bounds (without insets) in parent coordinates (without - // insets) to align activity bounds (without insets) as requested in config. Activity - // accounts for insets that overlap with its bounds (this overlap can be partial) so - // ignoring overlap with insets when computing the position. Also, cropping unwanted insets - // while keeping the top one if the activity is aligned at the top of the window to show - // status bar decor view. - if (parentBounds.height() >= parentBounds.width()) { - final int gravity = mLetterboxConfigController.getPortraitGravity(); - // Center activity horizontally. - positionInParent.x += - (parentBoundsWithInsets.width() - activityBoundsWithInsets.width()) / 2 - + taskBoundsWithInsets.left - activityBoundsWithInsets.left; - switch (gravity) { - case Gravity.TOP: - positionInParent.y += taskBoundsWithInsets.top - activityBoundsWithInsets.top; - break; - case Gravity.CENTER: - positionInParent.y += - taskBoundsWithInsets.top - activityBoundsWithInsets.top - + (parentBoundsWithInsets.height() - - activityBoundsWithInsets.height()) / 2; - break; - case Gravity.BOTTOM: - positionInParent.y += - parentBoundsWithInsets.height() - activityBoundsWithInsets.bottom - + taskBoundsWithInsets.top; - break; - default: - throw new AssertionError( - "Unexpected portrait gravity " + gravity - + " for task: #" + taskInfo.taskId); - } - } else { - final int gravity = mLetterboxConfigController.getLandscapeGravity(); - // Align activity to the top. - positionInParent.y += taskBoundsWithInsets.top - activityBoundsWithInsets.top; - switch (gravity) { - case Gravity.LEFT: - positionInParent.x += taskBoundsWithInsets.left - activityBoundsWithInsets.left; - break; - case Gravity.CENTER: - positionInParent.x += - (parentBoundsWithInsets.width() - activityBoundsWithInsets.width()) / 2 - + taskBoundsWithInsets.left - activityBoundsWithInsets.left; - break; - case Gravity.RIGHT: - positionInParent.x += - parentBoundsWithInsets.width() - - activityBoundsWithInsets.right + taskBoundsWithInsets.left; - break; - default: - throw new AssertionError( - "Unexpected landscape gravity " + gravity - + " for task: #" + taskInfo.taskId); - } - } - - // New bounds of the activity after it's repositioned with required gravity. - Rect newActivityBounds = new Rect(activityBounds); - // Task's surfce will be repositioned to positionInParent together with the activity - // inside it so the new activity bounds are the original activity bounds offset by - // the task's offset. - newActivityBounds.offset( - positionInParent.x - taskBounds.left, positionInParent.y - taskBounds.top); - Rect newActivityBoundsWithInsets = new Rect(newActivityBounds); - newActivityBoundsWithInsets.intersect(displayBoundsWithInsets); - // Activity handles insets on its own (e.g. under status bar or navigation bar). - // crop that is calculated above crops all insets from an activity and below insets that - // can be shown are added back to the crop bounds (e.g. if activity is still shown at the - // top of the display then the top inset won't be cropped). - // After task's surface is repositioned, intersection between an activity and insets can - // change but if it doesn't, the activity should be shown under insets to maximize visible - // area. - // Also, an activity can use area under insets and insets shouldn't be cropped in this case - // regardless of a position on the screen. - final Rect activityInsetsFromCore = taskInfo.letterboxActivityInsets; - if (newActivityBounds.top - newActivityBoundsWithInsets.top - == activityBounds.top - activityBoundsWithInsets.top - // Check whether an activity is shown under inset. If it is, then the inset from - // WM Core and the inset computed here will be different because local insets - // doesn't take into account visibility of insets requested by the activity. - || activityBoundsWithInsets.top - activityBounds.top - != activityInsetsFromCore.top) { - crop.top -= activityBoundsWithInsets.top - activityBounds.top; - } - if (newActivityBounds.bottom - newActivityBoundsWithInsets.bottom - == activityBounds.bottom - activityBoundsWithInsets.bottom - || activityBounds.bottom - activityBoundsWithInsets.bottom - != activityInsetsFromCore.bottom) { - crop.bottom += activityBounds.bottom - activityBoundsWithInsets.bottom; - } - if (newActivityBounds.left - newActivityBoundsWithInsets.left - == activityBounds.left - activityBoundsWithInsets.left - || activityBoundsWithInsets.left - activityBounds.left - != activityInsetsFromCore.left) { - crop.left -= activityBoundsWithInsets.left - activityBounds.left; - } - if (newActivityBounds.right - newActivityBoundsWithInsets.right - == activityBounds.right - activityBoundsWithInsets.right - || activityBounds.right - activityBoundsWithInsets.right - != activityInsetsFromCore.right) { - crop.right += activityBounds.right - activityBoundsWithInsets.right; - } - } - - private Insets getInsets() { - return mWindowManager - .getMaximumWindowMetrics() - .getWindowInsets() - .getInsets( - WindowInsets.Type.navigationBars() - | WindowInsets.Type.statusBars() - | WindowInsets.Type.displayCutout()); - } - -} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java index 3b1e6cbe5ccd..951a68884e11 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedGestureHandler.java @@ -75,6 +75,7 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback, @Nullable OneHandedGestureEventCallback mGestureEventCallback; private Rect mGestureRegion = new Rect(); + private boolean mIsStopGesture; /** * Constructor of OneHandedGestureHandler, we only handle the gesture of @@ -153,20 +154,20 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback, float distance = (float) Math.hypot(mLastPos.x - mDownPos.x, mLastPos.y - mDownPos.y); if (distance > mDragDistThreshold) { - mGestureEventCallback.onStop(); + mIsStopGesture = true; } } break; case MotionEvent.ACTION_UP: if (mLastPos.y >= mDownPos.y && mPassedSlop) { mGestureEventCallback.onStart(); + } else if (mIsStopGesture) { + mGestureEventCallback.onStop(); } - mPassedSlop = false; - mAllowGesture = false; + clearState(); break; case MotionEvent.ACTION_CANCEL: - mPassedSlop = false; - mAllowGesture = false; + clearState(); break; default: break; @@ -174,6 +175,11 @@ public class OneHandedGestureHandler implements OneHandedTransitionCallback, } } + private void clearState() { + mPassedSlop = false; + mIsStopGesture = false; + } + private void disposeInputChannel() { if (mInputEventReceiver != null) { mInputEventReceiver.dispose(); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java index d65ad62cdbbb..a944e3bc50cf 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedTutorialHandler.java @@ -63,6 +63,16 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback { private String mStartOneHandedDescription; private String mStopOneHandedDescription; + private enum ONE_HANDED_TRIGGER_STATE { + UNSET, ENTERING, EXITING + } + /** + * Current One-Handed trigger state. + * Note: This is a dynamic state, whenever last state has been confirmed + * (i.e. onStartFinished() or onStopFinished()), the state should be set "UNSET" at final. + */ + private ONE_HANDED_TRIGGER_STATE mTriggerState = ONE_HANDED_TRIGGER_STATE.UNSET; + /** * Container of the tutorial panel showing at outside region when one handed starting */ @@ -74,6 +84,21 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback { public void onTutorialAnimationUpdate(int offset) { mUpdateHandler.post(() -> onAnimationUpdate(offset)); } + + @Override + public void onOneHandedAnimationStart( + OneHandedAnimationController.OneHandedTransitionAnimator animator) { + mUpdateHandler.post(() -> { + final Rect startValue = (Rect) animator.getStartValue(); + if (mTriggerState == ONE_HANDED_TRIGGER_STATE.UNSET) { + mTriggerState = (startValue.top == 0) + ? ONE_HANDED_TRIGGER_STATE.ENTERING : ONE_HANDED_TRIGGER_STATE.EXITING; + if (mCanShowTutorial && mTriggerState == ONE_HANDED_TRIGGER_STATE.ENTERING) { + createTutorialTarget(); + } + } + }); + } }; public OneHandedTutorialHandler(Context context) { @@ -100,9 +125,6 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback { R.string.accessibility_action_start_one_handed); mStopOneHandedDescription = context.getResources().getString( R.string.accessibility_action_stop_one_handed); - if (mCanShowTutorial) { - createOrUpdateTutorialTarget(); - } } @Override @@ -111,6 +133,7 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback { updateFinished(View.VISIBLE, 0f); updateTutorialCount(); announcementForScreenReader(true); + mTriggerState = ONE_HANDED_TRIGGER_STATE.UNSET; }); } @@ -119,6 +142,8 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback { mUpdateHandler.post(() -> { updateFinished(View.INVISIBLE, -mTargetViewContainer.getHeight()); announcementForScreenReader(false); + removeTutorialFromWindowManager(); + mTriggerState = ONE_HANDED_TRIGGER_STATE.UNSET; }); } @@ -126,7 +151,6 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback { if (!canShowTutorial()) { return; } - mTargetViewContainer.setVisibility(visible); mTargetViewContainer.setTranslationY(finalPosition); } @@ -155,24 +179,23 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback { * Adds the tutorial target view to the WindowManager and update its layout, so it's ready * to be animated in. */ - private void createOrUpdateTutorialTarget() { - mUpdateHandler.post(() -> { - if (!mTargetViewContainer.isAttachedToWindow()) { - mTargetViewContainer.setVisibility(View.INVISIBLE); - - try { - mWindowManager.addView(mTargetViewContainer, getTutorialTargetLayoutParams()); - } catch (IllegalStateException e) { - // This shouldn't happen, but if the target is already added, just update its - // layout params. - mWindowManager.updateViewLayout( - mTargetViewContainer, getTutorialTargetLayoutParams()); - } - } else { - mWindowManager.updateViewLayout(mTargetViewContainer, - getTutorialTargetLayoutParams()); + private void createTutorialTarget() { + if (!mTargetViewContainer.isAttachedToWindow()) { + try { + mWindowManager.addView(mTargetViewContainer, getTutorialTargetLayoutParams()); + } catch (IllegalStateException e) { + // This shouldn't happen, but if the target is already added, just update its + // layout params. + mWindowManager.updateViewLayout( + mTargetViewContainer, getTutorialTargetLayoutParams()); } - }); + } + } + + private void removeTutorialFromWindowManager() { + if (mTargetViewContainer.isAttachedToWindow()) { + mWindowManager.removeViewImmediate(mTargetViewContainer); + } } OneHandedAnimationCallback getAnimationCallback() { @@ -193,7 +216,6 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback { lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS; lp.setFitInsetsTypes(0 /* types */); lp.setTitle("one-handed-tutorial-overlay"); - return lp; } @@ -206,10 +228,12 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback { private boolean canShowTutorial() { if (!mCanShowTutorial) { + // Since canSHowTutorial() will be called in onAnimationUpdate() and we still need to + // hide Tutorial text in the period of continuously onAnimationUpdate() API call, + // so we have to hide mTargetViewContainer here. mTargetViewContainer.setVisibility(View.GONE); return false; } - return true; } 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 22d8ed50c10e..484592e87a20 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 @@ -123,15 +123,16 @@ public class PipBoundsAlgorithm { /** Returns the destination bounds to place the PIP window on entry. */ public Rect getEntryDestinationBounds() { final PipBoundsState.PipReentryState reentryState = mPipBoundsState.getReentryState(); - final boolean shouldRestoreReentryBounds = reentryState != null; - final Rect destinationBounds = shouldRestoreReentryBounds + final Rect destinationBounds = reentryState != null ? getDefaultBounds(reentryState.getSnapFraction(), reentryState.getSize()) : getDefaultBounds(); - return transformBoundsToAspectRatioIfValid(destinationBounds, + final boolean useCurrentSize = reentryState != null && reentryState.getSize() != null; + final Rect r = transformBoundsToAspectRatioIfValid(destinationBounds, mPipBoundsState.getAspectRatio(), false /* useCurrentMinEdgeSize */, - shouldRestoreReentryBounds); + useCurrentSize); + return r; } /** Returns the current bounds adjusted to the new aspect ratio, if valid. */ @@ -221,24 +222,36 @@ public class PipBoundsAlgorithm { private Rect getDefaultBounds(float snapFraction, Size size) { final Rect defaultBounds = new Rect(); if (snapFraction != INVALID_SNAP_FRACTION && size != null) { + // The default bounds are the given size positioned at the given snap fraction. defaultBounds.set(0, 0, size.getWidth(), size.getHeight()); final Rect movementBounds = getMovementBounds(defaultBounds); mSnapAlgorithm.applySnapFraction(defaultBounds, movementBounds, snapFraction); + return defaultBounds; + } + + // Calculate the default size. + final Size defaultSize; + final Rect insetBounds = new Rect(); + getInsetBounds(insetBounds); + final DisplayInfo displayInfo = mPipBoundsState.getDisplayInfo(); + final Size overrideMinSize = mPipBoundsState.getOverrideMinSize(); + if (overrideMinSize != null) { + // The override minimal size is set, use that as the default size making sure it's + // adjusted to the aspect ratio. + defaultSize = adjustSizeToAspectRatio(overrideMinSize, mDefaultAspectRatio); + } else { + // Calculate the default size using the display size and default min edge size. + defaultSize = getSizeForAspectRatio(mDefaultAspectRatio, + mDefaultMinSize, displayInfo.logicalWidth, displayInfo.logicalHeight); + } + + // Now that we have the default size, apply the snap fraction if valid or position the + // bounds using the default gravity. + if (snapFraction != INVALID_SNAP_FRACTION) { + defaultBounds.set(0, 0, defaultSize.getWidth(), defaultSize.getHeight()); + final Rect movementBounds = getMovementBounds(defaultBounds); + mSnapAlgorithm.applySnapFraction(defaultBounds, movementBounds, snapFraction); } else { - final Rect insetBounds = new Rect(); - getInsetBounds(insetBounds); - final DisplayInfo displayInfo = mPipBoundsState.getDisplayInfo(); - final Size defaultSize; - final Size overrideMinSize = mPipBoundsState.getOverrideMinSize(); - if (overrideMinSize != null) { - // The override minimal size is set, use that as the default size making sure it's - // adjusted to the aspect ratio. - defaultSize = adjustSizeToAspectRatio(overrideMinSize, mDefaultAspectRatio); - } else { - // Calculate the default size using the display size and default min edge size. - defaultSize = getSizeForAspectRatio(mDefaultAspectRatio, - mDefaultMinSize, displayInfo.logicalWidth, displayInfo.logicalHeight); - } Gravity.apply(mDefaultStackGravity, defaultSize.getWidth(), defaultSize.getHeight(), insetBounds, 0, Math.max( mPipBoundsState.isImeShowing() ? mPipBoundsState.getImeHeight() : 0, 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 53aa61477483..4493d38d2144 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 @@ -76,6 +76,8 @@ public final class PipBoundsState { private int mImeHeight; private boolean mIsShelfShowing; private int mShelfHeight; + /** Whether the user has resized the PIP manually. */ + private boolean mHasUserResizedPip; private @Nullable Runnable mOnMinimalSizeChangeCallback; private @Nullable BiConsumer<Boolean, Integer> mOnShelfVisibilityChangeCallback; @@ -189,8 +191,8 @@ public final class PipBoundsState { } /** Save the reentry state to restore to when re-entering PIP mode. */ - public void saveReentryState(@NonNull Rect bounds, float fraction) { - mPipReentryState = new PipReentryState(new Size(bounds.width(), bounds.height()), fraction); + public void saveReentryState(Size size, float fraction) { + mPipReentryState = new PipReentryState(size, fraction); } /** Returns the saved reentry state. */ @@ -205,6 +207,7 @@ public final class PipBoundsState { mLastPipComponentName = lastPipComponentName; if (changed) { clearReentryState(); + setHasUserResizedPip(false); } } @@ -329,6 +332,16 @@ public final class PipBoundsState { return mShelfHeight; } + /** Returns whether the user has resized the PIP. */ + public boolean hasUserResizedPip() { + return mHasUserResizedPip; + } + + /** Set whether the user has resized the PIP. */ + public void setHasUserResizedPip(boolean hasUserResizedPip) { + mHasUserResizedPip = hasUserResizedPip; + } + /** * Registers a callback when the minimal size of PIP that is set by the app changes. */ @@ -397,15 +410,15 @@ public final class PipBoundsState { static final class PipReentryState { private static final String TAG = PipReentryState.class.getSimpleName(); - private final @NonNull Size mSize; + private final @Nullable Size mSize; private final float mSnapFraction; - PipReentryState(@NonNull Size size, float snapFraction) { + PipReentryState(@Nullable Size size, float snapFraction) { mSize = size; mSnapFraction = snapFraction; } - @NonNull + @Nullable Size getSize() { return mSize; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java index 9081783eeab8..4b283e465f1d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java @@ -66,7 +66,7 @@ import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.pip.phone.PipMotionHelper; import com.android.wm.shell.pip.phone.PipUpdateThread; -import com.android.wm.shell.splitscreen.SplitScreen; +import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import java.io.PrintWriter; import java.util.ArrayList; @@ -142,7 +142,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, private final int mEnterExitAnimationDuration; private final PipSurfaceTransactionHelper mSurfaceTransactionHelper; private final Map<IBinder, Configuration> mInitialState = new HashMap<>(); - private final Optional<SplitScreen> mSplitScreenOptional; + private final Optional<LegacySplitScreen> mSplitScreenOptional; protected final ShellTaskOrganizer mTaskOrganizer; // These callbacks are called on the update thread @@ -265,7 +265,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, @NonNull PipBoundsAlgorithm boundsHandler, @NonNull PipMenuController pipMenuController, @NonNull PipSurfaceTransactionHelper surfaceTransactionHelper, - Optional<SplitScreen> splitScreenOptional, + Optional<LegacySplitScreen> splitScreenOptional, @NonNull DisplayController displayController, @NonNull PipUiEventLogger pipUiEventLogger, @NonNull ShellTaskOrganizer shellTaskOrganizer) { @@ -1118,7 +1118,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, } /** - * Sync with {@link SplitScreen} on destination bounds if PiP is going to split screen. + * Sync with {@link LegacySplitScreen} on destination bounds if PiP is going to split screen. * * @param destinationBoundsOut contain the updated destination bounds if applicable * @return {@code true} if destinationBounds is altered for split screen @@ -1128,15 +1128,15 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, return false; } - SplitScreen splitScreen = mSplitScreenOptional.get(); - if (!splitScreen.isDividerVisible()) { + LegacySplitScreen legacySplitScreen = mSplitScreenOptional.get(); + if (!legacySplitScreen.isDividerVisible()) { // fail early if system is not in split screen mode return false; } // PiP window will go to split-secondary mode instead of fullscreen, populates the // split screen bounds here. - destinationBoundsOut.set(splitScreen.getDividerView() + destinationBoundsOut.set(legacySplitScreen.getDividerView() .getNonMinimizedSplitScreenSecondaryBounds()); return true; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java index 46fff85ca58d..4d2760259521 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 @@ -40,6 +40,7 @@ import android.os.UserHandle; import android.os.UserManager; import android.util.Log; import android.util.Pair; +import android.util.Size; import android.util.Slog; import android.view.DisplayInfo; import android.view.WindowManagerGlobal; @@ -86,7 +87,6 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac private final DisplayInfo mTmpDisplayInfo = new DisplayInfo(); private final Rect mTmpInsetBounds = new Rect(); - protected final Rect mReentryBounds = new Rect(); private boolean mIsInFixedRotation; private Consumer<Boolean> mPinnedStackAnimationRecentsCallback; @@ -438,10 +438,8 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac @Override public void onPipTransitionStarted(ComponentName activity, int direction, Rect pipBounds) { if (isOutPipDirection(direction)) { - // Exiting PIP, save the reentry bounds to restore to when re-entering. - updateReentryBounds(pipBounds); - final float snapFraction = mPipBoundsAlgorithm.getSnapFraction(mReentryBounds); - mPipBoundsState.saveReentryState(mReentryBounds, snapFraction); + // Exiting PIP, save the reentry state to restore to when re-entering. + saveReentryState(pipBounds); } // Disable touches while the animation is running mTouchHandler.setTouchEnabled(false); @@ -450,14 +448,16 @@ public class PipController implements Pip, PipTaskOrganizer.PipTransitionCallbac } } - /** - * Update the bounds used to save the re-entry size and snap fraction when exiting PIP. - */ - public void updateReentryBounds(Rect bounds) { - final Rect reentryBounds = mTouchHandler.getUserResizeBounds(); - float snapFraction = mPipBoundsAlgorithm.getSnapFraction(bounds); - mPipBoundsAlgorithm.applySnapFraction(reentryBounds, snapFraction); - mReentryBounds.set(reentryBounds); + /** Save the state to restore to on re-entry. */ + public void saveReentryState(Rect pipBounds) { + float snapFraction = mPipBoundsAlgorithm.getSnapFraction(pipBounds); + if (mPipBoundsState.hasUserResizedPip()) { + final Rect reentryBounds = mTouchHandler.getUserResizeBounds(); + final Size reentrySize = new Size(reentryBounds.width(), reentryBounds.height()); + mPipBoundsState.saveReentryState(reentrySize, snapFraction); + } else { + mPipBoundsState.saveReentryState(null /* bounds */, snapFraction); + } } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java index 2f5219c59bf2..02f6231c6ecf 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java @@ -410,6 +410,7 @@ public class PipResizeGestureHandler { mPipTaskOrganizer.scheduleUserResizePip(mLastDownBounds, mLastResizeBounds, null); + mPipBoundsState.setHasUserResizedPip(true); } } } @@ -462,6 +463,7 @@ public class PipResizeGestureHandler { true /* useCurrentSize */); mPipTaskOrganizer.scheduleUserResizePip(mLastDownBounds, mLastResizeBounds, null); + mPipBoundsState.setHasUserResizedPip(true); } break; case MotionEvent.ACTION_UP: 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 1638d72f9914..c5b54bc4abcb 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt @@ -16,8 +16,10 @@ package com.android.wm.shell.flicker +import android.graphics.Region import com.android.server.wm.flicker.dsl.EventLogAssertion import com.android.server.wm.flicker.dsl.LayersAssertion +import com.android.server.wm.flicker.helpers.WindowUtils @JvmOverloads fun LayersAssertion.appPairsDividerIsVisible( @@ -59,6 +61,50 @@ fun LayersAssertion.dockedStackDividerIsInvisible( } } +@JvmOverloads +fun LayersAssertion.dockedStackPrimaryBoundsIsVisible( + rotation: Int, + primaryLayerName: String, + bugId: Int = 0, + enabled: Boolean = bugId == 0 +) { + end("PrimaryAppBounds", bugId, enabled) { + val entry = this.trace.entries.firstOrNull() + ?: throw IllegalStateException("Trace is empty") + val dividerRegion = entry.getVisibleBounds(FlickerTestBase.DOCKED_STACK_DIVIDER) + this.hasVisibleRegion(primaryLayerName, getPrimaryRegion(dividerRegion, rotation)) + } +} + +@JvmOverloads +fun LayersAssertion.dockedStackSecondaryBoundsIsVisible( + rotation: Int, + secondaryLayerName: String, + bugId: Int = 0, + enabled: Boolean = bugId == 0 +) { + end("SecondaryAppBounds", bugId, enabled) { + val entry = this.trace.entries.firstOrNull() + ?: throw IllegalStateException("Trace is empty") + val dividerRegion = entry.getVisibleBounds(FlickerTestBase.DOCKED_STACK_DIVIDER) + this.hasVisibleRegion(secondaryLayerName, getSecondaryRegion(dividerRegion, rotation)) + } +} + +fun getPrimaryRegion(dividerRegion: Region, rotation: Int): Region { + val displayBounds = WindowUtils.getDisplayBounds(rotation) + return Region(0, 0, displayBounds.getBounds().right, + dividerRegion.getBounds().bottom - WindowUtils.dockedStackDividerInset) +} + +fun getSecondaryRegion(dividerRegion: Region, rotation: Int): Region { + val displayBounds = WindowUtils.getDisplayBounds(rotation) + return Region(0, + dividerRegion.getBounds().bottom - WindowUtils.dockedStackDividerInset, + displayBounds.getBounds().right, + displayBounds.getBounds().bottom - WindowUtils.navigationBarHeight) +} + fun EventLogAssertion.focusChanges( vararg windows: String, bugId: Int = 0, diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt index 96234fcc8570..5125a3972cf4 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt @@ -37,3 +37,4 @@ const val TEST_APP_FIXED_ACTIVITY_LABEL = "FixedApp" // Test App > SplitScreen Activity const val TEST_APP_SPLITSCREEN_PRIMARY_LABEL = "SplitScreenPrimaryApp" const val TEST_APP_SPLITSCREEN_SECONDARY_LABEL = "SplitScreenSecondaryApp" +const val TEST_APP_NONRESIZEABLE_LABEL = "NonResizeableApp" diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTest.kt index 0f8d30a94ec6..379ec95b6792 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTest.kt @@ -61,10 +61,9 @@ class AppPairsTest( setup { eachRun { uiDevice.wakeUpAndGoToHomeScreen() - primaryApp.open() - uiDevice.pressHome() - secondaryApp.open() - uiDevice.pressHome() + primaryApp.launchViaIntent() + secondaryApp.launchViaIntent() + nonResizeableApp.launchViaIntent() updateTaskId() } } @@ -90,7 +89,7 @@ class AppPairsTest( @Test fun testAppPairs_pairPrimaryAndSecondaryApps() { - val testTag = "testAppPaired_pairPrimaryAndSecondary" + val testTag = "testAppPairs_pairPrimaryAndSecondaryApps" runWithFlicker(appPairsSetup) { withTestName { testTag } repeat { @@ -176,6 +175,36 @@ class AppPairsTest( } } + @Test + fun testAppPairs_canNotPairNonResizeableApps() { + val testTag = "testAppPairs_canNotPairNonResizeableApps" + runWithFlicker(appPairsSetup) { + withTestName { testTag } + repeat { + TEST_REPETITIONS + } + transitions { + nonResizeableApp.launchViaIntent() + // TODO pair apps through normal UX flow + executeShellCommand(composePairsCommand( + primaryTaskId, nonResizeableTaskId, true /* pair */)) + SystemClock.sleep(AppPairsHelper.TIMEOUT_MS) + } + assertions { + layersTrace { + appPairsDividerIsInvisible() + } + windowManagerTrace { + end { + showsAppWindow(nonResizeableApp.defaultWindowName) + .and() + .hidesAppWindow(primaryApp.defaultWindowName) + } + } + } + } + } + private fun composePairsCommand( primaryApp: String, secondaryApp: String, @@ -202,6 +231,7 @@ class AppPairsTest( private fun updateTaskId() { val primaryAppComponent = primaryApp.openAppIntent.component val secondaryAppComponent = secondaryApp.openAppIntent.component + val nonResizeableAppComponent = nonResizeableApp.openAppIntent.component if (primaryAppComponent != null) { primaryTaskId = appPairsHelper.getTaskIdForActivity( primaryAppComponent.packageName, primaryAppComponent.className).toString() @@ -210,11 +240,17 @@ class AppPairsTest( secondaryTaskId = appPairsHelper.getTaskIdForActivity( secondaryAppComponent.packageName, secondaryAppComponent.className).toString() } + if (nonResizeableAppComponent != null) { + nonResizeableTaskId = appPairsHelper.getTaskIdForActivity( + nonResizeableAppComponent.packageName, + nonResizeableAppComponent.className).toString() + } } companion object { var primaryTaskId = "" var secondaryTaskId = "" + var nonResizeableTaskId = "" @Parameterized.Parameters(name = "{0}") @JvmStatic fun getParams(): Collection<Array<Any>> { diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestBase.kt index f32cd8842074..4d46f2856704 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestBase.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestBase.kt @@ -17,6 +17,7 @@ package com.android.wm.shell.flicker.apppairs 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 import com.android.wm.shell.flicker.TEST_APP_SPLITSCREEN_SECONDARY_LABEL import com.android.wm.shell.flicker.helpers.AppPairsHelper @@ -36,4 +37,7 @@ abstract class AppPairsTestBase( protected val secondaryApp = SplitScreenHelper(instrumentation, TEST_APP_SPLITSCREEN_SECONDARY_LABEL, Components.SplitScreenSecondaryActivity()) + protected val nonResizeableApp = SplitScreenHelper(instrumentation, + TEST_APP_NONRESIZEABLE_LABEL, + Components.NonResizeableActivity()) } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt index e67fc97dad2e..fb795c72b106 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt @@ -17,9 +17,7 @@ package com.android.wm.shell.flicker.helpers import android.app.Instrumentation -import android.graphics.Region import android.os.SystemClock -import com.android.server.wm.flicker.helpers.WindowUtils import com.android.wm.shell.flicker.testapp.Components class SplitScreenHelper( @@ -43,20 +41,6 @@ class SplitScreenHelper( SystemClock.sleep(TIMEOUT_MS) } - fun getPrimaryBounds(dividerBounds: Region): android.graphics.Region { - val primaryAppBounds = Region(0, 0, dividerBounds.bounds.right, - dividerBounds.bounds.bottom + WindowUtils.dockedStackDividerInset) - return primaryAppBounds - } - - fun getSecondaryBounds(dividerBounds: Region): android.graphics.Region { - val displayBounds = WindowUtils.displayBounds - val secondaryAppBounds = Region(0, - dividerBounds.bounds.bottom - WindowUtils.dockedStackDividerInset, - displayBounds.right, displayBounds.bottom - WindowUtils.navigationBarHeight) - return secondaryAppBounds - } - companion object { const val TEST_REPETITIONS = 1 const val TIMEOUT_MS = 3_000L diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterLegacySplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterLegacySplitScreenTest.kt new file mode 100644 index 000000000000..02f6f8c4b32f --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterLegacySplitScreenTest.kt @@ -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 com.android.wm.shell.flicker.legacysplitscreen + +import android.platform.test.annotations.Presubmit +import android.view.Surface +import androidx.test.filters.RequiresDevice +import com.android.server.wm.flicker.dsl.FlickerBuilder +import com.android.server.wm.flicker.dsl.runWithFlicker +import com.android.server.wm.flicker.helpers.WindowUtils +import com.android.server.wm.flicker.helpers.canSplitScreen +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.openQuickstep +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 +import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible +import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible +import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisible +import com.android.wm.shell.flicker.dockedStackSecondaryBoundsIsVisible +import org.junit.Assert +import org.junit.FixMethodOrder +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.MethodSorters +import org.junit.runners.Parameterized + +/** + * Test SplitScreen launch. + * To run this test: `atest WMShellFlickerTests:EnterSplitScreenTest` + */ +@Presubmit +@RequiresDevice +@RunWith(Parameterized::class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +class EnterLegacySplitScreenTest( + rotationName: String, + rotation: Int +) : SplitScreenTestBase(rotationName, rotation) { + private val splitScreenSetup: FlickerBuilder + get() = FlickerBuilder(instrumentation).apply { + val testLaunchActivity = "launch_splitScreen_test_activity" + withTestName { + testLaunchActivity + } + setup { + eachRun { + uiDevice.wakeUpAndGoToHomeScreen() + } + } + teardown { + eachRun { + if (uiDevice.isInSplitScreen()) { + uiDevice.exitSplitScreen() + } + splitScreenApp.exit() + secondaryApp.exit() + nonResizeableApp.exit() + } + } + assertions { + layersTrace { + navBarLayerIsAlwaysVisible() + statusBarLayerIsAlwaysVisible() + } + windowManagerTrace { + navBarWindowIsAlwaysVisible() + statusBarWindowIsAlwaysVisible() + } + } + } + + @Test + fun testEnterSplitScreen_dockActivity() { + val testTag = "testEnterSplitScreen_dockActivity" + runWithFlicker(splitScreenSetup) { + withTestName { testTag } + repeat { + TEST_REPETITIONS + } + transitions { + splitScreenApp.launchViaIntent() + uiDevice.launchSplitScreen() + } + assertions { + layersTrace { + dockedStackDividerIsVisible() + dockedStackPrimaryBoundsIsVisible( + rotation, splitScreenApp.defaultWindowName, 169271943) + } + windowManagerTrace { + end { + showsAppWindow(splitScreenApp.defaultWindowName) + } + } + } + } + } + + @Test + fun testEnterSplitScreen_launchToSide() { + val testTag = "testEnterSplitScreen_launchToSide" + runWithFlicker(splitScreenSetup) { + withTestName { testTag } + repeat { + TEST_REPETITIONS + } + transitions { + secondaryApp.launchViaIntent() + splitScreenApp.launchViaIntent() + uiDevice.launchSplitScreen() + splitScreenApp.reopenAppFromOverview() + } + assertions { + layersTrace { + dockedStackDividerIsVisible() + dockedStackPrimaryBoundsIsVisible( + rotation, splitScreenApp.defaultWindowName, 169271943) + dockedStackSecondaryBoundsIsVisible( + rotation, secondaryApp.defaultWindowName, 169271943) + } + windowManagerTrace { + end { + showsAppWindow(splitScreenApp.defaultWindowName) + .and().showsAppWindow(secondaryApp.defaultWindowName) + } + } + } + } + } + + @Test + fun testNonResizeableNotDocked() { + val testTag = "testNonResizeableNotDocked" + runWithFlicker(splitScreenSetup) { + withTestName { testTag } + repeat { + TEST_REPETITIONS + } + transitions { + nonResizeableApp.launchViaIntent() + uiDevice.openQuickstep() + if (uiDevice.canSplitScreen()) { + Assert.fail("Non-resizeable app should not enter split screen") + } + } + assertions { + layersTrace { + dockedStackDividerIsInvisible() + } + windowManagerTrace { + end { + hidesAppWindow(nonResizeableApp.defaultWindowName) + } + } + } + } + } + + @Test + fun testNonResizeableWhenAlreadyInSplitScreenPrimary() { + val testTag = "testNonResizeableWhenAlreadyInSplitScreenPrimary" + runWithFlicker(splitScreenSetup) { + withTestName { testTag } + repeat { + TEST_REPETITIONS + } + transitions { + nonResizeableApp.launchViaIntent() + splitScreenApp.launchViaIntent() + uiDevice.launchSplitScreen() + nonResizeableApp.reopenAppFromOverview() + } + assertions { + layersTrace { + dockedStackDividerIsInvisible() + end("appsEndingBounds", enabled = false) { + val displayBounds = WindowUtils.getDisplayBounds(rotation) + this.hasVisibleRegion(nonResizeableApp.defaultWindowName, displayBounds) + } + } + windowManagerTrace { + end { + showsAppWindow(nonResizeableApp.defaultWindowName) + hidesAppWindow(splitScreenApp.defaultWindowName) + } + } + } + } + } + + @Test + fun testNonResizeableWhenAlreadyInSplitScreenSecondary() { + val testTag = "testNonResizeableWhenAlreadyInSplitScreenSecondary" + runWithFlicker(splitScreenSetup) { + withTestName { testTag } + repeat { + TEST_REPETITIONS + } + transitions { + splitScreenApp.launchViaIntent() + uiDevice.launchSplitScreen() + uiDevice.pressBack() + nonResizeableApp.launchViaIntent() + } + assertions { + layersTrace { + dockedStackDividerIsInvisible() + end("appsEndingBounds", enabled = false) { + val displayBounds = WindowUtils.getDisplayBounds(rotation) + this.hasVisibleRegion(nonResizeableApp.defaultWindowName, displayBounds) + } + } + windowManagerTrace { + end { + showsAppWindow(nonResizeableApp.defaultWindowName) + hidesAppWindow(splitScreenApp.defaultWindowName) + } + } + } + } + } + + companion object { + @Parameterized.Parameters(name = "{0}") + @JvmStatic + fun getParams(): Collection<Array<Any>> { + val supportedRotations = intArrayOf(Surface.ROTATION_0) + return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) } + } + } +}
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/ExitSplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenTest.kt index 7c47d1f1b1ae..33306bf94639 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/ExitSplitScreenTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenTest.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.wm.shell.flicker.splitscreen +package com.android.wm.shell.flicker.legacysplitscreen import android.platform.test.annotations.Presubmit import android.util.Rational @@ -45,7 +45,7 @@ import org.junit.runners.Parameterized @RequiresDevice @RunWith(Parameterized::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) -class ExitSplitScreenTest( +class ExitLegacySplitScreenTest( rotationName: String, rotation: Int ) : SplitScreenTestBase(rotationName, rotation) { diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenToLauncherTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncherTest.kt index 00979fa9fac0..cc02aa30a4ba 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenToLauncherTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncherTest.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.wm.shell.flicker.splitscreen +package com.android.wm.shell.flicker.legacysplitscreen import android.platform.test.annotations.Presubmit import android.view.Surface @@ -54,7 +54,7 @@ import org.junit.runners.Parameterized @RequiresDevice @RunWith(Parameterized::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) -class SplitScreenToLauncherTest( +class LegacySplitScreenToLauncherTest( testName: String, flickerSpec: Flicker ) : FlickerTestRunner(testName, flickerSpec) { diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/OpenAppToSplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OpenAppToLegacySplitScreenTest.kt index c85561d96091..bb80726bf05f 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/OpenAppToSplitScreenTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OpenAppToLegacySplitScreenTest.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.wm.shell.flicker.splitscreen +package com.android.wm.shell.flicker.legacysplitscreen import android.platform.test.annotations.Presubmit import android.view.Surface @@ -54,7 +54,7 @@ import org.junit.runners.Parameterized @RequiresDevice @RunWith(Parameterized::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) -class OpenAppToSplitScreenTest( +class OpenAppToLegacySplitScreenTest( testName: String, flickerSpec: Flicker ) : FlickerTestRunner(testName, flickerSpec) { diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/ResizeSplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreenTest.kt index 7c83846621de..e3beb41750f3 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/ResizeSplitScreenTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreenTest.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.wm.shell.flicker.splitscreen +package com.android.wm.shell.flicker.legacysplitscreen import android.graphics.Region import android.util.Rational @@ -63,7 +63,7 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) @FlakyTest(bugId = 159096424) -class ResizeSplitScreenTest( +class ResizeLegacySplitScreenTest( testName: String, flickerSpec: Flicker ) : FlickerTestRunner(testName, flickerSpec) { diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppTest.kt new file mode 100644 index 000000000000..ae2200ca5909 --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppTest.kt @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.flicker.legacysplitscreen + +import android.view.Surface +import androidx.test.filters.RequiresDevice +import com.android.server.wm.flicker.dsl.FlickerBuilder +import com.android.server.wm.flicker.dsl.runWithFlicker +import com.android.server.wm.flicker.helpers.exitSplitScreen +import com.android.server.wm.flicker.helpers.isInSplitScreen +import com.android.server.wm.flicker.helpers.launchSplitScreen +import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen +import com.android.server.wm.flicker.navBarLayerRotatesAndScales +import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible +import com.android.server.wm.flicker.statusBarLayerRotatesScales +import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible +import com.android.wm.shell.flicker.dockedStackDividerIsVisible +import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisible +import com.android.wm.shell.flicker.helpers.SplitScreenHelper +import org.junit.FixMethodOrder +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.MethodSorters +import org.junit.runners.Parameterized + +/** + * Test open app to split screen. + * To run this test: `atest WMShellFlickerTests:RotateOneLaunchedAppTest` + */ +@RequiresDevice +@RunWith(Parameterized::class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +class RotateOneLaunchedAppTest( + rotationName: String, + rotation: Int +) : SplitScreenTestBase(rotationName, rotation) { + private val splitScreenRotationSetup: FlickerBuilder + get() = FlickerBuilder(instrumentation).apply { + val testSetupRotation = "testSetupRotation" + withTestName { + testSetupRotation + } + setup { + test { + device.wakeUpAndGoToHomeScreen() + } + } + teardown { + eachRun { + if (uiDevice.isInSplitScreen()) { + uiDevice.exitSplitScreen() + } + setRotation(Surface.ROTATION_0) + splitScreenApp.exit() + secondaryApp.exit() + } + } + } + + @Test + fun testRotateInSplitScreenMode() { + val testTag = "testEnterSplitScreen_launchToSide" + runWithFlicker(splitScreenRotationSetup) { + withTestName { testTag } + repeat { + SplitScreenHelper.TEST_REPETITIONS + } + transitions { + splitScreenApp.launchViaIntent() + device.launchSplitScreen() + setRotation(rotation) + } + assertions { + layersTrace { + navBarLayerRotatesAndScales(Surface.ROTATION_0, rotation, 169271943) + statusBarLayerRotatesScales(Surface.ROTATION_0, rotation, 169271943) + dockedStackDividerIsVisible() + dockedStackPrimaryBoundsIsVisible( + rotation, splitScreenApp.defaultWindowName, 169271943) + } + windowManagerTrace { + navBarWindowIsAlwaysVisible() + statusBarWindowIsAlwaysVisible() + end { + showsAppWindow(splitScreenApp.defaultWindowName) + } + } + } + } + } + + @Test + fun testRotateAndEnterSplitScreenMode() { + val testTag = "testRotateAndEnterSplitScreenMode" + runWithFlicker(splitScreenRotationSetup) { + withTestName { testTag } + repeat { + SplitScreenHelper.TEST_REPETITIONS + } + transitions { + splitScreenApp.launchViaIntent() + setRotation(rotation) + device.launchSplitScreen() + } + assertions { + layersTrace { + navBarLayerRotatesAndScales(Surface.ROTATION_0, rotation, 169271943) + statusBarLayerRotatesScales(Surface.ROTATION_0, rotation, 169271943) + dockedStackDividerIsVisible() + dockedStackPrimaryBoundsIsVisible( + rotation, splitScreenApp.defaultWindowName, 169271943) + } + windowManagerTrace { + navBarWindowIsAlwaysVisible() + statusBarWindowIsAlwaysVisible() + end { + showsAppWindow(splitScreenApp.defaultWindowName) + } + } + } + } + } + + companion object { + @Parameterized.Parameters(name = "{0}") + @JvmStatic + fun getParams(): Collection<Array<Any>> { + val supportedRotations = intArrayOf(Surface.ROTATION_90, Surface.ROTATION_270) + return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) } + } + } +}
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppTest.kt index 5570a562a515..a1b44f0da6ac 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppTest.kt @@ -14,21 +14,24 @@ * limitations under the License. */ -package com.android.wm.shell.flicker.splitscreen +package com.android.wm.shell.flicker.legacysplitscreen -import android.platform.test.annotations.Presubmit import android.view.Surface import androidx.test.filters.RequiresDevice import com.android.server.wm.flicker.dsl.FlickerBuilder import com.android.server.wm.flicker.dsl.runWithFlicker +import com.android.server.wm.flicker.helpers.exitSplitScreen +import com.android.server.wm.flicker.helpers.isInSplitScreen import com.android.server.wm.flicker.helpers.launchSplitScreen import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen -import com.android.wm.shell.flicker.dockedStackDividerIsVisible -import com.android.wm.shell.flicker.helpers.SplitScreenHelper.Companion.TEST_REPETITIONS +import com.android.server.wm.flicker.navBarLayerRotatesAndScales import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible -import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible -import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible +import com.android.server.wm.flicker.statusBarLayerRotatesScales import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible +import com.android.wm.shell.flicker.dockedStackDividerIsVisible +import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisible +import com.android.wm.shell.flicker.dockedStackSecondaryBoundsIsVisible +import com.android.wm.shell.flicker.helpers.SplitScreenHelper import org.junit.FixMethodOrder import org.junit.Test import org.junit.runner.RunWith @@ -36,73 +39,70 @@ import org.junit.runners.MethodSorters import org.junit.runners.Parameterized /** - * Test SplitScreen launch. - * To run this test: `atest WMShellFlickerTests:EnterSplitScreenTest` + * Test open app to split screen. + * To run this test: `atest WMShellFlickerTests:RotateTwoLaunchedAppTest` */ -@Presubmit @RequiresDevice @RunWith(Parameterized::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) -class EnterSplitScreenTest( +class RotateTwoLaunchedAppTest( rotationName: String, rotation: Int ) : SplitScreenTestBase(rotationName, rotation) { - private val splitScreenSetup: FlickerBuilder + private val splitScreenRotationSetup: FlickerBuilder get() = FlickerBuilder(instrumentation).apply { - val testLaunchActivity = "launch_splitScreen_test_activity" + val testSetupRotation = "testSetupRotation" withTestName { - testLaunchActivity + testSetupRotation } setup { - eachRun { - uiDevice.wakeUpAndGoToHomeScreen() - splitScreenApp.open() - uiDevice.pressHome() + test { + device.wakeUpAndGoToHomeScreen() } } teardown { eachRun { + if (uiDevice.isInSplitScreen()) { + uiDevice.exitSplitScreen() + } + setRotation(Surface.ROTATION_0) splitScreenApp.exit() secondaryApp.exit() } } - assertions { - layersTrace { - navBarLayerIsAlwaysVisible() - statusBarLayerIsAlwaysVisible() - } - windowManagerTrace { - navBarWindowIsAlwaysVisible() - statusBarWindowIsAlwaysVisible() - } - } } @Test - fun testEnterSplitScreen_dockActivity() { - val testTag = "testEnterSplitScreen_dockActivity" - runWithFlicker(splitScreenSetup) { + fun testRotateInSplitScreenMode() { + val testTag = "testRotateInSplitScreenMode" + runWithFlicker(splitScreenRotationSetup) { withTestName { testTag } repeat { - TEST_REPETITIONS + SplitScreenHelper.TEST_REPETITIONS } transitions { - uiDevice.launchSplitScreen() + secondaryApp.launchViaIntent() + splitScreenApp.launchViaIntent() + device.launchSplitScreen() + splitScreenApp.reopenAppFromOverview() + setRotation(rotation) } assertions { layersTrace { + navBarLayerRotatesAndScales(Surface.ROTATION_0, rotation, 169271943) + statusBarLayerRotatesScales(Surface.ROTATION_0, rotation, 169271943) dockedStackDividerIsVisible() - end("appsEndingBounds", enabled = false) { - val entry = this.trace.entries.firstOrNull() - ?: throw IllegalStateException("Trace is empty") - this.hasVisibleRegion(splitScreenApp.defaultWindowName, - splitScreenApp.getPrimaryBounds( - entry.getVisibleBounds(DOCKED_STACK_DIVIDER))) - } + dockedStackPrimaryBoundsIsVisible( + rotation, splitScreenApp.defaultWindowName, 169271943) + dockedStackSecondaryBoundsIsVisible( + rotation, secondaryApp.defaultWindowName, 169271943) } windowManagerTrace { + navBarWindowIsAlwaysVisible() + statusBarWindowIsAlwaysVisible() end { showsAppWindow(splitScreenApp.defaultWindowName) + .and().showsAppWindow(secondaryApp.defaultWindowName) } } } @@ -110,37 +110,33 @@ class EnterSplitScreenTest( } @Test - fun testEnterSplitScreen_launchToSide() { - val testTag = "testEnterSplitScreen_launchToSide" - runWithFlicker(splitScreenSetup) { + fun testRotateAndEnterSplitScreenMode() { + val testTag = "testRotateAndEnterSplitScreenMode" + runWithFlicker(splitScreenRotationSetup) { withTestName { testTag } repeat { - TEST_REPETITIONS + SplitScreenHelper.TEST_REPETITIONS } transitions { - secondaryApp.open() - uiDevice.pressHome() - splitScreenApp.open() - uiDevice.pressHome() - uiDevice.launchSplitScreen() + secondaryApp.launchViaIntent() + splitScreenApp.launchViaIntent() + setRotation(rotation) + device.launchSplitScreen() splitScreenApp.reopenAppFromOverview() } assertions { layersTrace { + navBarLayerRotatesAndScales(Surface.ROTATION_0, rotation, 169271943) + statusBarLayerRotatesScales(Surface.ROTATION_0, rotation, 169271943) dockedStackDividerIsVisible() - end("appsEndingBounds", enabled = false) { - val entry = this.trace.entries.firstOrNull() - ?: throw IllegalStateException("Trace is empty") - this.hasVisibleRegion(splitScreenApp.defaultWindowName, - splitScreenApp.getPrimaryBounds( - entry.getVisibleBounds(DOCKED_STACK_DIVIDER))) - .and() - .hasVisibleRegion(secondaryApp.defaultWindowName, - splitScreenApp.getSecondaryBounds( - entry.getVisibleBounds(DOCKED_STACK_DIVIDER))) - } + dockedStackPrimaryBoundsIsVisible( + rotation, splitScreenApp.defaultWindowName, 169271943) + dockedStackSecondaryBoundsIsVisible( + rotation, secondaryApp.defaultWindowName, 169271943) } windowManagerTrace { + navBarWindowIsAlwaysVisible() + statusBarWindowIsAlwaysVisible() end { showsAppWindow(splitScreenApp.defaultWindowName) .and().showsAppWindow(secondaryApp.defaultWindowName) @@ -154,7 +150,7 @@ class EnterSplitScreenTest( @Parameterized.Parameters(name = "{0}") @JvmStatic fun getParams(): Collection<Array<Any>> { - val supportedRotations = intArrayOf(Surface.ROTATION_0) + val supportedRotations = intArrayOf(Surface.ROTATION_90, Surface.ROTATION_270) return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) } } } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/SplitScreenTestBase.kt index a3440df9ddf8..a2e325e49674 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenTestBase.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/SplitScreenTestBase.kt @@ -14,9 +14,10 @@ * limitations under the License. */ -package com.android.wm.shell.flicker.splitscreen +package com.android.wm.shell.flicker.legacysplitscreen import com.android.wm.shell.flicker.NonRotationTestBase +import com.android.wm.shell.flicker.TEST_APP_NONRESIZEABLE_LABEL import com.android.wm.shell.flicker.TEST_APP_SPLITSCREEN_PRIMARY_LABEL import com.android.wm.shell.flicker.TEST_APP_SPLITSCREEN_SECONDARY_LABEL import com.android.wm.shell.flicker.helpers.SplitScreenHelper @@ -32,4 +33,7 @@ abstract class SplitScreenTestBase( protected val secondaryApp = SplitScreenHelper(instrumentation, TEST_APP_SPLITSCREEN_SECONDARY_LABEL, Components.SplitScreenSecondaryActivity()) + protected val nonResizeableApp = SplitScreenHelper(instrumentation, + TEST_APP_NONRESIZEABLE_LABEL, + Components.NonResizeableActivity()) } diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipSplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt index f79b21ff278d..81cdbf05be6c 100644 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipSplitScreenTest.kt +++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt @@ -47,7 +47,7 @@ import org.junit.runners.Parameterized @RunWith(Parameterized::class) @FixMethodOrder(MethodSorters.NAME_ASCENDING) @FlakyTest(bugId = 161435597) -class PipSplitScreenTest( +class PipLegacySplitScreenTest( rotationName: String, rotation: Int ) : AppTestBase(rotationName, rotation) { diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenRotateOneLaunchedAppTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenRotateOneLaunchedAppTest.kt deleted file mode 100644 index d2371bd766f5..000000000000 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenRotateOneLaunchedAppTest.kt +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.wm.shell.flicker.splitscreen - -import androidx.test.filters.FlakyTest -import android.view.Surface -import androidx.test.filters.RequiresDevice -import androidx.test.platform.app.InstrumentationRegistry -import com.android.server.wm.flicker.Flicker -import com.android.server.wm.flicker.FlickerTestRunner -import com.android.server.wm.flicker.FlickerTestRunnerFactory -import com.android.server.wm.flicker.helpers.StandardAppHelper -import com.android.server.wm.flicker.startRotation -import com.android.server.wm.flicker.endRotation -import com.android.server.wm.flicker.helpers.buildTestTag -import com.android.server.wm.flicker.helpers.exitSplitScreen -import com.android.server.wm.flicker.helpers.isInSplitScreen -import com.android.server.wm.flicker.helpers.launchSplitScreen -import com.android.server.wm.flicker.helpers.setRotation -import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen -import com.android.server.wm.flicker.repetitions -import org.junit.FixMethodOrder -import org.junit.runner.RunWith -import org.junit.runners.MethodSorters -import org.junit.runners.Parameterized - -/** - * Test open app to split screen. - * To run this test: `atest WMShellFlickerTests:SplitScreenRotateOneLaunchedAppTest` - */ -@RequiresDevice -@RunWith(Parameterized::class) -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -@FlakyTest -class SplitScreenRotateOneLaunchedAppTest( - testName: String, - flickerSpec: Flicker -) : FlickerTestRunner(testName, flickerSpec) { - companion object { - @Parameterized.Parameters(name = "{0}") - @JvmStatic - fun getParams(): Collection<Array<Any>> { - val instrumentation = InstrumentationRegistry.getInstrumentation() - val testApp = StandardAppHelper(instrumentation, - "com.android.wm.shell.flicker.testapp", "SimpleApp") - - return FlickerTestRunnerFactory(instrumentation, repetitions = 3) - .buildTest { configuration -> - withTestName { - buildTestTag("splitScreenRotateOneApp", testApp, configuration) - } - repeat { configuration.repetitions } - setup { - test { - device.wakeUpAndGoToHomeScreen() - testApp.open() - device.launchSplitScreen() - device.waitForIdle() - } - eachRun { - this.setRotation(configuration.startRotation) - } - } - teardown { - eachRun { - setRotation(Surface.ROTATION_0) - } - test { - testApp.exit() - if (device.isInSplitScreen()) { - device.exitSplitScreen() - } - } - } - transitions { - this.setRotation(configuration.endRotation) - } - } - } - } -}
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenRotateTwoLaunchedAppTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenRotateTwoLaunchedAppTest.kt deleted file mode 100644 index 67346424acd2..000000000000 --- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenRotateTwoLaunchedAppTest.kt +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.wm.shell.flicker.splitscreen - -import androidx.test.filters.FlakyTest -import android.view.Surface -import androidx.test.filters.RequiresDevice -import androidx.test.platform.app.InstrumentationRegistry -import com.android.server.wm.flicker.Flicker -import com.android.server.wm.flicker.FlickerTestRunner -import com.android.server.wm.flicker.FlickerTestRunnerFactory -import com.android.server.wm.flicker.helpers.StandardAppHelper -import com.android.server.wm.flicker.startRotation -import com.android.server.wm.flicker.endRotation -import com.android.server.wm.flicker.helpers.buildTestTag -import com.android.server.wm.flicker.helpers.exitSplitScreen -import com.android.server.wm.flicker.helpers.reopenAppFromOverview -import com.android.server.wm.flicker.helpers.isInSplitScreen -import com.android.server.wm.flicker.helpers.launchSplitScreen -import com.android.server.wm.flicker.helpers.setRotation -import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen -import com.android.server.wm.flicker.repetitions -import org.junit.FixMethodOrder -import org.junit.runner.RunWith -import org.junit.runners.MethodSorters -import org.junit.runners.Parameterized - -/** - * Test open app to split screen. - * To run this test: `atest WMShellFlickerTests:SplitScreenRotateTwoLaunchedAppTest` - */ -@RequiresDevice -@RunWith(Parameterized::class) -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -@FlakyTest -class SplitScreenRotateTwoLaunchedAppTest( - testName: String, - flickerSpec: Flicker -) : FlickerTestRunner(testName, flickerSpec) { - companion object { - @Parameterized.Parameters(name = "{0}") - @JvmStatic - fun getParams(): Collection<Array<Any>> { - val instrumentation = InstrumentationRegistry.getInstrumentation() - val testApp = StandardAppHelper(instrumentation, - "com.android.wm.shell.flicker.testapp", "SimpleApp") - val secondaryApp = StandardAppHelper(instrumentation, - "com.android.wm.shell.flicker.testapp", - "SplitScreenSecondaryApp") - - return FlickerTestRunnerFactory(instrumentation, repetitions = 3) - .buildTest { configuration -> - withTestName { - buildTestTag("splitScreenRotateTwoApps", testApp, configuration) - } - repeat { configuration.repetitions } - setup { - test { - device.wakeUpAndGoToHomeScreen() - testApp.open() - device.pressHome() - secondaryApp.open() - device.pressHome() - device.launchSplitScreen() - device.reopenAppFromOverview() - device.waitForIdle() - } - eachRun { - this.setRotation(configuration.startRotation) - } - } - teardown { - eachRun { - setRotation(Surface.ROTATION_0) - } - test { - testApp.exit() - secondaryApp.exit() - if (device.isInSplitScreen()) { - device.exitSplitScreen() - } - } - } - transitions { - this.setRotation(configuration.endRotation) - } - } - } - } -}
\ No newline at end of file diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/AndroidManifest.xml b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/AndroidManifest.xml index a583b725899b..28ed3431db62 100644 --- a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/AndroidManifest.xml +++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/AndroidManifest.xml @@ -86,6 +86,17 @@ </intent-filter> </activity> + <activity android:name=".NonResizeableActivity" + android:resizeableActivity="false" + android:taskAffinity="com.android.wm.shell.flicker.testapp.NonResizeableActivity" + android:label="NonResizeableApp" + android:exported="true"> + <intent-filter> + <action android:name="android.intent.action.MAIN"/> + <category android:name="android.intent.category.LAUNCHER"/> + </intent-filter> + </activity> + <activity android:name=".SimpleActivity" android:taskAffinity="com.android.wm.shell.flicker.testapp.SimpleActivity" android:label="SimpleApp" diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/layout/activity_non_resizeable.xml b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/layout/activity_non_resizeable.xml new file mode 100644 index 000000000000..45d5917f86d6 --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/res/layout/activity_non_resizeable.xml @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. +--> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + android:background="@android:color/holo_orange_light"> + + <TextView + android:id="@+id/NonResizeableTest" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:gravity="center_vertical|center_horizontal" + android:text="NonResizeableActivity" + android:textAppearance="?android:attr/textAppearanceLarge"/> + +</LinearLayout> diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/Components.java b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/Components.java index 8e9b4cb2d53e..f729ea554072 100644 --- a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/Components.java +++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/Components.java @@ -38,6 +38,13 @@ public class Components { } } + public static class NonResizeableActivity extends ComponentsInfo { + @Override + public String getActivityName() { + return NonResizeableActivity.class.getSimpleName(); + } + } + public static class PipActivity extends ComponentsInfo { // Intent action that this activity dynamically registers to enter picture-in-picture public static final String ACTION_ENTER_PIP = PACKAGE_NAME + ".PipActivity.ENTER_PIP"; diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/NonResizeableActivity.java b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/NonResizeableActivity.java new file mode 100644 index 000000000000..24275e002c7f --- /dev/null +++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/src/com/android/wm/shell/flicker/testapp/NonResizeableActivity.java @@ -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 com.android.wm.shell.flicker.testapp; + +import android.app.Activity; +import android.os.Bundle; + +public class NonResizeableActivity extends Activity { + + @Override + protected void onCreate(Bundle icicle) { + super.onCreate(icicle); + setContentView(R.layout.activity_non_resizeable); + } +} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java index fdf4d31f0281..862776ec7df2 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java @@ -16,18 +16,14 @@ package com.android.wm.shell; -import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy; -import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_FULLSCREEN; -import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_LETTERBOX; import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_MULTI_WINDOW; import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_PIP; -import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -38,7 +34,6 @@ import static org.mockito.Mockito.verify; import android.app.ActivityManager.RunningTaskInfo; import android.content.Context; import android.content.pm.ParceledListSlice; -import android.graphics.Rect; import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; @@ -47,7 +42,6 @@ import android.window.ITaskOrganizer; import android.window.ITaskOrganizerController; import android.window.TaskAppearedInfo; -import androidx.annotation.Nullable; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; @@ -108,8 +102,7 @@ public class ShellTaskOrganizerTests { doReturn(ParceledListSlice.<TaskAppearedInfo>emptyList()) .when(mTaskOrganizerController).registerTaskOrganizer(any()); } catch (RemoteException e) {} - mOrganizer = spy(new ShellTaskOrganizer(mTaskOrganizerController, mSyncTransactionQueue, - mTransactionPool, mTestExecutor, mTestExecutor, mContext)); + mOrganizer = spy(new ShellTaskOrganizer(mTaskOrganizerController, mTestExecutor, mContext)); } @Test @@ -264,28 +257,6 @@ public class ShellTaskOrganizerTests { assertTrue(mwListener.appeared.contains(task2)); } - @Test - public void testTaskInfoToTaskListenerType_whenLetterboxBoundsPassed_returnsLetterboxType() { - RunningTaskInfo taskInfo = createTaskInfo( - /* taskId */ 1, - WINDOWING_MODE_FULLSCREEN, - /* letterboxActivityBounds */ new Rect(1, 1, 1, 1)); - - assertEquals( - ShellTaskOrganizer.taskInfoToTaskListenerType(taskInfo), - TASK_LISTENER_TYPE_LETTERBOX); - } - - @Test - public void testTaskInfoToTaskListenerType_whenLetterboxBoundsIsNull_returnsFullscreenType() { - RunningTaskInfo taskInfo = createTaskInfo( - /* taskId */ 1, WINDOWING_MODE_FULLSCREEN, /* letterboxActivityBounds */ null); - - assertEquals( - ShellTaskOrganizer.taskInfoToTaskListenerType(taskInfo), - TASK_LISTENER_TYPE_FULLSCREEN); - } - private static RunningTaskInfo createTaskInfo(int taskId, int windowingMode) { RunningTaskInfo taskInfo = new RunningTaskInfo(); taskInfo.taskId = taskId; @@ -293,12 +264,4 @@ public class ShellTaskOrganizerTests { return taskInfo; } - private static RunningTaskInfo createTaskInfo( - int taskId, int windowingMode, @Nullable Rect letterboxActivityBounds) { - RunningTaskInfo taskInfo = new RunningTaskInfo(); - taskInfo.taskId = taskId; - taskInfo.configuration.windowConfiguration.setWindowingMode(windowingMode); - taskInfo.letterboxActivityBounds = Rect.copyOrNull(letterboxActivityBounds); - return taskInfo; - } } 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 34f772faf9a9..11bf4ff2fd35 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 @@ -30,6 +30,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.app.ActivityManager; import android.app.ActivityOptions; @@ -96,8 +97,8 @@ public class TaskViewTest extends ShellTestCase { return null; }).when(mExecutor).execute(any()); + when(mOrganizer.getExecutor()).thenReturn(mExecutor); mTaskView = new TaskView(mContext, mOrganizer); - mTaskView.setExecutor(mExecutor); mTaskView.setListener(mViewListener); } @@ -111,7 +112,6 @@ public class TaskViewTest extends ShellTestCase { @Test public void testSetPendingListener_throwsException() { TaskView taskView = new TaskView(mContext, mOrganizer); - mTaskView.setExecutor(mExecutor); taskView.setListener(mViewListener); try { taskView.setListener(mViewListener); 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 d87f4c60fad4..9fdd59bee176 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 @@ -69,24 +69,27 @@ public class SplitLayoutTests extends ShellTestCase { } @Test - public void testUpdateDividePosition() { - mSplitLayout.updateDividePosition(anyInt()); + public void testUpdateDivideBounds() { + mSplitLayout.updateDivideBounds(anyInt()); verify(mLayoutChangeListener).onBoundsChanging(any(SplitLayout.class)); } @Test - public void testSetSnapTarget() { - DividerSnapAlgorithm.SnapTarget snapTarget = getSnapTarget(0, + @UiThreadTest + public void testSnapToTarget() { + DividerSnapAlgorithm.SnapTarget snapTarget = getSnapTarget(0 /* position */, DividerSnapAlgorithm.SnapTarget.FLAG_NONE); - mSplitLayout.setSnapTarget(snapTarget); - verify(mLayoutChangeListener).onBoundsChanged(any(SplitLayout.class)); + mSplitLayout.snapToTarget(0 /* currentPosition */, snapTarget); + verify(mLayoutChangeListener).onBoundsChanging(any(SplitLayout.class)); // verify it callbacks properly when the snap target indicates dismissing split. - snapTarget = getSnapTarget(0, DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_START); - mSplitLayout.setSnapTarget(snapTarget); + snapTarget = getSnapTarget(0 /* position */, + DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_START); + mSplitLayout.snapToTarget(0 /* currentPosition */, snapTarget); verify(mLayoutChangeListener).onSnappedToDismiss(eq(false)); - snapTarget = getSnapTarget(0, DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_END); - mSplitLayout.setSnapTarget(snapTarget); + snapTarget = getSnapTarget(0 /* position */, + DividerSnapAlgorithm.SnapTarget.FLAG_DISMISS_END); + mSplitLayout.snapToTarget(0 /* currentPosition */, snapTarget); verify(mLayoutChangeListener).onSnappedToDismiss(eq(true)); } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java index 92d4bee7cfc2..912418d0eebd 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropPolicyTest.java @@ -61,8 +61,8 @@ import androidx.test.filters.SmallTest; import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.draganddrop.DragAndDropPolicy.Target; -import com.android.wm.shell.splitscreen.DividerView; -import com.android.wm.shell.splitscreen.SplitScreen; +import com.android.wm.shell.legacysplitscreen.DividerView; +import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import org.junit.Before; import org.junit.Test; @@ -90,7 +90,7 @@ public class DragAndDropPolicyTest { private ActivityTaskManager mActivityTaskManager; @Mock - private SplitScreen mSplitScreen; + private LegacySplitScreen mLegacySplitScreen; @Mock private DragAndDropPolicy.Starter mStarter; @@ -123,7 +123,7 @@ public class DragAndDropPolicyTest { mInsets = Insets.of(0, 0, 0, 0); DividerView divider = mock(DividerView.class); - doReturn(divider).when(mSplitScreen).getDividerView(); + doReturn(divider).when(mLegacySplitScreen).getDividerView(); doReturn(new Rect(50, 0, 100, 100)).when(divider) .getNonMinimizedSplitScreenSecondaryBounds(); @@ -131,9 +131,10 @@ public class DragAndDropPolicyTest { Consumer<Boolean> callback = invocation.getArgument(0); callback.accept(true); return null; - }).when(mSplitScreen).registerInSplitScreenListener(any()); + }).when(mLegacySplitScreen).registerInSplitScreenListener(any()); - mPolicy = new DragAndDropPolicy(mContext, mActivityTaskManager, mSplitScreen, mStarter); + mPolicy = new DragAndDropPolicy( + mContext, mActivityTaskManager, mLegacySplitScreen, mStarter); mActivityClipData = createClipData(MIMETYPE_APPLICATION_ACTIVITY); mNonResizeableActivityClipData = createClipData(MIMETYPE_APPLICATION_ACTIVITY); setClipDataResizeable(mNonResizeableActivityClipData, false); @@ -207,7 +208,7 @@ public class DragAndDropPolicyTest { } private void setInSplitScreen(boolean inSplitscreen) { - doReturn(inSplitscreen).when(mSplitScreen).isDividerVisible(); + doReturn(inSplitscreen).when(mLegacySplitScreen).isDividerVisible(); } @Test diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/letterbox/LetterboxConfigControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/letterbox/LetterboxConfigControllerTest.java deleted file mode 100644 index 29233366d4f3..000000000000 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/letterbox/LetterboxConfigControllerTest.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.wm.shell.letterbox; - -import static org.junit.Assert.assertEquals; - -import android.view.Gravity; - -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.filters.SmallTest; - -import com.android.wm.shell.R; -import com.android.wm.shell.ShellTestCase; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Tests for {@link LetterboxConfigController}. - */ -@SmallTest -@RunWith(AndroidJUnit4.class) -public final class LetterboxConfigControllerTest extends ShellTestCase { - - private LetterboxConfigController mLetterboxConfigController; - - @Before - public void setUp() { - mLetterboxConfigController = new LetterboxConfigController(getContext()); - } - - @Test - public void testGetPortraitGravity_noOverrides_returnConfigValue() { - assertEquals( - mLetterboxConfigController.getPortraitGravity(), - getContext().getResources().getInteger(R.integer.config_letterboxPortraitGravity)); - } - - @Test - public void testGetLandscapeGravity_noOverrides_returnConfigValue() { - assertEquals( - mLetterboxConfigController.getLandscapeGravity(), - getContext().getResources().getInteger(R.integer.config_letterboxLandscapeGravity)); - } - - @Test - public void testSetPortraitGravity_validValue_savesValue() { - mLetterboxConfigController.setPortraitGravity(Gravity.BOTTOM); - assertEquals(mLetterboxConfigController.getPortraitGravity(), Gravity.BOTTOM); - - mLetterboxConfigController.setPortraitGravity(Gravity.CENTER); - assertEquals(mLetterboxConfigController.getPortraitGravity(), Gravity.CENTER); - - mLetterboxConfigController.setPortraitGravity(Gravity.TOP); - assertEquals(mLetterboxConfigController.getPortraitGravity(), Gravity.TOP); - } - - @Test - public void testSetLandscapeGravity_validValue_savesValue() { - mLetterboxConfigController.setLandscapeGravity(Gravity.LEFT); - assertEquals(mLetterboxConfigController.getLandscapeGravity(), Gravity.LEFT); - - mLetterboxConfigController.setLandscapeGravity(Gravity.CENTER); - assertEquals(mLetterboxConfigController.getLandscapeGravity(), Gravity.CENTER); - - mLetterboxConfigController.setLandscapeGravity(Gravity.RIGHT); - assertEquals(mLetterboxConfigController.getLandscapeGravity(), Gravity.RIGHT); - } - - @Test(expected = IllegalArgumentException.class) - public void testSetPortraitGravity_invalidValue_throwsException() { - mLetterboxConfigController.setPortraitGravity(Gravity.RIGHT); - } - - @Test(expected = IllegalArgumentException.class) - public void testSetLandscapeGravity_invalidValue_throwsException() { - mLetterboxConfigController.setLandscapeGravity(Gravity.TOP); - } - - @Test - public void testResetPortraitGravity() { - int defaultGravity = - getContext().getResources().getInteger(R.integer.config_letterboxPortraitGravity); - - mLetterboxConfigController.setPortraitGravity(Gravity.BOTTOM); - mLetterboxConfigController.resetPortraitGravity(); - assertEquals(mLetterboxConfigController.getPortraitGravity(), defaultGravity); - - mLetterboxConfigController.setPortraitGravity(Gravity.CENTER); - mLetterboxConfigController.resetPortraitGravity(); - assertEquals(mLetterboxConfigController.getPortraitGravity(), defaultGravity); - - mLetterboxConfigController.setPortraitGravity(Gravity.TOP); - mLetterboxConfigController.resetPortraitGravity(); - assertEquals(mLetterboxConfigController.getPortraitGravity(), defaultGravity); - } - - @Test - public void testResetLandscapeGravity() { - int defaultGravity = - getContext().getResources().getInteger(R.integer.config_letterboxLandscapeGravity); - - mLetterboxConfigController.setLandscapeGravity(Gravity.RIGHT); - mLetterboxConfigController.resetLandscapeGravity(); - assertEquals(mLetterboxConfigController.getLandscapeGravity(), defaultGravity); - - mLetterboxConfigController.setLandscapeGravity(Gravity.CENTER); - mLetterboxConfigController.resetLandscapeGravity(); - assertEquals(mLetterboxConfigController.getLandscapeGravity(), defaultGravity); - - mLetterboxConfigController.setLandscapeGravity(Gravity.LEFT); - mLetterboxConfigController.resetLandscapeGravity(); - assertEquals(mLetterboxConfigController.getLandscapeGravity(), defaultGravity); - } - -} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/letterbox/LetterboxTaskListenerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/letterbox/LetterboxTaskListenerTest.java deleted file mode 100644 index 5cbc7d927d61..000000000000 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/letterbox/LetterboxTaskListenerTest.java +++ /dev/null @@ -1,367 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.wm.shell.letterbox; - -import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; - -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.when; - -import android.app.ActivityManager.RunningTaskInfo; -import android.graphics.Insets; -import android.graphics.Rect; -import android.os.Handler; -import android.os.Looper; -import android.view.Gravity; -import android.view.SurfaceControl; -import android.view.WindowInsets; -import android.view.WindowManager; -import android.view.WindowMetrics; - -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.filters.SmallTest; - -import com.android.wm.shell.ShellTestCase; -import com.android.wm.shell.common.SyncTransactionQueue; -import com.android.wm.shell.common.TransactionPool; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -/** - * Tests for {@link LetterboxTaskListener}. - */ -@SmallTest -@RunWith(AndroidJUnit4.class) -public final class LetterboxTaskListenerTest extends ShellTestCase { - - @Mock private SurfaceControl mLeash; - @Mock private SurfaceControl.Transaction mTransaction; - @Mock private WindowManager mWindowManager; - @Mock private WindowMetrics mWindowMetrics; - @Mock private WindowInsets mWindowInsets; - private LetterboxTaskListener mLetterboxTaskListener; - private LetterboxConfigController mLetterboxConfigController; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - - mLetterboxConfigController = new LetterboxConfigController(getContext()); - mLetterboxTaskListener = new LetterboxTaskListener( - new SyncTransactionQueue( - new TransactionPool() { - @Override - public SurfaceControl.Transaction acquire() { - return mTransaction; - } - - @Override - public void release(SurfaceControl.Transaction t) { - } - }, - new Handler(Looper.getMainLooper())), - mLetterboxConfigController, - mWindowManager); - - when(mWindowManager.getMaximumWindowMetrics()).thenReturn(mWindowMetrics); - when(mWindowMetrics.getWindowInsets()).thenReturn(mWindowInsets); - } - - @Test - public void testOnTaskInfoChanged_updatesPositionAndCrop() { - setWindowBoundsAndInsets( - /* windowBounds= */ new Rect(0, 0, 200, 100), // equal to parent bounds - Insets.NONE); - - mLetterboxConfigController.setLandscapeGravity(Gravity.CENTER); - mLetterboxTaskListener.onTaskAppeared( - createTaskInfo( - /* taskId */ 1, - /* maxBounds= */ new Rect(0, 0, 200, 100), // equal to parent bounds - /* parentBounds */ new Rect(0, 0, 200, 100), - /* activityBounds */ new Rect(75, 0, 125, 75), - /* taskBounds */ new Rect(50, 0, 125, 100), - /* activityInsets */ new Rect(0, 0, 0, 0)), - mLeash); - - // Task doesn't need to repositioned - verifySetPosition(50, 0); - // Should return activity coordinates offset by task coordinates - verifySetWindowCrop(new Rect(25, 0, 75, 75)); - - mLetterboxTaskListener.onTaskInfoChanged( - createTaskInfo( - /* taskId */ 1, - /* maxBounds= */ new Rect(0, 0, 200, 100), // equal to parent bounds - /* parentBounds */ new Rect(0, 0, 200, 100), - // Activity is offset by 25 to the left - /* activityBounds */ new Rect(50, 0, 100, 75), - /* taskBounds */ new Rect(50, 0, 125, 100), - /* activityInsets */ new Rect(0, 0, 0, 0))); - - // Task needs to be repositioned by 25 to the left - verifySetPosition(75, 0); - // Should return activity coordinates offset by task coordinates - verifySetWindowCrop(new Rect(0, 0, 50, 75)); - } - - @Test - public void testOnTaskInfoAppeared_landscapeWithLeftGravity() { - mLetterboxConfigController.setLandscapeGravity(Gravity.LEFT); - setWindowBoundsAndInsets( - /* windowBounds= */ new Rect(0, 0, 200, 100), // equal to parent bounds - Insets.of(/* left= */ 10, /* top= */ 10, /* right= */ 10, /* bottom= */ 10)); - - mLetterboxTaskListener.onTaskAppeared( - createTaskInfo( - /* taskId */ 1, - /* maxBounds= */ new Rect(0, 0, 200, 100), // equal to parent bounds - /* parentBounds */ new Rect(0, 0, 200, 100), - /* activityBounds */ new Rect(150, 0, 200, 75), - /* taskBounds */ new Rect(125, 0, 200, 100), - /* activityInsets */ new Rect(0, 10, 10, 0)), - mLeash); - - verifySetPosition(-15, 0); - // Should return activity coordinates offset by task coordinates minus unwanted right inset - verifySetWindowCrop(new Rect(25, 0, 65, 75)); - } - - @Test - public void testOnTaskInfoAppeared_landscapeWithCenterGravity() { - mLetterboxConfigController.setLandscapeGravity(Gravity.CENTER); - setWindowBoundsAndInsets( - /* windowBounds= */ new Rect(0, 0, 200, 100), // equal to parent bounds - Insets.of(/* left= */ 10, /* top= */ 10, /* right= */ 10, /* bottom= */ 10)); - - mLetterboxTaskListener.onTaskAppeared( - createTaskInfo( - /* taskId */ 1, - /* maxBounds= */ new Rect(0, 0, 200, 100), // equal to parent bounds - /* parentBounds */ new Rect(0, 0, 200, 100), - /* activityBounds */ new Rect(150, 0, 200, 75), - /* taskBounds */ new Rect(125, 0, 200, 100), - /* activityInsets */ new Rect(0, 10, 10, 0)), - mLeash); - - verifySetPosition(55, 0); - // Should return activity coordinates offset by task coordinates minus unwanted right inset - verifySetWindowCrop(new Rect(25, 0, 65, 75)); - } - - @Test - public void testOnTaskInfoAppeared_landscapeWithRightGravity() { - mLetterboxConfigController.setLandscapeGravity(Gravity.RIGHT); - setWindowBoundsAndInsets( - /* windowBounds= */ new Rect(0, 0, 200, 100), // equal to parent bounds - Insets.of(/* left= */ 10, /* top= */ 10, /* right= */ 10, /* bottom= */ 10)); - - mLetterboxTaskListener.onTaskAppeared( - createTaskInfo( - /* taskId */ 1, - /* maxBounds= */ new Rect(0, 0, 200, 100), // equal to parent bounds - /* parentBounds */ new Rect(0, 0, 200, 100), - /* activityBounds */ new Rect(50, 0, 100, 75), - /* taskBounds */ new Rect(25, 0, 100, 100), - /* activityInsets */ new Rect(0, 10, 10, 0)), - mLeash); - - verifySetPosition(115, 0); - // Should return activity coordinates offset by task coordinates - verifySetWindowCrop(new Rect(25, 0, 75, 75)); - } - - @Test - public void testOnTaskInfoAppeared_portraitWithTopGravity() { - mLetterboxConfigController.setPortraitGravity(Gravity.TOP); - setWindowBoundsAndInsets( - /* windowBounds= */ new Rect(0, 0, 100, 150), // equal to parent bounds - Insets.of(/* left= */ 10, /* top= */ 10, /* right= */ 10, /* bottom= */ 20)); - - mLetterboxTaskListener.onTaskAppeared( - createTaskInfo( - /* taskId */ 1, - /* maxBounds= */ new Rect(0, 0, 100, 150), // equal to parent bounds - /* parentBounds */ new Rect(0, 0, 100, 150), - /* activityBounds */ new Rect(0, 75, 50, 125), - /* taskBounds */ new Rect(0, 50, 100, 125), - /* activityInsets */ new Rect(10, 0, 0, 0)), - mLeash); - - verifySetPosition(20, -15); - // Should return activity coordinates offset by task coordinates minus unwanted left inset - verifySetWindowCrop(new Rect(10, 25, 50, 75)); - } - - @Test - public void testOnTaskInfoAppeared_portraitWithCenterGravity() { - mLetterboxConfigController.setPortraitGravity(Gravity.CENTER); - setWindowBoundsAndInsets( - /* windowBounds= */ new Rect(0, 0, 100, 150), // equal to parent bounds - Insets.of(/* left= */ 10, /* top= */ 10, /* right= */ 10, /* bottom= */ 20)); - - mLetterboxTaskListener.onTaskAppeared( - createTaskInfo( - /* taskId */ 1, - /* maxBounds= */ new Rect(0, 0, 100, 150), // equal to parent bounds - /* parentBounds */ new Rect(0, 0, 100, 150), - /* activityBounds */ new Rect(0, 75, 50, 125), - /* taskBounds */ new Rect(0, 50, 100, 125), - /* activityInsets */ new Rect(10, 0, 0, 0)), - mLeash); - - verifySetPosition(20, 20); - // Should return activity coordinates offset by task coordinates minus unwanted left inset - verifySetWindowCrop(new Rect(10, 25, 50, 75)); - } - - @Test - public void testOnTaskInfoAppeared_portraitWithCenterGravity_visibleLeftInset() { - mLetterboxConfigController.setPortraitGravity(Gravity.CENTER); - setWindowBoundsAndInsets( - /* windowBounds= */ new Rect(0, 0, 100, 150), // equal to parent bounds - Insets.of(/* left= */ 10, /* top= */ 10, /* right= */ 10, /* bottom= */ 20)); - - mLetterboxTaskListener.onTaskAppeared( - createTaskInfo( - /* taskId */ 1, - /* maxBounds= */ new Rect(0, 0, 100, 150), // equal to parent bounds - /* parentBounds */ new Rect(0, 0, 100, 150), - /* activityBounds */ new Rect(0, 75, 50, 125), - /* taskBounds */ new Rect(0, 50, 100, 125), - // Activity is drawn under the left inset. - /* activityInsets */ new Rect(0, 0, 0, 0)), - mLeash); - - verifySetPosition(20, 20); - // Should return activity coordinates offset by task coordinates - verifySetWindowCrop(new Rect(0, 25, 50, 75)); - } - - @Test - public void testOnTaskInfoAppeared_portraitWithBottomGravity() { - mLetterboxConfigController.setPortraitGravity(Gravity.BOTTOM); - setWindowBoundsAndInsets( - /* windowBounds= */ new Rect(0, 0, 100, 150), // equal to parent bounds - Insets.of(/* left= */ 10, /* top= */ 10, /* right= */ 10, /* bottom= */ 20)); - - mLetterboxTaskListener.onTaskAppeared( - createTaskInfo( - /* taskId */ 1, - /* maxBounds= */ new Rect(0, 0, 100, 150), // equal to parent bounds - /* parentBounds */ new Rect(0, 0, 100, 150), - /* activityBounds */ new Rect(0, 75, 50, 125), - /* taskBounds */ new Rect(0, 50, 100, 125), - /* activityInsets */ new Rect(10, 0, 0, 0)), - mLeash); - - verifySetPosition(20, 55); - // Should return activity coordinates offset by task coordinates minus unwanted left inset - verifySetWindowCrop(new Rect(10, 25, 50, 75)); - } - - @Test - public void testOnTaskInfoAppeared_partlyOverlapsWithAllInsets() { - mLetterboxConfigController.setPortraitGravity(Gravity.TOP); - setWindowBoundsAndInsets( - /* windowBounds= */ new Rect(0, 0, 200, 125), // equal to parent bounds - Insets.of(/* left= */ 25, /* top= */ 25, /* right= */ 35, /* bottom= */ 15)); - - mLetterboxTaskListener.onTaskAppeared( - createTaskInfo( - /* taskId */ 1, - /* maxBounds= */ new Rect(0, 0, 200, 125), // equal to parent bounds - /* parentBounds */ new Rect(0, 0, 200, 125), - /* activityBounds */ new Rect(15, 0, 175, 120), - /* taskBounds */ new Rect(0, 0, 200, 125), - /* activityInsets */ new Rect(10, 25, 10, 10)), // equal to parent bounds - mLeash); - - // Activity fully covers parent bounds with insets so doesn't need to be moved. - verifySetPosition(0, 0); - // Should return activity coordinates offset by task coordinates - verifySetWindowCrop(new Rect(15, 0, 175, 120)); - } - - @Test - public void testOnTaskInfoAppeared_parentShiftedLikeInOneHandedMode() { - mLetterboxConfigController.setPortraitGravity(Gravity.TOP); - setWindowBoundsAndInsets( - /* windowBounds= */ new Rect(0, 0, 100, 150), - Insets.of(/* left= */ 0, /* top= */ 10, /* right= */ 0, /* bottom= */ 0)); - - mLetterboxTaskListener.onTaskAppeared( - createTaskInfo( - /* taskId */ 1, - /* maxBounds= */ new Rect(0, 0, 100, 150), - /* parentBounds */ new Rect(0, 75, 100, 225), - /* activityBounds */ new Rect(25, 75, 75, 125), - /* taskBounds */ new Rect(0, 75, 100, 125), - /* activityInsets */ new Rect(10, 0, 0, 0)), - mLeash); - - verifySetPosition(0, 0); - verifySetWindowCrop(new Rect(25, 0, 75, 50)); - } - - @Test(expected = IllegalStateException.class) - public void testOnTaskAppeared_calledSecondTimeWithSameTaskId_throwsException() { - setWindowBoundsAndInsets(new Rect(), Insets.NONE); - RunningTaskInfo taskInfo = - createTaskInfo(/* taskId */ 1, new Rect(), new Rect(), new Rect(), new Rect(), - new Rect()); - mLetterboxTaskListener.onTaskAppeared(taskInfo, mLeash); - mLetterboxTaskListener.onTaskAppeared(taskInfo, mLeash); - } - - private void setWindowBoundsAndInsets(Rect windowBounds, Insets insets) { - when(mWindowMetrics.getBounds()).thenReturn(windowBounds); - when(mWindowInsets.getInsets(anyInt())).thenReturn(insets); - } - - private void verifySetPosition(int x, int y) { - verify(mTransaction).setPosition(eq(mLeash), eq((float) x), eq((float) y)); - } - - private void verifySetWindowCrop(final Rect crop) { - // Should return activty coordinates offset by task coordinates - verify(mTransaction).setWindowCrop(eq(mLeash), eq(crop)); - } - - private static RunningTaskInfo createTaskInfo( - int taskId, - final Rect maxBounds, - final Rect parentBounds, - final Rect activityBounds, - final Rect taskBounds, - final Rect activityInsets) { - RunningTaskInfo taskInfo = new RunningTaskInfo(); - taskInfo.taskId = taskId; - taskInfo.configuration.windowConfiguration.setMaxBounds(maxBounds); - taskInfo.parentBounds = parentBounds; - taskInfo.configuration.windowConfiguration.setBounds(taskBounds); - taskInfo.letterboxActivityBounds = Rect.copyOrNull(activityBounds); - taskInfo.letterboxActivityInsets = Rect.copyOrNull(activityInsets); - - return taskInfo; - } -} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java index a65d832359d2..ef9923550fc5 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java @@ -337,7 +337,8 @@ public class PipBoundsAlgorithmTest extends ShellTestCase { reentryBounds.scale(1.25f); final float reentrySnapFraction = mPipBoundsAlgorithm.getSnapFraction(reentryBounds); - mPipBoundsState.saveReentryState(reentryBounds, reentrySnapFraction); + mPipBoundsState.saveReentryState( + new Size(reentryBounds.width(), reentryBounds.height()), reentrySnapFraction); final Rect destinationBounds = mPipBoundsAlgorithm.getEntryDestinationBounds(); assertEquals(reentryBounds.width(), destinationBounds.width()); @@ -351,7 +352,8 @@ public class PipBoundsAlgorithmTest extends ShellTestCase { reentryBounds.offset(0, -100); final float reentrySnapFraction = mPipBoundsAlgorithm.getSnapFraction(reentryBounds); - mPipBoundsState.saveReentryState(reentryBounds, reentrySnapFraction); + mPipBoundsState.saveReentryState( + new Size(reentryBounds.width(), reentryBounds.height()), reentrySnapFraction); final Rect destinationBounds = mPipBoundsAlgorithm.getEntryDestinationBounds(); 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 4bcca06b592f..8ba301a9ebfa 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 @@ -47,7 +47,7 @@ import java.util.function.BiConsumer; @SmallTest public class PipBoundsStateTest extends ShellTestCase { - private static final Rect DEFAULT_BOUNDS = new Rect(0, 0, 10, 10); + private static final Size DEFAULT_SIZE = new Size(10, 10); private static final float DEFAULT_SNAP_FRACTION = 1.0f; private PipBoundsState mPipBoundsState; @@ -71,22 +71,22 @@ public class PipBoundsStateTest extends ShellTestCase { @Test public void testSetReentryState() { - final Rect bounds = new Rect(0, 0, 100, 100); + final Size size = new Size(100, 100); final float snapFraction = 0.5f; - mPipBoundsState.saveReentryState(bounds, snapFraction); + mPipBoundsState.saveReentryState(size, snapFraction); final PipBoundsState.PipReentryState state = mPipBoundsState.getReentryState(); - assertEquals(new Size(100, 100), state.getSize()); + assertEquals(size, state.getSize()); assertEquals(snapFraction, state.getSnapFraction(), 0.01); } @Test public void testClearReentryState() { - final Rect bounds = new Rect(0, 0, 100, 100); + final Size size = new Size(100, 100); final float snapFraction = 0.5f; - mPipBoundsState.saveReentryState(bounds, snapFraction); + mPipBoundsState.saveReentryState(size, snapFraction); mPipBoundsState.clearReentryState(); assertNull(mPipBoundsState.getReentryState()); @@ -95,20 +95,20 @@ public class PipBoundsStateTest extends ShellTestCase { @Test public void testSetLastPipComponentName_notChanged_doesNotClearReentryState() { mPipBoundsState.setLastPipComponentName(mTestComponentName1); - mPipBoundsState.saveReentryState(DEFAULT_BOUNDS, DEFAULT_SNAP_FRACTION); + mPipBoundsState.saveReentryState(DEFAULT_SIZE, DEFAULT_SNAP_FRACTION); mPipBoundsState.setLastPipComponentName(mTestComponentName1); final PipBoundsState.PipReentryState state = mPipBoundsState.getReentryState(); assertNotNull(state); - assertEquals(new Size(DEFAULT_BOUNDS.width(), DEFAULT_BOUNDS.height()), state.getSize()); + assertEquals(DEFAULT_SIZE, state.getSize()); assertEquals(DEFAULT_SNAP_FRACTION, state.getSnapFraction(), 0.01); } @Test public void testSetLastPipComponentName_changed_clearReentryState() { mPipBoundsState.setLastPipComponentName(mTestComponentName1); - mPipBoundsState.saveReentryState(DEFAULT_BOUNDS, DEFAULT_SNAP_FRACTION); + mPipBoundsState.saveReentryState(DEFAULT_SIZE, DEFAULT_SNAP_FRACTION); mPipBoundsState.setLastPipComponentName(mTestComponentName2); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java index 45e4241d5bc6..b5d10d71e693 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java @@ -45,7 +45,7 @@ import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.pip.phone.PhonePipMenuController; -import com.android.wm.shell.splitscreen.SplitScreen; +import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import org.junit.Before; import org.junit.Test; @@ -69,7 +69,7 @@ public class PipTaskOrganizerTest extends ShellTestCase { @Mock private PhonePipMenuController mMockPhonePipMenuController; @Mock private PipSurfaceTransactionHelper mMockPipSurfaceTransactionHelper; @Mock private PipUiEventLogger mMockPipUiEventLogger; - @Mock private Optional<SplitScreen> mMockOptionalSplitScreen; + @Mock private Optional<LegacySplitScreen> mMockOptionalSplitScreen; @Mock private ShellTaskOrganizer mMockShellTaskOrganizer; private PipBoundsState mPipBoundsState; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java index 4687d2d9667c..62ffac4fbd3f 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java @@ -30,10 +30,12 @@ import static org.mockito.Mockito.when; import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageManager; +import android.graphics.Rect; import android.os.RemoteException; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; +import android.util.Size; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.WindowManagerShellWrapper; @@ -135,4 +137,28 @@ public class PipControllerTest extends ShellTestCase { verify(mMockPipBoundsState, never()).setLastPipComponentName(null); } + + @Test + public void saveReentryState_noUserResize_doesNotSaveSize() { + final Rect bounds = new Rect(0, 0, 10, 10); + when(mMockPipBoundsAlgorithm.getSnapFraction(bounds)).thenReturn(1.0f); + when(mMockPipBoundsState.hasUserResizedPip()).thenReturn(false); + + mPipController.saveReentryState(bounds); + + verify(mMockPipBoundsState).saveReentryState(null, 1.0f); + } + + @Test + public void saveReentryState_userHasResized_savesSize() { + final Rect bounds = new Rect(0, 0, 10, 10); + final Rect resizedBounds = new Rect(0, 0, 30, 30); + when(mMockPipBoundsAlgorithm.getSnapFraction(bounds)).thenReturn(1.0f); + when(mMockPipTouchHandler.getUserResizeBounds()).thenReturn(resizedBounds); + when(mMockPipBoundsState.hasUserResizedPip()).thenReturn(true); + + mPipController.saveReentryState(bounds); + + verify(mMockPipBoundsState).saveReentryState(new Size(30, 30), 1.0f); + } } diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index 1ff1978044b9..0533aa6ad45d 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -672,6 +672,7 @@ cc_benchmark { srcs: [ "tests/microbench/main.cpp", + "tests/microbench/CanvasOpBench.cpp", "tests/microbench/DisplayListCanvasBench.cpp", "tests/microbench/LinearAllocatorBench.cpp", "tests/microbench/PathParserBench.cpp", diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h index dc63e5db4a70..dd2476313b19 100644 --- a/libs/hwui/DisplayList.h +++ b/libs/hwui/DisplayList.h @@ -16,14 +16,15 @@ #pragma once -#include "pipeline/skia/SkiaDisplayList.h" - namespace android { namespace uirenderer { namespace VectorDrawable { class Tree; }; +namespace skiapipeline { +class SkiaDisplayList; +} typedef uirenderer::VectorDrawable::Tree VectorDrawableRoot; /** diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index 31e45558139d..74c70c8969f2 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -380,7 +380,7 @@ void RenderNode::deleteDisplayList(TreeObserver& observer, TreeInfo* info) { if (mDisplayList) { mDisplayList->updateChildren( [&observer, info](RenderNode* child) { child->decParentRefCount(observer, info); }); - if (!mDisplayList->reuseDisplayList(this, info ? &info->canvasContext : nullptr)) { + if (!mDisplayList->reuseDisplayList(this)) { delete mDisplayList; } } diff --git a/libs/hwui/canvas/CanvasFrontend.cpp b/libs/hwui/canvas/CanvasFrontend.cpp index 2c839b0ffc15..8f261c83b8d3 100644 --- a/libs/hwui/canvas/CanvasFrontend.cpp +++ b/libs/hwui/canvas/CanvasFrontend.cpp @@ -21,7 +21,14 @@ namespace android::uirenderer { CanvasStateHelper::CanvasStateHelper(int width, int height) { + resetState(width, height); +} + +void CanvasStateHelper::resetState(int width, int height) { mInitialBounds = SkIRect::MakeWH(width, height); + mSaveStack.clear(); + mClipStack.clear(); + mTransformStack.clear(); mSaveStack.emplace_back(); mClipStack.emplace_back().setRect(mInitialBounds); mTransformStack.emplace_back(); diff --git a/libs/hwui/canvas/CanvasFrontend.h b/libs/hwui/canvas/CanvasFrontend.h index 5fccccb0bb43..d749d2f2596b 100644 --- a/libs/hwui/canvas/CanvasFrontend.h +++ b/libs/hwui/canvas/CanvasFrontend.h @@ -57,9 +57,7 @@ protected: } bool internalSave(SaveEntry saveEntry); - bool internalSave(SaveFlags::Flags flags) { - return internalSave(flagsToSaveEntry(flags)); - } + void internalSaveLayer(const SkCanvas::SaveLayerRec& layerRec) { internalSave({ .clip = true, @@ -90,6 +88,8 @@ protected: return mClipStack[mCurrentClipIndex]; } + void resetState(int width, int height); + public: int saveCount() const { return mSaveStack.size(); } @@ -186,14 +186,26 @@ public: submit(std::move(op)); } - const CanvasOpReceiver& receiver() const { return mReceiver; } + const CanvasOpReceiver& receiver() const { return *mReceiver; } + + CanvasOpReceiver finish() { + auto ret = std::move(mReceiver.value()); + mReceiver.reset(); + return std::move(ret); + } + + template<class... Args> + void reset(int newWidth, int newHeight, Args&&... args) { + resetState(newWidth, newHeight); + mReceiver.emplace(std::forward<Args>(args)...); + } private: - CanvasOpReceiver mReceiver; + std::optional<CanvasOpReceiver> mReceiver; template <CanvasOpType T> void submit(CanvasOp<T>&& op) { - mReceiver.push_container(CanvasOpContainer(std::move(op), transform())); + mReceiver->push_container(CanvasOpContainer(std::move(op), transform())); } }; diff --git a/libs/hwui/canvas/CanvasOps.h b/libs/hwui/canvas/CanvasOps.h index 242dbdb27362..62c26c7b6f6a 100644 --- a/libs/hwui/canvas/CanvasOps.h +++ b/libs/hwui/canvas/CanvasOps.h @@ -310,7 +310,7 @@ struct CanvasOp<CanvasOpType::DrawVertices> { template<> struct CanvasOp<CanvasOpType::DrawImage> { - CanvasOp<CanvasOpType::DrawImageRect>( + CanvasOp( const sk_sp<Bitmap>& bitmap, float left, float top, @@ -336,7 +336,7 @@ struct CanvasOp<CanvasOpType::DrawImage> { template<> struct CanvasOp<CanvasOpType::DrawImageRect> { - CanvasOp<CanvasOpType::DrawImageRect>( + CanvasOp( const sk_sp<Bitmap>& bitmap, SkRect src, SkRect dst, @@ -367,7 +367,7 @@ struct CanvasOp<CanvasOpType::DrawImageRect> { template<> struct CanvasOp<CanvasOpType::DrawImageLattice> { - CanvasOp<CanvasOpType::DrawImageLattice>( + CanvasOp( const sk_sp<Bitmap>& bitmap, SkRect dst, SkCanvas::Lattice lattice, diff --git a/libs/hwui/canvas/OpBuffer.h b/libs/hwui/canvas/OpBuffer.h index 98e385f37a6e..6dc29d9a4bfe 100644 --- a/libs/hwui/canvas/OpBuffer.h +++ b/libs/hwui/canvas/OpBuffer.h @@ -60,9 +60,8 @@ class OpBuffer { return (size + (Alignment - 1)) & -Alignment; } - static constexpr auto STARTING_SIZE = PadAlign(sizeof(BufferHeader)); - public: + static constexpr auto STARTING_SIZE = PadAlign(sizeof(BufferHeader)); using ItemHeader = OpBufferItemHeader<ItemTypes>; OpBuffer() = default; diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h index 4d67166dd8d2..11fa3223a9c8 100644 --- a/libs/hwui/hwui/Canvas.h +++ b/libs/hwui/hwui/Canvas.h @@ -21,6 +21,7 @@ #include <SaveFlags.h> #include <androidfw/ResourceTypes.h> +#include "DisplayList.h" #include "Properties.h" #include "utils/Macros.h" @@ -47,18 +48,6 @@ class CanvasPropertyPaint; class CanvasPropertyPrimitive; class DeferredLayerUpdater; class RenderNode; - -namespace skiapipeline { -class SkiaDisplayList; -} - -/** - * Data structure that holds the list of commands used in display list stream - */ -using DisplayList = skiapipeline::SkiaDisplayList; -} - -namespace uirenderer { namespace VectorDrawable { class Tree; } diff --git a/libs/hwui/jni/Typeface.cpp b/libs/hwui/jni/Typeface.cpp index a2964d6627a1..10c80774fd16 100644 --- a/libs/hwui/jni/Typeface.cpp +++ b/libs/hwui/jni/Typeface.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#define ATRACE_TAG ATRACE_TAG_VIEW #include "FontUtils.h" #include "GraphicsJNI.h" #include "fonts/Font.h" @@ -25,8 +26,13 @@ #include <minikin/FontCollection.h> #include <minikin/FontFamily.h> #include <minikin/SystemFonts.h> +#include <utils/TraceUtils.h> + +#include <mutex> +#include <unordered_map> using namespace android; +using android::uirenderer::TraceUtils; static inline Typeface* toTypeface(jlong ptr) { return reinterpret_cast<Typeface*>(ptr); @@ -149,6 +155,20 @@ static void Typeface_registerGenericFamily(JNIEnv *env, jobject, jstring familyN toTypeface(ptr)->fFontCollection); } +static sk_sp<SkData> makeSkDataCached(const std::string& path) { + // We don't clear cache as Typeface objects created by Typeface_readTypefaces() will be stored + // in a static field and will not be garbage collected. + static std::unordered_map<std::string, sk_sp<SkData>> cache; + static std::mutex mutex; + ALOG_ASSERT(!path.empty()); + std::lock_guard lock{mutex}; + sk_sp<SkData>& entry = cache[path]; + if (entry.get() == nullptr) { + entry = SkData::MakeFromFileName(path.c_str()); + } + return entry; +} + static std::function<std::shared_ptr<minikin::MinikinFont>()> readMinikinFontSkia( minikin::BufferReader* reader) { std::string_view fontPath = reader->readString(); @@ -158,8 +178,9 @@ static std::function<std::shared_ptr<minikin::MinikinFont>()> readMinikinFontSki std::tie(axesPtr, axesCount) = reader->readArray<minikin::FontVariation>(); return [fontPath, fontIndex, axesPtr, axesCount]() -> std::shared_ptr<minikin::MinikinFont> { std::string path(fontPath.data(), fontPath.size()); - sk_sp<SkData> data = SkData::MakeFromFileName(path.c_str()); - if (data == nullptr) { + ATRACE_FORMAT("Loading font %s", path.c_str()); + sk_sp<SkData> data = makeSkDataCached(path); + if (data.get() == nullptr) { // This may happen if: // 1. When the process failed to open the file (e.g. invalid path or permission). // 2. When the process failed to map the file (e.g. hitting max_map_count limit). diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp index 158c3493a90c..c63f5d349311 100644 --- a/libs/hwui/pipeline/skia/SkiaDisplayList.cpp +++ b/libs/hwui/pipeline/skia/SkiaDisplayList.cpp @@ -47,7 +47,7 @@ void SkiaDisplayList::syncContents(const WebViewSyncData& data) { } } -bool SkiaDisplayList::reuseDisplayList(RenderNode* node, renderthread::CanvasContext* context) { +bool SkiaDisplayList::reuseDisplayList(RenderNode* node) { reset(); node->attachAvailableList(this); return true; diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.h b/libs/hwui/pipeline/skia/SkiaDisplayList.h index cdd00db9afdc..f2f19ba2975e 100644 --- a/libs/hwui/pipeline/skia/SkiaDisplayList.h +++ b/libs/hwui/pipeline/skia/SkiaDisplayList.h @@ -98,7 +98,7 @@ public: * * @return true if the displayList will be reused and therefore should not be deleted */ - bool reuseDisplayList(RenderNode* node, renderthread::CanvasContext* context); + bool reuseDisplayList(RenderNode* node); /** * ONLY to be called by RenderNode::syncDisplayList so that we can notify any diff --git a/libs/hwui/tests/microbench/CanvasOpBench.cpp b/libs/hwui/tests/microbench/CanvasOpBench.cpp new file mode 100644 index 000000000000..ef5749e6b79b --- /dev/null +++ b/libs/hwui/tests/microbench/CanvasOpBench.cpp @@ -0,0 +1,96 @@ +/* + * 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. + */ + +#include <benchmark/benchmark.h> + +#include "DisplayList.h" +#include "hwui/Paint.h" +#include "canvas/CanvasOpBuffer.h" +#include "canvas/CanvasFrontend.h" +#include "tests/common/TestUtils.h" + +using namespace android; +using namespace android::uirenderer; + +void BM_CanvasOpBuffer_alloc(benchmark::State& benchState) { + while (benchState.KeepRunning()) { + auto displayList = new CanvasOpBuffer(); + benchmark::DoNotOptimize(displayList); + delete displayList; + } +} +BENCHMARK(BM_CanvasOpBuffer_alloc); + +void BM_CanvasOpBuffer_record_saverestore(benchmark::State& benchState) { + CanvasFrontend<CanvasOpBuffer> canvas(100, 100); + while (benchState.KeepRunning()) { + canvas.reset(100, 100); + canvas.save(SaveFlags::MatrixClip); + canvas.save(SaveFlags::MatrixClip); + benchmark::DoNotOptimize(&canvas); + canvas.restore(); + canvas.restore(); + canvas.finish(); + } +} +BENCHMARK(BM_CanvasOpBuffer_record_saverestore); + +void BM_CanvasOpBuffer_record_saverestoreWithReuse(benchmark::State& benchState) { + CanvasFrontend<CanvasOpBuffer> canvas(100, 100); + + while (benchState.KeepRunning()) { + canvas.reset(100, 100); + canvas.save(SaveFlags::MatrixClip); + canvas.save(SaveFlags::MatrixClip); + benchmark::DoNotOptimize(&canvas); + canvas.restore(); + canvas.restore(); + } +} +BENCHMARK(BM_CanvasOpBuffer_record_saverestoreWithReuse); + +void BM_CanvasOpBuffer_record_simpleBitmapView(benchmark::State& benchState) { + CanvasFrontend<CanvasOpBuffer> canvas(100, 100); + + Paint rectPaint; + sk_sp<Bitmap> iconBitmap(TestUtils::createBitmap(80, 80)); + + while (benchState.KeepRunning()) { + canvas.reset(100, 100); + { + canvas.save(SaveFlags::MatrixClip); + canvas.draw(CanvasOp<CanvasOpType::DrawRect> { + .rect = SkRect::MakeWH(100, 100), + .paint = rectPaint, + }); + canvas.restore(); + } + { + canvas.save(SaveFlags::MatrixClip); + canvas.translate(10, 10); + canvas.draw(CanvasOp<CanvasOpType::DrawImage> { + iconBitmap, + 0, + 0, + SkPaint{} + }); + canvas.restore(); + } + benchmark::DoNotOptimize(&canvas); + canvas.finish(); + } +} +BENCHMARK(BM_CanvasOpBuffer_record_simpleBitmapView); diff --git a/libs/hwui/tests/microbench/RenderNodeBench.cpp b/libs/hwui/tests/microbench/RenderNodeBench.cpp index 206dcd58d785..011939a6e4b2 100644 --- a/libs/hwui/tests/microbench/RenderNodeBench.cpp +++ b/libs/hwui/tests/microbench/RenderNodeBench.cpp @@ -30,3 +30,29 @@ void BM_RenderNode_create(benchmark::State& state) { } } BENCHMARK(BM_RenderNode_create); + +void BM_RenderNode_recordSimple(benchmark::State& state) { + sp<RenderNode> node = new RenderNode(); + std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(100, 100)); + delete canvas->finishRecording(); + + while (state.KeepRunning()) { + canvas->resetRecording(100, 100, node.get()); + canvas->drawColor(0x00000000, SkBlendMode::kSrcOver); + node->setStagingDisplayList(canvas->finishRecording()); + } +} +BENCHMARK(BM_RenderNode_recordSimple); + +void BM_RenderNode_recordSimpleWithReuse(benchmark::State& state) { + sp<RenderNode> node = new RenderNode(); + std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(100, 100)); + delete canvas->finishRecording(); + + while (state.KeepRunning()) { + canvas->resetRecording(100, 100, node.get()); + canvas->drawColor(0x00000000, SkBlendMode::kSrcOver); + canvas->finishRecording()->reuseDisplayList(node.get()); + } +} +BENCHMARK(BM_RenderNode_recordSimpleWithReuse);
\ No newline at end of file diff --git a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp index 2d34b0980546..c63f008c4aed 100644 --- a/libs/hwui/tests/unit/SkiaDisplayListTests.cpp +++ b/libs/hwui/tests/unit/SkiaDisplayListTests.cpp @@ -84,7 +84,7 @@ TEST(SkiaDisplayList, reuseDisplayList) { // attach a displayList for reuse SkiaDisplayList skiaDL; - ASSERT_TRUE(skiaDL.reuseDisplayList(renderNode.get(), nullptr)); + ASSERT_TRUE(skiaDL.reuseDisplayList(renderNode.get())); // detach the list that you just attempted to reuse availableList = renderNode->detachAvailableList(); diff --git a/location/java/android/location/Location.java b/location/java/android/location/Location.java index 47ecbd80a07f..a7e9a0de538a 100644 --- a/location/java/android/location/Location.java +++ b/location/java/android/location/Location.java @@ -1049,11 +1049,7 @@ public class Location implements Parcelable { * <ul> * <li> satellites - the number of satellites used to derive the fix * </ul> - * - * @deprecated Do not use. For GNSS related information, prefer listening for GNSS status - * information via {@link LocationManager}. */ - @Deprecated public Bundle getExtras() { return mExtras; } @@ -1063,10 +1059,7 @@ public class Location implements Parcelable { * * <p>Note this stores a copy of the given extras, so any changes to extras after calling this * method won't be reflected in the location bundle. - * - * @deprecated Do not use. */ - @Deprecated public void setExtras(@Nullable Bundle extras) { mExtras = (extras == null) ? null : new Bundle(extras); } diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 7085a755990f..914beaff225e 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -159,21 +159,21 @@ public class LocationManager { public static final long BLOCK_GPS_STATUS_USAGE = 144027538L; /** - * Name of the network location provider. + * Standard name of the network location provider. * - * <p>This provider determines location based on nearby of cell tower and WiFi access points. - * Results are retrieved by means of a network lookup. + * <p>If present, this provider determines location based on nearby of cell tower and WiFi + * access points. Operation of this provider may require a data connection. */ public static final String NETWORK_PROVIDER = "network"; /** - * Name of the GNSS location provider. + * Standard name of the GNSS location provider. * - * <p>This provider determines location using GNSS satellites. Depending on conditions, this - * provider may take a while to return a location fix. Requires the - * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission. + * <p>If present, this provider determines location using GNSS satellites. The responsiveness + * and accuracy of location fixes may depend on GNSS signal conditions. * - * <p>The extras Bundle for the GPS location provider can contain the following key/value pairs: + * <p>The extras Bundle for locations derived by this location provider may contain the + * following key/value pairs: * <ul> * <li> satellites - the number of satellites used to derive the fix * </ul> @@ -181,29 +181,22 @@ public class LocationManager { public static final String GPS_PROVIDER = "gps"; /** - * A special location provider for receiving locations without actually initiating a location - * fix. + * A special location provider for receiving locations without actively initiating a location + * fix. This location provider is always present. * * <p>This provider can be used to passively receive location updates when other applications or * services request them without actually requesting the locations yourself. This provider will - * only return locations generated by other providers. You can query the - * {@link Location#getProvider()} method to determine the actual provider that supplied the - * location update. Requires the {@link android.Manifest.permission#ACCESS_FINE_LOCATION} - * permission, although there is no guarantee of fine locations. + * only return locations generated by other providers. */ public static final String PASSIVE_PROVIDER = "passive"; /** - * The fused location provider. - * - * <p>This provider may combine inputs from several location sources to provide the - * best possible location fix. It is implicitly used for all API's that involve the - * {@link LocationRequest} object. + * Standard name of the fused location provider. * - * @hide + * <p>If present, this provider may combine inputs from several other location providers to + * provide the best possible location fix. It is implicitly used for all requestLocationUpdates + * APIs that involve a {@link Criteria}. */ - @SystemApi - @TestApi public static final String FUSED_PROVIDER = "fused"; /** @@ -918,6 +911,9 @@ public class LocationManager { /** * Register for a single location update using a Criteria and a callback. * + * <p>Note: Since Android KitKat, Criteria requests will always result in using the + * {@link #FUSED_PROVIDER}. + * * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)} for more detail * on how to use this method. * @@ -985,6 +981,9 @@ public class LocationManager { /** * Register for a single location update using a Criteria and pending intent. * + * <p>Note: Since Android KitKat, Criteria requests will always result in using the + * {@link #FUSED_PROVIDER}. + * * <p>See {@link #requestLocationUpdates(long, float, Criteria, PendingIntent)} for more detail * on how to use this method. * @@ -1113,6 +1112,9 @@ public class LocationManager { * Register for location updates using a provider selected through the given Criteria, and a * callback on the specified {@link Looper}. * + * <p>Note: Since Android KitKat, Criteria requests will always result in using the + * {@link #FUSED_PROVIDER}. + * * <p>See {@link #requestLocationUpdates(String, LocationRequest, Executor, LocationListener)} * for more detail on how this method works. * @@ -1124,7 +1126,12 @@ public class LocationManager { * @throws IllegalArgumentException if criteria is null * @throws IllegalArgumentException if listener is null * @throws SecurityException if no suitable permission is present + * + * @deprecated Use + * {@link #requestLocationUpdates(String, long, float, LocationListener, Looper)} instead to + * explicitly select a provider. */ + @Deprecated @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long minTimeMs, float minDistanceM, @NonNull Criteria criteria, @NonNull LocationListener listener, @@ -1138,6 +1145,9 @@ public class LocationManager { * Register for location updates using a provider selected through the given Criteria, and a * callback on the specified {@link Executor}. * + * <p>Note: Since Android KitKat, Criteria requests will always result in using the + * {@link #FUSED_PROVIDER}. + * * <p>See {@link #requestLocationUpdates(String, LocationRequest, Executor, LocationListener)} * for more detail on how this method works. * @@ -1151,7 +1161,12 @@ public class LocationManager { * @throws IllegalArgumentException if executor is null * @throws IllegalArgumentException if listener is null * @throws SecurityException if no suitable permission is present + * + * @deprecated Use + * {@link #requestLocationUpdates(String, long, float, Executor, LocationListener)} instead to + * explicitly select a provider. */ + @Deprecated @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) public void requestLocationUpdates( long minTimeMs, @@ -1199,6 +1214,9 @@ public class LocationManager { * Register for location updates using a provider selected through the given Criteria, and * callbacks delivered via the provided {@link PendingIntent}. * + * <p>Note: Since Android KitKat, Criteria requests will always result in using the + * {@link #FUSED_PROVIDER}. + * * <p>See {@link #requestLocationUpdates(String, long, float, PendingIntent)} for more detail on * how this method works. * @@ -1210,7 +1228,11 @@ public class LocationManager { * @throws IllegalArgumentException if provider is null or doesn't exist * @throws IllegalArgumentException if pendingIntent is null * @throws SecurityException if no suitable permission is present + * + * @deprecated Use {@link #requestLocationUpdates(String, long, float, PendingIntent)} instead + * to explicitly select a provider. */ + @Deprecated @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION}) public void requestLocationUpdates(long minTimeMs, float minDistanceM, @NonNull Criteria criteria, @NonNull PendingIntent pendingIntent) { @@ -1594,9 +1616,8 @@ public class LocationManager { } /** - * Returns a list of the names of all known location providers. All providers are returned, - * including ones that are not permitted to be accessed by the calling activity or are currently - * disabled. + * Returns a list of the names of all available location providers. All providers are returned, + * including those that are currently disabled. * * @return list of provider names */ @@ -1609,8 +1630,8 @@ public class LocationManager { } /** - * Returns a list of the names of location providers. Only providers that the caller has - * permission to access will be returned. + * Returns a list of the names of available location providers. If {@code enabledOnly} is false, + * this is functionally the same as {@link #getAllProviders()}. * * @param enabledOnly if true then only enabled providers are included * @return list of provider names @@ -1624,8 +1645,7 @@ public class LocationManager { } /** - * Returns a list of the names of providers that satisfy the given criteria. Only providers that - * the caller has permission to access will be returned. + * Returns a list of the names of available location providers that satisfy the given criteria. * * @param criteria the criteria that providers must match * @param enabledOnly if true then only enabled providers are included diff --git a/location/java/android/location/OWNERS b/location/java/android/location/OWNERS index 383321bc3d69..60321448a58a 100644 --- a/location/java/android/location/OWNERS +++ b/location/java/android/location/OWNERS @@ -1,6 +1,6 @@ # Bug component: 880425 -mstogaitis@google.com +sooniln@google.com wyattriley@google.com -etn@google.com +yuhany@google.com weiwa@google.com diff --git a/lowpan/java/android/net/lowpan/LowpanManager.java b/lowpan/java/android/net/lowpan/LowpanManager.java index 76876ce01c96..33b35e6af7af 100644 --- a/lowpan/java/android/net/lowpan/LowpanManager.java +++ b/lowpan/java/android/net/lowpan/LowpanManager.java @@ -24,6 +24,10 @@ import android.os.IBinder; import android.os.Looper; import android.os.RemoteException; import android.os.ServiceManager; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.os.BackgroundThread; + import java.lang.ref.WeakReference; import java.util.HashMap; import java.util.Map; @@ -97,10 +101,14 @@ public class LowpanManager { * * @param context the application context * @param service the Binder interface - * @param looper the default Looper to run callbacks on * @hide - hide this because it takes in a parameter of type ILowpanManager, which is a system * private class. */ + public LowpanManager(Context context, ILowpanManager service) { + this(context, service, BackgroundThread.get().getLooper()); + } + + @VisibleForTesting public LowpanManager(Context context, ILowpanManager service, Looper looper) { mContext = context; mService = service; diff --git a/media/OWNERS b/media/OWNERS index b2875e7f067c..e74149019b11 100644 --- a/media/OWNERS +++ b/media/OWNERS @@ -10,7 +10,7 @@ insun@google.com jaewan@google.com jinpark@google.com jmtrivi@google.com -jsharkey@google.com +jsharkey@android.com klhyun@google.com lajos@google.com marcone@google.com diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java index b67851a6b64f..2a3704df77db 100644 --- a/media/java/android/media/AudioDeviceInfo.java +++ b/media/java/android/media/AudioDeviceInfo.java @@ -23,6 +23,7 @@ import android.util.SparseIntArray; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; +import java.util.List; import java.util.Objects; import java.util.TreeSet; @@ -498,6 +499,13 @@ public final class AudioDeviceInfo { } /** + * @return A list of {@link AudioProfile} supported by the audio devices. + */ + public @NonNull List<AudioProfile> getAudioProfiles() { + return mPort.profiles(); + } + + /** * Returns an array of supported encapsulation modes for the device. * * The array can include any of the {@code AudioTrack} encapsulation modes, diff --git a/media/java/android/media/AudioDevicePort.java b/media/java/android/media/AudioDevicePort.java index 0f79675862c7..9c42bf7e5605 100644 --- a/media/java/android/media/AudioDevicePort.java +++ b/media/java/android/media/AudioDevicePort.java @@ -21,6 +21,7 @@ import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; import java.util.Arrays; +import java.util.List; /** * The AudioDevicePort is a specialized type of AudioPort @@ -57,6 +58,18 @@ public class AudioDevicePort extends AudioPort { mEncapsulationMetadataTypes = encapsulationMetadataTypes; } + AudioDevicePort(AudioHandle handle, String deviceName, List<AudioProfile> profiles, + AudioGain[] gains, int type, String address, int[] encapsulationModes, + @AudioTrack.EncapsulationMetadataType int[] encapsulationMetadataTypes) { + super(handle, + AudioManager.isInputDevice(type) ? AudioPort.ROLE_SOURCE : AudioPort.ROLE_SINK, + deviceName, profiles, gains); + mType = type; + mAddress = address; + mEncapsulationModes = encapsulationModes; + mEncapsulationMetadataTypes = encapsulationMetadataTypes; + } + /** * Get the device type (e.g AudioManager.DEVICE_OUT_SPEAKER) */ diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index c67d90a5ea0f..3bd68d893521 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -2319,7 +2319,55 @@ public class AudioManager { if (attributes == null) { throw new NullPointerException("Illegal null AudioAttributes"); } - return AudioSystem.isOffloadSupported(format, attributes); + return AudioSystem.getOffloadSupport(format, attributes) != PLAYBACK_OFFLOAD_NOT_SUPPORTED; + } + + /** Return value for {@link #getPlaybackOffloadSupport(AudioFormat, AudioAttributes)}: + offload playback not supported */ + public static final int PLAYBACK_OFFLOAD_NOT_SUPPORTED = AudioSystem.OFFLOAD_NOT_SUPPORTED; + /** Return value for {@link #getPlaybackOffloadSupport(AudioFormat, AudioAttributes)}: + offload playback supported */ + public static final int PLAYBACK_OFFLOAD_SUPPORTED = AudioSystem.OFFLOAD_SUPPORTED; + /** Return value for {@link #getPlaybackOffloadSupport(AudioFormat, AudioAttributes)}: + offload playback supported with gapless transitions */ + public static final int PLAYBACK_OFFLOAD_GAPLESS_SUPPORTED = + AudioSystem.OFFLOAD_GAPLESS_SUPPORTED; + + /** @hide */ + @IntDef(flag = false, prefix = "PLAYBACK_OFFLOAD_", value = { + PLAYBACK_OFFLOAD_NOT_SUPPORTED, + PLAYBACK_OFFLOAD_SUPPORTED, + PLAYBACK_OFFLOAD_GAPLESS_SUPPORTED } + ) + @Retention(RetentionPolicy.SOURCE) + public @interface AudioOffloadMode {} + + /** + * Returns whether offloaded playback of an audio format is supported on the device or not and + * when supported whether gapless transitions are possible or not. + * <p>Offloaded playback is the feature where the decoding and playback of an audio stream + * is not competing with other software resources. In general, it is supported by dedicated + * hardware, such as audio DSPs. + * <p>Note that this query only provides information about the support of an audio format, + * it does not indicate whether the resources necessary for the offloaded playback are + * available at that instant. + * @param format the audio format (codec, sample rate, channels) being checked. + * @param attributes the {@link AudioAttributes} to be used for playback + * @return {@link #PLAYBACK_OFFLOAD_NOT_SUPPORTED} if offload playback if not supported, + * {@link #PLAYBACK_OFFLOAD_SUPPORTED} if offload playback is supported or + * {@link #PLAYBACK_OFFLOAD_GAPLESS_SUPPORTED} if gapless transitions are + * also supported. + */ + @AudioOffloadMode + public static int getPlaybackOffloadSupport(@NonNull AudioFormat format, + @NonNull AudioAttributes attributes) { + if (format == null) { + throw new NullPointerException("Illegal null AudioFormat"); + } + if (attributes == null) { + throw new NullPointerException("Illegal null AudioAttributes"); + } + return AudioSystem.getOffloadSupport(format, attributes); } //==================================================================== diff --git a/media/java/android/media/AudioMixPort.java b/media/java/android/media/AudioMixPort.java index 0e286b0f1f89..7f2249d05ec2 100644 --- a/media/java/android/media/AudioMixPort.java +++ b/media/java/android/media/AudioMixPort.java @@ -19,6 +19,8 @@ package android.media; import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; +import java.util.List; + /** * The AudioMixPort is a specialized type of AudioPort * describing an audio mix or stream at an input or output stream of the audio @@ -42,6 +44,12 @@ public class AudioMixPort extends AudioPort { mIoHandle = ioHandle; } + AudioMixPort(AudioHandle handle, int ioHandle, int role, String deviceName, + List<AudioProfile> profiles, AudioGain[] gains) { + super(handle, role, deviceName, profiles, gains); + mIoHandle = ioHandle; + } + /** * Build a specific configuration of this audio mix port for use by methods * like AudioManager.connectAudioPatch(). diff --git a/media/java/android/media/AudioPort.java b/media/java/android/media/AudioPort.java index e6dc622a11c1..03022501fbca 100644 --- a/media/java/android/media/AudioPort.java +++ b/media/java/android/media/AudioPort.java @@ -19,6 +19,13 @@ package android.media; import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + /** * An audio port is a node of the audio framework or hardware that can be connected to or * disconnect from another audio node to create a specific audio routing configuration. @@ -78,6 +85,7 @@ public class AudioPort { private final int[] mChannelMasks; private final int[] mChannelIndexMasks; private final int[] mFormats; + private final List<AudioProfile> mProfiles; @UnsupportedAppUsage private final AudioGain[] mGains; @UnsupportedAppUsage @@ -87,7 +95,6 @@ public class AudioPort { AudioPort(AudioHandle handle, int role, String name, int[] samplingRates, int[] channelMasks, int[] channelIndexMasks, int[] formats, AudioGain[] gains) { - mHandle = handle; mRole = role; mName = name; @@ -96,6 +103,39 @@ public class AudioPort { mChannelIndexMasks = channelIndexMasks; mFormats = formats; mGains = gains; + mProfiles = new ArrayList<>(); + if (mFormats != null) { + for (int format : mFormats) { + mProfiles.add(new AudioProfile( + format, samplingRates, channelMasks, channelIndexMasks)); + } + } + } + + AudioPort(AudioHandle handle, int role, String name, + List<AudioProfile> profiles, AudioGain[] gains) { + mHandle = handle; + mRole = role; + mName = name; + mProfiles = profiles; + mGains = gains; + Set<Integer> formats = new HashSet<>(); + Set<Integer> samplingRates = new HashSet<>(); + Set<Integer> channelMasks = new HashSet<>(); + Set<Integer> channelIndexMasks = new HashSet<>(); + for (AudioProfile profile : profiles) { + formats.add(profile.getFormat()); + samplingRates.addAll(Arrays.stream(profile.getSampleRates()).boxed() + .collect(Collectors.toList())); + channelMasks.addAll(Arrays.stream(profile.getChannelMasks()).boxed() + .collect(Collectors.toList())); + channelIndexMasks.addAll(Arrays.stream(profile.getChannelIndexMasks()).boxed() + .collect(Collectors.toList())); + } + mSamplingRates = samplingRates.stream().mapToInt(Number::intValue).toArray(); + mChannelMasks = channelMasks.stream().mapToInt(Number::intValue).toArray(); + mChannelIndexMasks = channelIndexMasks.stream().mapToInt(Number::intValue).toArray(); + mFormats = formats.stream().mapToInt(Number::intValue).toArray(); } AudioHandle handle() { @@ -163,6 +203,13 @@ public class AudioPort { } /** + * Get the list of supported audio profiles + */ + public List<AudioProfile> profiles() { + return mProfiles; + } + + /** * Get the list of gain descriptors * Empty array if this port does not have gain control */ diff --git a/media/java/android/media/AudioProfile.java b/media/java/android/media/AudioProfile.java new file mode 100644 index 000000000000..42041667476a --- /dev/null +++ b/media/java/android/media/AudioProfile.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media; + +import android.annotation.NonNull; + +/** + * AudioProfile is a class used by {@link AudioDeviceInfo} to list the audio formats, sampling rates + * and channel masks supported. + * Each AudioProfile is specific to an audio format and lists all sampling rates and channel masks + * supported for this format. + */ +public class AudioProfile { + private final int mFormat; + private final int[] mSamplingRates; + private final int[] mChannelMasks; + private final int[] mChannelIndexMasks; + + AudioProfile(int format, @NonNull int[] samplingRates, @NonNull int[] channelMasks, + @NonNull int[] channelIndexMasks) { + mFormat = format; + mSamplingRates = samplingRates; + mChannelMasks = channelMasks; + mChannelIndexMasks = channelIndexMasks; + } + + /** + * @return the encoding format for this AudioProfile. + */ + public @AudioFormat.Encoding int getFormat() { + return mFormat; + } + + /** + * @return an array of channel position masks that are associated with the encoding format. + */ + public @NonNull int[] getChannelMasks() { + return mChannelMasks; + } + + /** + * @return an array of channel index masks that are associated with the encoding format. + */ + public @NonNull int[] getChannelIndexMasks() { + return mChannelIndexMasks; + } + + /** + * @return an array of sample rates that are associated with the encoding format. + */ + public @NonNull int[] getSampleRates() { + return mSamplingRates; + } +} diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index bd27f6d068bc..8987a713e505 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -1639,13 +1639,22 @@ public class AudioSystem */ public static native int setAllowedCapturePolicy(int uid, int flags); - static boolean isOffloadSupported(@NonNull AudioFormat format, @NonNull AudioAttributes attr) { - return native_is_offload_supported(format.getEncoding(), format.getSampleRate(), + /** + * @hide + * Compressed audio offload decoding modes supported by audio HAL implementation. + * Keep in sync with system/media/include/media/audio.h. + */ + public static final int OFFLOAD_NOT_SUPPORTED = 0; + public static final int OFFLOAD_SUPPORTED = 1; + public static final int OFFLOAD_GAPLESS_SUPPORTED = 2; + + static int getOffloadSupport(@NonNull AudioFormat format, @NonNull AudioAttributes attr) { + return native_get_offload_support(format.getEncoding(), format.getSampleRate(), format.getChannelMask(), format.getChannelIndexMask(), attr.getVolumeControlStream()); } - private static native boolean native_is_offload_supported(int encoding, int sampleRate, + private static native int native_get_offload_support(int encoding, int sampleRate, int channelMask, int channelIndexMask, int streamType); /** @hide */ diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java index e8c62067580f..e3b6fba18eb0 100644 --- a/media/java/android/media/AudioTrack.java +++ b/media/java/android/media/AudioTrack.java @@ -1256,7 +1256,8 @@ public class AudioTrack extends PlayerBase throw new UnsupportedOperationException( "Offload and low latency modes are incompatible"); } - if (!AudioSystem.isOffloadSupported(mFormat, mAttributes)) { + if (AudioSystem.getOffloadSupport(mFormat, mAttributes) + == AudioSystem.OFFLOAD_NOT_SUPPORTED) { throw new UnsupportedOperationException( "Cannot create AudioTrack, offload format / attributes not supported"); } diff --git a/media/java/android/media/IMediaRouterService.aidl b/media/java/android/media/IMediaRouterService.aidl index 068f9689d06f..4b8a8adade1f 100644 --- a/media/java/android/media/IMediaRouterService.aidl +++ b/media/java/android/media/IMediaRouterService.aidl @@ -73,6 +73,8 @@ interface IMediaRouterService { void unregisterManager(IMediaRouter2Manager manager); void setRouteVolumeWithManager(IMediaRouter2Manager manager, int requestId, in MediaRoute2Info route, int volume); + void startScan(IMediaRouter2Manager manager); + void stopScan(IMediaRouter2Manager manager); void requestCreateSessionWithManager(IMediaRouter2Manager manager, int requestId, in RoutingSessionInfo oldSession, in @nullable MediaRoute2Info route); diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java index c2168f12a351..e7e83ebb001f 100644 --- a/media/java/android/media/MediaCodecInfo.java +++ b/media/java/android/media/MediaCodecInfo.java @@ -25,6 +25,7 @@ import android.annotation.SuppressLint; import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.os.Build; +import android.os.Process; import android.os.SystemProperties; import android.util.Log; import android.util.Pair; @@ -188,13 +189,14 @@ public final class MediaCodecInfo { // COMMON CONSTANTS private static final Range<Integer> POSITIVE_INTEGERS = - Range.create(1, Integer.MAX_VALUE); + Range.create(1, Integer.MAX_VALUE); private static final Range<Long> POSITIVE_LONGS = - Range.create(1l, Long.MAX_VALUE); + Range.create(1L, Long.MAX_VALUE); private static final Range<Rational> POSITIVE_RATIONALS = - Range.create(new Rational(1, Integer.MAX_VALUE), - new Rational(Integer.MAX_VALUE, 1)); - private static final Range<Integer> SIZE_RANGE = Range.create(1, 32768); + Range.create(new Rational(1, Integer.MAX_VALUE), + new Rational(Integer.MAX_VALUE, 1)); + private static final Range<Integer> SIZE_RANGE = + Process.is64Bit() ? Range.create(1, 32768) : Range.create(1, 4096); private static final Range<Integer> FRAME_RATE_RANGE = Range.create(0, 960); private static final Range<Integer> BITRATE_RANGE = Range.create(0, 500000000); private static final int DEFAULT_MAX_SUPPORTED_INSTANCES = 32; @@ -1399,6 +1401,9 @@ public final class MediaCodecInfo { /** * Returns the range of supported video widths. + * <p class=note> + * 32-bit processes will not support resolutions larger than 4096x4096 due to + * the limited address space. */ public Range<Integer> getSupportedWidths() { return mWidthRange; @@ -1406,6 +1411,9 @@ public final class MediaCodecInfo { /** * Returns the range of supported video heights. + * <p class=note> + * 32-bit processes will not support resolutions larger than 4096x4096 due to + * the limited address space. */ public Range<Integer> getSupportedHeights() { return mHeightRange; @@ -1857,6 +1865,10 @@ public final class MediaCodecInfo { && aligned.mMaxMacroBlockRate >= otherAligned.mMaxMacroBlockRate); } + /* package private */ boolean isEqualDimension(@NonNull PerformancePoint other) { + return mWidth == other.mWidth && mHeight == other.mHeight; + } + private @NonNull Size getCommonBlockSize(@NonNull PerformancePoint other) { return new Size( Math.max(mBlockSize.getWidth(), other.mBlockSize.getWidth()) * 16, @@ -1997,6 +2009,9 @@ public final class MediaCodecInfo { * Performance points assume a single active codec. For use cases where multiple * codecs are active, should use that highest pixel count, and add the frame rates of * each individual codec. + * <p class=note> + * Supported resolution could be further restricted for 32-bit processes due to + * the limited virtual memory space. */ @Nullable public List<PerformancePoint> getSupportedPerformancePoints() { @@ -2164,6 +2179,12 @@ public final class MediaCodecInfo { if (size == null || size.getWidth() * size.getHeight() <= 0) { continue; } + if (size.getWidth() > SIZE_RANGE.getUpper() + || size.getHeight() > SIZE_RANGE.getUpper()) { + size = new Size( + Math.min(size.getWidth(), SIZE_RANGE.getUpper()), + Math.min(size.getHeight(), SIZE_RANGE.getUpper())); + } Range<Long> range = Utils.parseLongRange(map.get(key), null); if (range == null || range.getLower() < 0 || range.getUpper() < 0) { continue; @@ -2193,6 +2214,29 @@ public final class MediaCodecInfo { (a.getMaxMacroBlockRate() < b.getMaxMacroBlockRate() ? -1 : 1) : (a.getMaxFrameRate() != b.getMaxFrameRate()) ? (a.getMaxFrameRate() < b.getMaxFrameRate() ? -1 : 1) : 0)); + + // remove redundant points + for (int i = 1; i < ret.size(); ++i) { + PerformancePoint a = ret.get(i); + for (int j = 0; j < i; ++j) { + PerformancePoint b = ret.get(j); + if (b.isEqualDimension(a) && b.covers(a)) { + ret.set(i, null); + break; + } + } + } + int newSize = 0; + for (int i = 0; i < ret.size(); ++i) { + PerformancePoint a = ret.get(i); + if (a == null) { + continue; + } + ret.set(newSize, a); + ++newSize; + } + ret.setSize(newSize); + return Collections.unmodifiableList(ret); } diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java index 4b09a5f19fb0..68237de2ca98 100644 --- a/media/java/android/media/MediaRouter2Manager.java +++ b/media/java/android/media/MediaRouter2Manager.java @@ -147,6 +147,36 @@ public final class MediaRouter2Manager { } /** + * Starts scanning remote routes. + * @see #stopScan(String) + */ + public void startScan() { + Client client = getOrCreateClient(); + if (client != null) { + try { + mMediaRouterService.startScan(client); + } catch (RemoteException ex) { + Log.e(TAG, "Unable to get sessions. Service probably died.", ex); + } + } + } + + /** + * Stops scanning remote routes to reduce resource consumption. + * @see #startScan(String) + */ + public void stopScan() { + Client client = getOrCreateClient(); + if (client != null) { + try { + mMediaRouterService.stopScan(client); + } catch (RemoteException ex) { + Log.e(TAG, "Unable to get sessions. Service probably died.", ex); + } + } + } + + /** * Gets a {@link android.media.session.MediaController} associated with the * given routing session. * If there is no matching media session, {@code null} is returned. diff --git a/media/java/android/media/RouteDiscoveryPreference.java b/media/java/android/media/RouteDiscoveryPreference.java index 68f2964dbeb2..2f952474b7f0 100644 --- a/media/java/android/media/RouteDiscoveryPreference.java +++ b/media/java/android/media/RouteDiscoveryPreference.java @@ -153,6 +153,7 @@ public final class RouteDiscoveryPreference implements Parcelable { return false; } RouteDiscoveryPreference other = (RouteDiscoveryPreference) o; + //TODO: Make this order-free return Objects.equals(mPreferredFeatures, other.mPreferredFeatures) && mShouldPerformActiveScan == other.mShouldPerformActiveScan; } diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java index b1a88ed16bcd..e7d30ebba4b1 100644 --- a/media/java/android/media/session/PlaybackState.java +++ b/media/java/android/media/session/PlaybackState.java @@ -46,7 +46,8 @@ public final class PlaybackState implements Parcelable { ACTION_SKIP_TO_PREVIOUS, ACTION_SKIP_TO_NEXT, ACTION_FAST_FORWARD, ACTION_SET_RATING, ACTION_SEEK_TO, ACTION_PLAY_PAUSE, ACTION_PLAY_FROM_MEDIA_ID, ACTION_PLAY_FROM_SEARCH, ACTION_SKIP_TO_QUEUE_ITEM, ACTION_PLAY_FROM_URI, ACTION_PREPARE, - ACTION_PREPARE_FROM_MEDIA_ID, ACTION_PREPARE_FROM_SEARCH, ACTION_PREPARE_FROM_URI}) + ACTION_PREPARE_FROM_MEDIA_ID, ACTION_PREPARE_FROM_SEARCH, ACTION_PREPARE_FROM_URI, + ACTION_SET_PLAYBACK_SPEED}) @Retention(RetentionPolicy.SOURCE) public @interface Actions {} @@ -176,6 +177,14 @@ public final class PlaybackState implements Parcelable { */ public static final long ACTION_PREPARE_FROM_URI = 1 << 17; + // Note: The value jumps from 1 << 17 to 1 << 22 for matching same value with AndroidX. + /** + * Indicates this session supports the set playback speed command. + * + * @see Builder#setActions(long) + */ + public static final long ACTION_SET_PLAYBACK_SPEED = 1 << 22; + /** * @hide */ @@ -428,6 +437,7 @@ public final class PlaybackState implements Parcelable { * <li> {@link PlaybackState#ACTION_PREPARE_FROM_MEDIA_ID}</li> * <li> {@link PlaybackState#ACTION_PREPARE_FROM_SEARCH}</li> * <li> {@link PlaybackState#ACTION_PREPARE_FROM_URI}</li> + * <li> {@link PlaybackState#ACTION_SET_PLAYBACK_SPEED}</li> * </ul> */ @Actions @@ -823,6 +833,7 @@ public final class PlaybackState implements Parcelable { * <li> {@link PlaybackState#ACTION_PREPARE_FROM_MEDIA_ID}</li> * <li> {@link PlaybackState#ACTION_PREPARE_FROM_SEARCH}</li> * <li> {@link PlaybackState#ACTION_PREPARE_FROM_URI}</li> + * <li> {@link PlaybackState#ACTION_SET_PLAYBACK_SPEED}</li> * </ul> * * @param actions The set of actions allowed. diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java index d094c2cd3c63..20f02a46ea63 100644 --- a/media/java/android/media/tv/tuner/Tuner.java +++ b/media/java/android/media/tv/tuner/Tuner.java @@ -279,6 +279,7 @@ public class Tuner implements AutoCloseable { @Nullable private FrontendInfo mFrontendInfo; private Integer mFrontendHandle; + private Boolean mIsSharedFrontend = false; private int mFrontendType = FrontendSettings.TYPE_UNDEFINED; private int mUserId; private Lnb mLnb; @@ -441,8 +442,11 @@ public class Tuner implements AutoCloseable { */ public void shareFrontendFromTuner(@NonNull Tuner tuner) { mTunerResourceManager.shareFrontend(mClientId, tuner.mClientId); - mFrontendHandle = tuner.mFrontendHandle; - mFrontend = nativeOpenFrontendByHandle(mFrontendHandle); + synchronized (mIsSharedFrontend) { + mFrontendHandle = tuner.mFrontendHandle; + mFrontend = tuner.mFrontend; + mIsSharedFrontend = true; + } } /** @@ -473,14 +477,19 @@ public class Tuner implements AutoCloseable { private void releaseAll() { if (mFrontendHandle != null) { - int res = nativeCloseFrontend(mFrontendHandle); - if (res != Tuner.RESULT_SUCCESS) { - TunerUtils.throwExceptionForResult(res, "failed to close frontend"); + synchronized (mIsSharedFrontend) { + if (!mIsSharedFrontend) { + int res = nativeCloseFrontend(mFrontendHandle); + if (res != Tuner.RESULT_SUCCESS) { + TunerUtils.throwExceptionForResult(res, "failed to close frontend"); + } + } + mIsSharedFrontend = false; } mTunerResourceManager.releaseFrontend(mFrontendHandle, mClientId); FrameworkStatsLog .write(FrameworkStatsLog.TV_TUNER_STATE_CHANGED, mUserId, - FrameworkStatsLog.TV_TUNER_STATE_CHANGED__STATE__UNKNOWN); + FrameworkStatsLog.TV_TUNER_STATE_CHANGED__STATE__UNKNOWN); mFrontendHandle = null; mFrontend = null; } diff --git a/media/java/android/mtp/OWNERS b/media/java/android/mtp/OWNERS index e27d06f4825a..1928ba811e7e 100644 --- a/media/java/android/mtp/OWNERS +++ b/media/java/android/mtp/OWNERS @@ -1,7 +1,7 @@ set noparent marcone@google.com -jsharkey@google.com +jsharkey@android.com jameswei@google.com rmojumder@google.com diff --git a/media/jni/OWNERS b/media/jni/OWNERS index e6e4f86505cf..f1b0237d9008 100644 --- a/media/jni/OWNERS +++ b/media/jni/OWNERS @@ -1,5 +1,5 @@ # extra for MTP related files -per-file android_mtp_*.cpp=marcone@google.com,jsharkey@google.com,jameswei@google.com,rmojumder@google.com +per-file android_mtp_*.cpp=marcone@google.com,jsharkey@android.com,jameswei@google.com,rmojumder@google.com # extra for TV related files per-file android_media_tv_*=nchalko@google.com,quxiangfang@google.com diff --git a/media/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp index 948ebcd9fdd5..6a622c5a1566 100644 --- a/media/jni/android_media_MediaExtractor.cpp +++ b/media/jni/android_media_MediaExtractor.cpp @@ -68,7 +68,7 @@ JMediaExtractor::JMediaExtractor(JNIEnv *env, jobject thiz) mClass = (jclass)env->NewGlobalRef(clazz); mObject = env->NewWeakGlobalRef(thiz); - mImpl = new NuMediaExtractor; + mImpl = new NuMediaExtractor(NuMediaExtractor::EntryPoint::SDK); } JMediaExtractor::~JMediaExtractor() { diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp index 126897a908f8..ddc51cdb861c 100644 --- a/media/jni/android_media_MediaMetadataRetriever.cpp +++ b/media/jni/android_media_MediaMetadataRetriever.cpp @@ -464,11 +464,13 @@ static jobject android_media_MediaMetadataRetriever_getThumbnailImageAtIndex( || thumbPixels * 6 >= maxPixels) { frameMemory = retriever->getImageAtIndex( index, colorFormat, false /*metaOnly*/, true /*thumbnail*/); - // TODO: Using unsecurePointer() has some associated security pitfalls - // (see declaration for details). - // Either document why it is safe in this case or address the - // issue (e.g. by copying). - videoFrame = static_cast<VideoFrame *>(frameMemory->unsecurePointer()); + if (frameMemory != 0) { + // TODO: Using unsecurePointer() has some associated security pitfalls + // (see declaration for details). + // Either document why it is safe in this case or address the + // issue (e.g. by copying). + videoFrame = static_cast<VideoFrame *>(frameMemory->unsecurePointer()); + } if (thumbPixels > maxPixels) { int downscale = ceil(sqrt(thumbPixels / (float)maxPixels)); diff --git a/media/native/midi/amidi.cpp b/media/native/midi/amidi.cpp index 35c4d42a0aa8..923377c8180e 100644 --- a/media/native/midi/amidi.cpp +++ b/media/native/midi/amidi.cpp @@ -131,7 +131,7 @@ static media_status_t AMIDI_getDeviceInfo(const AMidiDevice *device, MidiDeviceInfo deviceInfo; Status txResult = device->server->getDeviceInfo(&deviceInfo); if (!txResult.isOk()) { - ALOGE("AMIDI_getDeviceInfo transaction error: %d", txResult.transactionError()); + ALOGE("%s server exception code: %d", __func__, txResult.exceptionCode()); return AMEDIA_ERROR_UNKNOWN; } @@ -253,7 +253,7 @@ static media_status_t AMIDI_openPort(const AMidiDevice *device, int32_t portNumb ? device->server->openOutputPort(portToken, portNumber, &ufd) : device->server->openInputPort(portToken, portNumber, &ufd); if (!txResult.isOk()) { - ALOGE("AMIDI_openPort transaction error: %d", txResult.transactionError()); + ALOGE("%s server exception code: %d", __func__, txResult.exceptionCode()); return AMEDIA_ERROR_UNKNOWN; } @@ -282,7 +282,7 @@ static void AMIDI_closePort(AMIDI_Port *port) { Status txResult = port->device->server->closePort(port->binderToken); if (!txResult.isOk()) { - ALOGE("Transaction error closing MIDI port:%d", txResult.transactionError()); + ALOGE("%s server exception code: %d", __func__, txResult.exceptionCode()); } delete port; diff --git a/media/tests/MtpTests/OWNERS b/media/tests/MtpTests/OWNERS index e27d06f4825a..1928ba811e7e 100644 --- a/media/tests/MtpTests/OWNERS +++ b/media/tests/MtpTests/OWNERS @@ -1,7 +1,7 @@ set noparent marcone@google.com -jsharkey@google.com +jsharkey@android.com jameswei@google.com rmojumder@google.com diff --git a/packages/CarrierDefaultApp/AndroidManifest.xml b/packages/CarrierDefaultApp/AndroidManifest.xml index 4473610f647a..3e65df23fb2b 100644 --- a/packages/CarrierDefaultApp/AndroidManifest.xml +++ b/packages/CarrierDefaultApp/AndroidManifest.xml @@ -48,6 +48,7 @@ android:name="com.android.carrierdefaultapp.CaptivePortalLoginActivity" android:label="@string/action_bar_label" android:exported="true" + android:permission="android.permission.MODIFY_PHONE_STATE" android:theme="@style/AppTheme" android:configChanges="keyboardHidden|orientation|screenSize"> <intent-filter> diff --git a/packages/Connectivity/OWNERS b/packages/Connectivity/OWNERS new file mode 100644 index 000000000000..48e54da82cc2 --- /dev/null +++ b/packages/Connectivity/OWNERS @@ -0,0 +1,3 @@ +set noparent + +include platform/frameworks/base:/services/core/java/com/android/server/net/OWNERS diff --git a/packages/CtsShim/build/Android.bp b/packages/CtsShim/build/Android.bp index 43e386852713..14a3376380df 100644 --- a/packages/CtsShim/build/Android.bp +++ b/packages/CtsShim/build/Android.bp @@ -34,6 +34,8 @@ android_app { compile_multilib: "both", jni_libs: ["libshim_jni"], + + uses_libs: ["android.test.runner"], } genrule { @@ -108,6 +110,7 @@ android_app { compile_multilib: "both", jni_libs: ["libshim_jni"], + uses_libs: ["android.test.runner"], } //########################################################## diff --git a/packages/OsuLogin/res/values-my/strings.xml b/packages/OsuLogin/res/values-my/strings.xml deleted file mode 100644 index 1bd992e8485b..000000000000 --- a/packages/OsuLogin/res/values-my/strings.xml +++ /dev/null @@ -1,7 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="app_name" msgid="8288271429327488421">"OsuLogin"</string> - <string name="action_bar_label" msgid="550995560341508693">"အွန်လိုင်း အကောင့်ဖွင့်ရန်"</string> - <string name="sign_up_failed" msgid="837216244603867568">"အကောင့်ဖွင့်၍ မရပါ"</string> -</resources> diff --git a/packages/SettingsLib/HelpUtils/res/values-ar/strings.xml b/packages/SettingsLib/HelpUtils/res/values-ar/strings.xml index 7ab3abcf7540..5b12fc586ef9 100644 --- a/packages/SettingsLib/HelpUtils/res/values-ar/strings.xml +++ b/packages/SettingsLib/HelpUtils/res/values-ar/strings.xml @@ -17,5 +17,5 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="help_feedback_label" msgid="7106780063063027882">"المساعدة والتعليقات"</string> + <string name="help_feedback_label" msgid="7106780063063027882">"المساعدة والملاحظات والآراء"</string> </resources> diff --git a/packages/SettingsLib/OWNERS b/packages/SettingsLib/OWNERS index 30c10d3ef3b8..8eafbdfdf6bc 100644 --- a/packages/SettingsLib/OWNERS +++ b/packages/SettingsLib/OWNERS @@ -1,5 +1,5 @@ # People who can approve changes for submission -dsandler@google.com +dsandler@android.com edgarwang@google.com emilychuang@google.com evanlaird@google.com diff --git a/packages/SystemUI/res/drawable/ic_1x_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_1x_mobiledata.xml index 52135198bdf6..52135198bdf6 100644 --- a/packages/SystemUI/res/drawable/ic_1x_mobiledata.xml +++ b/packages/SettingsLib/res/drawable/ic_1x_mobiledata.xml diff --git a/packages/SystemUI/res/drawable/ic_3g_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_3g_mobiledata.xml index 0c942bdf993c..0c942bdf993c 100644 --- a/packages/SystemUI/res/drawable/ic_3g_mobiledata.xml +++ b/packages/SettingsLib/res/drawable/ic_3g_mobiledata.xml diff --git a/packages/SystemUI/res/drawable/ic_4g_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_4g_mobiledata.xml index 535f3589ea6b..535f3589ea6b 100644 --- a/packages/SystemUI/res/drawable/ic_4g_mobiledata.xml +++ b/packages/SettingsLib/res/drawable/ic_4g_mobiledata.xml diff --git a/packages/SystemUI/res/drawable/ic_4g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_4g_plus_mobiledata.xml index 1d048ae44049..1d048ae44049 100644 --- a/packages/SystemUI/res/drawable/ic_4g_plus_mobiledata.xml +++ b/packages/SettingsLib/res/drawable/ic_4g_plus_mobiledata.xml diff --git a/packages/SystemUI/res/drawable/ic_5g_e_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_5g_e_mobiledata.xml index 7c7c8c1e4729..7c7c8c1e4729 100644 --- a/packages/SystemUI/res/drawable/ic_5g_e_mobiledata.xml +++ b/packages/SettingsLib/res/drawable/ic_5g_e_mobiledata.xml diff --git a/packages/SystemUI/res/drawable/ic_5g_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_5g_mobiledata.xml index 2aa6e57f6f82..2aa6e57f6f82 100644 --- a/packages/SystemUI/res/drawable/ic_5g_mobiledata.xml +++ b/packages/SettingsLib/res/drawable/ic_5g_mobiledata.xml diff --git a/packages/SystemUI/res/drawable/ic_5g_plus_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_5g_plus_mobiledata.xml index 10bbcc7b3737..10bbcc7b3737 100644 --- a/packages/SystemUI/res/drawable/ic_5g_plus_mobiledata.xml +++ b/packages/SettingsLib/res/drawable/ic_5g_plus_mobiledata.xml diff --git a/packages/SystemUI/res/drawable/ic_e_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_e_mobiledata.xml index b360e3dd1012..b360e3dd1012 100644 --- a/packages/SystemUI/res/drawable/ic_e_mobiledata.xml +++ b/packages/SettingsLib/res/drawable/ic_e_mobiledata.xml diff --git a/packages/SystemUI/res/drawable/ic_g_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_g_mobiledata.xml index 82c8e18fb3ed..82c8e18fb3ed 100644 --- a/packages/SystemUI/res/drawable/ic_g_mobiledata.xml +++ b/packages/SettingsLib/res/drawable/ic_g_mobiledata.xml diff --git a/packages/SystemUI/res/drawable/ic_h_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_h_mobiledata.xml index f31ec7871683..f31ec7871683 100644 --- a/packages/SystemUI/res/drawable/ic_h_mobiledata.xml +++ b/packages/SettingsLib/res/drawable/ic_h_mobiledata.xml diff --git a/packages/SystemUI/res/drawable/ic_h_plus_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_h_plus_mobiledata.xml index b6ed876a2b02..b6ed876a2b02 100644 --- a/packages/SystemUI/res/drawable/ic_h_plus_mobiledata.xml +++ b/packages/SettingsLib/res/drawable/ic_h_plus_mobiledata.xml diff --git a/packages/SystemUI/res/drawable/ic_lte_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_lte_mobiledata.xml index e6b4fb698242..e6b4fb698242 100644 --- a/packages/SystemUI/res/drawable/ic_lte_mobiledata.xml +++ b/packages/SettingsLib/res/drawable/ic_lte_mobiledata.xml diff --git a/packages/SystemUI/res/drawable/ic_lte_plus_mobiledata.xml b/packages/SettingsLib/res/drawable/ic_lte_plus_mobiledata.xml index e5cdff33fe98..e5cdff33fe98 100644 --- a/packages/SystemUI/res/drawable/ic_lte_plus_mobiledata.xml +++ b/packages/SettingsLib/res/drawable/ic_lte_plus_mobiledata.xml diff --git a/packages/SystemUI/res/drawable/stat_sys_airplane_mode.xml b/packages/SettingsLib/res/drawable/stat_sys_airplane_mode.xml index 0f8c57183950..0f8c57183950 100644 --- a/packages/SystemUI/res/drawable/stat_sys_airplane_mode.xml +++ b/packages/SettingsLib/res/drawable/stat_sys_airplane_mode.xml diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml index 41af185da0b7..438e8b8c5bf2 100644 --- a/packages/SettingsLib/res/values-af/strings.xml +++ b/packages/SettingsLib/res/values-af/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktief. Tik om te wissel."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Programbystandstatus:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Mediakodewisselinginstellings"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Deaktiveer kodewisseling"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> oor tot battery gelaai is"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tot battery gelaai is"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Battery word tydelik beperk"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimeer tans vir batterygesondheid"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Onbekend"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Laai"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Laai tans vinnig"</string> diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml index 8e4e402c2e16..fd5777d5fe70 100644 --- a/packages/SettingsLib/res/values-am/strings.xml +++ b/packages/SettingsLib/res/values-am/strings.xml @@ -400,7 +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> - <string name="transcode_enable_all" msgid="9102460144086871903">"ትራንስኮንግን አሰናክል"</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="runningservices_settings_title" msgid="6460099290493086515">"አሂድ አገልግሎቶች"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"በአሁኑጊዜ እየሄዱ ያሉ አገልግሎቶችን ተቆጣጠር እና እይ"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> ኃይል እስከሚሞላ ድረስ ይቀራል"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ኃይል እስከሚሞላ ድረስ"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - ባትሪ ለጊዜው ተገድቧል"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - ለባትሪ ጤና ማመቻቸት"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"ያልታወቀ"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ኃይል በመሙላት ላይ"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ኃይል በፍጥነት በመሙላት ላይ"</string> diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml index 691ec046da02..b81031ee5835 100644 --- a/packages/SettingsLib/res/values-ar/strings.xml +++ b/packages/SettingsLib/res/values-ar/strings.xml @@ -400,7 +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> - <string name="transcode_enable_all" msgid="9102460144086871903">"إيقاف تحويل الترميز"</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="runningservices_settings_title" msgid="6460099290493086515">"الخدمات قيد التشغيل"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"عرض الخدمات قيد التشغيل في الوقت الحالي والتحكم فيها"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> إلى أن يتم شحن الجهاز بالكامل"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> إلى أن يتم شحن الجهاز بالكامل"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - تأثير محدود على البطارية مؤقتًا"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - التحسين لسلامة البطارية"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"غير معروف"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"جارٍ الشحن"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"جارٍ الشحن سريعًا"</string> @@ -518,7 +520,7 @@ <string name="media_transfer_this_device_name" msgid="2716555073132169240">"مكبر صوت الهاتف"</string> <string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"حدثت مشكلة أثناء الاتصال. يُرجى إيقاف الجهاز ثم إعادة تشغيله."</string> <string name="media_transfer_wired_device_name" msgid="4447880899964056007">"جهاز سماعي سلكي"</string> - <string name="help_label" msgid="3528360748637781274">"المساعدة والتعليقات"</string> + <string name="help_label" msgid="3528360748637781274">"المساعدة والملاحظات والآراء"</string> <string name="storage_category" msgid="2287342585424631813">"مساحة التخزين"</string> <string name="shared_data_title" msgid="1017034836800864953">"البيانات المشتركة"</string> <string name="shared_data_summary" msgid="5516326713822885652">"عرض البيانات المشتركة وتعديلها"</string> diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml index 61214e09ba26..e4823299c296 100644 --- a/packages/SettingsLib/res/values-as/strings.xml +++ b/packages/SettingsLib/res/values-as/strings.xml @@ -400,7 +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> - <string name="transcode_enable_all" msgid="9102460144086871903">"ট্ৰান্সক\'ডিং অক্ষম কৰক"</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="runningservices_settings_title" msgid="6460099290493086515">"চলিত সেৱা"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"বৰ্তমান চলি থকা সেৱাসমূহ চাওক আৰু নিয়ন্ত্ৰণ কৰক"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"চাৰ্জ হ’বলৈ <xliff:g id="TIME">%1$s</xliff:g> বাকী আছে"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> চাৰ্জ হ\'বলৈ"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - বেটাৰী সাময়িকভাৱে সীমিত কৰা হৈছে"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - বেটাৰীৰ অৱস্থা অপ্টিমাইজ কৰি থকা হৈছে"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"অজ্ঞাত"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"চাৰ্জ কৰি থকা হৈছে"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"দ্ৰুততাৰে চাৰ্জ হৈছে"</string> diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml index db61527a54d8..637785d06d2e 100644 --- a/packages/SettingsLib/res/values-az/strings.xml +++ b/packages/SettingsLib/res/values-az/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktivdir. Keçid etmək üçün basın."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Tətbiqin gözləmə rejimi:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Media yenidən kodlaşdırma ayarları"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Yenidən kodlaşdırmanı deaktiv edin"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Enerjinin dolmasına <xliff:g id="TIME">%1$s</xliff:g> qalıb"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - Enerjinin dolmasına <xliff:g id="TIME">%2$s</xliff:g> qalıb"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Batareya müvəqqəti məhdudlaşdırılıb"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Enerjiyə qənaət üçün optimallaşdırma"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Naməlum"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Enerji doldurma"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Sürətlə doldurulur"</string> diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml index 70fb3636b492..219d5a072c45 100644 --- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml +++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktivna. Dodirnite da biste je deaktivirali."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Stanje pripravnosti aplikacije: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Podešavanja transkodiranja medija"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Onemogući transkodiranje"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Napuniće se za <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – napuniće se za <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – baterija je trenutno ograničena"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimizuje se radi stanja baterije"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Nepoznato"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Puni se"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Brzo se puni"</string> diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml index 8a0db8261a71..4772e032268f 100644 --- a/packages/SettingsLib/res/values-be/strings.xml +++ b/packages/SettingsLib/res/values-be/strings.xml @@ -400,7 +400,12 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Актыўная. Краніце, каб пераключыць."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Стан праграмы ў рэжыме чакання: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Налады перакадзіравання мультымедыя"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Выключыць перакадзіраванне"</string> + <!-- 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="runningservices_settings_title" msgid="6460099290493086515">"Запушчаныя службы"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Прагляд запушчаных службаў i кіраванне iмi"</string> @@ -449,7 +454,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Засталося <xliff:g id="TIME">%1$s</xliff:g> да поўнай зарадкі"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> да поўнай зарадкі"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – зарад акумулятара часова абмежаваны"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Аптымізацыя стану акумулятара"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Невядома"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Зарадка"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Хуткая зарадка"</string> diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml index 27dcf105fd2e..75d1eeb1093f 100644 --- a/packages/SettingsLib/res/values-bg/strings.xml +++ b/packages/SettingsLib/res/values-bg/strings.xml @@ -400,7 +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> - <string name="transcode_enable_all" msgid="9102460144086871903">"Деактивиране на прекодирането"</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="runningservices_settings_title" msgid="6460099290493086515">"Изпълнявани услуги"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Преглед и контрол върху изпълняващите се понастоящем услуги"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Оставащо време до пълно зареждане: <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до пълно зареждане"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Батерията е временно ограничена"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Оптимизиране за състоян. на батерията"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Неизвестно"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Зарежда се"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Зарежда се бързо"</string> diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml index 29862e6efd31..325f2bdc5807 100644 --- a/packages/SettingsLib/res/values-bn/strings.xml +++ b/packages/SettingsLib/res/values-bn/strings.xml @@ -400,7 +400,12 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"সক্রিয় রয়েছে৷ টগল করতে আলতো চাপুন৷"</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"অ্যাপ স্ট্যান্ডবাই-এর অবস্থা:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"মিডিয়া ট্রান্সকোডিং সেটিংস"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"ট্রান্সকোডিং বন্ধ করুন"</string> + <!-- 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="runningservices_settings_title" msgid="6460099290493086515">"এখন চলছে যে পরিষেবাগুলি"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"বর্তমান চলমান পরিষেবাগুলি দেখুন এবং নিয়ন্ত্রণ করুন"</string> @@ -449,7 +454,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"সম্পূর্ণ চার্জ হতে <xliff:g id="TIME">%1$s</xliff:g> বাকি আছে"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>-এ সম্পূর্ণ চার্জ হয়ে যাবে"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - ব্যাটারি কিছুক্ষণের জন্য সীমিত করা হয়েছে"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - ব্যাটারির চার্জ অপটিমাইজ করা হচ্ছে"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"অজানা"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"চার্জ হচ্ছে"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"দ্রুত চার্জ হচ্ছে"</string> diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml index 4704ec8db79a..ab4ac1460d6f 100644 --- a/packages/SettingsLib/res/values-bs/strings.xml +++ b/packages/SettingsLib/res/values-bs/strings.xml @@ -28,7 +28,7 @@ <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"Greška u konfiguraciji IP-a"</string> <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"Niste povezani zbog slabog kvaliteta mreže"</string> <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"Greška pri povezivanju na WiFi"</string> - <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problem pri autentifikaciji."</string> + <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problem pri autentifikaciji"</string> <string name="wifi_cant_connect" msgid="5718417542623056783">"Nije se moguće povezati"</string> <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"Nije se moguće povezati na aplikaciju \'<xliff:g id="AP_NAME">%1$s</xliff:g>\'"</string> <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Provjerite lozinku i pokušajte ponovo"</string> @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktivno. Dodirnite za promjenu opcije."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Stanje mirovanja aplikacije:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Postavke transkodiranja medija"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Onemogućite transkodiranje"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Napunit će se za <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – napunit će se za <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Baterija je privremeno ograničena"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimiziranje radi očuvanja baterije"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Nepoznato"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Punjenje"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Brzo punjenje"</string> diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml index 5d04963d9b4a..9bb919f39091 100644 --- a/packages/SettingsLib/res/values-ca/strings.xml +++ b/packages/SettingsLib/res/values-ca/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aplicació activa. Toca per desactivar-la."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Estat de les aplicacions inactives: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Configuració de la transcodificació de contingut multimèdia"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Desactiva la transcodificació"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> per completar la càrrega"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> per completar la càrrega"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g>: bateria limitada temporalment"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g>: optimitzant per a l\'estat de la bateria"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconegut"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"S\'està carregant"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregant ràpidament"</string> diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml index a99a4dabbc60..5f2e00534461 100644 --- a/packages/SettingsLib/res/values-cs/strings.xml +++ b/packages/SettingsLib/res/values-cs/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktivní. Klepnutím možnost přepnete."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Stav pohotovostního režimu aplikace: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Nastavení překódování médií"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Zakázat překódování"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Do nabití zbývá: <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do nabití"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Baterie dočasně omezena"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimalizace pro výdrž baterie"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Neznámé"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Nabíjí se"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Rychlé nabíjení"</string> diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml index c90155eb2b68..f4f46507a9f3 100644 --- a/packages/SettingsLib/res/values-da/strings.xml +++ b/packages/SettingsLib/res/values-da/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktiv. Tryk for at skifte."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Standbystatus for appen:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Indstillinger for omkodning af medier"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Deaktiver omkodning"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Opladet om <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – opladet om <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Batteriet er midlertidigt begrænset"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimerer batteritilstanden"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Ukendt"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Oplader"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Oplader hurtigt"</string> diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml index b5b9fc480607..1d6894b097f7 100644 --- a/packages/SettingsLib/res/values-de/strings.xml +++ b/packages/SettingsLib/res/values-de/strings.xml @@ -400,7 +400,12 @@ <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> - <string name="transcode_enable_all" msgid="9102460144086871903">"Transcodierung deaktivieren"</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="runningservices_settings_title" msgid="6460099290493086515">"Aktive Dienste"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Momentan ausgeführte Dienste anzeigen und steuern"</string> @@ -449,7 +454,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Noch <xliff:g id="TIME">%1$s</xliff:g> bis zur Aufladung"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> bis zur Aufladung"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Akku vorübergehend eingeschränkt"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimierung des Akkuzustands"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Unbekannt"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Wird aufgeladen"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Schnelles Aufladen"</string> diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml index 203ec40c5a42..3affbce49f09 100644 --- a/packages/SettingsLib/res/values-el/strings.xml +++ b/packages/SettingsLib/res/values-el/strings.xml @@ -400,7 +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> - <string name="transcode_enable_all" msgid="9102460144086871903">"Απενεργοποίηση διακωδικοποίησης"</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="runningservices_settings_title" msgid="6460099290493086515">"Υπηρεσίες που εκτελούνται"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Προβολή και έλεγχος των εφαρμογών που εκτελούνται αυτή τη στιγμή"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Απομένουν <xliff:g id="TIME">%1$s</xliff:g> για ολοκλήρωση της φόρτισης"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> για την ολοκλήρωση της φόρτισης"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Η μπαταρία περιορίστηκε προσωρινά."</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Βελτιστοποίηση κατάστασης μπαταρίας"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Άγνωστο"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Φόρτιση"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ταχεία φόρτιση"</string> diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml index f8019d21c65b..9d5debba80c5 100644 --- a/packages/SettingsLib/res/values-en-rAU/strings.xml +++ b/packages/SettingsLib/res/values-en-rAU/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Active. Tap to toggle."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"App standby state:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Media transcoding settings"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Disable transcoding"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> left until charged"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until charged"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Battery limited temporarily"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimising for battery health"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string> diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml index 7135de5676b2..b0190a2e1112 100644 --- a/packages/SettingsLib/res/values-en-rCA/strings.xml +++ b/packages/SettingsLib/res/values-en-rCA/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Active. Tap to toggle."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"App standby state:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Media transcoding settings"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Disable transcoding"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> left until charged"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until charged"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Battery limited temporarily"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimising for battery health"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string> diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml index f8019d21c65b..9d5debba80c5 100644 --- a/packages/SettingsLib/res/values-en-rGB/strings.xml +++ b/packages/SettingsLib/res/values-en-rGB/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Active. Tap to toggle."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"App standby state:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Media transcoding settings"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Disable transcoding"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> left until charged"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until charged"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Battery limited temporarily"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimising for battery health"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string> diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml index f8019d21c65b..9d5debba80c5 100644 --- a/packages/SettingsLib/res/values-en-rIN/strings.xml +++ b/packages/SettingsLib/res/values-en-rIN/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Active. Tap to toggle."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"App standby state:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Media transcoding settings"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Disable transcoding"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> left until charged"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until charged"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Battery limited temporarily"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimising for battery health"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string> diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml index 54290d269f44..9296a5968ec1 100644 --- a/packages/SettingsLib/res/values-en-rXC/strings.xml +++ b/packages/SettingsLib/res/values-en-rXC/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Active. Tap to toggle."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"App standby state:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Media transcoding settings"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Disable transcoding"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> left until charged"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until charged"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Battery limited temporarily"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Optimizing for battery health"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string> diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml index 08ff55099c9c..41466be75fb7 100644 --- a/packages/SettingsLib/res/values-es-rUS/strings.xml +++ b/packages/SettingsLib/res/values-es-rUS/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Activa. Presiona para activar o desactivar."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Estado de la app en espera: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Configuración de transcodificación de contenido multimedia"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Inhabilitar transcodificación"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> para completar la carga"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar la carga"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Batería limitada temporalmente"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g>: Optimizando el estado de la batería"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconocido"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Cargando"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Cargando rápido"</string> diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml index 6f6a1a1c9b17..8a0a123081e3 100644 --- a/packages/SettingsLib/res/values-es/strings.xml +++ b/packages/SettingsLib/res/values-es/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Activa. Toca para alternar."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Estado de la aplicación en espera: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Configuración de la transcodificación multimedia"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Inhabilitar transcodificación"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> hasta cargarse completamente"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> (<xliff:g id="TIME">%2$s</xliff:g> hasta cargarse completamente)"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g>: batería limitada temporalmente"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g>: preservando estado de la batería"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconocido"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Cargando"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Cargando rápidamente"</string> diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml index 9d6326e45706..4b82c08a46e7 100644 --- a/packages/SettingsLib/res/values-et/strings.xml +++ b/packages/SettingsLib/res/values-et/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktiivne. Puudutage vahetamiseks."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Rakenduse ootelolek:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Meedia transkodeerimise seaded"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Keela transkodeerimine"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Täislaadimiseni on jäänud <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> täislaadimiseni"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – akutase on ajutiselt piiratud"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – optimeerimine aku seisukorra põhjal"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Tundmatu"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Laadimine"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Kiirlaadimine"</string> diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml index 01afa1706e3e..37c1fd8db552 100644 --- a/packages/SettingsLib/res/values-eu/strings.xml +++ b/packages/SettingsLib/res/values-eu/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktibo. Aldatzeko, sakatu hau."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Egonean moduko aplikazioaren egoera: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Multimedia-edukia transkodetzeko ezarpenak"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Desgaitu transkodetzeko aukera"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> guztiz kargatu arte"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> guztiz kargatu arte"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g>: bateria mugatuta egongo da aldi batez"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Optimizatzen bateria egoera onean mantentzeko"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Ezezaguna"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Kargatzen"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Bizkor kargatzen"</string> diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml index dd7ab9672e96..7d20aaf0f5f7 100644 --- a/packages/SettingsLib/res/values-fa/strings.xml +++ b/packages/SettingsLib/res/values-fa/strings.xml @@ -34,7 +34,7 @@ <string name="wifi_check_password_try_again" msgid="8817789642851605628">"گذرواژه را بررسی و دوباره امتحان کنید"</string> <string name="wifi_not_in_range" msgid="1541760821805777772">"در محدوده نیست"</string> <string name="wifi_no_internet_no_reconnect" msgid="821591791066497347">"اتصال بهصورت خودکار انجام نمیشود"</string> - <string name="wifi_no_internet" msgid="1774198889176926299">"بدون دسترسی به اینترنت"</string> + <string name="wifi_no_internet" msgid="1774198889176926299">"دسترسی به اینترنت ندارد"</string> <string name="saved_network" msgid="7143698034077223645">"ذخیرهشده توسط <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="connected_via_network_scorer" msgid="7665725527352893558">"اتصال خودکار ازطریق %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7973529709744526285">"اتصال خودکار ازطریق ارائهدهنده رتبهبندی شبکه"</string> @@ -400,7 +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> - <string name="transcode_enable_all" msgid="9102460144086871903">"غیرفعال کردن تراتبدیل"</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="runningservices_settings_title" msgid="6460099290493086515">"سرویسهای در حال اجرا"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"مشاهده و کنترل سرویسهای در حال اجرای فعلی"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> مانده تا شارژ کامل"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> تا شارژ کامل"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - باتری موقتاً محدود شده است"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - بهینهسازی برای سلامت باتری"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"ناشناس"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"در حال شارژ شدن"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"درحال شارژ شدن سریع"</string> diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml index b86b02d8c25f..a43c5d706e3b 100644 --- a/packages/SettingsLib/res/values-fi/strings.xml +++ b/packages/SettingsLib/res/values-fi/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktiivinen. Vaihda koskettamalla."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Sovelluksen valmiusluokka: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Median transkoodausasetukset"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Poista transkoodaus käytöstä"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> jäljellä täyteen lataukseen"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> täyteen lataukseen"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Akun käyttöä rajoitettu tilapäisesti"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Akun kunnon optimointi"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Tuntematon"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Ladataan"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Nopea lataus"</string> diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml index 0bca1dba1aa4..0cb7b1746101 100644 --- a/packages/SettingsLib/res/values-fr-rCA/strings.xml +++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Application active. Touchez ici pour la désactiver."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"État de l\'application en veille :<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Paramètres de transcodage des éléments multimédias"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Désactiver le transcodage"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> jusqu\'à la charge complète"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> : <xliff:g id="TIME">%2$s</xliff:g> jusqu\'à la charge complète"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Pile limitée temporairement"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimisation pour la santé de la pile"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Inconnu"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Charge en cours…"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Recharge rapide"</string> diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml index ebde43ba52a2..e928a48fca26 100644 --- a/packages/SettingsLib/res/values-fr/strings.xml +++ b/packages/SettingsLib/res/values-fr/strings.xml @@ -28,7 +28,7 @@ <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"Échec de configuration de l\'adresse IP"</string> <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"Non connecté en raison de la faible qualité du réseau"</string> <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"Échec de la connexion Wi-Fi"</string> - <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problème d\'authentification."</string> + <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problème d\'authentification"</string> <string name="wifi_cant_connect" msgid="5718417542623056783">"Connexion impossible"</string> <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"Impossible de se connecter au réseau \"<xliff:g id="AP_NAME">%1$s</xliff:g>\""</string> <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Vérifiez le mot de passe et réessayez"</string> @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Application active. Appuyez ici pour la désactiver."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"État de mise en veille de l\'application : <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Paramètres de transcodage des contenus multimédias"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Désactiver le transcodage"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> jusqu\'à ce que la batterie soit chargée"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> jusqu\'à la charge complète"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Batterie limitée temporairement"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Optimisation pour préserver batterie"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Inconnu"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Batterie en charge"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charge rapide"</string> diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml index b040817b2801..c43925375a2b 100644 --- a/packages/SettingsLib/res/values-gl/strings.xml +++ b/packages/SettingsLib/res/values-gl/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aplicación activa. Toca para alternar a configuración."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Estado en espera da aplicación: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Configuración de transcodificación de contido multimedia"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Desactivar transcodificación"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> para completar a carga"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> para completar a carga"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> (batería limitada temporalmente)"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g>: optimizando para manter a batería en bo estado"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Descoñecido"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Cargando"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Cargando rapidamente"</string> diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml index c1bd7cac30a6..7dfdceeaf867 100644 --- a/packages/SettingsLib/res/values-gu/strings.xml +++ b/packages/SettingsLib/res/values-gu/strings.xml @@ -400,7 +400,12 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"સક્રિય. ટોગલ કરવા માટે ટૅપ કરો."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"ઍપ સ્ટૅન્ડબાયની સ્થિતિ:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"મીડિયાનું ફૉર્મેટ બદલવાની પ્રક્રિયાના સેટિંગ"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"ફૉર્મેટ બદલવાની પ્રક્રિયા બંધ કરો"</string> + <!-- 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="runningservices_settings_title" msgid="6460099290493086515">"ચાલુ સેવાઓ"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"હાલમાં ચાલતી સેવાઓ જુઓ અને નિયંત્રિત કરો"</string> @@ -449,7 +454,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ચાર્જ થવામાં <xliff:g id="TIME">%1$s</xliff:g> બાકી છે"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - ચાર્જ થવા માટે <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - બૅટરીનો વપરાશ હંગામી રૂપે મર્યાદિત છે"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> • બૅટરીની ક્ષમતા વધારવા ઑપ્ટિમાઇઝ કરી રહ્યાં છીએ"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"અજાણ્યું"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ચાર્જ થઈ રહ્યું છે"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ઝડપથી ચાર્જ થાય છે"</string> diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml index d9153a1ab542..26d1a756318d 100644 --- a/packages/SettingsLib/res/values-hi/strings.xml +++ b/packages/SettingsLib/res/values-hi/strings.xml @@ -28,7 +28,7 @@ <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"IP कॉन्फ़िगरेशन की विफलता"</string> <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"खराब नेटवर्क होने के कारण कनेक्ट नहीं हुआ"</string> <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"वाईफ़ाई कनेक्शन विफलता"</string> - <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"प्रमाणीकरण समस्या"</string> + <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"पुष्टि नहीं हो सकी"</string> <string name="wifi_cant_connect" msgid="5718417542623056783">"कनेक्ट नहीं हो पा रहा है"</string> <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"\'<xliff:g id="AP_NAME">%1$s</xliff:g>\' से कनेक्ट नहीं हो पा रहा है"</string> <string name="wifi_check_password_try_again" msgid="8817789642851605628">"पासवर्ड जाँचें और दोबारा कोशिश करें"</string> @@ -400,7 +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> - <string name="transcode_enable_all" msgid="9102460144086871903">"ट्रांसकोडिंग को बंद करें"</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="runningservices_settings_title" msgid="6460099290493086515">"चल रही सेवाएं"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"इस समय चल रही सेवाओं को देखें और नियंत्रित करें"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"चार्ज पूरा होने में <xliff:g id="TIME">%1$s</xliff:g> बचा है"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> में पूरा चार्ज हो जाएगा"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - कुछ समय के लिए, बैटरी का सीमित इस्तेमाल होगा"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - बैटरी की परफ़ॉर्मेंस बेहतर करने के लिए, ऑप्टिमाइज़ किया जा रहा है"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"अज्ञात"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"चार्ज हो रही है"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"तेज़ चार्ज हो रही है"</string> diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml index b51e096ca6b7..eccfd7ad56ba 100644 --- a/packages/SettingsLib/res/values-hr/strings.xml +++ b/packages/SettingsLib/res/values-hr/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktivno. Dodirnite da biste to promijenili."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Stanje aplikacije u mirovanju: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Postavke konvertiranja medija"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Onemogućivanje konvertiranja"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Napunit će se za <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – napunit će se za <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Baterija je privremeno ograničena"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimiziranje radi zdravlja baterije"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Nepoznato"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Punjenje"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Brzo punjenje"</string> diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml index 33770fc1bdd8..e5d4bd15ce72 100644 --- a/packages/SettingsLib/res/values-hu/strings.xml +++ b/packages/SettingsLib/res/values-hu/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Bekapcsolva. Koppintson ide a váltáshoz."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Alkalmazás készenléti állapota:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Médiaátkódolási beállítások"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Átkódolás letiltása"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> van hátra a feltöltésből"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> a feltöltésig"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Akkumulátor ideiglenesen korlátozva"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Akkumulátor-élettartam optimalizálása"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Ismeretlen"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Töltés"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Gyorstöltés"</string> diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml index 06d70f854f27..53eb766e3b17 100644 --- a/packages/SettingsLib/res/values-hy/strings.xml +++ b/packages/SettingsLib/res/values-hy/strings.xml @@ -400,7 +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> - <string name="transcode_enable_all" msgid="9102460144086871903">"Անջատել վերակոդավորումը"</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="runningservices_settings_title" msgid="6460099290493086515">"Աշխատող ծառայություններ"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Դիտել և վերահսկել ընթացիկ աշխատող ծառայությունները"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> մինչև լիցքավորումը"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> մինչև լիցքավորումը"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Մարտկոցը ժամանակավորապես սահմանափակված է"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Օպտիմալացվում է"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Անհայտ"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Լիցքավորում"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Արագ լիցքավորում"</string> diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml index 4123d9e3b755..edce3c5d7336 100644 --- a/packages/SettingsLib/res/values-in/strings.xml +++ b/packages/SettingsLib/res/values-in/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktif. Ketuk untuk beralih."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Status standby aplikasi:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Setelan transcoding media"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Menonaktifkan transcoding"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Sisa <xliff:g id="TIME">%1$s</xliff:g> hingga terisi penuh"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> lagi terisi penuh"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Daya baterai terbatas untuk sementara"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Mengoptimalkan untuk kesehatan baterai"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Tidak diketahui"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Mengisi daya"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Mengisi daya cepat"</string> diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml index 3b9bef872177..9e072ccdc8f7 100644 --- a/packages/SettingsLib/res/values-is/strings.xml +++ b/packages/SettingsLib/res/values-is/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Virkt. Ýttu til að breyta."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Biðstaða forrits: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Stillingar efnisumkóðunar"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Slökkva á umkóðun"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> að fullri hleðslu"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> að fullri hleðslu"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Rafhlaða takmörkuð tímabundið"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Fínstillir fyrir rafhlöðuendingu"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Óþekkt"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Í hleðslu"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Hröð hleðsla"</string> diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml index 1ab6b24456f3..fc87d89b915d 100644 --- a/packages/SettingsLib/res/values-it/strings.xml +++ b/packages/SettingsLib/res/values-it/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Attiva. Tocca per attivare/disattivare."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Stato di standby dell\'app: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Impostazioni transcodifica contenuti multimediali"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Disattiva transcodifica"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Tempo rimanente alla carica completa: <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> alla carica completa"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Batteria momentaneamente limitata"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ottimizzazione per integrità batteria"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Sconosciuta"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"In carica"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ricarica veloce"</string> diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml index 15868d5fc997..b899b594e784 100644 --- a/packages/SettingsLib/res/values-iw/strings.xml +++ b/packages/SettingsLib/res/values-iw/strings.xml @@ -400,7 +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> - <string name="transcode_enable_all" msgid="9102460144086871903">"השבתה של המרת קידוד"</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="runningservices_settings_title" msgid="6460099290493086515">"שירותים פועלים"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"הצגת השירותים הפועלים כעת ושליטה בהם"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"נשארו <xliff:g id="TIME">%1$s</xliff:g> עד הטעינה"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> עד הטעינה"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - הסוללה מוגבלת באופן זמני"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> ﹣ מופעל מיטוב לשמירה על תקינות הסוללה"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"לא ידוע"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"בטעינה"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"הסוללה נטענת מהר"</string> diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml index 89ee98eeeb42..ded207d325a3 100644 --- a/packages/SettingsLib/res/values-ja/strings.xml +++ b/packages/SettingsLib/res/values-ja/strings.xml @@ -400,7 +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> - <string name="transcode_enable_all" msgid="9102460144086871903">"コード変換を無効にする"</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="runningservices_settings_title" msgid="6460099290493086515">"実行中のサービス"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"現在実行中のサービスを表示して制御する"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"充電完了まであと <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充電完了まで <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - 電池の使用が一時的に制限されています"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - 電池の状態を最適化"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"不明"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"充電中"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"急速充電中"</string> diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml index d1885789779a..2d89dc65cb60 100644 --- a/packages/SettingsLib/res/values-ka/strings.xml +++ b/packages/SettingsLib/res/values-ka/strings.xml @@ -400,7 +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> - <string name="transcode_enable_all" msgid="9102460144086871903">"ტრანსკოდირების გათიშვა"</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="runningservices_settings_title" msgid="6460099290493086515">"მიმდინარე სერვისები"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"ამჟამად მოქმედი სერვისების ნახვა და მართვა"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"დატენვამდე დარჩა <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> დატენვამდე"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> — ბატარეა დროებით შეზღუდულია"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> — ოპტიმიზაცია ბატარეის გამართულობისთვის"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"უცნობი"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"იტენება"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"სწრაფად იტენება"</string> diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml index 2bc1c4d20728..fa99529f84d4 100644 --- a/packages/SettingsLib/res/values-kk/strings.xml +++ b/packages/SettingsLib/res/values-kk/strings.xml @@ -400,7 +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> - <string name="transcode_enable_all" msgid="9102460144086871903">"Қайта кодтауды өшіру"</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="runningservices_settings_title" msgid="6460099290493086515">"Қосылып тұрған қызметтер"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Қазір істеп тұрған қызметтерді көру және басқару"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Зарядталғанға дейін <xliff:g id="TIME">%1$s</xliff:g> қалды"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – зарядталғанға дейін <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Батарея жұмысы уақытша шектелген"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Батареяның жұмыс істеу қабілеті оңтайландырылуда"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Белгісіз"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Зарядталуда"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Жылдам зарядталуда"</string> diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml index 7306cf8c5d3f..a2b5e014937e 100644 --- a/packages/SettingsLib/res/values-km/strings.xml +++ b/packages/SettingsLib/res/values-km/strings.xml @@ -400,7 +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> - <string name="transcode_enable_all" msgid="9102460144086871903">"បិទការបំប្លែងកូដ"</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="runningservices_settings_title" msgid="6460099290493086515">"សេវាកម្មកំពុងដំណើរការ"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"មើល និងគ្រប់គ្រងសេវាកម្មកំពុងដំណើរការបច្ចុប្បន្ន"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> ទៀតទើបសាកថ្មពេញ"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ទៀតទើបសាកថ្មពេញ"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - បានដាក់កម្រិតថ្មជាបណ្ដោះអាសន្ន"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - កំពុងបង្កើនប្រសិទ្ធភាពគុណភាពថ្ម"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"មិនស្គាល់"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"កំពុងបញ្ចូលថ្ម"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"កំពុងសាកថ្មយ៉ាងឆាប់រហ័ស"</string> diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml index 0c1502ca620d..f37cf8be13f5 100644 --- a/packages/SettingsLib/res/values-kn/strings.xml +++ b/packages/SettingsLib/res/values-kn/strings.xml @@ -400,7 +400,12 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"ಸಕ್ರಿಯ. ಟಾಗಲ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"ಅಪ್ಲಿಕೇಶನ್ ಸ್ಟ್ಯಾಂಡ್ಬೈ ಸ್ಥಿತಿ:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"ಮೀಡಿಯಾ ಟ್ರಾನ್ಸ್ಕೋಡಿಂಗ್ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"ಟ್ರಾನ್ಸ್ಕೋಡಿಂಗ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</string> + <!-- 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="runningservices_settings_title" msgid="6460099290493086515">"ರನ್ ಆಗುತ್ತಿರುವ ಸೇವೆಗಳು"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"ಈಗ ರನ್ ಆಗುತ್ತಿರುವ ಸೇವೆಗಳನ್ನು ವೀಕ್ಷಿಸಿ ಮತ್ತು ನಿಯಂತ್ರಿಸಿ"</string> @@ -449,7 +454,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ಚಾರ್ಜ್ ಆಗಲು <xliff:g id="TIME">%1$s</xliff:g> ಸಮಯ ಬಾಕಿ ಇದೆ"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಚಾರ್ಜ್ ಆಗಲು <xliff:g id="TIME">%2$s</xliff:g> ಸಮಯ ಬೇಕು"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಬ್ಯಾಟರಿ ತಾತ್ಕಾಲಿಕವಾಗಿ ಸೀಮಿತವಾಗಿದೆ"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಬ್ಯಾಟರಿಯ ಆರೋಗ್ಯಕ್ಕಾಗಿ ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"ಅಪರಿಚಿತ"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ವೇಗದ ಚಾರ್ಜಿಂಗ್"</string> diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml index 13223440d098..73921c29815f 100644 --- a/packages/SettingsLib/res/values-ko/strings.xml +++ b/packages/SettingsLib/res/values-ko/strings.xml @@ -400,7 +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> - <string name="transcode_enable_all" msgid="9102460144086871903">"트랜스코딩 사용 중지"</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="runningservices_settings_title" msgid="6460099290493086515">"실행 중인 서비스"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"현재 실행 중인 서비스 보기 및 제어"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"충전 완료까지 <xliff:g id="TIME">%1$s</xliff:g> 남음"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - 충전 완료까지 <xliff:g id="TIME">%2$s</xliff:g> 남음"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - 일시적으로 배터리 사용 제한"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - 배터리 상태 최적화 중"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"알 수 없음"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"충전 중"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"고속 충전 중"</string> diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml index 9697aa70e44f..5e978ba7ac1b 100644 --- a/packages/SettingsLib/res/values-ky/strings.xml +++ b/packages/SettingsLib/res/values-ky/strings.xml @@ -400,7 +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> - <string name="transcode_enable_all" msgid="9102460144086871903">"Транскоддоону өчүрүү"</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="runningservices_settings_title" msgid="6460099290493086515">"Иштеп жаткан кызматтар"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Учурда иштеп жаткан кызматтарды көрүп, көзөмөлдөп турасыз"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> кийин толук кубатталып бүтөт"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> кийин толук кубатталып бүтөт"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Батареяны колдонуу убактлуу чектелген"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Батареянын кубатын үнөмдөө иштетилди"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Белгисиз"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Кубатталууда"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ыкчам кубатталууда"</string> diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml index 720122262dcf..498cb25d96ff 100644 --- a/packages/SettingsLib/res/values-lo/strings.xml +++ b/packages/SettingsLib/res/values-lo/strings.xml @@ -400,7 +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> - <string name="transcode_enable_all" msgid="9102460144086871903">"ປິດການນຳໃຊ້ການປ່ຽນຮູບແບບລະຫັດ"</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="runningservices_settings_title" msgid="6460099290493086515">"ບໍລິການທີ່ເຮັດວຽກຢູ່"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"ເບິ່ງ ແລະຈັດການບໍລິການທີ່ກຳລັງເຮັດວຽກຢູ່ໃນປັດຈຸບັນ"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> ຈົນກວ່າຈະສາກເຕັມ"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ຈົນກວ່າຈະສາກເຕັມ"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - ຈຳກັດແບັດເຕີຣີຊົ່ວຄາວ"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - ກຳລັງເພີ່ມປະສິດທິພາບເພື່ອສຸຂະພາບແບັດເຕີຣີ"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"ບໍ່ຮູ້ຈັກ"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ກຳລັງສາກໄຟ"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ກຳລັງສາກໄຟດ່ວນ"</string> diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml index e62eeb2dbd97..c077268f3fad 100644 --- a/packages/SettingsLib/res/values-lt/strings.xml +++ b/packages/SettingsLib/res/values-lt/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktyvi. Palieskite, kad perjungtumėte."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Programų budėjimo režimo būsena: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Medijos perkodavimo nustatymai"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Išjungti perkodavimą"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Iki visiškos įkrovos liko <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – iki visiškos įkrovos liko <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – akumuliatorius laikinai apribotas"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – optimizuoj. siekiant apsaugoti akum."</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Nežinomas"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Kraunasi..."</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Greitai įkraunama"</string> diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml index 2f305612a5fc..d5755511f032 100644 --- a/packages/SettingsLib/res/values-lv/strings.xml +++ b/packages/SettingsLib/res/values-lv/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktīva. Pieskarieties, lai pārslēgtu."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Lietotnes gaidstāves stāvoklis: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Multivides failu pārkodēšanas iestatījumi"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Atspējot pārkodēšanu"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Vēl <xliff:g id="TIME">%1$s</xliff:g> līdz pilnai uzlādei"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g> līdz pilnai uzlādei"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g>, akumulatora uzlāde pagaidām ierobežota"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g>: akumulatora darbības optimizēšana"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Nezināms"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Uzlāde"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Notiek ātrā uzlāde"</string> diff --git a/packages/SystemUI/res/values-mcc310-mnc004/strings.xml b/packages/SettingsLib/res/values-mcc310-mnc004/strings.xml index f8ed0c01fa83..f8ed0c01fa83 100644 --- a/packages/SystemUI/res/values-mcc310-mnc004/strings.xml +++ b/packages/SettingsLib/res/values-mcc310-mnc004/strings.xml diff --git a/packages/SystemUI/res/values-mcc311-mnc480/strings.xml b/packages/SettingsLib/res/values-mcc311-mnc480/strings.xml index f8ed0c01fa83..f8ed0c01fa83 100644 --- a/packages/SystemUI/res/values-mcc311-mnc480/strings.xml +++ b/packages/SettingsLib/res/values-mcc311-mnc480/strings.xml diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml index 1936fe2d32a4..21dcb0285557 100644 --- a/packages/SettingsLib/res/values-mk/strings.xml +++ b/packages/SettingsLib/res/values-mk/strings.xml @@ -400,7 +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> - <string name="transcode_enable_all" msgid="9102460144086871903">"Оневозможи транскодирање"</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="runningservices_settings_title" msgid="6460099290493086515">"Активни услуги"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Погледнете и контролирајте услуги што се моментално активни"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Уште <xliff:g id="TIME">%1$s</xliff:g> до целосно полнење"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> до целосно полнење"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Батеријата е привремено ограничена"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Се оптимизира за состојба на батерија"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Непознато"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Се полни"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Брзо полнење"</string> diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml index de4a49a2ed06..97c22d569775 100644 --- a/packages/SettingsLib/res/values-ml/strings.xml +++ b/packages/SettingsLib/res/values-ml/strings.xml @@ -400,7 +400,12 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"സജീവം. മാറ്റുന്നതിന് ടാപ്പുചെയ്യുക."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"ആപ്പ് സ്റ്റാൻഡ്ബൈ നില:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"മീഡിയ ട്രാൻസ്കോഡ് ചെയ്യൽ ക്രമീകരണം"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"ട്രാൻസ്കോഡ് ചെയ്യൽ പ്രവർത്തനരഹിതമാക്കുക"</string> + <!-- 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="runningservices_settings_title" msgid="6460099290493086515">"പ്രവർത്തിക്കുന്ന സേവനങ്ങൾ"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"നിലവിൽ പ്രവർത്തിക്കുന്ന സേവനങ്ങൾ കാണുക, നിയന്ത്രിക്കുക"</string> @@ -449,7 +454,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"പൂർണ്ണമായി ചാർജാവാൻ <xliff:g id="TIME">%1$s</xliff:g> ശേഷിക്കുന്നു"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - പൂർണ്ണമായി ചാർജാവാൻ <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - ബാറ്ററി താൽക്കാലം പരിമിതപ്പെടുത്തി"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - ബാറ്ററി നില ഒപ്റ്റിമൈസ് ചെയ്യുന്നു"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"അജ്ഞാതം"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ചാർജ് ചെയ്യുന്നു"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"അതിവേഗ ചാർജിംഗ്"</string> diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml index dee8add685f9..8d1cc3391c5a 100644 --- a/packages/SettingsLib/res/values-mn/strings.xml +++ b/packages/SettingsLib/res/values-mn/strings.xml @@ -28,7 +28,7 @@ <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"IP тохируулга амжилтгүй"</string> <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"Сүлжээний чанар муу байгаа тул холбогдож чадсангүй"</string> <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"WiFi холболт амжилтгүй"</string> - <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Гэрчлэлийн асуудал"</string> + <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Баталгаажуулалтын асуудал"</string> <string name="wifi_cant_connect" msgid="5718417542623056783">"Холбогдож чадсангүй"</string> <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"\'<xliff:g id="AP_NAME">%1$s</xliff:g>\'-д холбогдож чадсангүй"</string> <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Нууц үгийг шалгаад дахин оролдоно уу"</string> @@ -400,7 +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> - <string name="transcode_enable_all" msgid="9102460144086871903">"Хөрвүүлгийг идэвхгүй болгох"</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="runningservices_settings_title" msgid="6460099290493086515">"Ажиллаж байгаа үйлчилгээнүүд"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Одоо ажиллаж байгаа үйлчилгээнүүдийг харах болон хянах"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Цэнэглэх хүртэл үлдсэн <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - цэнэглэх хүртэл <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Батарейг түр хугацаанд хязгаарласан"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Батарейн чанарыг оновчилж байна"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Тодорхойгүй"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Цэнэглэж байна"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Хурдан цэнэглэж байна"</string> @@ -534,7 +536,7 @@ <string name="user_add_user_item_title" msgid="2394272381086965029">"Хэрэглэгч"</string> <string name="user_add_profile_item_title" msgid="3111051717414643029">"Хязгаарлагдсан профайл"</string> <string name="user_add_user_title" msgid="5457079143694924885">"Шинэ хэрэглэгч нэмэх үү?"</string> - <string name="user_add_user_message_long" msgid="1527434966294733380">"Та нэмэлт хэрэглэгч үүсгэх замаар бусад хүмүүстэй энэ төхөөрөмжийг хуваалцаж болно. Хэрэглэгч тус бүр апп, ханын цаас болон бусад зүйлээ өөрчлөх боломжтой хувийн орон зайтай байдаг. Түүнчлэн хэрэглэгч нь бүх хэрэглэгчид нөлөөлөх боломжтой Wi-Fi зэрэг төхөөрөмжийн тохиргоог өөрчлөх боломжтой.\n\nХэрэв та шинэ хэрэглэгч нэмэх бол тухайн хүн хувийн орон зайгаа бүрдүүлэх ёстой.\n\nХэрэглэгч бүр бусад бүх хэрэглэгчийн өмнөөс апп шинэчилж болно. Хүртээмжийн тохиргоо болон үйлчилгээг шинэ хэрэглэгчид шилжүүлэх боломжгүй байж болзошгүй."</string> + <string name="user_add_user_message_long" msgid="1527434966294733380">"Та нэмэлт хэрэглэгч үүсгэх замаар бусад хүмүүстэй энэ төхөөрөмжийг хуваалцаж болно. Хэрэглэгч тус бүр апп, дэлгэцийн зураг болон бусад зүйлээ өөрчлөх боломжтой хувийн орон зайтай байдаг. Түүнчлэн хэрэглэгч нь бүх хэрэглэгчид нөлөөлөх боломжтой Wi-Fi зэрэг төхөөрөмжийн тохиргоог өөрчлөх боломжтой.\n\nХэрэв та шинэ хэрэглэгч нэмэх бол тухайн хүн хувийн орон зайгаа бүрдүүлэх ёстой.\n\nХэрэглэгч бүр бусад бүх хэрэглэгчийн өмнөөс апп шинэчилж болно. Хүртээмжийн тохиргоо болон үйлчилгээг шинэ хэрэглэгчид шилжүүлэх боломжгүй байж болзошгүй."</string> <string name="user_add_user_message_short" msgid="3295959985795716166">"Та шинэ хэрэглэгч нэмбэл тухайн хүн өөрийн профайлыг тохируулах шаардлагатай.\n\nАль ч хэрэглэгч бүх хэрэглэгчийн апп-уудыг шинэчлэх боломжтой."</string> <string name="user_setup_dialog_title" msgid="8037342066381939995">"Хэрэглэгчийг одоо тохируулах уу?"</string> <string name="user_setup_dialog_message" msgid="269931619868102841">"Хэрэглэгч төхөөрөмжийг авч өөрийн профайлыг тохируулах боломжтой эсэхийг шалгана уу"</string> diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml index 60ad68e42c09..c20888ea0af2 100644 --- a/packages/SettingsLib/res/values-mr/strings.xml +++ b/packages/SettingsLib/res/values-mr/strings.xml @@ -400,7 +400,12 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"सक्रिय. टॉगल करण्यासाठी टॅप करा."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"अॅप स्टँडबाय स्थिती: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"मीडिया ट्रान्सकोडिंगची सेटिंग्ज"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"ट्रान्सकोडिंग बंद करा"</string> + <!-- 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="runningservices_settings_title" msgid="6460099290493086515">"सुरू सेवा"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"सध्या सुरू असलेल्या सेवा पहा आणि नियंत्रित करा"</string> @@ -449,7 +454,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> पर्यंत पूर्ण चार्ज होईल"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> पर्यंत पूर्ण चार्ज होईल"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - बॅटरी तात्पुरती मर्यादित आहे"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - बॅटरीची क्षमता वाढवण्यासाठी ऑप्टिमाइझ करत आहे"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"अज्ञात"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"चार्ज होत आहे"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"वेगाने चार्ज होत आहे"</string> diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml index e4d591207937..76840a52b0a2 100644 --- a/packages/SettingsLib/res/values-ms/strings.xml +++ b/packages/SettingsLib/res/values-ms/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktif. Ketik untuk menogol."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Keadaan tunggu sedia apl:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Tetapan transpengekodan media"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Lumpuhkan transpengekodan"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> lagi sehingga dicas penuh"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sehingga dicas"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Bateri terhad untuk sementara"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Pengoptimuman untuk kesihatan bateri"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Tidak diketahui"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Mengecas"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Mengecas dgn cepat"</string> diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml index 09a8bf87700b..377e49da5031 100644 --- a/packages/SettingsLib/res/values-my/strings.xml +++ b/packages/SettingsLib/res/values-my/strings.xml @@ -28,7 +28,7 @@ <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"IP ပြုပြင်ခြင်း မအောင်မြင်ပါ"</string> <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"ကွန်ရက်ချိတ်ဆက်မှု အားနည်းသည့်အတွက် ချိတ်ဆက်ထားခြင်း မရှိပါ"</string> <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"WiFi ချိတ်ဆက်မှု မအောင်မြင်ပါ"</string> - <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"စစ်မှန်ကြောင်းအတည်ပြုရန်၌ ပြသနာရှိခြင်း"</string> + <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"အထောက်အထားစိစစ်မှု ပြဿနာ"</string> <string name="wifi_cant_connect" msgid="5718417542623056783">"ချိတ်ဆက်၍ မရပါ"</string> <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"\'<xliff:g id="AP_NAME">%1$s</xliff:g>\' နှင့် ချိတ်ဆက်၍ မရပါ"</string> <string name="wifi_check_password_try_again" msgid="8817789642851605628">"စကားဝှက်ကို စစ်ဆေးပြီး ထပ်လုပ်ကြည့်ပါ"</string> @@ -400,7 +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> - <string name="transcode_enable_all" msgid="9102460144086871903">"အမျိုးအစားပြောင်းခြင်းကို ပိတ်ရန်"</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="runningservices_settings_title" msgid="6460099290493086515">"အလုပ်လုပ်နေသောဝန်ဆောင်မှုများ"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"လက်ရှိ ဝန်ဆောင်မှုများကို ကြည့်ရှု ထိန်းသိမ်းသည်"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"အားပြည့်ရန် <xliff:g id="TIME">%1$s</xliff:g> ကျန်သည်"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - အားပြည့်ရန် <xliff:g id="TIME">%2$s</xliff:g> ကျန်သည်"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - ဘက်ထရီ ယာယီကန့်သတ်ထားသည်"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - ဘက်ထရီအခြေအနေကို အကောင်းဆုံးဖြစ်အောင် လုပ်နေသည်"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"မသိ"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"အားသွင်းနေပါသည်"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"အမြန် အားသွင်းနေသည်"</string> diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml index d1af28940f1b..db931218567f 100644 --- a/packages/SettingsLib/res/values-nb/strings.xml +++ b/packages/SettingsLib/res/values-nb/strings.xml @@ -34,7 +34,7 @@ <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Sjekk passordet og prøv igjen"</string> <string name="wifi_not_in_range" msgid="1541760821805777772">"Utenfor område"</string> <string name="wifi_no_internet_no_reconnect" msgid="821591791066497347">"Kobler ikke til automatisk"</string> - <string name="wifi_no_internet" msgid="1774198889176926299">"Ingen Internett-tilgang"</string> + <string name="wifi_no_internet" msgid="1774198889176926299">"Ingen internettilgang"</string> <string name="saved_network" msgid="7143698034077223645">"Lagret av <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="connected_via_network_scorer" msgid="7665725527352893558">"Automatisk tilkoblet via %1$s"</string> <string name="connected_via_network_scorer_default" msgid="7973529709744526285">"Automatisk tilkoblet via leverandør av nettverksvurdering"</string> @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktiv. Trykk for å slå av/på."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Hvilemodus:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Innstillinger for omkoding av medier"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Deaktiver omkoding"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> til batteriet er fulladet"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> til batteriet er fulladet"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Batteriet er midlertidig begrenset"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimaliserer batteritilstanden"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Ukjent"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Lader"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Lader raskt"</string> diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml index 0c6114b9e220..25a2919f0958 100644 --- a/packages/SettingsLib/res/values-ne/strings.xml +++ b/packages/SettingsLib/res/values-ne/strings.xml @@ -400,7 +400,12 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"सक्रिय। टगल गर्न ट्याप गर्नुहोस्।"</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"एपको स्ट्यान्डबाई अवस्था:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"मिडिया ट्रान्सकोडिङ सेटिङ"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"ट्रान्सकोडिङ अफ गर्नुहोस्"</string> + <!-- 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="runningservices_settings_title" msgid="6460099290493086515">"चलिरहेका सेवाहरू"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"हाल चालु भइरहेका सेवाहरू हेर्नुहोस् र नियन्त्रण गर्नुहोस्"</string> @@ -449,7 +454,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"पूर्ण चार्ज हुन <xliff:g id="TIME">%1$s</xliff:g> बाँकी"</string> <string name="power_charging_duration" msgid="5005740040558984057">"पूर्ण चार्ज हुन <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> लाग्छ"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - केही समयका लागि ब्याट्री प्रयोग सीमित गरिएको छ"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - ब्याट्री लामो समयसम्म टिक्ने बनाउन अप्टिमाइज गरिँदै छ"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"अज्ञात"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"चार्ज हुँदै"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"द्रुत गतिमा चार्ज गरिँदै"</string> diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml index a409756e5b5f..0f2cc6ff66e8 100644 --- a/packages/SettingsLib/res/values-nl/strings.xml +++ b/packages/SettingsLib/res/values-nl/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Actief. Tik om te schakelen."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Stand-bystatus app: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Instellingen voor mediatranscodering"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Transcodering uitschakelen"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Nog <xliff:g id="TIME">%1$s</xliff:g> tot opgeladen"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> tot opgeladen"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Batterij tijdelijk beperkt"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Optimaliseren voor batterijduur"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Onbekend"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Opladen"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Snel opladen"</string> diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml index 0a0eeff6de60..040ddddf96f7 100644 --- a/packages/SettingsLib/res/values-or/strings.xml +++ b/packages/SettingsLib/res/values-or/strings.xml @@ -28,7 +28,7 @@ <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"IP କନଫିଗରେଶନ ବିଫଳ ହୋଇଛି"</string> <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"ନିମ୍ନ ମାନର ନେଟ୍ୱର୍କ କାରଣରୁ ସଂଯୁକ୍ତ ହୋଇନାହିଁ"</string> <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"ୱାଇଫାଇ ସଂଯୋଗ ବିଫଳ ହୋଇଛି"</string> - <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"ସତ୍ୟାପନରେ ସମସ୍ୟା"</string> + <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"ପ୍ରମାଣୀକରଣରେ ସମସ୍ୟା"</string> <string name="wifi_cant_connect" msgid="5718417542623056783">"ସଂଯୋଗ କରିପାରିବ ନାହିଁ"</string> <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"\'<xliff:g id="AP_NAME">%1$s</xliff:g>\' ସହିତ ସଂଯୁକ୍ତ ହୋଇପାରୁନାହିଁ"</string> <string name="wifi_check_password_try_again" msgid="8817789642851605628">"ପାସ୍ୱର୍ଡ ଯାଞ୍ଚ କରନ୍ତୁ ଏବଂ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string> @@ -400,7 +400,12 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"ସକ୍ରିୟ। ବଦଳାଇବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ"</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"ଆପ୍ ଷ୍ଟାଣ୍ଡବାଏ ଅବସ୍ଥା:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"ମିଡିଆ ଟ୍ରାନ୍ସକୋଡିଂ ସେଟିଂସ୍"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"ଟ୍ରାନ୍ସକୋଡିଂ ଅକ୍ଷମ କରନ୍ତୁ"</string> + <!-- 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="runningservices_settings_title" msgid="6460099290493086515">"ଚାଲୁଥିବା ସେବାଗୁଡ଼ିକ"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"ଏବେ ଚାଲୁଥିବା ସେବାଗୁଡ଼ିକୁ ଦେଖନ୍ତୁ ଓ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ"</string> @@ -449,7 +454,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ଚାର୍ଜ ହେବା ପାଇଁ <xliff:g id="TIME">%1$s</xliff:g> ବାକି ଅଛି"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ଚାର୍ଜ ହେବା ପର୍ଯ୍ୟନ୍ତ"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - ବ୍ୟାଟେରୀ ଅସ୍ଥାୟୀ ଭାବେ ସୀମିତ ଅଛି"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - ବ୍ୟାଟେରୀ ହେଲ୍ଥ ପାଇଁ ଅପ୍ଟିମାଇଜ୍ ହେଉଛି"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"ଅଜ୍ଞାତ"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ଚାର୍ଜ ହେଉଛି"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ଶୀଘ୍ର ଚାର୍ଜ ହେଉଛି"</string> diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml index c9c37d922537..e6adff30b2cf 100644 --- a/packages/SettingsLib/res/values-pa/strings.xml +++ b/packages/SettingsLib/res/values-pa/strings.xml @@ -400,7 +400,12 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"ਕਿਰਿਆਸ਼ੀਲ। ਟੌਗਲ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"ਐਪ ਸਟੈਂਡਬਾਈ ਸਥਿਤੀ:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"ਮੀਡੀਆ ਟ੍ਰਾਂਸਕੋਡਿੰਗ ਸੈਟਿੰਗਾਂ"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"ਟ੍ਰਾਂਸਕੋਡਿੰਗ ਬੰਦ ਕਰੋ"</string> + <!-- 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="runningservices_settings_title" msgid="6460099290493086515">"ਚੱਲ ਰਹੀਆਂ ਸੇਵਾਵਾਂ"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"ਇਸ ਵੇਲੇ ਚੱਲ ਰਹੀਆਂ ਸੇਵਾਵਾਂ ਦੇਖੋ ਅਤੇ ਇਹਨਾਂ ਨੂੰ ਕੰਟਰੋਲ ਕਰੋ"</string> @@ -449,7 +454,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ਚਾਰਜ ਹੋਣ ਵਿੱਚ <xliff:g id="TIME">%1$s</xliff:g> ਬਾਕੀ"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ਤੱਕ ਚਾਰਜ ਹੋ ਜਾਵੇਗੀ"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਬੈਟਰੀ ਕੁਝ ਸਮੇਂ ਲਈ ਸੀਮਤ"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - ਬੈਟਰੀ ਸਥਿਤੀ ਲਈ ਅਨੁਕੂਲ ਬਣਾਇਆ ਜਾ ਰਿਹਾ"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"ਅਗਿਆਤ"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ਤੇਜ਼ ਚਾਰਜ ਹੋ ਰਹੀ ਹੈ"</string> diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml index e894c2cbc34c..5690e748c4cd 100644 --- a/packages/SettingsLib/res/values-pl/strings.xml +++ b/packages/SettingsLib/res/values-pl/strings.xml @@ -400,7 +400,12 @@ <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> - <string name="transcode_enable_all" msgid="9102460144086871903">"Wyłącz transkodowanie"</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="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> @@ -449,7 +454,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Do naładowania <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – do naładowania <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – bateria tymczasowo ograniczona"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optymalizuję, by utrzymać baterię w dobrym stanie"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Nieznane"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Ładowanie"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Szybkie ładowanie"</string> diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml index acaabc793970..a0ddcf226a0d 100644 --- a/packages/SettingsLib/res/values-pt-rBR/strings.xml +++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Ativo. Tocar para alternar."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Estado em espera do app:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Configurações de transcodificação de mídia"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Desativar transcodificação"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Tempo restante até a carga completa: <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> até a carga completa"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g>: bateria limitada temporariamente"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g>: otimizando para integridade da bateria"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconhecido"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Carregando"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregando rápido"</string> diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml index 2c1a9678f158..adaed743477e 100644 --- a/packages/SettingsLib/res/values-pt-rPT/strings.xml +++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Ativo. Toque para ativar/desativar."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Estado do Modo de espera das apps:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Definições da transcodificação de multimédia"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Desativar a transcodificação"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Falta(m) <xliff:g id="TIME">%1$s</xliff:g> até ficar carregada"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> até ficar carregada"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Bateria limitada temporariamente."</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – A otimizar o estado da bateria"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconhecido"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"A carregar"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregamento rápido"</string> diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml index acaabc793970..a0ddcf226a0d 100644 --- a/packages/SettingsLib/res/values-pt/strings.xml +++ b/packages/SettingsLib/res/values-pt/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Ativo. Tocar para alternar."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Estado em espera do app:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Configurações de transcodificação de mídia"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Desativar transcodificação"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Tempo restante até a carga completa: <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> até a carga completa"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g>: bateria limitada temporariamente"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g>: otimizando para integridade da bateria"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconhecido"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Carregando"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregando rápido"</string> diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml index 57a0454f3465..266dff2fa81b 100644 --- a/packages/SettingsLib/res/values-ro/strings.xml +++ b/packages/SettingsLib/res/values-ro/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Activă. Atingeți pentru a comuta."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Stare Standby aplicații: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Setări pentru transcodarea conținutului media"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Dezactivați transcodarea"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Au mai rămas <xliff:g id="TIME">%1$s</xliff:g> până la încărcare"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> până la încărcare"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – baterie limitată temporar"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Se fac optimizări pentru buna funcționare a bateriei"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Necunoscut"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Se încarcă"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Se încarcă rapid"</string> diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml index 09b8de04388b..ca20baee55b1 100644 --- a/packages/SettingsLib/res/values-ru/strings.xml +++ b/packages/SettingsLib/res/values-ru/strings.xml @@ -400,7 +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> - <string name="transcode_enable_all" msgid="9102460144086871903">"Отключить перекодирование"</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="runningservices_settings_title" msgid="6460099290493086515">"Работающие службы"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Просмотр и управление работающими службами"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> до полной зарядки"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полной зарядки"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> • Уровень заряда временно ограничен"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"Оптимизация для увеличения срока службы батареи (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Неизвестно"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Идет зарядка"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Быстрая зарядка"</string> diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml index d36140f66b54..da69b813ee88 100644 --- a/packages/SettingsLib/res/values-si/strings.xml +++ b/packages/SettingsLib/res/values-si/strings.xml @@ -400,7 +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> - <string name="transcode_enable_all" msgid="9102460144086871903">"ට්රාන්ස්කෝඩින් අබල කරන්න"</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="runningservices_settings_title" msgid="6460099290493086515">"ධාවනය වන සේවා"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"දැනට ධාවනය වන සේවා බලන්න සහ පාලනය කරන්න"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ආරෝපණය වන තෙක් <xliff:g id="TIME">%1$s</xliff:g> ඇත"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - ආරෝපණය වන තෙක් <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - බැටරිය තාවකාලිකව සීමිතයි"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - බැටරි සෞඛ්යය සඳහා ප්රශස්ත කරමින්"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"නොදනී"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ආරෝපණය වෙමින්"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ශීඝ්ර ආරෝපණය"</string> diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml index 096e95e7050b..b428b421ad32 100644 --- a/packages/SettingsLib/res/values-sk/strings.xml +++ b/packages/SettingsLib/res/values-sk/strings.xml @@ -28,7 +28,7 @@ <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"Zlyhanie konfigurácie adresy IP"</string> <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"Nepripojené z dôvodu siete nízkej kvality"</string> <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"Zlyhanie pripojenia Wi‑Fi"</string> - <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problém s overením totožnosti"</string> + <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problém s overením"</string> <string name="wifi_cant_connect" msgid="5718417542623056783">"Nedá sa pripojiť"</string> <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"K sieti <xliff:g id="AP_NAME">%1$s</xliff:g> sa nedá pripojiť"</string> <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Skontrolujte heslo a skúste to znova"</string> @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktívne. Prepnite klepnutím."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Stav pohotovostného režimu aplikácie: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Nastavenia prekódovania médií"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Vypnúť prekódovanie"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Zostávajúci čas do úplného nabitia: <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Batéria je dočasne obmedzená"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimalizácia stavu batérie"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Neznáme"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Nabíja sa"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Rýchle nabíjanie"</string> diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml index 345fa36d3bd6..3ba31fa1eed5 100644 --- a/packages/SettingsLib/res/values-sl/strings.xml +++ b/packages/SettingsLib/res/values-sl/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktivno. Dotaknite se za preklop."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Stanje pripravljenosti aplikacije: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Nastavitve prekodiranja predstavnosti"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Onemogočanje prekodiranja"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Še <xliff:g id="TIME">%1$s</xliff:g> do polne napolnjenosti"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do polne napolnjenosti"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – baterija je začasno omejena"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimizacija za ohran. zmog. baterije"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Neznano"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Polnjenje"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Hitro polnjenje"</string> diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml index 3953a6a4f6e0..15cbb7439c64 100644 --- a/packages/SettingsLib/res/values-sq/strings.xml +++ b/packages/SettingsLib/res/values-sq/strings.xml @@ -400,7 +400,12 @@ <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> - <string name="transcode_enable_all" msgid="9102460144086871903">"Çaktivizo transkodimin"</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="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> @@ -449,7 +454,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> të mbetura deri në karikim"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> derisa të karikohet"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Bateria e kufizuar përkohësisht"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Po optimizohet për integritetin e baterisë"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"I panjohur"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Po karikohet"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Po ngarkon me shpejtësi"</string> diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml index 70b287933c93..c3371829361d 100644 --- a/packages/SettingsLib/res/values-sr/strings.xml +++ b/packages/SettingsLib/res/values-sr/strings.xml @@ -400,7 +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> - <string name="transcode_enable_all" msgid="9102460144086871903">"Онемогући транскодирање"</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="runningservices_settings_title" msgid="6460099290493086515">"Покренуте услуге"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Приказ и контрола тренутно покренутих услуга"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Напуниће се за <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – напуниће се за <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – батерија је тренутно ограничена"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Оптимизује се ради стања батерије"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Непознато"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Пуни се"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Брзо се пуни"</string> diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml index f466e882c2fc..2bf9785f67d4 100644 --- a/packages/SettingsLib/res/values-sv/strings.xml +++ b/packages/SettingsLib/res/values-sv/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktiv. Tryck om du vill inaktivera."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Status för strömsparfunktion för appar:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Inställningar för medieomkodning"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Inaktivera omkodning"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> kvar till full laddning"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> till full laddning"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – batteriet är tillfälligt begränsat"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Optimerar batteriets livslängd"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Okänd"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Laddar"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Laddas snabbt"</string> diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml index e1060fec2a66..610bfeefc743 100644 --- a/packages/SettingsLib/res/values-sw/strings.xml +++ b/packages/SettingsLib/res/values-sw/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Inatumika. Gusa ili ugeuze."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Hali ya kisitisha programu:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Mipangilio ya kubadilisha muundo wa faili ya maudhui"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Zima ubadilishaji muundo wa faili"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Imebakisha <xliff:g id="TIME">%1$s</xliff:g> ijae chaji"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ijae chaji"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Betri imedhibitiwa kwa muda"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Inaboresha muda wa kutumia betri"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Haijulikani"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Inachaji"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Inachaji kwa kasi"</string> diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml index ba98d79ff7e4..7d77967e0daf 100644 --- a/packages/SettingsLib/res/values-ta/strings.xml +++ b/packages/SettingsLib/res/values-ta/strings.xml @@ -400,7 +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> - <string name="transcode_enable_all" msgid="9102460144086871903">"குறிமாற்றத்தை முடக்கு"</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="runningservices_settings_title" msgid="6460099290493086515">"இயங்கும் சேவைகள்"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"தற்போது இயக்கத்தில் இருக்கும் சேவைகளைப் பார்த்து கட்டுப்படுத்து"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"முழு சார்ஜாக <xliff:g id="TIME">%1$s</xliff:g> ஆகும்"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - முழு சார்ஜாக <xliff:g id="TIME">%2$s</xliff:g> ஆகும்"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g>-பேட்டரி தற்காலிகக் கட்டுப்பாட்டிலுள்ளது"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - பேட்டரியின் ஆயுளை மேம்படுத்துகிறது"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"அறியப்படாத"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"சார்ஜ் ஆகிறது"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"வேகமாக சார்ஜாகிறது"</string> diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml index 0b93979dbd07..f24caecc453f 100644 --- a/packages/SettingsLib/res/values-te/strings.xml +++ b/packages/SettingsLib/res/values-te/strings.xml @@ -400,7 +400,12 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"సక్రియంగా ఉంది. టోగుల్ చేయడానికి నొక్కండి."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"యాప్ స్టాండ్బై స్థితి:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"మీడియా ట్రాన్స్కోడింగ్ సెట్టింగ్లు"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"ట్రాన్స్కోడింగ్ను డిజేబుల్ చేయండి"</string> + <!-- 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="runningservices_settings_title" msgid="6460099290493086515">"అమలులో ఉన్న సేవలు"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"ప్రస్తుతం అమలులో ఉన్న సేవలను వీక్షించండి మరియు నియంత్రించండి"</string> @@ -449,7 +454,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ఛార్జ్ అవ్వడానికి <xliff:g id="TIME">%1$s</xliff:g> సమయం మిగిలి ఉంది"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - ఛార్జ్ అవ్వడానికి <xliff:g id="TIME">%2$s</xliff:g> పడుతుంది"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> -బ్యాటరీ తాత్కాలికంగా పరిమితం చేయబడింది"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - బ్యాటరీ స్థితిని ఆప్టిమైజ్ చేయడం కోసం"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"తెలియదు"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"ఛార్జ్ అవుతోంది"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"వేగవంతమైన ఛార్జింగ్"</string> diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml index a31e14611bf6..2c019983f639 100644 --- a/packages/SettingsLib/res/values-th/strings.xml +++ b/packages/SettingsLib/res/values-th/strings.xml @@ -400,7 +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> - <string name="transcode_enable_all" msgid="9102460144086871903">"ปิดใช้การแปลง"</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="runningservices_settings_title" msgid="6460099290493086515">"บริการที่ทำงานอยู่"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"ดูและควบคุมบริการที่ทำงานอยู่"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"เหลือ <xliff:g id="TIME">%1$s</xliff:g> จนกว่าจะชาร์จเต็ม"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> จนกว่าจะชาร์จ"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - การชาร์จแบตเตอรี่จำกัดชั่วคราว"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - กำลังเพิ่มประสิทธิภาพแบตเตอรี่"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"ไม่ทราบ"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"กำลังชาร์จ"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"กำลังชาร์จอย่างเร็ว"</string> diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml index bbb77790e68a..54ba90ef4b31 100644 --- a/packages/SettingsLib/res/values-tl/strings.xml +++ b/packages/SettingsLib/res/values-tl/strings.xml @@ -28,7 +28,7 @@ <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"Pagkabigo ng Configuration ng IP"</string> <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"Hindi nakakonekta dahil mababa ang kalidad ng network"</string> <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"Pagkabigo ng Koneksyon sa WiFi"</string> - <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problema sa pagpapatotoo"</string> + <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problema sa pag-authenticate"</string> <string name="wifi_cant_connect" msgid="5718417542623056783">"Hindi makakonekta"</string> <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"Hindi makakonekta sa \'<xliff:g id="AP_NAME">%1$s</xliff:g>\'"</string> <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Suriin ang password at subukang muli"</string> @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktibo. I-tap upang i-toggle."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Status ng app standby:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Mga setting ng pag-transcode ng media"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"I-disable ang pag-transcode"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> ang natitira bago matapos mag-charge"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> hanggang matapos mag-charge"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Pansamantalang limitado ang baterya"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ino-optimize para sa tagal ng baterya"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Hindi Kilala"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Nagcha-charge"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Mabilis na charge"</string> diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml index fba7f41bbbf5..942834f230eb 100644 --- a/packages/SettingsLib/res/values-tr/strings.xml +++ b/packages/SettingsLib/res/values-tr/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Etkin. Geçiş yapmak için dokunun."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Uygulamayı beklemeye alma durumu: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Medya kod dönüştürme ayarları"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Kod dönüştürmeyi devre dışı bırak"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Şarj olmaya <xliff:g id="TIME">%1$s</xliff:g> kaldı"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - şarj olmaya <xliff:g id="TIME">%2$s</xliff:g> kaldı"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Pil geçici olarak sınırlı"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Pil sağlığı için optimize ediliyor"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Bilinmiyor"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Şarj oluyor"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Hızlı şarj oluyor"</string> diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml index b633752d28a9..f6063f8147ba 100644 --- a/packages/SettingsLib/res/values-uk/strings.xml +++ b/packages/SettingsLib/res/values-uk/strings.xml @@ -400,7 +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> - <string name="transcode_enable_all" msgid="9102460144086871903">"Вимкнути перекодування"</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="runningservices_settings_title" msgid="6460099290493086515">"Запущені сервіси"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Переглянути й налаштувати запущені сервіси"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> до повного заряду"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до повного заряду"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – дані акумулятора тимчасово недоступні"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – стан акумулятора оптимізується"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Невідомо"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Заряджається"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Швидке заряджання"</string> diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml index b4d8ad2576bd..5d754373a5a4 100644 --- a/packages/SettingsLib/res/values-ur/strings.xml +++ b/packages/SettingsLib/res/values-ur/strings.xml @@ -400,7 +400,12 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"فعال۔ ٹوگل کرنے کیلئے تھپتھپائیں۔"</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"ایپ اسٹینڈ بائی کی حالت:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"میڈیا ٹرانسکوڈنگ کی ترتیبات"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"ٹرانسکوڈنگ غیر فعال کریں"</string> + <!-- 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="runningservices_settings_title" msgid="6460099290493086515">"چل رہی سروسز"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"فی الحال چل رہی سروسز دیکھیں اور انہیں کنٹرول کریں"</string> @@ -449,7 +454,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"چارج ہونے میں <xliff:g id="TIME">%1$s</xliff:g> باقی"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> چارج ہونے تک"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - بیٹری عارضی طور پر محدود ہے"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - بیٹری کی صحت کیلئے بہتر بنایا جا رہا ہے"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"نامعلوم"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"چارج ہو رہا ہے"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"تیزی سے چارج ہو رہا ہے"</string> diff --git a/packages/SettingsLib/res/values-uz/arrays.xml b/packages/SettingsLib/res/values-uz/arrays.xml index 2f06fcfd5dee..0770dcc42bc8 100644 --- a/packages/SettingsLib/res/values-uz/arrays.xml +++ b/packages/SettingsLib/res/values-uz/arrays.xml @@ -25,7 +25,7 @@ <item msgid="3288373008277313483">"Qidiruv…"</item> <item msgid="6050951078202663628">"Ulanmoqda…"</item> <item msgid="8356618438494652335">"Tasdiqdan o‘tilmoqda…"</item> - <item msgid="2837871868181677206">"IP manzil o‘zlashtirilmoqda…"</item> + <item msgid="2837871868181677206">"IP manzil olinmoqda…"</item> <item msgid="4613015005934755724">"Ulangan"</item> <item msgid="3763530049995655072">"Muzlatildi"</item> <item msgid="7852381437933824454">"Uzilmoqda…"</item> diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml index 5bb422ecf96a..f1fc8ddcc5ea 100644 --- a/packages/SettingsLib/res/values-uz/strings.xml +++ b/packages/SettingsLib/res/values-uz/strings.xml @@ -28,7 +28,7 @@ <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"IP manzilini sozlab bo‘lmadi"</string> <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"Sifatsiz tarmoq sababli ulanib bo‘lmadi"</string> <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"Wi-Fi ulanishini o‘rnatib bo‘lmadi"</string> - <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Tasdiqdan o‘tishda muammo"</string> + <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Tekshiruvda muammo"</string> <string name="wifi_cant_connect" msgid="5718417542623056783">"Tarmoqqa ulanilmadi"</string> <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"“<xliff:g id="AP_NAME">%1$s</xliff:g>” nomli tarmoqqa ulanilmadi"</string> <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Parolni tekshirib, qaytadan urining"</string> @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Faol. O‘zgartirish uchun bu yerga bosing."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Kutish rejimi holati: <xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Media transkripsiyasi sozlamalari"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Transkripsiyani faolsizlantirish"</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="runningservices_settings_title" msgid="6460099290493086515">"Ishlab turgan ilovalar"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"Ishlab turgan ilovalarni ko‘rish va boshqarish"</string> @@ -432,8 +434,8 @@ <skip /> <string name="power_discharge_by_enhanced" msgid="563438403581662942">"Joriy holatda taxminan <xliff:g id="TIME">%1$s</xliff:g> gacha davom etadi (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> <string name="power_discharge_by_only_enhanced" msgid="3268796172652988877">"Joriy holatda taxminan <xliff:g id="TIME">%1$s</xliff:g> gacha davom etadi"</string> - <string name="power_discharge_by" msgid="4113180890060388350">"Taxminan <xliff:g id="TIME">%1$s</xliff:g> gacha davom etadi (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> - <string name="power_discharge_by_only" msgid="92545648425937000">"Taxminan <xliff:g id="TIME">%1$s</xliff:g> gacha davom etadi"</string> + <string name="power_discharge_by" msgid="4113180890060388350">"Taxminan <xliff:g id="TIME">%1$s</xliff:g> gacha yetadi (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string> + <string name="power_discharge_by_only" msgid="92545648425937000">"Taxminan <xliff:g id="TIME">%1$s</xliff:g> gacha yetadi"</string> <string name="power_discharge_by_only_short" msgid="5883041507426914446">"<xliff:g id="TIME">%1$s</xliff:g> gacha"</string> <string name="power_suggestion_battery_run_out" msgid="6332089307827787087">"Batareya quvvati tugash vaqti: <xliff:g id="TIME">%1$s</xliff:g>"</string> <string name="power_remaining_less_than_duration_only" msgid="8956656616031395152">"<xliff:g id="THRESHOLD">%1$s</xliff:g>dan kam qoldi"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> ichida toʻladi"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> ichida toʻladi"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Quvvat darajasi vaqtincha cheklangan"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Batareya quvvati muvozanatlanmoqda"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Noma’lum"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Quvvat olmoqda"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Tezkor quvvat olmoqda"</string> diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml index 0acf9418b718..910fa2634f8c 100644 --- a/packages/SettingsLib/res/values-vi/strings.xml +++ b/packages/SettingsLib/res/values-vi/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Hiện hoạt. Nhấn để chuyển đổi."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Trạng thái chờ ứng dụng:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Cài đặt chuyển mã nội dung nghe nhìn"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Tắt tùy chọn chuyển mã"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Còn <xliff:g id="TIME">%1$s</xliff:g> nữa là sạc đầy"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> nữa là sạc đầy"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> – Thời lượng pin bị hạn chế tạm thời"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> – Đang tối ưu hóa để cải thiện độ bền của pin"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Không xác định"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Đang sạc"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Đang sạc nhanh"</string> diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml index ca2ad87fb864..c9ecab19bfaf 100644 --- a/packages/SettingsLib/res/values-zh-rCN/strings.xml +++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml @@ -400,7 +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> - <string name="transcode_enable_all" msgid="9102460144086871903">"停用转码功能"</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="runningservices_settings_title" msgid="6460099290493086515">"正在运行的服务"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"查看和控制当前正在运行的服务"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"还剩 <xliff:g id="TIME">%1$s</xliff:g>充满电"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>后充满电"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - 暂时限用电池"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - 正在针对电池状况进行优化"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"未知"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"正在充电"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"正在快速充电"</string> diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml index 16ca19d313c1..3bbfa21220de 100644 --- a/packages/SettingsLib/res/values-zh-rHK/strings.xml +++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml @@ -400,7 +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> - <string name="transcode_enable_all" msgid="9102460144086871903">"停用轉碼功能"</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="runningservices_settings_title" msgid="6460099290493086515">"執行中的服務"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"查看並控制目前正在執行中的服務"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"還需 <xliff:g id="TIME">%1$s</xliff:g>才能充滿電"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - 還需 <xliff:g id="TIME">%2$s</xliff:g>才能充滿電"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - 暫時限制電池充電"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - 正在優化電池狀態"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"未知"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"充電中"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"正在快速充電"</string> diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml index 810119b97777..b0dbb5fdac66 100644 --- a/packages/SettingsLib/res/values-zh-rTW/strings.xml +++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml @@ -400,7 +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> - <string name="transcode_enable_all" msgid="9102460144086871903">"停用轉碼功能"</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="runningservices_settings_title" msgid="6460099290493086515">"正在運作的服務"</string> <string name="runningservices_settings_summary" msgid="1046080643262665743">"查看並管理目前正在執行的服務"</string> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g>後充飽電"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽電"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - 暫時限制電池用量"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - 針對電池狀態進行最佳化調整"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"不明"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"充電中"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"快速充電中"</string> diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml index 23beeb1aee82..8f7c2ac100bc 100644 --- a/packages/SettingsLib/res/values-zu/strings.xml +++ b/packages/SettingsLib/res/values-zu/strings.xml @@ -400,7 +400,9 @@ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Kuyasebenza. Thepha ukuze ushintshe."</string> <string name="standby_bucket_summary" msgid="5128193447550429600">"Isimo sokulinda kohlelo lokusebenza:<xliff:g id="BUCKET"> %s</xliff:g>"</string> <string name="transcode_settings_title" msgid="2581975870429850549">"Amasethingi wemidiya yokudlulisela ikhodi"</string> - <string name="transcode_enable_all" msgid="9102460144086871903">"Khubaza ukudlulisela ikhodi"</string> + <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> @@ -449,7 +451,7 @@ <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string> <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> esele ize ishaje"</string> <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ize igcwale"</string> - <string name="power_charging_limited" msgid="5902301801611726210">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ibhethri ikhawulelwe okwesikhashana"</string> + <string name="power_charging_limited" msgid="1956874810658999681">"<xliff:g id="LEVEL">%1$s</xliff:g> - Ilungiselela impilo yebhethri"</string> <string name="battery_info_status_unknown" msgid="268625384868401114">"Akwaziwa"</string> <string name="battery_info_status_charging" msgid="4279958015430387405">"Iyashaja"</string> <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ishaja ngokushesha"</string> diff --git a/packages/SettingsLib/res/values/config.xml b/packages/SettingsLib/res/values/config.xml index 332d6c7bc0fa..45253bb7944a 100644 --- a/packages/SettingsLib/res/values/config.xml +++ b/packages/SettingsLib/res/values/config.xml @@ -21,4 +21,11 @@ <!-- Threshold in micro watts above which a charger is rated as "fast"; 1.5A @ 5V --> <integer name="config_chargingFastThreshold">7500000</integer> + + <!-- When true, show 1/2G networks as 3G. --> + <bool name="config_showMin3G">false</bool> + + <!-- Control whether status bar should distinguish HSPA data icon form UMTS + data icon on devices --> + <bool name="config_hspa_data_distinguishable">false</bool> </resources>
\ No newline at end of file diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index 4e9721218a02..f518b74e3c31 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -1112,7 +1112,7 @@ <string name="power_remaining_charging_duration_only"><xliff:g id="time">%1$s</xliff:g> left until charged</string> <!-- [CHAR_LIMIT=40] Label for battery level chart when charging with duration --> <string name="power_charging_duration"><xliff:g id="level">%1$s</xliff:g> - <xliff:g id="time">%2$s</xliff:g> until charged</string> - <!-- [CHAR_LIMIT=40] Label for battery level chart when charge been limited --> + <!-- [CHAR_LIMIT=80] Label for battery level chart when charge been limited --> <string name="power_charging_limited"><xliff:g id="level">%1$s</xliff:g> - Optimizing for battery health</string> <!-- Battery Info screen. Value for a status item. Used for diagnostic info screens, precise translation isn't needed --> @@ -1404,4 +1404,79 @@ <string name="wifi_hotspot_switch_on_text">On</string> <!-- Label for Wifi hotspot switch off. Toggles hotspot off [CHAR LIMIT=30] --> <string name="wifi_hotspot_switch_off_text">Off</string> + + <!-- Content description of the carrier network changing icon. [CHAR LIMIT=NONE] --> + <string name="carrier_network_change_mode">Carrier network changing</string> + + <!-- Content description of the data connection type 3G. [CHAR LIMIT=NONE] --> + <string name="data_connection_3g">3G</string> + + <!-- Content description of the data connection type Edge. [CHAR LIMIT=NONE] --> + <string name="data_connection_edge">EDGE</string> + + <!-- Content description of the data connection type CDMA. [CHAR LIMIT=NONE] --> + <string name="data_connection_cdma">1X</string> + + <!-- Content description of the data connection type GPRS. [CHAR LIMIT=NONE] --> + <string name="data_connection_gprs">GPRS</string> + + <!-- Content description of the data connection type 3.5G. [CHAR LIMIT=NONE] --> + <string name="data_connection_3_5g">H</string> + + <!-- Content description of the data connection type 3.5G+. [CHAR LIMIT=NONE] --> + <string name="data_connection_3_5g_plus">H+</string> + + <!-- Content description of the data connection type 4G . [CHAR LIMIT=NONE] --> + <string name="data_connection_4g">4G</string> + + <!-- Content description of the data connection type 4G+. [CHAR LIMIT=NONE] --> + <string name="data_connection_4g_plus">4G+</string> + + <!-- Content description of the data connection type LTE. [CHAR LIMIT=NONE] --> + <string name="data_connection_lte">LTE</string> + + <!-- Content description of the data connection type LTE+. [CHAR LIMIT=NONE] --> + <string name="data_connection_lte_plus">LTE+</string> + + <!-- Content description of the data connection type 5Ge with HTML styling. DO NOT TRANSLATE [CHAR LIMIT=NONE] --> + <string name="data_connection_5ge_html" translate="false"> <i>5G <small>E</small></i> </string> + + <!-- Content description of the data connection type 5G. [CHAR LIMIT=NONE] --> + <string name="data_connection_5g" translatable="false">5G</string> + + <!-- Content description of the data connection type 5G+. [CHAR LIMIT=NONE] --> + <string name="data_connection_5g_plus" translatable="false">5G+</string> + + <!-- Content description of the cell data being disabled. [CHAR LIMIT=NONE] --> + <string name="cell_data_off_content_description">Mobile data off</string> + + <!-- Content description of the cell data for not default subscription. [CHAR LIMIT=NONE] --> + <string name="not_default_data_content_description">Not set to use data</string> + + <!-- Content description of the phone signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_no_phone">No phone.</string> + <!-- Content description of the phone signal when it is one bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_phone_one_bar">Phone one bar.</string> + <!-- Content description of the phone signal when it is two bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_phone_two_bars">Phone two bars.</string> + <!-- Content description of the phone signal when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_phone_three_bars">Phone three bars.</string> + <!-- Content description of the phone signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_phone_signal_full">Phone signal full.</string> + + <!-- Content description of the data signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_no_data">No data.</string> + <!-- Content description of the data signal when it is one bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_data_one_bar">Data one bar.</string> + <!-- Content description of the data signal when it is two bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_data_two_bars">Data two bars.</string> + <!-- Content description of the data signal when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_data_three_bars">Data three bars.</string> + <!-- Content description of the data signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_data_signal_full">Data signal full.</string> + + <!-- Content description of the Ethernet connection when disconnected for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_ethernet_disconnected">Ethernet disconnected.</string> + <!-- Content description of the Ethernet connection when connected for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> + <string name="accessibility_ethernet_connected">Ethernet connected.</string> </resources> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java b/packages/SettingsLib/src/com/android/settingslib/AccessibilityContentDescriptions.java index 8f86e2d300da..45028ff8f4f9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityContentDescriptions.java +++ b/packages/SettingsLib/src/com/android/settingslib/AccessibilityContentDescriptions.java @@ -1,8 +1,20 @@ -// Copyright 2011 Google Inc. All Rights Reserved. - -package com.android.systemui.statusbar.policy; +/* + * 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. + */ -import com.android.systemui.R; +package com.android.settingslib; /** * Content descriptions for accessibility support. @@ -10,7 +22,7 @@ import com.android.systemui.R; public class AccessibilityContentDescriptions { private AccessibilityContentDescriptions() {} - static final int[] PHONE_SIGNAL_STRENGTH = { + public static final int[] PHONE_SIGNAL_STRENGTH = { R.string.accessibility_no_phone, R.string.accessibility_phone_one_bar, R.string.accessibility_phone_two_bars, @@ -18,7 +30,7 @@ public class AccessibilityContentDescriptions { R.string.accessibility_phone_signal_full }; - static final int[] DATA_CONNECTION_STRENGTH = { + public static final int[] DATA_CONNECTION_STRENGTH = { R.string.accessibility_no_data, R.string.accessibility_data_one_bar, R.string.accessibility_data_two_bars, @@ -26,7 +38,7 @@ public class AccessibilityContentDescriptions { R.string.accessibility_data_signal_full }; - static final int[] WIFI_CONNECTION_STRENGTH = { + public static final int[] WIFI_CONNECTION_STRENGTH = { R.string.accessibility_no_wifi, R.string.accessibility_wifi_one_bar, R.string.accessibility_wifi_two_bars, @@ -34,9 +46,9 @@ public class AccessibilityContentDescriptions { R.string.accessibility_wifi_signal_full }; - static final int WIFI_NO_CONNECTION = R.string.accessibility_no_wifi; + public static final int WIFI_NO_CONNECTION = R.string.accessibility_no_wifi; - static final int[] ETHERNET_CONNECTION_VALUES = { + public static final int[] ETHERNET_CONNECTION_VALUES = { R.string.accessibility_ethernet_disconnected, R.string.accessibility_ethernet_connected, }; diff --git a/packages/SettingsLib/src/com/android/settingslib/SignalIcon.java b/packages/SettingsLib/src/com/android/settingslib/SignalIcon.java new file mode 100644 index 000000000000..bc0c6f36e96a --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/SignalIcon.java @@ -0,0 +1,224 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.settingslib; + +import java.text.SimpleDateFormat; +import java.util.Objects; + +/** + * Icons and states for SysUI and Settings. + */ +public class SignalIcon { + + /** + * Holds icons for a given state. Arrays are generally indexed as inet + * state (full connectivity or not) first, and second dimension as + * signal strength. + */ + public static class IconGroup { + public final int[][] sbIcons; + public final int[][] qsIcons; + public final int[] contentDesc; + public final int sbNullState; + public final int qsNullState; + public final int sbDiscState; + public final int qsDiscState; + public final int discContentDesc; + // For logging. + public final String name; + + public IconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc, + int sbNullState, int qsNullState, int sbDiscState, int qsDiscState, + int discContentDesc) { + this.name = name; + this.sbIcons = sbIcons; + this.qsIcons = qsIcons; + this.contentDesc = contentDesc; + this.sbNullState = sbNullState; + this.qsNullState = qsNullState; + this.sbDiscState = sbDiscState; + this.qsDiscState = qsDiscState; + this.discContentDesc = discContentDesc; + } + + @Override + public String toString() { + return "IconGroup(" + name + ")"; + } + } + + /** + * Holds states for SysUI. + */ + public static class State { + // No locale as it's only used for logging purposes + private static SimpleDateFormat sSDF = new SimpleDateFormat("MM-dd HH:mm:ss.SSS"); + public boolean connected; + public boolean enabled; + public boolean activityIn; + public boolean activityOut; + public int level; + public IconGroup iconGroup; + public int inetCondition; + public int rssi; // Only for logging. + + // Not used for comparison, just used for logging. + public long time; + + /** + * Generates a copy of the source state. + */ + public void copyFrom(State state) { + connected = state.connected; + enabled = state.enabled; + level = state.level; + iconGroup = state.iconGroup; + inetCondition = state.inetCondition; + activityIn = state.activityIn; + activityOut = state.activityOut; + rssi = state.rssi; + time = state.time; + } + + @Override + public String toString() { + if (time != 0) { + StringBuilder builder = new StringBuilder(); + toString(builder); + return builder.toString(); + } else { + return "Empty " + getClass().getSimpleName(); + } + } + + protected void toString(StringBuilder builder) { + builder.append("connected=").append(connected).append(',') + .append("enabled=").append(enabled).append(',') + .append("level=").append(level).append(',') + .append("inetCondition=").append(inetCondition).append(',') + .append("iconGroup=").append(iconGroup).append(',') + .append("activityIn=").append(activityIn).append(',') + .append("activityOut=").append(activityOut).append(',') + .append("rssi=").append(rssi).append(',') + .append("lastModified=").append(sSDF.format(time)); + } + + @Override + public boolean equals(Object o) { + if (!o.getClass().equals(getClass())) { + return false; + } + State other = (State) o; + return other.connected == connected + && other.enabled == enabled + && other.level == level + && other.inetCondition == inetCondition + && other.iconGroup == iconGroup + && other.activityIn == activityIn + && other.activityOut == activityOut + && other.rssi == rssi; + } + } + + /** + * Holds icons for a given MobileState. + */ + public static class MobileIconGroup extends IconGroup { + public final int dataContentDescription; // mContentDescriptionDataType + public final int dataType; + public final boolean isWide; + public final int qsDataType; + + public MobileIconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc, + int sbNullState, int qsNullState, int sbDiscState, int qsDiscState, + int discContentDesc, int dataContentDesc, int dataType, boolean isWide) { + super(name, sbIcons, qsIcons, contentDesc, sbNullState, qsNullState, sbDiscState, + qsDiscState, discContentDesc); + this.dataContentDescription = dataContentDesc; + this.dataType = dataType; + this.isWide = isWide; + this.qsDataType = dataType; // TODO: remove this field + } + } + + /** + * Holds mobile states for SysUI. + */ + public static class MobileState extends State { + public String networkName; + public String networkNameData; + public boolean dataSim; + public boolean dataConnected; + public boolean isEmergency; + public boolean airplaneMode; + public boolean carrierNetworkChangeMode; + public boolean isDefault; + public boolean userSetup; + public boolean roaming; + public boolean defaultDataOff; // Tracks the on/off state of the defaultDataSubscription + + @Override + public void copyFrom(State s) { + super.copyFrom(s); + MobileState state = (MobileState) s; + dataSim = state.dataSim; + networkName = state.networkName; + networkNameData = state.networkNameData; + dataConnected = state.dataConnected; + isDefault = state.isDefault; + isEmergency = state.isEmergency; + airplaneMode = state.airplaneMode; + carrierNetworkChangeMode = state.carrierNetworkChangeMode; + userSetup = state.userSetup; + roaming = state.roaming; + defaultDataOff = state.defaultDataOff; + } + + @Override + protected void toString(StringBuilder builder) { + super.toString(builder); + builder.append(','); + builder.append("dataSim=").append(dataSim).append(','); + builder.append("networkName=").append(networkName).append(','); + builder.append("networkNameData=").append(networkNameData).append(','); + builder.append("dataConnected=").append(dataConnected).append(','); + builder.append("roaming=").append(roaming).append(','); + builder.append("isDefault=").append(isDefault).append(','); + builder.append("isEmergency=").append(isEmergency).append(','); + builder.append("airplaneMode=").append(airplaneMode).append(','); + builder.append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode) + .append(','); + builder.append("userSetup=").append(userSetup).append(','); + builder.append("defaultDataOff=").append(defaultDataOff); + } + + @Override + public boolean equals(Object o) { + return super.equals(o) + && Objects.equals(((MobileState) o).networkName, networkName) + && Objects.equals(((MobileState) o).networkNameData, networkNameData) + && ((MobileState) o).dataSim == dataSim + && ((MobileState) o).dataConnected == dataConnected + && ((MobileState) o).isEmergency == isEmergency + && ((MobileState) o).airplaneMode == airplaneMode + && ((MobileState) o).carrierNetworkChangeMode == carrierNetworkChangeMode + && ((MobileState) o).userSetup == userSetup + && ((MobileState) o).isDefault == isDefault + && ((MobileState) o).roaming == roaming + && ((MobileState) o).defaultDataOff == defaultDataOff; + } + } +} diff --git a/packages/SettingsLib/src/com/android/settingslib/mobile/MobileMappings.java b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileMappings.java new file mode 100644 index 000000000000..09f285b445e9 --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileMappings.java @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.settingslib.mobile; + +import android.content.Context; +import android.content.res.Resources; +import android.os.PersistableBundle; +import android.telephony.Annotation; +import android.telephony.CarrierConfigManager; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyDisplayInfo; +import android.telephony.TelephonyManager; + +import com.android.settingslib.R; +import com.android.settingslib.SignalIcon.MobileIconGroup; + +import java.util.HashMap; +import java.util.Map; + +/** + * Holds the utility functions to create the RAT to MobileIconGroup mappings. + */ +public class MobileMappings { + + /** + * Generates the RAT key from the TelephonyDisplayInfo. + */ + public static String getIconKey(TelephonyDisplayInfo telephonyDisplayInfo) { + if (telephonyDisplayInfo.getOverrideNetworkType() + == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE) { + return toIconKey(telephonyDisplayInfo.getNetworkType()); + } else { + return toDisplayIconKey(telephonyDisplayInfo.getOverrideNetworkType()); + } + } + + /** + * Converts the networkType into the RAT key. + */ + public static String toIconKey(@Annotation.NetworkType int networkType) { + return Integer.toString(networkType); + } + + /** + * Converts the displayNetworkType into the RAT key. + */ + public static String toDisplayIconKey(@Annotation.OverrideNetworkType int displayNetworkType) { + switch (displayNetworkType) { + case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA: + return toIconKey(TelephonyManager.NETWORK_TYPE_LTE) + "_CA"; + case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO: + return toIconKey(TelephonyManager.NETWORK_TYPE_LTE) + "_CA_Plus"; + case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA: + return toIconKey(TelephonyManager.NETWORK_TYPE_NR); + case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE: + return toIconKey(TelephonyManager.NETWORK_TYPE_NR) + "_Plus"; + default: + return "unsupported"; + } + } + + /** + * Produce the default MobileIconGroup. + */ + public static MobileIconGroup getDefaultIcons(Config config) { + if (!config.showAtLeast3G) { + return TelephonyIcons.G; + } else { + return TelephonyIcons.THREE_G; + } + } + + /** + * Produce a mapping of data network types to icon groups for simple and quick use in + * updateTelephony. + */ + public static Map<String, MobileIconGroup> mapIconSets(Config config) { + final Map<String, MobileIconGroup> networkToIconLookup = new HashMap<>(); + + networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EVDO_0), + TelephonyIcons.THREE_G); + networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EVDO_A), + TelephonyIcons.THREE_G); + networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EVDO_B), + TelephonyIcons.THREE_G); + networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EHRPD), + TelephonyIcons.THREE_G); + if (config.show4gFor3g) { + networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_UMTS), + TelephonyIcons.FOUR_G); + } else { + networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_UMTS), + TelephonyIcons.THREE_G); + } + networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_TD_SCDMA), + TelephonyIcons.THREE_G); + + if (!config.showAtLeast3G) { + networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_UNKNOWN), + TelephonyIcons.UNKNOWN); + networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EDGE), + TelephonyIcons.E); + networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_CDMA), + TelephonyIcons.ONE_X); + networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_1xRTT), + TelephonyIcons.ONE_X); + } else { + networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_UNKNOWN), + TelephonyIcons.THREE_G); + networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EDGE), + TelephonyIcons.THREE_G); + networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_CDMA), + TelephonyIcons.THREE_G); + networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_1xRTT), + TelephonyIcons.THREE_G); + } + + MobileIconGroup hGroup = TelephonyIcons.THREE_G; + MobileIconGroup hPlusGroup = TelephonyIcons.THREE_G; + if (config.show4gFor3g) { + hGroup = TelephonyIcons.FOUR_G; + hPlusGroup = TelephonyIcons.FOUR_G; + } else if (config.hspaDataDistinguishable) { + hGroup = TelephonyIcons.H; + hPlusGroup = TelephonyIcons.H_PLUS; + } + + networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_HSDPA), hGroup); + networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_HSUPA), hGroup); + networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_HSPA), hGroup); + networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_HSPAP), hPlusGroup); + + if (config.show4gForLte) { + networkToIconLookup.put(toIconKey( + TelephonyManager.NETWORK_TYPE_LTE), + TelephonyIcons.FOUR_G); + if (config.hideLtePlus) { + networkToIconLookup.put(toDisplayIconKey( + TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA), + TelephonyIcons.FOUR_G); + } else { + networkToIconLookup.put(toDisplayIconKey( + TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA), + TelephonyIcons.FOUR_G_PLUS); + } + } else { + networkToIconLookup.put(toIconKey( + TelephonyManager.NETWORK_TYPE_LTE), + TelephonyIcons.LTE); + if (config.hideLtePlus) { + networkToIconLookup.put(toDisplayIconKey( + TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA), + TelephonyIcons.LTE); + } else { + networkToIconLookup.put(toDisplayIconKey( + TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA), + TelephonyIcons.LTE_PLUS); + } + } + networkToIconLookup.put(toIconKey( + TelephonyManager.NETWORK_TYPE_IWLAN), + TelephonyIcons.WFC); + networkToIconLookup.put(toDisplayIconKey( + TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO), + TelephonyIcons.LTE_CA_5G_E); + networkToIconLookup.put(toDisplayIconKey( + TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA), + TelephonyIcons.NR_5G); + networkToIconLookup.put(toDisplayIconKey( + TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE), + TelephonyIcons.NR_5G_PLUS); + networkToIconLookup.put(toIconKey( + TelephonyManager.NETWORK_TYPE_NR), + TelephonyIcons.NR_5G); + return networkToIconLookup; + } + + /** + * Wrapper class of system configs and Carrier configs. + */ + public static class Config { + public boolean showAtLeast3G = false; + public boolean show4gFor3g = false; + public boolean alwaysShowCdmaRssi = false; + public boolean show4gForLte = false; + public boolean hideLtePlus = false; + public boolean hspaDataDistinguishable; + public boolean alwaysShowDataRatIcon = false; + + /** + * Reads the latest configs. + */ + public static Config readConfig(Context context) { + Config config = new Config(); + Resources res = context.getResources(); + + config.showAtLeast3G = res.getBoolean(R.bool.config_showMin3G); + config.alwaysShowCdmaRssi = + res.getBoolean(com.android.internal.R.bool.config_alwaysUseCdmaRssi); + config.hspaDataDistinguishable = + res.getBoolean(R.bool.config_hspa_data_distinguishable); + + CarrierConfigManager configMgr = (CarrierConfigManager) + context.getSystemService(Context.CARRIER_CONFIG_SERVICE); + // Handle specific carrier config values for the default data SIM + int defaultDataSubId = SubscriptionManager.from(context) + .getDefaultDataSubscriptionId(); + PersistableBundle b = configMgr.getConfigForSubId(defaultDataSubId); + if (b != null) { + config.alwaysShowDataRatIcon = b.getBoolean( + CarrierConfigManager.KEY_ALWAYS_SHOW_DATA_RAT_ICON_BOOL); + config.show4gForLte = b.getBoolean( + CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL); + config.show4gFor3g = b.getBoolean( + CarrierConfigManager.KEY_SHOW_4G_FOR_3G_DATA_ICON_BOOL); + config.hideLtePlus = b.getBoolean( + CarrierConfigManager.KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL); + } + return config; + } + } +} diff --git a/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java new file mode 100644 index 000000000000..b8030f166436 --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileStatusTracker.java @@ -0,0 +1,286 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.settingslib.mobile; + +import android.os.Handler; +import android.os.Looper; +import android.telephony.PhoneStateListener; +import android.telephony.ServiceState; +import android.telephony.SignalStrength; +import android.telephony.SubscriptionInfo; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyDisplayInfo; +import android.telephony.TelephonyManager; +import android.util.Log; + +/** + * Tracks the mobile signal status for the SysUI and Settings. + * + * This class is not threadsafe. All the mobile statuses monitored by this class is stored in + * MobileStatus. Whoever uses this class should only rely on the MobileStatusTracker#Callback + * to get the latest mobile statuses. Do not get mobile statues directly from + * MobileStatusTracker#MobileStatus. + */ +public class MobileStatusTracker { + private static final String TAG = "MobileStatusTracker"; + private final TelephonyManager mPhone; + private final SubscriptionInfo mSubscriptionInfo; + private final Callback mCallback; + private final MobileStatus mMobileStatus; + private final PhoneStateListener mPhoneStateListener; + private final SubscriptionDefaults mDefaults; + private final Handler mReceiverHandler; + + /** + * MobileStatusTracker constructors + * + * @param phone The TelephonyManager which corresponds to the subscription being monitored. + * @param receiverLooper The Looper on which the callback will be invoked. + * @param info The subscription being monitored. + * @param defaults The wrapper of the SubscriptionManager. + * @param callback The callback to notify any changes of the mobile status, users should only + * use this callback to get the latest mobile status. + */ + public MobileStatusTracker(TelephonyManager phone, Looper receiverLooper, + SubscriptionInfo info, SubscriptionDefaults defaults, Callback callback) { + mPhone = phone; + mReceiverHandler = new Handler(receiverLooper); + mPhoneStateListener = new MobilePhoneStateListener(); + mSubscriptionInfo = info; + mDefaults = defaults; + mCallback = callback; + mMobileStatus = new MobileStatus(); + updateDataSim(); + mReceiverHandler.post(() -> mCallback.onMobileStatusChanged( + /* updateTelephony= */false, new MobileStatus(mMobileStatus))); + } + + public PhoneStateListener getPhoneStateListener() { + return mPhoneStateListener; + } + + /** + * Config the MobileStatusTracker to start or stop monitoring platform signals. + */ + public void setListening(boolean listening) { + if (listening) { + mPhone.registerPhoneStateListener(mReceiverHandler::post, mPhoneStateListener); + } else { + mPhone.unregisterPhoneStateListener(mPhoneStateListener); + } + } + + private void updateDataSim() { + int activeDataSubId = mDefaults.getActiveDataSubId(); + if (SubscriptionManager.isValidSubscriptionId(activeDataSubId)) { + mMobileStatus.dataSim = activeDataSubId == mSubscriptionInfo.getSubscriptionId(); + } else { + // There doesn't seem to be a data sim selected, however if + // there isn't a MobileSignalController with dataSim set, then + // QS won't get any callbacks and will be blank. Instead + // lets just assume we are the data sim (which will basically + // show one at random) in QS until one is selected. The user + // should pick one soon after, so we shouldn't be in this state + // for long. + mMobileStatus.dataSim = true; + } + } + + private void setActivity(int activity) { + mMobileStatus.activityIn = activity == TelephonyManager.DATA_ACTIVITY_INOUT + || activity == TelephonyManager.DATA_ACTIVITY_IN; + mMobileStatus.activityOut = activity == TelephonyManager.DATA_ACTIVITY_INOUT + || activity == TelephonyManager.DATA_ACTIVITY_OUT; + } + + private class MobilePhoneStateListener extends PhoneStateListener implements + PhoneStateListener.ServiceStateChangedListener, + PhoneStateListener.SignalStrengthsChangedListener, + PhoneStateListener.CallStateChangedListener, + PhoneStateListener.DataConnectionStateChangedListener, + PhoneStateListener.DataActivityListener, + PhoneStateListener.CarrierNetworkChangeListener, + PhoneStateListener.ActiveDataSubscriptionIdChangedListener, + PhoneStateListener.DisplayInfoChangedListener{ + + @Override + public void onSignalStrengthsChanged(SignalStrength signalStrength) { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "onSignalStrengthsChanged signalStrength=" + signalStrength + + ((signalStrength == null) ? "" + : (" level=" + signalStrength.getLevel()))); + } + mMobileStatus.signalStrength = signalStrength; + mCallback.onMobileStatusChanged( + /* updateTelephony= */true, new MobileStatus(mMobileStatus)); + } + + @Override + public void onServiceStateChanged(ServiceState state) { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "onServiceStateChanged voiceState=" + + (state == null ? "" : state.getState()) + + " dataState=" + (state == null ? "" : state.getDataRegistrationState())); + } + mMobileStatus.serviceState = state; + mCallback.onMobileStatusChanged( + /* updateTelephony= */true, new MobileStatus(mMobileStatus)); + } + + @Override + public void onDataConnectionStateChanged(int state, int networkType) { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "onDataConnectionStateChanged: state=" + state + + " type=" + networkType); + } + mMobileStatus.dataState = state; + mCallback.onMobileStatusChanged( + /* updateTelephony= */true, new MobileStatus(mMobileStatus)); + } + + @Override + public void onDataActivity(int direction) { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "onDataActivity: direction=" + direction); + } + setActivity(direction); + mCallback.onMobileStatusChanged( + /* updateTelephony= */false, new MobileStatus(mMobileStatus)); + } + + @Override + public void onCarrierNetworkChange(boolean active) { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "onCarrierNetworkChange: active=" + active); + } + mMobileStatus.carrierNetworkChangeMode = active; + mCallback.onMobileStatusChanged( + /* updateTelephony= */true, new MobileStatus(mMobileStatus)); + } + + @Override + public void onActiveDataSubscriptionIdChanged(int subId) { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "onActiveDataSubscriptionIdChanged: subId=" + subId); + } + updateDataSim(); + mCallback.onMobileStatusChanged( + /* updateTelephony= */true, new MobileStatus(mMobileStatus)); + } + + @Override + public void onDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo) { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "onDisplayInfoChanged: telephonyDisplayInfo=" + telephonyDisplayInfo); + } + mMobileStatus.telephonyDisplayInfo = telephonyDisplayInfo; + mCallback.onMobileStatusChanged( + /* updateTelephony= */ true, new MobileStatus(mMobileStatus)); + } + } + + /** + * Wrapper class of the SubscriptionManager, for mock testing purpose + */ + public static class SubscriptionDefaults { + public int getDefaultVoiceSubId() { + return SubscriptionManager.getDefaultVoiceSubscriptionId(); + } + + public int getDefaultDataSubId() { + return SubscriptionManager.getDefaultDataSubscriptionId(); + } + + public int getActiveDataSubId() { + return SubscriptionManager.getActiveDataSubscriptionId(); + } + } + + /** + * Wrapper class which contains all the mobile status tracked by MobileStatusTracker. + */ + public static class MobileStatus { + public boolean activityIn; + public boolean activityOut; + public boolean dataSim; + public boolean carrierNetworkChangeMode; + public int dataState = TelephonyManager.DATA_DISCONNECTED; + public ServiceState serviceState; + public SignalStrength signalStrength; + public TelephonyDisplayInfo telephonyDisplayInfo = + new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_UNKNOWN, + TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE); + + /** + * Empty constructor + */ + public MobileStatus() { } + + /** + * Copy constructors + * + * @param status Source MobileStatus + */ + public MobileStatus(MobileStatus status) { + copyFrom(status); + } + + protected void copyFrom(MobileStatus status) { + activityIn = status.activityIn; + activityOut = status.activityOut; + dataSim = status.dataSim; + carrierNetworkChangeMode = status.carrierNetworkChangeMode; + dataState = status.dataState; + // We don't do deep copy for the below members since they may be Mockito instances. + serviceState = status.serviceState; + signalStrength = status.signalStrength; + telephonyDisplayInfo = status.telephonyDisplayInfo; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + return builder.append("[activityIn=").append(activityIn).append(',') + .append("activityOut=").append(activityOut).append(',') + .append("dataSim=").append(dataSim).append(',') + .append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode).append(',') + .append("dataState=").append(dataState).append(',') + .append("serviceState=").append(serviceState == null ? "" + : serviceState.toString()).append(',') + .append("signalStrength=").append(signalStrength == null ? "" + : signalStrength.toString()).append(',') + .append("telephonyDisplayInfo=").append(telephonyDisplayInfo == null ? "" + : telephonyDisplayInfo.toString()).append(']').toString(); + } + } + + /** + * Callback for notifying any changes of the mobile status. + * + * This callback will always be invoked on the receiverLooper which must be specified when + * MobileStatusTracker is constructed. + */ + public interface Callback { + /** + * Notify the mobile status has been updated. + * + * @param updateTelephony Whether needs to update other Telephony related parameters, this + * is only used by SysUI. + * @param mobileStatus Holds the latest mobile statuses + */ + void onMobileStatusChanged(boolean updateTelephony, MobileStatus mobileStatus); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SettingsLib/src/com/android/settingslib/mobile/TelephonyIcons.java index d9591cf5f5e9..c2613a5f4a4a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java +++ b/packages/SettingsLib/src/com/android/settingslib/mobile/TelephonyIcons.java @@ -14,33 +14,37 @@ * limitations under the License. */ -package com.android.systemui.statusbar.policy; +package com.android.settingslib.mobile; -import com.android.systemui.R; -import com.android.systemui.statusbar.policy.MobileSignalController.MobileIconGroup; +import com.android.settingslib.AccessibilityContentDescriptions; +import com.android.settingslib.R; +import com.android.settingslib.SignalIcon.MobileIconGroup; import java.util.HashMap; import java.util.Map; -class TelephonyIcons { +/** + * Telephony related icons and strings for SysUI and Settings. + */ +public class TelephonyIcons { //***** Data connection icons - static final int FLIGHT_MODE_ICON = R.drawable.stat_sys_airplane_mode; + public static final int FLIGHT_MODE_ICON = R.drawable.stat_sys_airplane_mode; - static final int ICON_LTE = R.drawable.ic_lte_mobiledata; - static final int ICON_LTE_PLUS = R.drawable.ic_lte_plus_mobiledata; - static final int ICON_G = R.drawable.ic_g_mobiledata; - static final int ICON_E = R.drawable.ic_e_mobiledata; - static final int ICON_H = R.drawable.ic_h_mobiledata; - static final int ICON_H_PLUS = R.drawable.ic_h_plus_mobiledata; - static final int ICON_3G = R.drawable.ic_3g_mobiledata; - static final int ICON_4G = R.drawable.ic_4g_mobiledata; - static final int ICON_4G_PLUS = R.drawable.ic_4g_plus_mobiledata; - static final int ICON_5G_E = R.drawable.ic_5g_e_mobiledata; - static final int ICON_1X = R.drawable.ic_1x_mobiledata; - static final int ICON_5G = R.drawable.ic_5g_mobiledata; - static final int ICON_5G_PLUS = R.drawable.ic_5g_plus_mobiledata; + public static final int ICON_LTE = R.drawable.ic_lte_mobiledata; + public static final int ICON_LTE_PLUS = R.drawable.ic_lte_plus_mobiledata; + public static final int ICON_G = R.drawable.ic_g_mobiledata; + public static final int ICON_E = R.drawable.ic_e_mobiledata; + public static final int ICON_H = R.drawable.ic_h_mobiledata; + public static final int ICON_H_PLUS = R.drawable.ic_h_plus_mobiledata; + public static final int ICON_3G = R.drawable.ic_3g_mobiledata; + public static final int ICON_4G = R.drawable.ic_4g_mobiledata; + public static final int ICON_4G_PLUS = R.drawable.ic_4g_plus_mobiledata; + public static final int ICON_5G_E = R.drawable.ic_5g_e_mobiledata; + public static final int ICON_1X = R.drawable.ic_1x_mobiledata; + public static final int ICON_5G = R.drawable.ic_5g_mobiledata; + public static final int ICON_5G_PLUS = R.drawable.ic_5g_plus_mobiledata; - static final MobileIconGroup CARRIER_NETWORK_CHANGE = new MobileIconGroup( + public static final MobileIconGroup CARRIER_NETWORK_CHANGE = new MobileIconGroup( "CARRIER_NETWORK_CHANGE", null, null, @@ -53,7 +57,7 @@ class TelephonyIcons { 0, false); - static final MobileIconGroup THREE_G = new MobileIconGroup( + public static final MobileIconGroup THREE_G = new MobileIconGroup( "3G", null, null, @@ -66,7 +70,7 @@ class TelephonyIcons { TelephonyIcons.ICON_3G, true); - static final MobileIconGroup WFC = new MobileIconGroup( + public static final MobileIconGroup WFC = new MobileIconGroup( "WFC", null, null, @@ -77,7 +81,7 @@ class TelephonyIcons { AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], 0, 0, false); - static final MobileIconGroup UNKNOWN = new MobileIconGroup( + public static final MobileIconGroup UNKNOWN = new MobileIconGroup( "Unknown", null, null, @@ -88,7 +92,7 @@ class TelephonyIcons { AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], 0, 0, false); - static final MobileIconGroup E = new MobileIconGroup( + public static final MobileIconGroup E = new MobileIconGroup( "E", null, null, @@ -101,7 +105,7 @@ class TelephonyIcons { TelephonyIcons.ICON_E, false); - static final MobileIconGroup ONE_X = new MobileIconGroup( + public static final MobileIconGroup ONE_X = new MobileIconGroup( "1X", null, null, @@ -114,7 +118,7 @@ class TelephonyIcons { TelephonyIcons.ICON_1X, true); - static final MobileIconGroup G = new MobileIconGroup( + public static final MobileIconGroup G = new MobileIconGroup( "G", null, null, @@ -127,7 +131,7 @@ class TelephonyIcons { TelephonyIcons.ICON_G, false); - static final MobileIconGroup H = new MobileIconGroup( + public static final MobileIconGroup H = new MobileIconGroup( "H", null, null, @@ -140,7 +144,7 @@ class TelephonyIcons { TelephonyIcons.ICON_H, false); - static final MobileIconGroup H_PLUS = new MobileIconGroup( + public static final MobileIconGroup H_PLUS = new MobileIconGroup( "H+", null, null, @@ -153,7 +157,7 @@ class TelephonyIcons { TelephonyIcons.ICON_H_PLUS, false); - static final MobileIconGroup FOUR_G = new MobileIconGroup( + public static final MobileIconGroup FOUR_G = new MobileIconGroup( "4G", null, null, @@ -166,12 +170,12 @@ class TelephonyIcons { TelephonyIcons.ICON_4G, true); - static final MobileIconGroup FOUR_G_PLUS = new MobileIconGroup( + public static final MobileIconGroup FOUR_G_PLUS = new MobileIconGroup( "4G+", null, null, AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH, - 0,0, + 0, 0, 0, 0, AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0], @@ -179,7 +183,7 @@ class TelephonyIcons { TelephonyIcons.ICON_4G_PLUS, true); - static final MobileIconGroup LTE = new MobileIconGroup( + public static final MobileIconGroup LTE = new MobileIconGroup( "LTE", null, null, @@ -192,7 +196,7 @@ class TelephonyIcons { TelephonyIcons.ICON_LTE, true); - static final MobileIconGroup LTE_PLUS = new MobileIconGroup( + public static final MobileIconGroup LTE_PLUS = new MobileIconGroup( "LTE+", null, null, @@ -205,7 +209,7 @@ class TelephonyIcons { TelephonyIcons.ICON_LTE_PLUS, true); - static final MobileIconGroup LTE_CA_5G_E = new MobileIconGroup( + public static final MobileIconGroup LTE_CA_5G_E = new MobileIconGroup( "5Ge", null, null, @@ -218,7 +222,7 @@ class TelephonyIcons { TelephonyIcons.ICON_5G_E, true); - static final MobileIconGroup NR_5G = new MobileIconGroup( + public static final MobileIconGroup NR_5G = new MobileIconGroup( "5G", null, null, @@ -232,7 +236,7 @@ class TelephonyIcons { TelephonyIcons.ICON_5G, true); - static final MobileIconGroup NR_5G_PLUS = new MobileIconGroup( + public static final MobileIconGroup NR_5G_PLUS = new MobileIconGroup( "5G_PLUS", null, null, @@ -246,7 +250,7 @@ class TelephonyIcons { TelephonyIcons.ICON_5G_PLUS, true); - static final MobileIconGroup DATA_DISABLED = new MobileIconGroup( + public static final MobileIconGroup DATA_DISABLED = new MobileIconGroup( "DataDisabled", null, null, @@ -259,7 +263,7 @@ class TelephonyIcons { 0, false); - static final MobileIconGroup NOT_DEFAULT_DATA = new MobileIconGroup( + public static final MobileIconGroup NOT_DEFAULT_DATA = new MobileIconGroup( "NotDefaultData", null, null, @@ -276,7 +280,7 @@ class TelephonyIcons { // in QSCarrier#hasValidTypeContentDescription /** Mapping icon name(lower case) to the icon object. */ - static final Map<String, MobileIconGroup> ICON_NAME_TO_ICON; + public static final Map<String, MobileIconGroup> ICON_NAME_TO_ICON; static { ICON_NAME_TO_ICON = new HashMap<>(); ICON_NAME_TO_ICON.put("carrier_network_change", CARRIER_NETWORK_CHANGE); diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml index 5ad43e3c6008..846efa78decf 100644 --- a/packages/SettingsProvider/res/values/defaults.xml +++ b/packages/SettingsProvider/res/values/defaults.xml @@ -180,7 +180,7 @@ <!-- Default state of tap to wake --> <bool name="def_double_tap_to_wake">true</bool> - <!-- Default for Settings.Secure.NFC_PAYMENT_COMPONENT --> + <!-- Default for Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT --> <string name="def_nfc_payment_component"></string> <!-- Default setting for ability to add users from the lock screen --> diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 7b1257b0f194..411a78ac2485 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -155,6 +155,7 @@ <uses-permission android:name="android.permission.MANAGE_CONTENT_CAPTURE" /> <uses-permission android:name="android.permission.MANAGE_CONTENT_SUGGESTIONS" /> <uses-permission android:name="android.permission.MANAGE_APP_PREDICTIONS" /> + <uses-permission android:name="android.permission.MANAGE_SEARCH_UI" /> <uses-permission android:name="android.permission.NETWORK_SETTINGS" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.SET_TIME" /> @@ -181,6 +182,8 @@ <!-- Permissions needed to test system only camera devices --> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.SYSTEM_CAMERA" /> + <!-- Permissions needed to test onCameraOpened/Closed callbacks --> + <uses-permission android:name="android.permission.CAMERA_OPEN_CLOSE_LISTENER" /> <!-- Permissions needed for CTS camera test: RecordingTest.java when assuming shell id --> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <!-- Permission needed to enable/disable Bluetooth/Wifi --> @@ -362,6 +365,9 @@ <!-- Permissions required for CTS tests to close system dialogs --> <uses-permission android:name="android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS" /> + <!-- Permission required for CTS test - HideOverlayWindowsTest --> + <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> + <application android:label="@string/app_label" android:theme="@android:style/Theme.DeviceDefault.DayNight" android:defaultToDeviceProtectedStorage="true" diff --git a/packages/Shell/OWNERS b/packages/Shell/OWNERS index 2d7a3e68f86a..6ba1fcb058b1 100644 --- a/packages/Shell/OWNERS +++ b/packages/Shell/OWNERS @@ -1,6 +1,6 @@ set noparent -jsharkey@google.com +jsharkey@android.com felipeal@google.com nandana@google.com svetoslavganov@google.com diff --git a/packages/StatementService/Android.bp b/packages/StatementService/Android.bp index ae37efc9a545..2664a0316f5c 100644 --- a/packages/StatementService/Android.bp +++ b/packages/StatementService/Android.bp @@ -21,6 +21,7 @@ android_app { platform_apis: true, privileged: true, libs: ["org.apache.http.legacy"], + uses_libs: ["org.apache.http.legacy"], static_libs: [ "libprotobuf-java-nano", "volley", diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 285c4a172e68..3fb5a9c59b2d 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -103,6 +103,7 @@ <uses-permission android:name="android.permission.START_ACTIVITY_AS_CALLER" /> <uses-permission android:name="android.permission.START_TASKS_FROM_RECENTS" /> <uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT" /> + <uses-permission android:name="android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS" /> <!-- WindowManager --> <uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" /> @@ -390,7 +391,7 @@ </activity-alias> <activity - android:name="com.android.wm.shell.splitscreen.ForcedResizableInfoActivity" + android:name="com.android.wm.shell.legacysplitscreen.ForcedResizableInfoActivity" android:theme="@style/ForcedResizableTheme" android:excludeFromRecents="true" android:stateNotNeeded="true" diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS index 3bda7106defa..f884270eaba8 100644 --- a/packages/SystemUI/OWNERS +++ b/packages/SystemUI/OWNERS @@ -1,6 +1,6 @@ set noparent -dsandler@google.com +dsandler@android.com aaliomer@google.com adamcohen@google.com diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java index 6e86f268a725..4fc197340e92 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java @@ -60,8 +60,8 @@ public interface FalsingManager { * Returns true if the last two gestures do not look like a double tap. * * Only works on data that has already been reported to the FalsingManager. Be sure that - * {@link #onTouchEvent(MotionEvent, int, int)} has already been called for all of the - * taps you want considered. + * {@link com.android.systemui.classifier.FalsingCollector#onTouchEvent(MotionEvent)} + * has already been called for all of the taps you want considered. * * This looks at the last two gestures on the screen, ensuring that they meet the following * criteria: @@ -85,8 +85,6 @@ public interface FalsingManager { boolean isReportingEnabled(); - void onTouchEvent(MotionEvent ev, int width, int height); - /** From com.android.systemui.Dumpable. */ void dump(FileDescriptor fd, PrintWriter pw, String[] args); diff --git a/packages/SystemUI/res-keyguard/values-af/strings.xml b/packages/SystemUI/res-keyguard/values-af/strings.xml index 276fa23e8578..6f23f8c0b2b8 100644 --- a/packages/SystemUI/res-keyguard/values-af/strings.xml +++ b/packages/SystemUI/res-keyguard/values-af/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans vinnig"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans stadig"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimeer tans vir batterygesondheid"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Koppel jou laaier."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Druk Kieslys om te ontsluit."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Netwerk is gesluit"</string> diff --git a/packages/SystemUI/res-keyguard/values-am/strings.xml b/packages/SystemUI/res-keyguard/values-am/strings.xml index ae5d1f675c52..62f955438e44 100644 --- a/packages/SystemUI/res-keyguard/values-am/strings.xml +++ b/packages/SystemUI/res-keyguard/values-am/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ኃይል በመሙላት ላይ"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • በፍጥነት ኃይልን በመሙላት ላይ"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • በዝግታ ኃይልን በመሙላት ላይ"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ለባትሪ ጤና ማመቻቸት"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"ኃይል መሙያዎን ያያይዙ።"</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ለመክፈት ምናሌ ተጫን።"</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"አውታረ መረብ ተቆልፏል"</string> diff --git a/packages/SystemUI/res-keyguard/values-ar/strings.xml b/packages/SystemUI/res-keyguard/values-ar/strings.xml index fb03fe340c3a..459d162c65db 100644 --- a/packages/SystemUI/res-keyguard/values-ar/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ar/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن سريعًا"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن ببطء"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • التحسين لسلامة البطارية"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"توصيل جهاز الشحن."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"اضغط على \"القائمة\" لإلغاء التأمين."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"الشبكة مؤمّنة"</string> diff --git a/packages/SystemUI/res-keyguard/values-as/strings.xml b/packages/SystemUI/res-keyguard/values-as/strings.xml index 8e8b13d0a160..84a8afa04286 100644 --- a/packages/SystemUI/res-keyguard/values-as/strings.xml +++ b/packages/SystemUI/res-keyguard/values-as/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • চ্চার্জ কৰি থকা হৈছে"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • দ্ৰুত গতিৰে চ্চাৰ্জ কৰি থকা হৈছে"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • লাহে লাহে চ্চাৰ্জ কৰি থকা হৈছে"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • বেটাৰীৰ অৱস্থা অপ্টিমাইজ কৰি থকা হৈছে"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"আপোনাৰ চ্চার্জাৰ সংযোগ কৰক।"</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"আনলক কৰিবলৈ মেনু টিপক।"</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"নেটৱর্ক লক কৰা অৱস্থাত আছে"</string> diff --git a/packages/SystemUI/res-keyguard/values-az/strings.xml b/packages/SystemUI/res-keyguard/values-az/strings.xml index f9bff73a671f..e1846796dc2f 100644 --- a/packages/SystemUI/res-keyguard/values-az/strings.xml +++ b/packages/SystemUI/res-keyguard/values-az/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Enerji yığır"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sürətlə enerji yığır"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Yavaş enerji yığır"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Enerjiyə qənaət üçün optimallaşdırma"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Adapteri qoşun."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Kilidi açmaq üçün Menyu düyməsinə basın."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Şəbəkə kilidlidir"</string> diff --git a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml index 3434ac67bb73..346874060759 100644 --- a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Puni se"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Brzo se puni"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sporo se puni"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimizuje se radi dobrog stanja baterije"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Priključite punjač."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pritisnite Meni da biste otključali."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Mreža je zaključana"</string> diff --git a/packages/SystemUI/res-keyguard/values-be/strings.xml b/packages/SystemUI/res-keyguard/values-be/strings.xml index 07d682f69f56..4f8ce16e9106 100644 --- a/packages/SystemUI/res-keyguard/values-be/strings.xml +++ b/packages/SystemUI/res-keyguard/values-be/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе зарадка"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе хуткая зарадка"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе павольная зарадка"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Аптымізацыя стану акумулятара"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Падключыце зарадную прыладу."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Націсніце кнопку \"Меню\", каб разблакіраваць."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Сетка заблакіравана"</string> diff --git a/packages/SystemUI/res-keyguard/values-bg/strings.xml b/packages/SystemUI/res-keyguard/values-bg/strings.xml index 3890c11f9450..0911efade706 100644 --- a/packages/SystemUI/res-keyguard/values-bg/strings.xml +++ b/packages/SystemUI/res-keyguard/values-bg/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се бързо"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се бавно"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Оптимизиране за състоянието на батерията"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Свържете зарядното си устройство."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Натиснете „Меню“, за да отключите."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Мрежата е заключена"</string> diff --git a/packages/SystemUI/res-keyguard/values-bn/strings.xml b/packages/SystemUI/res-keyguard/values-bn/strings.xml index f9163747aff7..0c878b6e0175 100644 --- a/packages/SystemUI/res-keyguard/values-bn/strings.xml +++ b/packages/SystemUI/res-keyguard/values-bn/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • চার্জ হচ্ছে"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • দ্রুত চার্জ হচ্ছে"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ধীরে চার্জ হচ্ছে"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ব্যাটারির চার্জ অপটিমাইজ করা হচ্ছে"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"আপনার চার্জার সংযুক্ত করুন।"</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"আনলক করতে মেনুতে টিপুন।"</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"নেটওয়ার্ক লক করা আছে"</string> diff --git a/packages/SystemUI/res-keyguard/values-bs/strings.xml b/packages/SystemUI/res-keyguard/values-bs/strings.xml index 59a881db8e33..83ad38c74598 100644 --- a/packages/SystemUI/res-keyguard/values-bs/strings.xml +++ b/packages/SystemUI/res-keyguard/values-bs/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Punjenje"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Brzo punjenje"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sporo punjenje"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimiziranje radi očuvanja baterije"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Priključite punjač."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pritisnite meni da otključate."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Mreža je zaključana"</string> diff --git a/packages/SystemUI/res-keyguard/values-ca/strings.xml b/packages/SystemUI/res-keyguard/values-ca/strings.xml index 82d63c157441..421ddb6d31e6 100644 --- a/packages/SystemUI/res-keyguard/values-ca/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ca/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant ràpidament"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant lentament"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està optimitzant per mantenir el bon estat de la bateria"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Connecta el carregador."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Prem Menú per desbloquejar."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"La xarxa està bloquejada"</string> diff --git a/packages/SystemUI/res-keyguard/values-cs/strings.xml b/packages/SystemUI/res-keyguard/values-cs/strings.xml index a4e653f19678..855d3f0eb968 100644 --- a/packages/SystemUI/res-keyguard/values-cs/strings.xml +++ b/packages/SystemUI/res-keyguard/values-cs/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíjení"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Rychlé nabíjení"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pomalé nabíjení"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimalizace pro výdrž baterie"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Připojte dobíjecí zařízení."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Klávesy odemknete stisknutím tlačítka nabídky."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Síť je blokována"</string> diff --git a/packages/SystemUI/res-keyguard/values-da/strings.xml b/packages/SystemUI/res-keyguard/values-da/strings.xml index 604852cfeb45..b5955c7d61e1 100644 --- a/packages/SystemUI/res-keyguard/values-da/strings.xml +++ b/packages/SystemUI/res-keyguard/values-da/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oplader"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oplader hurtigt"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oplader langsomt"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimerer batteritilstanden"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Tilslut din oplader."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Tryk på menuen for at låse op."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Netværket er låst"</string> diff --git a/packages/SystemUI/res-keyguard/values-de/strings.xml b/packages/SystemUI/res-keyguard/values-de/strings.xml index 0e2ea136f263..d700df382ea9 100644 --- a/packages/SystemUI/res-keyguard/values-de/strings.xml +++ b/packages/SystemUI/res-keyguard/values-de/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird geladen"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird schnell geladen"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird langsam geladen"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimierung des Akkuzustands"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Ladegerät anschließen."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Zum Entsperren die Menütaste drücken."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Netzwerk gesperrt"</string> diff --git a/packages/SystemUI/res-keyguard/values-el/strings.xml b/packages/SystemUI/res-keyguard/values-el/strings.xml index 90e255031dd1..b3056981caaa 100644 --- a/packages/SystemUI/res-keyguard/values-el/strings.xml +++ b/packages/SystemUI/res-keyguard/values-el/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Φόρτιση"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Γρήγορη φόρτιση"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Αργή φόρτιση"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Βελτιστοποίηση για τη διατήρηση της καλής κατάστασης της μπαταρίας"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Συνδέστε τον φορτιστή."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Πατήστε \"Μενού\" για ξεκλείδωμα."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Κλειδωμένο δίκτυο"</string> diff --git a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml index 7b0c638dcdf3..54c1a2b039a3 100644 --- a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml +++ b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml @@ -38,7 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Battery limited temporarily"</string> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimising for battery health"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Connect your charger."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string> diff --git a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml index 2ef720e44735..d8591e260d0b 100644 --- a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml +++ b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml @@ -38,7 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Battery limited temporarily"</string> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimising for battery health"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Connect your charger."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string> diff --git a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml index 7b0c638dcdf3..54c1a2b039a3 100644 --- a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml +++ b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml @@ -38,7 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Battery limited temporarily"</string> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimising for battery health"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Connect your charger."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string> diff --git a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml index 7b0c638dcdf3..54c1a2b039a3 100644 --- a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml +++ b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml @@ -38,7 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Battery limited temporarily"</string> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimising for battery health"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Connect your charger."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string> diff --git a/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml b/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml index 471ef8ba83d9..30f47d21b178 100644 --- a/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml +++ b/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml @@ -38,7 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Battery limited temporarily"</string> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimizing for battery health"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Connect your charger."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string> diff --git a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml index a5750b550295..4ea99ccdd419 100644 --- a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml +++ b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rápidamente"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando lentamente"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se está optimizando el estado de la batería"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Conecta tu cargador."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Presiona Menú para desbloquear."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Bloqueada para la red"</string> diff --git a/packages/SystemUI/res-keyguard/values-es/strings.xml b/packages/SystemUI/res-keyguard/values-es/strings.xml index 69488da11576..b7384c5e3893 100644 --- a/packages/SystemUI/res-keyguard/values-es/strings.xml +++ b/packages/SystemUI/res-keyguard/values-es/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rápidamente"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando lentamente"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimizando para preservar el estado de la batería"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Conecta el cargador."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pulsa el menú para desbloquear la pantalla."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Bloqueada para la red"</string> diff --git a/packages/SystemUI/res-keyguard/values-et/strings.xml b/packages/SystemUI/res-keyguard/values-et/strings.xml index 948e134e68ec..a01d30db30db 100644 --- a/packages/SystemUI/res-keyguard/values-et/strings.xml +++ b/packages/SystemUI/res-keyguard/values-et/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laadimine"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kiirlaadimine"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Aeglane laadimine"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimeerimine aku seisukorra põhjal"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Ühendage laadija."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Vajutage avamiseks menüüklahvi."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Võrk on lukus"</string> diff --git a/packages/SystemUI/res-keyguard/values-eu/strings.xml b/packages/SystemUI/res-keyguard/values-eu/strings.xml index b1aa206364a4..ce8ef202a038 100644 --- a/packages/SystemUI/res-keyguard/values-eu/strings.xml +++ b/packages/SystemUI/res-keyguard/values-eu/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kargatzen"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bizkor kargatzen"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mantso kargatzen"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimizatzen bateria egoera onean mantentzeko"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Konektatu kargagailua."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Desblokeatzeko, sakatu Menua."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Sarea blokeatuta dago"</string> diff --git a/packages/SystemUI/res-keyguard/values-fa/strings.xml b/packages/SystemUI/res-keyguard/values-fa/strings.xml index 8fecdd3ee980..61e2e1fc78db 100644 --- a/packages/SystemUI/res-keyguard/values-fa/strings.xml +++ b/packages/SystemUI/res-keyguard/values-fa/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • درحال شارژ شدن"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • درحال شارژ سریع"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • آهستهآهسته شارژ میشود"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • بهینهسازی برای سلامت باتری"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"شارژر را وصل کنید."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"برای باز کردن قفل روی «منو» فشار دهید."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"شبکه قفل شد"</string> diff --git a/packages/SystemUI/res-keyguard/values-fi/strings.xml b/packages/SystemUI/res-keyguard/values-fi/strings.xml index c47de5dc8cf7..021de770f2c1 100644 --- a/packages/SystemUI/res-keyguard/values-fi/strings.xml +++ b/packages/SystemUI/res-keyguard/values-fi/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan nopeasti"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan hitaasti"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Akun kunnon optimointi"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Kytke laturi."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Poista lukitus painamalla Valikkoa."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Verkko lukittu"</string> diff --git a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml index b330452f5bbe..d1a1582cbcb5 100644 --- a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"En recharge : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"En recharge rapide : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"En recharge lente : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimisation en fonction de la santé de la pile"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Branchez votre chargeur."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Appuyez sur la touche Menu pour déverrouiller l\'appareil."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Réseau verrouillé"</string> diff --git a/packages/SystemUI/res-keyguard/values-fr/strings.xml b/packages/SystemUI/res-keyguard/values-fr/strings.xml index 0c13c0f0cb0d..ba35acd34d8c 100644 --- a/packages/SystemUI/res-keyguard/values-fr/strings.xml +++ b/packages/SystemUI/res-keyguard/values-fr/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge…"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge rapide…"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge lente…"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimisation pour préserver la batterie"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Branchez votre chargeur."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Appuyez sur \"Menu\" pour déverrouiller le clavier."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Réseau verrouillé"</string> diff --git a/packages/SystemUI/res-keyguard/values-gl/strings.xml b/packages/SystemUI/res-keyguard/values-gl/strings.xml index 601b2e23aba1..01a0fac58016 100644 --- a/packages/SystemUI/res-keyguard/values-gl/strings.xml +++ b/packages/SystemUI/res-keyguard/values-gl/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rapidamente"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando lentamente"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimizando para manter a batería en bo estado"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Conecta o cargador."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Preme Menú para desbloquear."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Bloqueada pola rede"</string> diff --git a/packages/SystemUI/res-keyguard/values-gu/strings.xml b/packages/SystemUI/res-keyguard/values-gu/strings.xml index 296124fc743d..8ec7ba595837 100644 --- a/packages/SystemUI/res-keyguard/values-gu/strings.xml +++ b/packages/SystemUI/res-keyguard/values-gu/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ચાર્જિંગ"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ઝડપથી ચાર્જિંગ"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ધીમેથી ચાર્જિંગ"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • બૅટરીની ક્ષમતા વધારવા ઑપ્ટિમાઇઝ કરી રહ્યાં છીએ"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"તમારું ચાર્જર કનેક્ટ કરો."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"અનલૉક કરવા માટે મેનૂ દબાવો."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"નેટવર્ક લૉક થયું"</string> diff --git a/packages/SystemUI/res-keyguard/values-hi/strings.xml b/packages/SystemUI/res-keyguard/values-hi/strings.xml index c1c9dd57a64f..5869078dc598 100644 --- a/packages/SystemUI/res-keyguard/values-hi/strings.xml +++ b/packages/SystemUI/res-keyguard/values-hi/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्ज हो रहा है"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • तेज़ चार्ज हो रहा है"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • धीरे चार्ज हो रहा है"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • बैटरी की परफ़ॉर्मेंस बेहतर करने के लिए, ऑप्टिमाइज़ किया जा रहा है"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"अपना चार्जर कनेक्ट करें."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"लॉक खोलने के लिए मेन्यू दबाएं."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"नेटवर्क लॉक किया हुआ है"</string> diff --git a/packages/SystemUI/res-keyguard/values-hr/strings.xml b/packages/SystemUI/res-keyguard/values-hr/strings.xml index 1b51b33c9843..7e0697337481 100644 --- a/packages/SystemUI/res-keyguard/values-hr/strings.xml +++ b/packages/SystemUI/res-keyguard/values-hr/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • punjenje"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • brzo punjenje"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • sporo punjenje"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimiziranje radi zdravlja baterije"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Priključite punjač."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pritisnite Izbornik da biste otključali."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Mreža je zaključana"</string> diff --git a/packages/SystemUI/res-keyguard/values-hu/strings.xml b/packages/SystemUI/res-keyguard/values-hu/strings.xml index 4dcb22971979..e6c10d821cdb 100644 --- a/packages/SystemUI/res-keyguard/values-hu/strings.xml +++ b/packages/SystemUI/res-keyguard/values-hu/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Töltés"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Gyors töltés"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lassú töltés"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Az akkumulátor élettartamának optimalizálása…"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Csatlakoztassa a töltőt."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"A feloldáshoz nyomja meg a Menü gombot."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Hálózat zárolva"</string> diff --git a/packages/SystemUI/res-keyguard/values-hy/strings.xml b/packages/SystemUI/res-keyguard/values-hy/strings.xml index 354d93208f15..c8ed16d10327 100644 --- a/packages/SystemUI/res-keyguard/values-hy/strings.xml +++ b/packages/SystemUI/res-keyguard/values-hy/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Լիցքավորում"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Արագ լիցքավորում"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Դանդաղ լիցքավորում"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Օպտիմալացվում է մարտկոցի աշխատանքային հզորության համար"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Միացրեք լիցքավորիչը:"</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Ապակողպելու համար սեղմեք Ընտրացանկը:"</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Ցանցը կողպված է"</string> diff --git a/packages/SystemUI/res-keyguard/values-in/strings.xml b/packages/SystemUI/res-keyguard/values-in/strings.xml index d43823cea147..696f215c751e 100644 --- a/packages/SystemUI/res-keyguard/values-in/strings.xml +++ b/packages/SystemUI/res-keyguard/values-in/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya dengan cepat"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya dengan lambat"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengoptimalkan untuk kesehatan baterai"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Hubungkan pengisi daya."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Tekan Menu untuk membuka kunci."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Jaringan terkunci"</string> diff --git a/packages/SystemUI/res-keyguard/values-is/strings.xml b/packages/SystemUI/res-keyguard/values-is/strings.xml index 233402b33f26..3f3bec9b8c8c 100644 --- a/packages/SystemUI/res-keyguard/values-is/strings.xml +++ b/packages/SystemUI/res-keyguard/values-is/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Í hleðslu"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hröð hleðsla"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hæg hleðsla"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Fínstillir til að bæta rafhlöðuendingu"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Tengdu hleðslutækið."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Ýttu á valmyndarhnappinn til að taka úr lás."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Net læst"</string> diff --git a/packages/SystemUI/res-keyguard/values-it/strings.xml b/packages/SystemUI/res-keyguard/values-it/strings.xml index 87fd81cb1581..47d17ce57892 100644 --- a/packages/SystemUI/res-keyguard/values-it/strings.xml +++ b/packages/SystemUI/res-keyguard/values-it/strings.xml @@ -38,7 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • In carica"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ricarica veloce"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ricarica lenta"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Batteria momentaneamente limitata"</string> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • È in corso l\'ottimizzazione per l\'integrità della batteria"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Collega il caricabatterie."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Premi Menu per sbloccare."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rete bloccata"</string> diff --git a/packages/SystemUI/res-keyguard/values-iw/strings.xml b/packages/SystemUI/res-keyguard/values-iw/strings.xml index 6af70b4cebf3..8780dc5e3c01 100644 --- a/packages/SystemUI/res-keyguard/values-iw/strings.xml +++ b/packages/SystemUI/res-keyguard/values-iw/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה מהירה"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה איטית"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • מופעלת אופטימיזציה לשמירה על תקינות הסוללה"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"חבר את המטען."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"לחץ על \'תפריט\' כדי לבטל את הנעילה."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"הרשת נעולה"</string> diff --git a/packages/SystemUI/res-keyguard/values-ja/strings.xml b/packages/SystemUI/res-keyguard/values-ja/strings.xml index ab5a13c16bad..b4aea6182e65 100644 --- a/packages/SystemUI/res-keyguard/values-ja/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ja/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電中"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 急速充電中"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 低速充電中"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 電池の状態を最適化"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"充電してください。"</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"メニューからロックを解除できます。"</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"ネットワークがロックされました"</string> diff --git a/packages/SystemUI/res-keyguard/values-ka/strings.xml b/packages/SystemUI/res-keyguard/values-ka/strings.xml index b10ab615abd0..7e1e59b9f445 100644 --- a/packages/SystemUI/res-keyguard/values-ka/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ka/strings.xml @@ -38,7 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • იტენება"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • სწრაფად იტენება"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ნელა იტენება"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ბატარეა დროებით შეზღუდულია"</string> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ოპტიმიზაცია ბატარეის გამართულობისთვის"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"შეაერთეთ დამტენი."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"განსაბლოკად დააჭირეთ მენიუს."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"ქსელი ჩაკეტილია"</string> diff --git a/packages/SystemUI/res-keyguard/values-kk/strings.xml b/packages/SystemUI/res-keyguard/values-kk/strings.xml index c415bbbe1a72..b20cb05ea86f 100644 --- a/packages/SystemUI/res-keyguard/values-kk/strings.xml +++ b/packages/SystemUI/res-keyguard/values-kk/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарядталуда"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Жылдам зарядталуда"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Баяу зарядталуда"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Батареяның жұмыс істеу қабілеті оңтайландырылуда"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Зарядтағышты қосыңыз."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Ашу үшін \"Мәзір\" пернесін басыңыз."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Желі құлыптаулы"</string> diff --git a/packages/SystemUI/res-keyguard/values-km/strings.xml b/packages/SystemUI/res-keyguard/values-km/strings.xml index 1a278e8262c8..fb38bfd88bd4 100644 --- a/packages/SystemUI/res-keyguard/values-km/strings.xml +++ b/packages/SystemUI/res-keyguard/values-km/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុងសាកថ្ម"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុងសាកថ្មយ៉ាងឆាប់រហ័ស"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុងសាកថ្មយឺត"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុងបង្កើនប្រសិទ្ធភាពគុណភាពថ្ម"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"សូមសាកថ្មរបស់អ្នក។"</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ចុចម៉ឺនុយ ដើម្បីដោះសោ។"</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"បណ្ដាញជាប់សោ"</string> diff --git a/packages/SystemUI/res-keyguard/values-kn/strings.xml b/packages/SystemUI/res-keyguard/values-kn/strings.xml index 961fcec69853..a52712379776 100644 --- a/packages/SystemUI/res-keyguard/values-kn/strings.xml +++ b/packages/SystemUI/res-keyguard/values-kn/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ಚಾರ್ಜ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ವೇಗವಾಗಿ ಚಾರ್ಜ್ಮಾಡಲಾಗುತ್ತಿದೆ"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ನಿಧಾನವಾಗಿ ಚಾರ್ಜ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ಬ್ಯಾಟರಿಯ ಆರೋಗ್ಯಕ್ಕಾಗಿ ಆಪ್ಟಿಮೈಸ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"ನಿಮ್ಮ ಚಾರ್ಜರ್ ಸಂಪರ್ಕಗೊಳಿಸಿ."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ಅನ್ಲಾಕ್ ಮಾಡಲು ಮೆನು ಒತ್ತಿರಿ."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"ನೆಟ್ವರ್ಕ್ ಲಾಕ್ ಆಗಿದೆ"</string> diff --git a/packages/SystemUI/res-keyguard/values-ko/strings.xml b/packages/SystemUI/res-keyguard/values-ko/strings.xml index 2f93af920e17..7149cdf787b2 100644 --- a/packages/SystemUI/res-keyguard/values-ko/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ko/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 충전 중"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 고속 충전 중"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 저속 충전 중"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 배터리 상태 최적화 중"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"충전기를 연결하세요."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"잠금 해제하려면 메뉴를 누르세요."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"네트워크 잠김"</string> diff --git a/packages/SystemUI/res-keyguard/values-ky/strings.xml b/packages/SystemUI/res-keyguard/values-ky/strings.xml index 7e929199f1bc..5327c01e5471 100644 --- a/packages/SystemUI/res-keyguard/values-ky/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ky/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Кубатталууда"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Тез кубатталууда"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Жай кубатталууда"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Батареянын кубатын үнөмдөө иштетилди"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Кубаттагычка туташтырыңыз."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Кулпуну ачуу үчүн Менюну басыңыз."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Тармак кулпуланган"</string> diff --git a/packages/SystemUI/res-keyguard/values-lo/strings.xml b/packages/SystemUI/res-keyguard/values-lo/strings.xml index b96a2bb4aa4c..0f662c3c7f38 100644 --- a/packages/SystemUI/res-keyguard/values-lo/strings.xml +++ b/packages/SystemUI/res-keyguard/values-lo/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກ"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກແບບດ່ວນ"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກແບບຊ້າ"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງເພີ່ມປະສິດທິພາບເພື່ອສຸຂະພາບແບັດເຕີຣີ"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"ເຊື່ອມຕໍ່ສາຍສາກຂອງທ່ານ."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ກົດ \"ເມນູ\" ເພື່ອປົດລັອກ."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"ເຄືອຂ່າຍຖືກລັອກ"</string> diff --git a/packages/SystemUI/res-keyguard/values-lt/strings.xml b/packages/SystemUI/res-keyguard/values-lt/strings.xml index 773f7c42ebd1..cc8cdfd4ac1f 100644 --- a/packages/SystemUI/res-keyguard/values-lt/strings.xml +++ b/packages/SystemUI/res-keyguard/values-lt/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Įkraunama"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Greitai įkraunama"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lėtai įkraunama"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimizuojama siekiant apsaugoti akumuliatorių"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Prijunkite kroviklį."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Paspauskite meniu, jei norite atrakinti."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Tinklas užrakintas"</string> diff --git a/packages/SystemUI/res-keyguard/values-lv/strings.xml b/packages/SystemUI/res-keyguard/values-lv/strings.xml index 68bf4cde3086..d6fdfaf17e27 100644 --- a/packages/SystemUI/res-keyguard/values-lv/strings.xml +++ b/packages/SystemUI/res-keyguard/values-lv/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek uzlāde"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek ātrā uzlāde"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek lēnā uzlāde"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Akumulatora darbības optimizēšana"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Pievienojiet uzlādes ierīci."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Lai atbloķētu, nospiediet izvēlnes ikonu."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Tīkls ir bloķēts."</string> diff --git a/packages/SystemUI/res-keyguard/values-mk/strings.xml b/packages/SystemUI/res-keyguard/values-mk/strings.xml index e51f77488726..66744e797b9c 100644 --- a/packages/SystemUI/res-keyguard/values-mk/strings.xml +++ b/packages/SystemUI/res-keyguard/values-mk/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Се полни"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Брзо полнење"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Бавно полнење"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Се оптимизира за состојба на батерија"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Поврзете го полначот."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Притиснете „Мени“ за отклучување."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Мрежата е заклучена"</string> diff --git a/packages/SystemUI/res-keyguard/values-ml/strings.xml b/packages/SystemUI/res-keyguard/values-ml/strings.xml index 4b4391482833..66d0ac756bf5 100644 --- a/packages/SystemUI/res-keyguard/values-ml/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ml/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ചാർജ് ചെയ്യുന്നു"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • വേഗത്തിൽ ചാർജ് ചെയ്യുന്നു"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • പതുക്കെ ചാർജ് ചെയ്യുന്നു"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ബാറ്ററി നില ഒപ്റ്റിമൈസ് ചെയ്യുന്നു"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"നിങ്ങളുടെ ചാർജർ കണക്റ്റുചെയ്യുക."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"അൺലോക്കുചെയ്യാൻ മെനു അമർത്തുക."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"നെറ്റ്വർക്ക് ലോക്കുചെയ്തു"</string> diff --git a/packages/SystemUI/res-keyguard/values-mn/strings.xml b/packages/SystemUI/res-keyguard/values-mn/strings.xml index 4667252546c5..2ff4a22d6737 100644 --- a/packages/SystemUI/res-keyguard/values-mn/strings.xml +++ b/packages/SystemUI/res-keyguard/values-mn/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Цэнэглэж байна"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Хурдан цэнэглэж байна"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Удаан цэнэглэж байна"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Батарейн чанарыг оновчилж байна"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Цэнэглэгчээ холбоно уу."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Түгжээг тайлах бол цэсийг дарна уу."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Сүлжээ түгжигдсэн"</string> diff --git a/packages/SystemUI/res-keyguard/values-mr/strings.xml b/packages/SystemUI/res-keyguard/values-mr/strings.xml index bdd390475c4a..e2ffc6240c09 100644 --- a/packages/SystemUI/res-keyguard/values-mr/strings.xml +++ b/packages/SystemUI/res-keyguard/values-mr/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्ज होत आहे"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • वेगाने चार्ज होत आहे"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • सावकाश चार्ज होत आहे"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • बॅटरीची क्षमता वाढवण्यासाठी ऑप्टिमाइझ करत आहे"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"तुमचा चार्जर कनेक्ट करा."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"अनलॉक करण्यासाठी मेनू दाबा."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"नेटवर्क लॉक केले"</string> diff --git a/packages/SystemUI/res-keyguard/values-ms/strings.xml b/packages/SystemUI/res-keyguard/values-ms/strings.xml index a5179887ce5d..dcd460bf6c7a 100644 --- a/packages/SystemUI/res-keyguard/values-ms/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ms/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas dengan cepat"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas dengan perlahan"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pengoptimuman untuk kesihatan bateri"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Sambungkan pengecas anda."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Tekan Menu untuk membuka kunci."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rangkaian dikunci"</string> diff --git a/packages/SystemUI/res-keyguard/values-my/strings.xml b/packages/SystemUI/res-keyguard/values-my/strings.xml index 07f3d38aa8c8..bbeadd0cba13 100644 --- a/packages/SystemUI/res-keyguard/values-my/strings.xml +++ b/packages/SystemUI/res-keyguard/values-my/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • အားသွင်းနေသည်"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • အမြန်အားသွင်းနေသည်"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • နှေးကွေးစွာ အားသွင်းနေသည်"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ဘက်ထရီအခြေအနေကို အကောင်းဆုံးဖြစ်အောင် လုပ်နေသည်"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"အားသွင်းကိရိယာကို ချိတ်ဆက်ပါ။"</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"မီနူးကို နှိပ်၍ လော့ခ်ဖွင့်ပါ။"</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"ကွန်ရက်ကို လော့ခ်ချထားသည်"</string> diff --git a/packages/SystemUI/res-keyguard/values-nb/strings.xml b/packages/SystemUI/res-keyguard/values-nb/strings.xml index a391b9293c05..8a3045aa656e 100644 --- a/packages/SystemUI/res-keyguard/values-nb/strings.xml +++ b/packages/SystemUI/res-keyguard/values-nb/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader raskt"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader sakte"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimaliserer batteritilstanden"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Koble til en batterilader."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Trykk på menyknappen for å låse opp."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Nettverket er låst"</string> diff --git a/packages/SystemUI/res-keyguard/values-ne/strings.xml b/packages/SystemUI/res-keyguard/values-ne/strings.xml index 812aa38d4622..6f8a10885d5d 100644 --- a/packages/SystemUI/res-keyguard/values-ne/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ne/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्ज गरिँदै"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • द्रुत गतिमा चार्ज गरिँदै"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • मन्द गतिमा चार्ज गरिँदै"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ब्याट्री लामो समयसम्म टिक्ने बनाउन अप्टिमाइज गरिँदै छ"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"तपाईंको चार्जर जोड्नुहोस्।"</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"अनलक गर्न मेनु थिच्नुहोस्।"</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"नेटवर्क लक भएको छ"</string> diff --git a/packages/SystemUI/res-keyguard/values-nl/strings.xml b/packages/SystemUI/res-keyguard/values-nl/strings.xml index f1c2033baaa8..a9fd827442e6 100644 --- a/packages/SystemUI/res-keyguard/values-nl/strings.xml +++ b/packages/SystemUI/res-keyguard/values-nl/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Opladen"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Snel opladen"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Langzaam opladen"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimaliseren voor batterijduur"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Sluit de oplader aan."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Druk op Menu om te ontgrendelen."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Netwerk vergrendeld"</string> diff --git a/packages/SystemUI/res-keyguard/values-or/strings.xml b/packages/SystemUI/res-keyguard/values-or/strings.xml index be6e2856bd27..385c13b4bc0e 100644 --- a/packages/SystemUI/res-keyguard/values-or/strings.xml +++ b/packages/SystemUI/res-keyguard/values-or/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଚାର୍ଜ ହେଉଛି"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଦ୍ରୁତ ଭାବେ ଚାର୍ଜ ହେଉଛି"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଧୀରେ ଚାର୍ଜ ହେଉଛି"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ବ୍ୟାଟେରୀ ହେଲ୍ଥ ପାଇଁ ଅପ୍ଟିମାଇଜ୍ ହେଉଛି"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"ଆପଣଙ୍କ ଚାର୍ଜର୍ ସଂଯୋଗ କରନ୍ତୁ।"</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ଅନଲକ୍ କରିବା ପାଇଁ ମେନୁକୁ ଦବାନ୍ତୁ।"</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"ନେଟୱର୍କକୁ ଲକ୍ କରାଯାଇଛି"</string> diff --git a/packages/SystemUI/res-keyguard/values-pa/strings.xml b/packages/SystemUI/res-keyguard/values-pa/strings.xml index a6ea6aaf4162..43d549c92e6b 100644 --- a/packages/SystemUI/res-keyguard/values-pa/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pa/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਤੇਜ਼ੀ ਨਾਲ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਹੌਲੀ-ਹੌਲੀ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਬੈਟਰੀ ਸਥਿਤੀ ਲਈ ਅਨੁਕੂਲ ਬਣਾਇਆ ਜਾ ਰਿਹਾ"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"ਆਪਣਾ ਚਾਰਜਰ ਕਨੈਕਟ ਕਰੋ।"</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ਅਣਲਾਕ ਕਰਨ ਲਈ \"ਮੀਨੂ\" ਦਬਾਓ।"</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"ਨੈੱਟਵਰਕ ਲਾਕ ਕੀਤਾ ਗਿਆ"</string> diff --git a/packages/SystemUI/res-keyguard/values-pl/strings.xml b/packages/SystemUI/res-keyguard/values-pl/strings.xml index 9c6f27118600..76f755c2b96a 100644 --- a/packages/SystemUI/res-keyguard/values-pl/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pl/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ładowanie"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Szybkie ładowanie"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wolne ładowanie"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optymalizuję, by utrzymać baterię w dobrym stanie"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Podłącz ładowarkę."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Naciśnij Menu, aby odblokować."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Sieć zablokowana"</string> diff --git a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml index d2d5fb9d159a..29c46f8a592d 100644 --- a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml @@ -38,7 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando rapidamente"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando lentamente"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bateria limitada temporariamente"</string> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Otimizando para integridade da bateria"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Conecte o seu carregador."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pressione Menu para desbloquear."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rede bloqueada"</string> diff --git a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml index 7f0a4d883ee5..b15c9dc20772 100644 --- a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml @@ -38,7 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar…"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar rapidamente…"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar lentamente…"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bateria limitada temporariamente."</string> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A otimizar o estado da bateria"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Ligue o carregador."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Prima Menu para desbloquear."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rede bloqueada"</string> diff --git a/packages/SystemUI/res-keyguard/values-pt/strings.xml b/packages/SystemUI/res-keyguard/values-pt/strings.xml index d2d5fb9d159a..29c46f8a592d 100644 --- a/packages/SystemUI/res-keyguard/values-pt/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pt/strings.xml @@ -38,7 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando rapidamente"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando lentamente"</string> - <string name="keyguard_plugged_in_charging_limited" msgid="8190982388514496109">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bateria limitada temporariamente"</string> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Otimizando para integridade da bateria"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Conecte o seu carregador."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pressione Menu para desbloquear."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rede bloqueada"</string> diff --git a/packages/SystemUI/res-keyguard/values-ro/strings.xml b/packages/SystemUI/res-keyguard/values-ro/strings.xml index 572c1dbd0830..868d9f770980 100644 --- a/packages/SystemUI/res-keyguard/values-ro/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ro/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă rapid"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă lent"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se fac optimizări pentru buna funcționare a bateriei"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Conectați încărcătorul."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Apăsați pe Meniu pentru a debloca."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rețea blocată"</string> diff --git a/packages/SystemUI/res-keyguard/values-ru/strings.xml b/packages/SystemUI/res-keyguard/values-ru/strings.xml index 2c87608f9b9b..24d762d00f5e 100644 --- a/packages/SystemUI/res-keyguard/values-ru/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ru/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"Идет зарядка (<xliff:g id="PERCENTAGE">%s</xliff:g>)"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"Идет быстрая зарядка (<xliff:g id="PERCENTAGE">%s</xliff:g>)"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"Идет медленная зарядка (<xliff:g id="PERCENTAGE">%s</xliff:g>)"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Оптимизация для увеличения срока службы батареи"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Подключите зарядное устройство."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Для разблокировки нажмите \"Меню\"."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Сеть заблокирована"</string> diff --git a/packages/SystemUI/res-keyguard/values-si/strings.xml b/packages/SystemUI/res-keyguard/values-si/strings.xml index 8682192ce32a..3a6078224be2 100644 --- a/packages/SystemUI/res-keyguard/values-si/strings.xml +++ b/packages/SystemUI/res-keyguard/values-si/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ආරෝපණය වෙමින්"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • වේගයෙන් ආරෝපණය වෙමින්"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • සෙමින් ආරෝපණය වෙමින්"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • බැටරි සෞඛ්යය සඳහා ප්රශස්ත කරමින්"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"ඔබගේ ආරෝපකයට සම්බන්ධ කරන්න."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"අගුලු හැරීමට මෙනුව ඔබන්න."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"ජාලය අගුළු දමා ඇත"</string> diff --git a/packages/SystemUI/res-keyguard/values-sk/strings.xml b/packages/SystemUI/res-keyguard/values-sk/strings.xml index d5e6093b1a83..98aa79a206f8 100644 --- a/packages/SystemUI/res-keyguard/values-sk/strings.xml +++ b/packages/SystemUI/res-keyguard/values-sk/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa rýchlo"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa pomaly"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimalizuje sa na zaistenie dobrého stavu batérie"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Pripojte nabíjačku."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Odomknete stlačením tlačidla ponuky."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Sieť je zablokovaná"</string> diff --git a/packages/SystemUI/res-keyguard/values-sl/strings.xml b/packages/SystemUI/res-keyguard/values-sl/strings.xml index 82d5c5493010..cd41d9b76ebb 100644 --- a/packages/SystemUI/res-keyguard/values-sl/strings.xml +++ b/packages/SystemUI/res-keyguard/values-sl/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • polnjenje"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • hitro polnjenje"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • počasno polnjenje"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimizacija za ohranjanje zmogljivosti baterije"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Priključite napajalnik."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Če želite odkleniti, pritisnite meni."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Omrežje je zaklenjeno"</string> diff --git a/packages/SystemUI/res-keyguard/values-sq/strings.xml b/packages/SystemUI/res-keyguard/values-sq/strings.xml index a67413fdf5c2..0ad97a490a26 100644 --- a/packages/SystemUI/res-keyguard/values-sq/strings.xml +++ b/packages/SystemUI/res-keyguard/values-sq/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet me shpejtësi"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet ngadalë"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po optimizohet për integritetin e baterisë"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Lidh karikuesin."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Shtyp \"Meny\" për të shkyçur."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rrjeti është i kyçur"</string> diff --git a/packages/SystemUI/res-keyguard/values-sr/strings.xml b/packages/SystemUI/res-keyguard/values-sr/strings.xml index dec31650308e..90b8a3e362fd 100644 --- a/packages/SystemUI/res-keyguard/values-sr/strings.xml +++ b/packages/SystemUI/res-keyguard/values-sr/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Пуни се"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Брзо се пуни"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Споро се пуни"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Оптимизује се ради доброг стања батерије"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Прикључите пуњач."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Притисните Мени да бисте откључали."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Мрежа је закључана"</string> diff --git a/packages/SystemUI/res-keyguard/values-sv/strings.xml b/packages/SystemUI/res-keyguard/values-sv/strings.xml index 3ef2dfe87e88..80323e6e381d 100644 --- a/packages/SystemUI/res-keyguard/values-sv/strings.xml +++ b/packages/SystemUI/res-keyguard/values-sv/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas snabbt"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas långsamt"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Optimerar batteriets livslängd"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Anslut laddaren."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Lås upp genom att trycka på Meny."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Nätverk låst"</string> diff --git a/packages/SystemUI/res-keyguard/values-sw/strings.xml b/packages/SystemUI/res-keyguard/values-sw/strings.xml index 5c5fc10fe77e..da352620aace 100644 --- a/packages/SystemUI/res-keyguard/values-sw/strings.xml +++ b/packages/SystemUI/res-keyguard/values-sw/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji kwa kasi"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji pole pole"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inaboresha muda wa kutumia betri"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Unganisha chaja yako."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Bonyeza Menyu ili kufungua."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Mtandao umefungwa"</string> diff --git a/packages/SystemUI/res-keyguard/values-ta/strings.xml b/packages/SystemUI/res-keyguard/values-ta/strings.xml index c188301bb7ed..ca9257707b69 100644 --- a/packages/SystemUI/res-keyguard/values-ta/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ta/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • சார்ஜாகிறது"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • வேகமாகச் சார்ஜாகிறது"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • மெதுவாகச் சார்ஜாகிறது"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • பேட்டரியின் ஆயுளை மேம்படுத்துகிறது"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"சார்ஜரை இணைக்கவும்."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"திறக்க, மெனுவை அழுத்தவும்."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"நெட்வொர்க் பூட்டப்பட்டது"</string> diff --git a/packages/SystemUI/res-keyguard/values-te/strings.xml b/packages/SystemUI/res-keyguard/values-te/strings.xml index 27a5b285c485..c69a8f56b933 100644 --- a/packages/SystemUI/res-keyguard/values-te/strings.xml +++ b/packages/SystemUI/res-keyguard/values-te/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ఛార్జ్ అవుతోంది"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • వేగంగా ఛార్జ్ అవుతోంది"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • నెమ్మదిగా ఛార్జ్ అవుతోంది"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • బ్యాటరీ జీవితకాలాన్ని ఆప్టిమైజ్ చేయడం కోసం"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"మీ ఛార్జర్ను కనెక్ట్ చేయండి."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"అన్లాక్ చేయడానికి మెనుని నొక్కండి."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"నెట్వర్క్ లాక్ చేయబడింది"</string> diff --git a/packages/SystemUI/res-keyguard/values-th/strings.xml b/packages/SystemUI/res-keyguard/values-th/strings.xml index e506745d637e..4fd3dd177469 100644 --- a/packages/SystemUI/res-keyguard/values-th/strings.xml +++ b/packages/SystemUI/res-keyguard/values-th/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จ"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จอย่างเร็ว"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จอย่างช้าๆ"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังเพิ่มประสิทธิภาพแบตเตอรี่"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"เสียบที่ชาร์จของคุณ"</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"กด \"เมนู\" เพื่อปลดล็อก"</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"เครือข่ายถูกล็อก"</string> diff --git a/packages/SystemUI/res-keyguard/values-tl/strings.xml b/packages/SystemUI/res-keyguard/values-tl/strings.xml index 912fd9529f09..8f26ea97bb61 100644 --- a/packages/SystemUI/res-keyguard/values-tl/strings.xml +++ b/packages/SystemUI/res-keyguard/values-tl/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nagcha-charge"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mabilis na nagcha-charge"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mabagal na nagcha-charge"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ino-optimize para sa tagal ng baterya"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Ikonekta ang iyong charger."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pindutin ang Menu upang i-unlock."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Naka-lock ang network"</string> diff --git a/packages/SystemUI/res-keyguard/values-tr/strings.xml b/packages/SystemUI/res-keyguard/values-tr/strings.xml index 5390c4c5c4eb..53a1cc7f8608 100644 --- a/packages/SystemUI/res-keyguard/values-tr/strings.xml +++ b/packages/SystemUI/res-keyguard/values-tr/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Şarj oluyor"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hızlı şarj oluyor"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Yavaş şarj oluyor"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pil sağlığı için optimize ediliyor"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Şarj cihazınızı takın."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Kilidi açmak için Menü\'ye basın."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Ağ kilitli"</string> diff --git a/packages/SystemUI/res-keyguard/values-uk/strings.xml b/packages/SystemUI/res-keyguard/values-uk/strings.xml index 6263d79fd645..a16576d37e9c 100644 --- a/packages/SystemUI/res-keyguard/values-uk/strings.xml +++ b/packages/SystemUI/res-keyguard/values-uk/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Заряджання"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Швидке заряджання"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Повільне заряджання"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Стан акумулятора оптимізується"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Підключіть зарядний пристрій."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Натисніть меню, щоб розблокувати."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Мережу заблоковано"</string> diff --git a/packages/SystemUI/res-keyguard/values-ur/strings.xml b/packages/SystemUI/res-keyguard/values-ur/strings.xml index bf936cb86b51..a14f20df45d1 100644 --- a/packages/SystemUI/res-keyguard/values-ur/strings.xml +++ b/packages/SystemUI/res-keyguard/values-ur/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • چارج ہو رہا ہے"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • تیزی سے چارج ہو رہا ہے"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • آہستہ چارج ہو رہا ہے"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • بیٹری کی صحت کے لیے بہتر بنایا جا رہا ہے"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"اپنا چارجر منسلک کریں۔"</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"غیر مقفل کرنے کیلئے مینو دبائیں۔"</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"نیٹ ورک مقفل ہو گیا"</string> diff --git a/packages/SystemUI/res-keyguard/values-uz/strings.xml b/packages/SystemUI/res-keyguard/values-uz/strings.xml index 0b23e16ddd2f..24a14c73d006 100644 --- a/packages/SystemUI/res-keyguard/values-uz/strings.xml +++ b/packages/SystemUI/res-keyguard/values-uz/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Quvvat olmoqda"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Tezkor quvvat olmoqda"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sekin quvvat olmoqda"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Batareya quvvati muvozanatlanmoqda"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Quvvatlash moslamasini ulang."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Qulfdan chiqarish uchun Menyu tugmasini bosing."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Tarmoq qulflangan"</string> diff --git a/packages/SystemUI/res-keyguard/values-vi/strings.xml b/packages/SystemUI/res-keyguard/values-vi/strings.xml index 9357eba66432..32210664d383 100644 --- a/packages/SystemUI/res-keyguard/values-vi/strings.xml +++ b/packages/SystemUI/res-keyguard/values-vi/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc nhanh"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc chậm"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang tối ưu hóa để cải thiện độ bền của pin"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Kết nối bộ sạc của bạn."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Nhấn vào Menu để mở khóa."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Mạng đã bị khóa"</string> diff --git a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml index 96728ab6cead..a3921d0a5657 100644 --- a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在充电"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在快速充电"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在慢速充电"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在针对电池状况进行优化"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"请连接充电器。"</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"按“菜单”即可解锁。"</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"网络已锁定"</string> diff --git a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml index c683529d81ac..1054e36fc048 100644 --- a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在充電"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在快速充電"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> •正在慢速充電"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在優化電池狀態"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"請連接充電器。"</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"按下 [選單] 即可解鎖。"</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"網絡已鎖定"</string> diff --git a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml index 7a3b5c52acf7..7efa2f934d95 100644 --- a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電中"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 快速充電中"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 慢速充電中"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 針對電池狀態進行最佳化調整"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"請連接充電器。"</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"按選單鍵解鎖。"</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"網路已鎖定"</string> diff --git a/packages/SystemUI/res-keyguard/values-zu/strings.xml b/packages/SystemUI/res-keyguard/values-zu/strings.xml index ec38cbef456e..d87622af27bf 100644 --- a/packages/SystemUI/res-keyguard/values-zu/strings.xml +++ b/packages/SystemUI/res-keyguard/values-zu/strings.xml @@ -38,8 +38,7 @@ <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Iyashaja"</string> <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ishaja kaningi"</string> <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ishaja kancane"</string> - <!-- no translation found for keyguard_plugged_in_charging_limited (8190982388514496109) --> - <skip /> + <string name="keyguard_plugged_in_charging_limited" msgid="1158086783302116604">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ilungiselela impilo yebhethri"</string> <string name="keyguard_low_battery" msgid="1868012396800230904">"Xhuma ishaja yakho."</string> <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Chofoza Menyu ukuvula."</string> <string name="keyguard_network_locked_message" msgid="407096292844868608">"Inethiwekhi ivaliwe"</string> diff --git a/packages/SystemUI/res/color/camera_foreground.xml b/packages/SystemUI/res/color/camera_foreground.xml new file mode 100644 index 000000000000..6e039cc1df1e --- /dev/null +++ b/packages/SystemUI/res/color/camera_foreground.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright 2010, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:state_enabled="false" + android:color="@color/control_default_foreground" /> + <item android:color="@color/GM2_grey_100" /> +</selector> diff --git a/packages/SystemUI/res/drawable/brightness_mirror_background.xml b/packages/SystemUI/res/drawable/brightness_mirror_background.xml index 02261b275eb4..4b225b763f3e 100644 --- a/packages/SystemUI/res/drawable/brightness_mirror_background.xml +++ b/packages/SystemUI/res/drawable/brightness_mirror_background.xml @@ -15,6 +15,6 @@ ~ limitations under the License --> <shape xmlns:android="http://schemas.android.com/apk/res/android"> - <solid android:color="?android:attr/colorBackground" /> + <solid android:color="?android:attr/colorBackgroundFloating" /> <corners android:radius="8dp" /> </shape> diff --git a/packages/SystemUI/res/drawable/brightness_progress_drawable_thick.xml b/packages/SystemUI/res/drawable/brightness_progress_drawable_thick.xml index ca56ec17014b..108591beb05a 100644 --- a/packages/SystemUI/res/drawable/brightness_progress_drawable_thick.xml +++ b/packages/SystemUI/res/drawable/brightness_progress_drawable_thick.xml @@ -16,6 +16,27 @@ --> <layer-list xmlns:android="http://schemas.android.com/apk/res/android" android:paddingMode="stack"> + <item android:id="@android:id/background" + android:gravity="center_vertical|fill_horizontal"> + <layer-list > + <item> + <shape + android:tint="?android:attr/colorControlActivated" + android:alpha="?android:attr/disabledAlpha"> + <size android:height="48dp" /> + <solid android:color="@color/white_disabled" /> + <corners android:radius="24dp" /> + </shape> + </item> + <item + android:gravity="center_vertical|start" + android:start="32dp"> + <com.android.systemui.util.AlphaTintDrawableWrapper + android:drawable="@drawable/ic_brightness" + android:tint="?android:attr/colorControlActivated" /> + </item> + </layer-list> + </item> <item android:id="@android:id/progress" android:gravity="center_vertical|fill_horizontal"> <clip @@ -24,13 +45,4 @@ android:gravity="left" /> </item> - <item android:id="@android:id/background" - android:gravity="center_vertical|fill_horizontal"> - <shape android:shape="rectangle" - android:tint="?android:attr/colorControlNormal"> - <size android:height="48dp" /> - <solid android:color="@color/white_disabled" /> - <corners android:radius="24dp" /> - </shape> - </item> </layer-list>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml b/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml index a38b8b4e62db..b5def5ebf539 100644 --- a/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml +++ b/packages/SystemUI/res/drawable/brightness_progress_full_drawable.xml @@ -15,10 +15,21 @@ ~ limitations under the License. --> -<shape xmlns:android="http://schemas.android.com/apk/res/android" - android:shape="rectangle" - android:tint="?android:attr/colorControlActivated"> - <size android:height="48dp" /> - <solid android:color="@android:color/white" /> - <corners android:radius="24dp"/> -</shape>
\ No newline at end of file +<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@+id/slider_foreground"> + <shape> + <size android:height="48dp" /> + <solid android:color="?android:attr/colorControlActivated" /> + <corners android:radius="24dp"/> + </shape> + </item> + <item + android:id="@+id/slider_icon" + android:gravity="center_vertical|start" + android:start="32dp"> + <com.android.systemui.util.AlphaTintDrawableWrapper + android:drawable="@drawable/ic_brightness" + android:tint="?android:attr/colorBackground" + android:alpha="0.8"/> + </item> +</layer-list>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/qs_customizer_background_primary.xml b/packages/SystemUI/res/drawable/qs_customizer_background_primary.xml index 215dee41d548..c2d0841a1b8f 100644 --- a/packages/SystemUI/res/drawable/qs_customizer_background_primary.xml +++ b/packages/SystemUI/res/drawable/qs_customizer_background_primary.xml @@ -15,7 +15,7 @@ --> <inset xmlns:android="http://schemas.android.com/apk/res/android"> <shape> - <solid android:color="@color/qs_customize_background"/> + <solid android:color="?android:attr/colorBackgroundFloating"/> <corners android:radius="?android:attr/dialogCornerRadius" /> </shape> </inset> diff --git a/packages/SystemUI/res/drawable/qs_customizer_toolbar.xml b/packages/SystemUI/res/drawable/qs_customizer_toolbar.xml index 648d45b4f903..7cb44b3e1500 100644 --- a/packages/SystemUI/res/drawable/qs_customizer_toolbar.xml +++ b/packages/SystemUI/res/drawable/qs_customizer_toolbar.xml @@ -15,7 +15,7 @@ --> <inset xmlns:android="http://schemas.android.com/apk/res/android"> <shape> - <solid android:color="@color/qs_customize_background"/> + <solid android:color="?android:attr/colorBackgroundFloating"/> <corners android:topLeftRadius="?android:attr/dialogCornerRadius" android:topRightRadius="?android:attr/dialogCornerRadius" /> diff --git a/packages/SystemUI/res/drawable/qs_detail_background.xml b/packages/SystemUI/res/drawable/qs_detail_background.xml index 672abf14774e..76045e4126cb 100644 --- a/packages/SystemUI/res/drawable/qs_detail_background.xml +++ b/packages/SystemUI/res/drawable/qs_detail_background.xml @@ -25,7 +25,7 @@ Copyright (C) 2014 The Android Open Source Project <item> <inset> <shape> - <solid android:color="?android:attr/colorPrimary"/> + <solid android:color="?android:attr/colorBackgroundFloating"/> <corners android:radius="?android:attr/dialogCornerRadius" /> </shape> </inset> diff --git a/packages/SystemUI/res/layout-sw600dp-land/global_actions_grid_v2.xml b/packages/SystemUI/res/layout-sw600dp-land/global_actions_grid_v2.xml new file mode 100644 index 000000000000..953a29e3a07e --- /dev/null +++ b/packages/SystemUI/res/layout-sw600dp-land/global_actions_grid_v2.xml @@ -0,0 +1,68 @@ +<?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:id="@+id/global_actions_container" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="horizontal"> + + <LinearLayout + android:layout_weight="1" + android:layout_height="match_parent" + android:layout_width="0dp" + android:clipChildren="false" + android:orientation="vertical" + android:clipToPadding="false" + android:id="@+id/controls_pane" + > + <LinearLayout + android:id="@+id/global_actions_controls" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"/> + </LinearLayout> + + <LinearLayout + android:layout_weight="1" + android:layout_height="match_parent" + android:layout_width="0dp" + android:orientation="vertical" + android:id="@+id/nfc_pane" + > + <include layout="@layout/global_actions_view" /> + + <include layout="@layout/global_actions_lock_view" /> + + <LinearLayout + android:id="@+id/global_actions_grid_root" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:clipChildren="false" + android:orientation="vertical" + android:clipToPadding="false"> + + <FrameLayout + android:id="@+id/global_actions_wallet" + android:layout_width="match_parent" + android:layout_height="wrap_content"/> + + </LinearLayout> + + </LinearLayout> +</LinearLayout> diff --git a/packages/SystemUI/res/layout-sw600dp/global_actions_controls_list_view.xml b/packages/SystemUI/res/layout-sw600dp/global_actions_controls_list_view.xml new file mode 100644 index 000000000000..ef49b9c3b6ad --- /dev/null +++ b/packages/SystemUI/res/layout-sw600dp/global_actions_controls_list_view.xml @@ -0,0 +1,30 @@ +<!-- + ~ Copyright (C) 2020 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<com.android.systemui.globalactions.MinHeightScrollView + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + android:scrollbars="none"> + <LinearLayout + android:id="@+id/global_actions_controls_list" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:layout_marginLeft="@dimen/global_actions_side_margin" + android:layout_marginRight="@dimen/global_actions_side_margin" /> +</com.android.systemui.globalactions.MinHeightScrollView>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout-sw600dp/global_actions_grid_v2.xml b/packages/SystemUI/res/layout-sw600dp/global_actions_grid_v2.xml new file mode 100644 index 000000000000..6ffcef7b24e6 --- /dev/null +++ b/packages/SystemUI/res/layout-sw600dp/global_actions_grid_v2.xml @@ -0,0 +1,76 @@ +<?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:id="@+id/global_actions_container" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <LinearLayout + android:layout_weight="1" + android:layout_height="0dp" + android:layout_width="match_parent" + android:orientation="vertical" + android:id="@+id/nfc_pane" + > + + <include layout="@layout/global_actions_view" /> + + <include layout="@layout/global_actions_lock_view" /> + + + <com.android.systemui.globalactions.MinHeightScrollView + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + android:scrollbars="none"> + + <LinearLayout + android:id="@+id/global_actions_grid_root" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:clipChildren="false" + android:orientation="vertical" + android:clipToPadding="false"> + + <FrameLayout + android:id="@+id/global_actions_wallet" + android:layout_width="match_parent" + android:layout_height="wrap_content"/> + + </LinearLayout> + </com.android.systemui.globalactions.MinHeightScrollView> + + </LinearLayout> + + <LinearLayout + android:layout_weight="1" + android:layout_height="0dp" + android:layout_width="match_parent" + android:orientation="vertical" + android:id="@+id/controls_pane" + android:clipToPadding="false" + android:clipChildren="false"> + <LinearLayout + android:id="@+id/global_actions_controls" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"/> + </LinearLayout> +</LinearLayout> diff --git a/packages/SystemUI/res/layout/controls_with_favorites.xml b/packages/SystemUI/res/layout/controls_with_favorites.xml index 065ff68774eb..b060afdc18e3 100644 --- a/packages/SystemUI/res/layout/controls_with_favorites.xml +++ b/packages/SystemUI/res/layout/controls_with_favorites.xml @@ -58,11 +58,5 @@ android:background="?android:attr/selectableItemBackgroundBorderless" /> </LinearLayout> - <LinearLayout - android:id="@+id/global_actions_controls_list" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical" - android:layout_marginLeft="@dimen/global_actions_side_margin" - android:layout_marginRight="@dimen/global_actions_side_margin" /> + <include layout="@layout/global_actions_controls_list_view" /> </merge> diff --git a/packages/SystemUI/res/layout/feedback_info.xml b/packages/SystemUI/res/layout/feedback_info.xml index 753f56a18348..e013a4ebd26f 100644 --- a/packages/SystemUI/res/layout/feedback_info.xml +++ b/packages/SystemUI/res/layout/feedback_info.xml @@ -24,18 +24,18 @@ android:clipChildren="false" android:clipToPadding="false" android:orientation="vertical" - android:paddingStart="@*android:dimen/notification_content_margin_start" - android:paddingEnd="@*android:dimen/notification_content_margin_end" - android:background="?android:attr/colorBackground" - android:theme="@*android:style/Theme.DeviceDefault.Light"> + android:paddingStart="@dimen/notification_shade_content_margin_horizontal" + android:paddingEnd="@dimen/notification_shade_content_margin_horizontal" + android:background="?android:attr/colorBackground"> <!-- Package Info --> <LinearLayout android:id="@+id/header" android:layout_width="match_parent" - android:layout_height="@dimen/notification_guts_conversation_header_height" + android:layout_height="wrap_content" android:gravity="center_vertical" android:clipChildren="false" + android:paddingTop="@dimen/notification_guts_header_top_padding" android:clipToPadding="false"> <ImageView android:id="@+id/pkg_icon" @@ -49,7 +49,6 @@ android:layout_weight="1" android:layout_width="0dp" android:orientation="vertical" - android:layout_height="wrap_content" android:minHeight="@dimen/notification_guts_conversation_icon_size" android:layout_centerVertical="true" @@ -63,10 +62,11 @@ android:orientation="horizontal"> <TextView android:id="@+id/pkg_name" - android:layout_width="wrap_content" + android:layout_width="match_parent" android:layout_height="wrap_content" - style="@style/TextAppearance.NotificationImportanceChannelGroup" + style="@style/TextAppearance.NotificationImportanceApp" android:ellipsize="end" + android:textDirection="locale" android:maxLines="1"/> </LinearLayout> </LinearLayout> @@ -76,8 +76,7 @@ android:id="@+id/prompt" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginTop="@*android:dimen/notification_header_padding_top" - style="@style/TextAppearance.NotificationInfo.Secondary" /> + android:layout_marginTop="@*android:dimen/notification_header_padding_top" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" diff --git a/packages/SystemUI/res/layout/global_actions_controls_list_view.xml b/packages/SystemUI/res/layout/global_actions_controls_list_view.xml new file mode 100644 index 000000000000..e1c2611cc4d4 --- /dev/null +++ b/packages/SystemUI/res/layout/global_actions_controls_list_view.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/global_actions_controls_list" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:layout_marginLeft="@dimen/global_actions_side_margin" + android:layout_marginRight="@dimen/global_actions_side_margin" />
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/global_actions_grid_item_v2.xml b/packages/SystemUI/res/layout/global_actions_grid_item_v2.xml index 99b9ced53090..14a5e584a06d 100644 --- a/packages/SystemUI/res/layout/global_actions_grid_item_v2.xml +++ b/packages/SystemUI/res/layout/global_actions_grid_item_v2.xml @@ -18,7 +18,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="0dp" android:layout_weight="1" - android:layout_height="98dp" + android:layout_height="@dimen/global_actions_grid_item_layout_height" android:gravity="bottom|center_horizontal" android:orientation="vertical" android:paddingTop="12dp" diff --git a/packages/SystemUI/res/layout/quick_settings_brightness_dialog_thick.xml b/packages/SystemUI/res/layout/quick_settings_brightness_dialog_thick.xml index e08b44af1068..4f4b2af09799 100644 --- a/packages/SystemUI/res/layout/quick_settings_brightness_dialog_thick.xml +++ b/packages/SystemUI/res/layout/quick_settings_brightness_dialog_thick.xml @@ -14,10 +14,10 @@ limitations under the License. --> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_height="wrap_content" - android:layout_width="match_parent" - android:layout_gravity="center" - style="@style/BrightnessDialogContainer"> + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:layout_gravity="center" + style="@style/BrightnessDialogContainer"> <com.android.systemui.settings.brightness.BrightnessSliderView android:id="@+id/brightness_slider" @@ -38,16 +38,5 @@ android:progressDrawable="@drawable/brightness_progress_drawable_thick" android:splitTrack="false" /> - - <ImageView - android:id="@+id/image" - android:layout_width="24dp" - android:layout_height="24dp" - android:layout_marginLeft="48dp" - android:layout_gravity="center_vertical" - android:src="@drawable/ic_brightness" - android:tint="?android:attr/textColorTertiary" - android:visibility="visible" - /> </com.android.systemui.settings.brightness.BrightnessSliderView> </FrameLayout> diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index 1fab4780a4c1..ce47ed8dcfe7 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Skermkiekie is gestoor"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Tik om jou skermkiekie te bekyk"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Kon nie skermkiekie stoor nie"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Toestel moet ontsluit word voordat skermkiekie gestoor kan word"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Probeer weer skermkiekie neem"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Kan weens beperkte bergingspasie nie skermkiekie stoor nie"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Die program of jou organisasie laat nie toe dat skermkiekies geneem word nie"</string> diff --git a/packages/SystemUI/res/values-af/strings_tv.xml b/packages/SystemUI/res/values-af/strings_tv.xml index eb6316502e2d..2e9400e2e5b6 100644 --- a/packages/SystemUI/res/values-af/strings_tv.xml +++ b/packages/SystemUI/res/values-af/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN is gekoppel"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN is ontkoppel"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Kennisgewings"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Geen kennisgewings nie"</string> </resources> diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index 5153904f3e02..2573175f080a 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"ቅጽበታዊ ገጽ እይታ ተቀምጧል"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"የእርስዎን ቅጽበታዊ ገጽ እይታ ለማየት መታ ያድርጉ"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"ቅጽበታዊ ገጽ ዕይታን ማስቀመጥ አልተቻለም"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ቅጽበታዊ ገጽ እይታ ከመቀመጡ በፊት መሳሪያ መከፈት አለበት"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ቅጽበታዊ ገጽ ዕይታን እንደገና ማንሳት ይሞክሩ"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"ባለው ውሱን የማከማቻ ቦታ ምክንያት ቅጽበታዊ ገጽ ዕይታን ማስቀመጥ አይችልም"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ቅጽበታዊ ገጽ እይታዎችን ማንሳት በመተግበሪያው ወይም በእርስዎ ድርጅት አይፈቀድም"</string> diff --git a/packages/SystemUI/res/values-am/strings_tv.xml b/packages/SystemUI/res/values-am/strings_tv.xml index 3ba5a62a52d6..71d887d09752 100644 --- a/packages/SystemUI/res/values-am/strings_tv.xml +++ b/packages/SystemUI/res/values-am/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ተያይዟል"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ተቋርቷል"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"በ<xliff:g id="VPN_APP">%1$s</xliff:g> በኩል"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"ማሳወቂያዎች"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"ምንም ማሳወቂያዎች የሉም"</string> </resources> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index f6a1cf5e711b..f0d0b84ba087 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"تم حفظ لقطة الشاشة."</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"انقر لعرض لقطة الشاشة."</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"تعذّر حفظ لقطة الشاشة"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"يجب أن يتم فتح قفل الجهاز قبل حفظ لقطة الشاشة."</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"جرّب أخذ لقطة الشاشة مرة أخرى"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"يتعذر حفظ لقطة الشاشة لأن مساحة التخزين المتاحة محدودة."</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"يحظر التطبيق أو تحظر مؤسستك التقاط لقطات شاشة"</string> diff --git a/packages/SystemUI/res/values-ar/strings_tv.xml b/packages/SystemUI/res/values-ar/strings_tv.xml index 15ccb94a04a8..7297c898f99a 100644 --- a/packages/SystemUI/res/values-ar/strings_tv.xml +++ b/packages/SystemUI/res/values-ar/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"الشبكة الافتراضية الخاصة (VPN) متصلة."</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"الشبكة الافتراضية الخاصة (VPN) غير متصلة."</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"عبر <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"الإشعارات"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"ما من إشعارات"</string> </resources> diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml index b84f40972af5..366a86f571b5 100644 --- a/packages/SystemUI/res/values-as/strings.xml +++ b/packages/SystemUI/res/values-as/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"স্ক্ৰীণশ্বট ছেভ কৰা হ’ল"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"আপোনাৰ স্ক্ৰীণশ্বট চাবলৈ টিপক"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"স্ক্ৰীণশ্বট ছেভ কৰিব পৰা নগ\'ল"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"স্ক্ৰীনশ্বট ছেভ কৰিবলৈ ডিভাইচটো আনলক কৰিবই লাগিব"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"স্ক্ৰীণশ্বট আকৌ ল\'বলৈ চেষ্টা কৰক"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"সঞ্চয়াগাৰত সীমিত খালী ঠাই থকাৰ বাবে স্ক্ৰীণশ্বট ছেভ কৰিব পৰা নগ\'ল"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"এপটোৱে বা আপোনাৰ প্ৰতিষ্ঠানে স্ক্ৰীণশ্বট ল\'বলৈ অনুমতি নিদিয়ে"</string> @@ -935,7 +936,7 @@ <string name="notification_channel_general" msgid="4384774889645929705">"সাধাৰণ বার্তাসমূহ"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"সঞ্চয়াগাৰ"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"ইংগিতবোৰ"</string> - <string name="instant_apps" msgid="8337185853050247304">"তাৎক্ষণিক এপসমূহ"</string> + <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> চলি আছে"</string> <string name="instant_apps_message" msgid="6112428971833011754">"ইনষ্ট\'ল নকৰাকৈয়েই এপটো খোলা হৈছে।"</string> <string name="instant_apps_message_with_help" msgid="1816952263531203932">"ইনষ্ট\'ল নকৰাকৈয়েই এপটো খোলা হৈছে। অধিক জানিবলৈ টিপক।"</string> diff --git a/packages/SystemUI/res/values-as/strings_tv.xml b/packages/SystemUI/res/values-as/strings_tv.xml index f7afcfa5c6dc..859ea2c65093 100644 --- a/packages/SystemUI/res/values-as/strings_tv.xml +++ b/packages/SystemUI/res/values-as/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"ভিপিএন সংযোগ হৈ আছে"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"ভিপিএনৰ সংযোগ বিচ্ছিন্ন হৈছে"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>ৰ জৰিয়তে"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"জাননী"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"কোনো জাননী নাই"</string> </resources> diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml index a3292888e231..d2019261385f 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Skrinşot yadda saxlandı"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Skrinşotunuza baxmaq üçün klikləyin"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Skrinşotu yadda saxlamaq alınmadı"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Skrinşotu saxlamazdan əvvəl cihaz kiliddən çıxarılmalıdır"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Skrinşotu yenidən çəkin"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Yaddaş ehtiyatının az olması səbəbindən skrinşotu yadda saxlamaq olmur"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Skrinşot çəkməyə tətbiq və ya təşkilat tərəfindən icazə verilmir"</string> diff --git a/packages/SystemUI/res/values-az/strings_tv.xml b/packages/SystemUI/res/values-az/strings_tv.xml index cd9935f5f239..1f1b6491b533 100644 --- a/packages/SystemUI/res/values-az/strings_tv.xml +++ b/packages/SystemUI/res/values-az/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN qoşulub"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ayrılıb"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> vasitəsilə"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Bildirişlər"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Bildiriş yoxdur"</string> </resources> diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml index d800e8de8c2d..aa44b36819d5 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Snimak ekrana je sačuvan"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Dodirnite da biste videli snimak ekrana"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Čuvanje snimka ekrana nije uspelo"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Uređaj mora da bude otključan da bi snimak ekrana mogao da se sačuva"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Probajte da ponovo napravite snimak ekrana"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Čuvanje snimka ekrana nije uspelo zbog ograničenog memorijskog prostora"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Aplikacija ili organizacija ne dozvoljavaju pravljenje snimaka ekrana"</string> diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml b/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml index 8122e4d19ac0..2eaa4996b101 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN je povezan"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Veza sa VPN-om je prekinuta"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Preko: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Obaveštenja"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nema obaveštenja"</string> </resources> diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml index 9fd9a5ec4c9b..bc28f9b1375c 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Здымак экрана захаваны"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Дакраніцеся, каб прагледзець здымак экрана"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Не атрымалася зрабіць здымак экрана"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Перад захаваннем здымка экрана трэба разблакіраваць прыладу"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Паспрабуйце зрабіць здымак экрана яшчэ раз"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Немагчыма захаваць здымак экрана, бо мала месца ў сховішчы"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Рабіць здымкі экрана не дазваляе праграма ці ваша арганізацыя"</string> diff --git a/packages/SystemUI/res/values-be/strings_tv.xml b/packages/SystemUI/res/values-be/strings_tv.xml index 1016b8c59628..21a2e6ed1d42 100644 --- a/packages/SystemUI/res/values-be/strings_tv.xml +++ b/packages/SystemUI/res/values-be/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN падключаны"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN адключаны"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Праз <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Апавяшчэнні"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Апавяшчэнняў няма"</string> </resources> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index 78a826b6a898..faa7e560928c 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Екранната снимка е запазена"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Докоснете, за да видите екранната снимка"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Не можа да се запази екранна снимка"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"За да бъде запазена екранната снимка, устройството трябва да бъде отключено"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Опитайте да направите екранна снимка отново"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Екранната снимка не може да се запази поради ограничено място в хранилището"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Правенето на екранни снимки не е разрешено от приложението или организацията ви"</string> diff --git a/packages/SystemUI/res/values-bg/strings_tv.xml b/packages/SystemUI/res/values-bg/strings_tv.xml index 6f6b8248ce79..b7af7cb26c41 100644 --- a/packages/SystemUI/res/values-bg/strings_tv.xml +++ b/packages/SystemUI/res/values-bg/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN е свързана"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Връзката с VPN е прекратена"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Чрез <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Известия"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Няма известия"</string> </resources> diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index 92e0c1dd9613..04fd1ca184ae 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"স্ক্রিনশট সেভ করা হয়েছে"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"স্ক্রিনশটটি দেখতে ট্যাপ করুন"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"স্ক্রিনশট সেভ করা যায়নি"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"স্ক্রিনশট সেভ করার আগে ডিভাইসটি অবশ্যই আনলক করতে হবে"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"আবার স্ক্রিনশট নেওয়ার চেষ্টা করুন"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"বেশি জায়গা নেই তাই স্ক্রিনশটটি সেভ করা যাবে না৷"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"এই অ্যাপ বা আপনার প্রতিষ্ঠান স্ক্রিনশট নেওয়ার অনুমতি দেয়নি"</string> @@ -935,7 +936,7 @@ <string name="notification_channel_general" msgid="4384774889645929705">"সাধারণ বার্তাগুলি"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"স্টোরেজ"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"হিন্ট"</string> - <string name="instant_apps" msgid="8337185853050247304">"ইনস্ট্যান্ট অ্যাপ"</string> + <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> চলছে"</string> <string name="instant_apps_message" msgid="6112428971833011754">"অ্যাপটি ইনস্টল না করে চালু করা হয়েছে।"</string> <string name="instant_apps_message_with_help" msgid="1816952263531203932">"অ্যাপটি ইনস্টল না করে চালু করা হয়েছে। আরও জানতে ট্যাপ করুন।"</string> diff --git a/packages/SystemUI/res/values-bn/strings_tv.xml b/packages/SystemUI/res/values-bn/strings_tv.xml index 1c26840f1d18..38c24ace782e 100644 --- a/packages/SystemUI/res/values-bn/strings_tv.xml +++ b/packages/SystemUI/res/values-bn/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN কানেক্ট করা হয়েছে"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ডিসকানেক্ট করা হয়েছে"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>-এর মাধ্যমে"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"বিজ্ঞপ্তি"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"কোনও বিজ্ঞপ্তি নেই"</string> </resources> diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml index 1179a92547f0..e2a623c110c6 100644 --- a/packages/SystemUI/res/values-bs/strings.xml +++ b/packages/SystemUI/res/values-bs/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Snimak ekrana je sačuvan"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Dodirnite za prikaz snimka ekrana"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Nije moguće sačuvati snimak ekrana"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Morate otključati uređaj da možete sačuvati snimak ekrana"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Pokušajte ponovo snimiti ekran"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Snimak ekrana se ne može sačuvati zbog manjka prostora za pohranu"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Ova aplikacija ili vaša organizacija ne dozvoljavaju snimanje ekrana"</string> diff --git a/packages/SystemUI/res/values-bs/strings_tv.xml b/packages/SystemUI/res/values-bs/strings_tv.xml index 7507746b4e65..01916a1dea8c 100644 --- a/packages/SystemUI/res/values-bs/strings_tv.xml +++ b/packages/SystemUI/res/values-bs/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN je povezan"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Veza s VPN-om je prekinuta"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Putem: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Obavještenja"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nema obavještenja"</string> </resources> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index ca6316252588..1fa0c9a762ef 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"S\'ha desat la captura de pantalla"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Toca per veure la captura de pantalla"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"No s\'ha pogut desar la captura de pantalla"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"El dispositiu ha d\'estar desbloquejat abans que la captura de pantalla es pugui desar"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Prova de tornar a fer una captura de pantalla"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"La captura de pantalla no es pot desar perquè no hi ha prou espai d\'emmagatzematge"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"L\'aplicació o la teva organització no permeten fer captures de pantalla"</string> diff --git a/packages/SystemUI/res/values-ca/strings_tv.xml b/packages/SystemUI/res/values-ca/strings_tv.xml index 14bc9472f260..a0607854c0e2 100644 --- a/packages/SystemUI/res/values-ca/strings_tv.xml +++ b/packages/SystemUI/res/values-ca/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"La VPN està connectada"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"La VPN està desconnectada"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Mitjançant <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificacions"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Cap notificació"</string> </resources> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index aa6459e76548..e414fd00291d 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Snímek obrazovky byl uložen"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Klepnutím snímek obrazovky zobrazíte"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Snímek obrazovky se nepodařilo uložit"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Aby bylo možné uložit screenshot, zařízení musí být odemknuto"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Zkuste snímek pořídit znovu"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Snímek obrazovky kvůli nedostatku místa v úložišti nelze uložit"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Aplikace nebo organizace zakazuje pořizování snímků obrazovky"</string> diff --git a/packages/SystemUI/res/values-cs/strings_tv.xml b/packages/SystemUI/res/values-cs/strings_tv.xml index ad869b1399fa..0a9850c7b7a7 100644 --- a/packages/SystemUI/res/values-cs/strings_tv.xml +++ b/packages/SystemUI/res/values-cs/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"Síť VPN je připojena"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Síť VPN je odpojena"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Prostřednictvím aplikace <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Oznámení"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Žádná oznámení"</string> </resources> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index d20fc0cf0d5c..4be2c265b46b 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshottet blev gemt"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Tryk for at se dit screenshot"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Screenshottet kunne ikke gemmes"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Enheden skal være låst op, før du kan gemme screenshots"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Prøv at tage et screenshot igen"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Screenshottet kan ikke gemmes, fordi der er begrænset lagerplads"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Appen eller din organisation tillader ikke, at du tager screenshots"</string> diff --git a/packages/SystemUI/res/values-da/strings_tv.xml b/packages/SystemUI/res/values-da/strings_tv.xml index 84926e0c64f2..fb0bc2d513f9 100644 --- a/packages/SystemUI/res/values-da/strings_tv.xml +++ b/packages/SystemUI/res/values-da/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN er tilsluttet"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN er afbrudt"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifikationer"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Ingen notifikationer"</string> </resources> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index dcd6a5351489..038624094333 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot gespeichert"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Tippe, um deinen Screenshot anzusehen"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Screenshot konnte nicht gespeichert werden"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Damit Screenshots gespeichert werden können, muss das Gerät entsperrt sein"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Versuche noch einmal, den Screenshot zu erstellen"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Speichern des Screenshots aufgrund von zu wenig Speicher nicht möglich"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Die App oder deine Organisation lässt das Erstellen von Screenshots nicht zu"</string> diff --git a/packages/SystemUI/res/values-de/strings_tv.xml b/packages/SystemUI/res/values-de/strings_tv.xml index 34fc6aadcd41..0345c804f35a 100644 --- a/packages/SystemUI/res/values-de/strings_tv.xml +++ b/packages/SystemUI/res/values-de/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ist verbunden"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ist nicht verbunden"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Über <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Benachrichtigungen"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Keine Benachrichtigungen"</string> </resources> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index 197cd17de1f3..298506461338 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Το στιγμιότυπο οθόνης αποθηκεύτηκε"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Πατήστε για να δείτε το στιγμιότυπο οθόνης που δημιουργήσατε"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Μη δυνατή αποθήκευση του στιγμιότυπου οθόνης"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Η συσκευή πρέπει να ξεκλειδωθεί για να αποθηκευτεί το στιγμιότυπο οθόνης."</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Δοκιμάστε να κάνετε ξανά λήψη του στιγμιότυπου οθόνης"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Αδύνατη η αποθήκευση του στιγμιότυπου οθόνης λόγω περιορισμένου αποθηκευτικού χώρου"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Η λήψη στιγμιότυπων οθόνης δεν επιτρέπεται από την εφαρμογή ή τον οργανισμό σας"</string> diff --git a/packages/SystemUI/res/values-el/strings_tv.xml b/packages/SystemUI/res/values-el/strings_tv.xml index 21badf740bf0..cd9277234bd7 100644 --- a/packages/SystemUI/res/values-el/strings_tv.xml +++ b/packages/SystemUI/res/values-el/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"Το VPN συνδέθηκε"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Το VPN αποσυνδέθηκε"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Μέσω <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Ειδοποιήσεις"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Δεν υπάρχουν ειδοποιήσεις."</string> </resources> diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml index 85d6276b3885..fbc03967e414 100644 --- a/packages/SystemUI/res/values-en-rAU/strings.xml +++ b/packages/SystemUI/res/values-en-rAU/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot saved"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Tap to view your screenshot"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Couldn\'t save screenshot"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Device must be unlocked before screenshot can be saved"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Try taking screenshot again"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Can\'t save screenshot due to limited storage space"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Taking screenshots isn\'t allowed by the app or your organisation"</string> diff --git a/packages/SystemUI/res/values-en-rAU/strings_tv.xml b/packages/SystemUI/res/values-en-rAU/strings_tv.xml index ab370b14a326..3b3e2d6fef48 100644 --- a/packages/SystemUI/res/values-en-rAU/strings_tv.xml +++ b/packages/SystemUI/res/values-en-rAU/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN is connected"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN is disconnected"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"No notifications"</string> </resources> diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml index 5db104ccaa02..a8eed1588a63 100644 --- a/packages/SystemUI/res/values-en-rCA/strings.xml +++ b/packages/SystemUI/res/values-en-rCA/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot saved"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Tap to view your screenshot"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Couldn\'t save screenshot"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Device must be unlocked before screenshot can be saved"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Try taking screenshot again"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Can\'t save screenshot due to limited storage space"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Taking screenshots isn\'t allowed by the app or your organisation"</string> diff --git a/packages/SystemUI/res/values-en-rCA/strings_tv.xml b/packages/SystemUI/res/values-en-rCA/strings_tv.xml index ab370b14a326..3b3e2d6fef48 100644 --- a/packages/SystemUI/res/values-en-rCA/strings_tv.xml +++ b/packages/SystemUI/res/values-en-rCA/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN is connected"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN is disconnected"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"No notifications"</string> </resources> diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index 85d6276b3885..fbc03967e414 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot saved"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Tap to view your screenshot"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Couldn\'t save screenshot"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Device must be unlocked before screenshot can be saved"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Try taking screenshot again"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Can\'t save screenshot due to limited storage space"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Taking screenshots isn\'t allowed by the app or your organisation"</string> diff --git a/packages/SystemUI/res/values-en-rGB/strings_tv.xml b/packages/SystemUI/res/values-en-rGB/strings_tv.xml index ab370b14a326..3b3e2d6fef48 100644 --- a/packages/SystemUI/res/values-en-rGB/strings_tv.xml +++ b/packages/SystemUI/res/values-en-rGB/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN is connected"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN is disconnected"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"No notifications"</string> </resources> diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml index 85d6276b3885..fbc03967e414 100644 --- a/packages/SystemUI/res/values-en-rIN/strings.xml +++ b/packages/SystemUI/res/values-en-rIN/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot saved"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Tap to view your screenshot"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Couldn\'t save screenshot"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Device must be unlocked before screenshot can be saved"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Try taking screenshot again"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Can\'t save screenshot due to limited storage space"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Taking screenshots isn\'t allowed by the app or your organisation"</string> diff --git a/packages/SystemUI/res/values-en-rIN/strings_tv.xml b/packages/SystemUI/res/values-en-rIN/strings_tv.xml index ab370b14a326..3b3e2d6fef48 100644 --- a/packages/SystemUI/res/values-en-rIN/strings_tv.xml +++ b/packages/SystemUI/res/values-en-rIN/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN is connected"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN is disconnected"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"No notifications"</string> </resources> diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml index 3719aa7a10e0..47bda8bd0c7f 100644 --- a/packages/SystemUI/res/values-en-rXC/strings.xml +++ b/packages/SystemUI/res/values-en-rXC/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot saved"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Tap to view your screenshot"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Couldn\'t save screenshot"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Device must be unlocked before screenshot can be saved"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Try taking screenshot again"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Can\'t save screenshot due to limited storage space"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Taking screenshots isn\'t allowed by the app or your organization"</string> diff --git a/packages/SystemUI/res/values-en-rXC/strings_tv.xml b/packages/SystemUI/res/values-en-rXC/strings_tv.xml index 9fb261012dca..34882b31129d 100644 --- a/packages/SystemUI/res/values-en-rXC/strings_tv.xml +++ b/packages/SystemUI/res/values-en-rXC/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN is connected"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN is disconnected"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"No Notifications"</string> </resources> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index bd649506b6f5..ab23eb6c44e3 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Se guardó la captura de pantalla"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Presiona para ver la captura de pantalla"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"No se pudo guardar la captura de pantalla"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"El dispositivo debe estar desbloqueado para poder guardar la captura de pantalla"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Vuelve a hacer una captura de pantalla"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"No se puede guardar la captura de pantalla debido a que no hay suficiente espacio de almacenamiento"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"La app o tu organización no permiten las capturas de pantalla"</string> diff --git a/packages/SystemUI/res/values-es-rUS/strings_tv.xml b/packages/SystemUI/res/values-es-rUS/strings_tv.xml index 7aa99272e9bd..a0a355b8bc7a 100644 --- a/packages/SystemUI/res/values-es-rUS/strings_tv.xml +++ b/packages/SystemUI/res/values-es-rUS/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"La VPN está conectada."</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"La VPN está desconectada"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"A través de <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificaciones"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"No hay notificaciones"</string> </resources> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index 2ce271896c50..e589ce6ff7a1 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Se ha guardado la captura de pantalla"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Toca para ver la captura de pantalla"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"No se ha podido guardar la captura de pantalla"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"El dispositivo debe desbloquearse para que se pueda guardar la captura de pantalla"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Vuelve a intentar hacer la captura de pantalla"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"No se puede guardar la captura de pantalla porque no hay espacio de almacenamiento suficiente"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"La aplicación o tu organización no permiten realizar capturas de pantalla"</string> diff --git a/packages/SystemUI/res/values-es/strings_tv.xml b/packages/SystemUI/res/values-es/strings_tv.xml index f3bab286fda4..4607ad5d4fcb 100644 --- a/packages/SystemUI/res/values-es/strings_tv.xml +++ b/packages/SystemUI/res/values-es/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"La VPN está conectada"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"La VPN está desconectada"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"A través de <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificaciones"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Sin notificaciones"</string> </resources> diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml index c11f21ce80ed..cce8d8359b44 100644 --- a/packages/SystemUI/res/values-et/strings.xml +++ b/packages/SystemUI/res/values-et/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Ekraanipilt salvestati"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Puudutage ekraanipildi vaatamiseks"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Ekraanipilti ei õnnestunud salvestada"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Enne ekraanipildi salvestamist tuleb seade avada"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Proovige ekraanipilt uuesti jäädvustada"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Piiratud salvestusruumi tõttu ei saa ekraanipilti salvestada"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Rakendus või teie organisatsioon ei luba ekraanipilte jäädvustada"</string> diff --git a/packages/SystemUI/res/values-et/strings_tv.xml b/packages/SystemUI/res/values-et/strings_tv.xml index c59b5bcc4e29..b7039e394178 100644 --- a/packages/SystemUI/res/values-et/strings_tv.xml +++ b/packages/SystemUI/res/values-et/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN on ühendatud"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN-i ühendus on katkestatud"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"VPN-i <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Märguanded"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Märguandeid pole"</string> </resources> diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml index 835449f9939e..ad64da2c6ae9 100644 --- a/packages/SystemUI/res/values-eu/strings.xml +++ b/packages/SystemUI/res/values-eu/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Gorde da pantaila-argazkia"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Sakatu pantaila-argazkia ikusteko"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Ezin izan da gorde pantaila-argazkia"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Pantaila-argazkia gordetzeko, gailuak desblokeatuta egon beharko du"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Saiatu berriro pantaila-argazkia ateratzen"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Ezin da gorde pantaila-argazkia ez delako gelditzen tokirik"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Aplikazioak edo erakundeak ez du onartzen pantaila-argazkiak ateratzea"</string> diff --git a/packages/SystemUI/res/values-eu/strings_tv.xml b/packages/SystemUI/res/values-eu/strings_tv.xml index 67cb078b8788..e1c4fcc73ee4 100644 --- a/packages/SystemUI/res/values-eu/strings_tv.xml +++ b/packages/SystemUI/res/values-eu/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN sarera konektatuta dago"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ez dago sarera konektatuta"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> bidez"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Jakinarazpenak"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Ez dago jakinarazpenik"</string> </resources> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index 55ca0f30c63f..f5f95800eeff 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"نماگرفت ذخیره شد"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"برای مشاهده عکس صفحهنمایشتان ضربه بزنید"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"نماگرفت ذخیره نشد"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"برای ذخیره کردن نماگرفت، قفل دستگاه باید باز باشد"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"دوباره نماگرفت بگیرید"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"به دلیل محدود بودن فضای ذخیرهسازی نمیتوان نماگرفت را ذخیره کرد"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"برنامه یا سازمان شما اجازه نمیدهند نماگرفت بگیرید."</string> diff --git a/packages/SystemUI/res/values-fa/strings_tv.xml b/packages/SystemUI/res/values-fa/strings_tv.xml index 37aaa6408d76..5ad12dfd9d53 100644 --- a/packages/SystemUI/res/values-fa/strings_tv.xml +++ b/packages/SystemUI/res/values-fa/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN متصل است"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN قطع است"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"ازطریق <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"اعلانها"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"اعلانی ندارید"</string> </resources> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index f5441a28d65e..65db4ce30673 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Kuvakaappaus tallennettu"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Napauta katsoaksesi kuvakaappausta"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Kuvakaappauksen tallennus epäonnistui"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Laitteen lukitus täytyy avata ennen kuin kuvakaappaus voidaan tallentaa"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Yritä ottaa kuvakaappaus uudelleen."</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Kuvakaappauksen tallennus epäonnistui, sillä tallennustilaa ei ole riittävästi"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Sovellus tai organisaatio ei salli kuvakaappauksien tallentamista."</string> diff --git a/packages/SystemUI/res/values-fi/strings_tv.xml b/packages/SystemUI/res/values-fi/strings_tv.xml index 295780b7abdb..61cd5ab16d88 100644 --- a/packages/SystemUI/res/values-fi/strings_tv.xml +++ b/packages/SystemUI/res/values-fi/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN on yhdistetty"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ei ole yhdistettynä"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Palvelun <xliff:g id="VPN_APP">%1$s</xliff:g> kautta"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Ilmoitukset"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Ei ilmoituksia"</string> </resources> diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index 6b598da2826d..0e8e31597f8a 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Capture d\'écran enregistrée"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Touchez pour afficher votre capture d\'écran"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Impossible d\'enregistrer la capture d\'écran"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"L\'appareil doit être déverrouillé avant qu\'une capture d\'écran puisse être enregistrée"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Essayez de faire une autre capture d\'écran"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Impossible d\'enregistrer la capture d\'écran, car l\'espace de stockage est limité"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"L\'application ou votre organisation n\'autorise pas les saisies d\'écran"</string> diff --git a/packages/SystemUI/res/values-fr-rCA/strings_tv.xml b/packages/SystemUI/res/values-fr-rCA/strings_tv.xml index 696e95980dbf..a667d76a834a 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings_tv.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"RPV connecté"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"RPV déconnecté"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Par <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Aucune notification"</string> </resources> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index b9fa28c53540..28b9bbe90b89 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Capture d\'écran enregistrée"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Appuyez pour voir la capture d\'écran"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Impossible d\'enregistrer la capture d\'écran"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Vous devez déverrouiller l\'appareil pour que la capture d\'écran soit enregistrée"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Essayez de nouveau de faire une capture d\'écran"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Impossible d\'enregistrer la capture d\'écran, car l\'espace de stockage est limité"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Les captures d\'écran ne sont pas autorisées par l\'application ni par votre organisation"</string> diff --git a/packages/SystemUI/res/values-fr/strings_tv.xml b/packages/SystemUI/res/values-fr/strings_tv.xml index f2c5d976dd21..25fab4e5d6d9 100644 --- a/packages/SystemUI/res/values-fr/strings_tv.xml +++ b/packages/SystemUI/res/values-fr/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN connecté"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN déconnecté"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifications"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Aucune notification"</string> </resources> diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml index 6cf18b8beed6..808048b7c093 100644 --- a/packages/SystemUI/res/values-gl/strings.xml +++ b/packages/SystemUI/res/values-gl/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Gardouse a captura de pantalla"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Toca para ver a captura de pantalla"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Non se puido gardar a captura de pantalla"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Para que se poida gardar a captura de pantalla, o dispositivo debe estar desbloqueado"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Volve tentar crear unha captura de pantalla"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Non se puido gardar a captura de pantalla porque o espazo de almacenamento é limitado"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"A aplicación ou a túa organización non permite realizar capturas de pantalla"</string> diff --git a/packages/SystemUI/res/values-gl/strings_tv.xml b/packages/SystemUI/res/values-gl/strings_tv.xml index 095386be9f71..cd12b94e779d 100644 --- a/packages/SystemUI/res/values-gl/strings_tv.xml +++ b/packages/SystemUI/res/values-gl/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"A VPN está conectada"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"A VPN está desconectada"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"A través de <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificacións"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Non hai notificacións"</string> </resources> diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml index 35d4e1a36fbe..1ba649a25c30 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"સ્ક્રીનશૉટ સાચવ્યો"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"તમારા સ્ક્રીનશૉટને જોવા માટે ટૅપ કરો"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"સ્ક્રીનશૉટ સાચવી શક્યાં નથી"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"સ્ક્રીનશૉટ સાચવવામાં આવે તે પહેલાં ડિવાઇસને અનલૉક કરવું જરૂરી છે"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ફરીથી સ્ક્રીનશૉટ લેવાનો પ્રયાસ કરો"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"મર્યાદિત સ્ટોરેજ સ્પેસને કારણે સ્ક્રીનશૉટ સાચવી શકાતો નથી"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ઍપ્લિકેશન કે તમારી સંસ્થા દ્વારા સ્ક્રીનશૉટ લેવાની મંજૂરી નથી"</string> @@ -935,7 +936,7 @@ <string name="notification_channel_general" msgid="4384774889645929705">"સામાન્ય સંદેશા"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"સ્ટોરેજ"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"હિન્ટ"</string> - <string name="instant_apps" msgid="8337185853050247304">"ઝટપટ ઍપ્લિકેશન"</string> + <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> ચાલી રહી છે"</string> <string name="instant_apps_message" msgid="6112428971833011754">"ઍપ ઇન્સ્ટૉલ કર્યા વિના ખુલી જાય છે."</string> <string name="instant_apps_message_with_help" msgid="1816952263531203932">"ઍપ ઇન્સ્ટૉલ કર્યા વિના ખુલી જાય છે. વધુ જાણવા માટે ટૅપ કરો."</string> diff --git a/packages/SystemUI/res/values-gu/strings_tv.xml b/packages/SystemUI/res/values-gu/strings_tv.xml index 297b6e1a5511..a53e9838b4a0 100644 --- a/packages/SystemUI/res/values-gu/strings_tv.xml +++ b/packages/SystemUI/res/values-gu/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN કનેક્ટ કરેલું છે"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ડિસ્કનેક્ટ કરેલું છે"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> મારફતે"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"નોટિફિકેશન"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"કોઈ નોટિફિકેશન નથી"</string> </resources> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index 1d02fd0b5e3a..330ff90b3e2d 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"स्क्रीनशॉट सेव किया गया"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"अपना स्क्रीनशॉट देखने के लिए टैप करें"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"स्क्रीनशॉट सेव नहीं किया जा सका"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"स्क्रीनशॉट सेव करने के लिए डिवाइस का अनलॉक होना ज़रूरी है"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"स्क्रीनशॉट दोबारा लेने की कोशिश करें"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"मेमोरी कम होने की वजह से स्क्रीनशॉट सेव नहीं किया जा सका"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ऐप्लिकेशन या आपका संगठन स्क्रीनशॉट लेने की अनुमति नहीं देता"</string> @@ -937,7 +938,7 @@ <string name="notification_channel_general" msgid="4384774889645929705">"सामान्य संदेश"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"जगह"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"संकेत"</string> - <string name="instant_apps" msgid="8337185853050247304">"झटपट ऐप्लिकेशन"</string> + <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> चल रहा है"</string> <string name="instant_apps_message" msgid="6112428971833011754">"ऐप्लिकेशन इंस्टॉल किए बिना ही खुल गया है."</string> <string name="instant_apps_message_with_help" msgid="1816952263531203932">"ऐप्लिकेशन इंस्टॉल किए बिना ही खुल गया है. ज़्यादा जानने के लिए टैप करें."</string> diff --git a/packages/SystemUI/res/values-hi/strings_tv.xml b/packages/SystemUI/res/values-hi/strings_tv.xml index d2ce7a9a23f8..fedaae3f4710 100644 --- a/packages/SystemUI/res/values-hi/strings_tv.xml +++ b/packages/SystemUI/res/values-hi/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"वीपीएन कनेक्ट हो गया है"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"वीपीएन डिसकनेक्ट हो गया है"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> के ज़रिए"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"सूचनाएं"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"कोई सूचना नहीं है"</string> </resources> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index 9c4939cd5383..6879259e6be7 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Snimka zaslona spremljena"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Dodirnite da biste vidjeli snimku zaslona"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Snimka zaslona nije spremljena"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Uređaj mora biti otključan da bi se snimka zaslona mogla spremiti"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Pokušajte ponovo napraviti snimku zaslona"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Zaslon nije snimljen zbog ograničenog prostora za pohranu"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Aplikacija ili vaša organizacija ne dopuštaju snimanje zaslona"</string> diff --git a/packages/SystemUI/res/values-hr/strings_tv.xml b/packages/SystemUI/res/values-hr/strings_tv.xml index ee29a6c1ee70..3bfdf7038018 100644 --- a/packages/SystemUI/res/values-hr/strings_tv.xml +++ b/packages/SystemUI/res/values-hr/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN je spojen"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN je isključen"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Putem mreže <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Obavijesti"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nema obavijesti"</string> </resources> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index 2feb1b258370..90f42cbe0350 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"A képernyőkép mentése sikerült"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Koppintson a képernyőkép megtekintéséhez"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Nem sikerült a képernyőkép mentése"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Az eszközt fel kell oldani a képernyőkép mentése előtt"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Próbálja meg újra elkészíteni a képernyőképet"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Nem menthet képernyőképet, mert kevés a tárhely"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Az alkalmazás vagy az Ön szervezete nem engedélyezi képernyőkép készítését"</string> diff --git a/packages/SystemUI/res/values-hu/strings_tv.xml b/packages/SystemUI/res/values-hu/strings_tv.xml index cbbebb0710d6..78d6099b74a0 100644 --- a/packages/SystemUI/res/values-hu/strings_tv.xml +++ b/packages/SystemUI/res/values-hu/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"A VPN-kapcsolat létrejött"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"A VPN-kapcsolat megszakadt"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"A következő szolgáltatás használatával: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Értesítések"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nincs értesítés"</string> </resources> diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml index 0258e44ee64b..aaa27948c494 100644 --- a/packages/SystemUI/res/values-hy/strings.xml +++ b/packages/SystemUI/res/values-hy/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Սքրինշոթը պահվեց"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Հպեք՝ սքրինշոթը տեսնելու համար"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Չհաջողվեց պահել սքրինշոթը"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Սքրինշոթը պահելու համար ապակողպեք սարքը։"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Փորձեք նորից"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Չհաջողվեց պահել սքրինշոթը անբավարար հիշողության պատճառով"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Հավելվածը կամ ձեր կազմակերպությունը չի թույլատրում սքրինշոթի ստացումը"</string> diff --git a/packages/SystemUI/res/values-hy/strings_tv.xml b/packages/SystemUI/res/values-hy/strings_tv.xml index 58c514931cc6..cf4eb90faff2 100644 --- a/packages/SystemUI/res/values-hy/strings_tv.xml +++ b/packages/SystemUI/res/values-hy/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN-ը միացված է"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN-ն անջատված է"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>-ի միջոցով"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Ծանուցումներ"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Ծանուցումներ չկան"</string> </resources> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index bea37ae65dba..ff5d4ed0fdf5 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot disimpan"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Ketuk untuk melihat screenshot"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Tidak dapat menyimpan screenshot"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Perangkat harus dibuka kuncinya agar screenshot dapat disimpan"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Coba ambil screenshot lagi"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Tidak dapat menyimpan screenshot karena ruang penyimpanan terbatas"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Mengambil screenshot tidak diizinkan oleh aplikasi atau organisasi"</string> diff --git a/packages/SystemUI/res/values-in/strings_tv.xml b/packages/SystemUI/res/values-in/strings_tv.xml index bdd6742c39cf..3b446ad23ed5 100644 --- a/packages/SystemUI/res/values-in/strings_tv.xml +++ b/packages/SystemUI/res/values-in/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN tersambung"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN terputus"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Melalui <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifikasi"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Tidak Ada Notifikasi"</string> </resources> diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml index 7c7902faad2e..20231b4223c5 100644 --- a/packages/SystemUI/res/values-is/strings.xml +++ b/packages/SystemUI/res/values-is/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Skjámynd vistuð"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Ýttu til skoða skjámyndina"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Ekki var hægt að vista skjámynd"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Taka verður tækið úr lás áður en hægt er að vista skjámynd"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Prófaðu að taka skjámynd aftur"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Ekki tókst að vista skjámynd vegna takmarkaðs geymslupláss"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Forritið eða fyrirtækið þitt leyfir ekki skjámyndatöku"</string> diff --git a/packages/SystemUI/res/values-is/strings_tv.xml b/packages/SystemUI/res/values-is/strings_tv.xml index 88a43159c064..7c23e62dfdcf 100644 --- a/packages/SystemUI/res/values-is/strings_tv.xml +++ b/packages/SystemUI/res/values-is/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN er tengt"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN er ekki tengt"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Í gegnum <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Tilkynningar"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Engar tilkynningar"</string> </resources> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index 026b5a98a682..a7952ba45c82 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot salvato"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Tocca per visualizzare lo screenshot"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Impossibile salvare lo screenshot"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"È necessario sbloccare il dispositivo per poter salvare lo screenshot"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Riprova ad acquisire lo screenshot"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Impossibile salvare lo screenshot a causa dello spazio di archiviazione limitato"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"L\'acquisizione di screenshot non è consentita dall\'app o dall\'organizzazione"</string> diff --git a/packages/SystemUI/res/values-it/strings_tv.xml b/packages/SystemUI/res/values-it/strings_tv.xml index 97badc1e2180..57931b02d58a 100644 --- a/packages/SystemUI/res/values-it/strings_tv.xml +++ b/packages/SystemUI/res/values-it/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN connessa"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN disconnessa"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Tramite <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notifiche"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nessuna notifica"</string> </resources> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index b4df62b5207e..cd07d770d6b5 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"צילום המסך נשמר"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"אפשר להקיש כדי להציג את צילום המסך"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"לא ניתן היה לשמור צילום מסך"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"כדי שצילום המסך יישמר, צריך לבטל את הנעילה של המכשיר"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"יש לנסות שוב לבצע צילום מסך"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"לא היה מספיק מקום לשמור את צילום המסך"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"האפליקציה או הארגון שלך אינם מתירים ליצור צילומי מסך"</string> diff --git a/packages/SystemUI/res/values-iw/strings_tv.xml b/packages/SystemUI/res/values-iw/strings_tv.xml index 45d744ab8a57..7483116177f6 100644 --- a/packages/SystemUI/res/values-iw/strings_tv.xml +++ b/packages/SystemUI/res/values-iw/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN מחובר"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN מנותק"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"באמצעות <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"התראות"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"אין התראות"</string> </resources> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index be6f491b8356..1b30a925a330 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"スクリーンショットを保存しました"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"タップしてスクリーンショットを表示します"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"スクリーンショット保存エラー"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"スクリーンショットを保存するには、デバイスのロックを解除する必要があります"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"スクリーンショットを撮り直してください"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"空き容量が足りないため、スクリーンショットを保存できません"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"スクリーンショットの作成はアプリまたは組織で許可されていません"</string> diff --git a/packages/SystemUI/res/values-ja/strings_tv.xml b/packages/SystemUI/res/values-ja/strings_tv.xml index 9d7a36a20f76..7f676b5acbe2 100644 --- a/packages/SystemUI/res/values-ja/strings_tv.xml +++ b/packages/SystemUI/res/values-ja/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN に接続しました"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN に接続していません"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> 経由"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"通知"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"通知はありません"</string> </resources> diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml index 6fdb8b89918f..f128ddeefb2c 100644 --- a/packages/SystemUI/res/values-ka/strings.xml +++ b/packages/SystemUI/res/values-ka/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"ეკრანის ანაბეჭდი შენახულია"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"შეეხეთ ეკრანის ანაბეჭდის სანახავად"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"ეკრანის ანაბეჭდის შენახვა ვერ მოხერხდა"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"მოწყობილობა უნდა განიბლოკოს ეკრანის ანაბეჭდის შენახვა რომ შეძლოთ"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ხელახლა ცადეთ ეკრანის ანაბეჭდის გაკეთება"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"ეკრანის ანაბეჭდის შენახვა ვერ მოხერხდა შეზღუდული მეხსიერების გამო"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ეკრანის ანაბეჭდების შექმნა არ არის ნებადართული აპის ან თქვენი ორგანიზაციის მიერ"</string> diff --git a/packages/SystemUI/res/values-ka/strings_tv.xml b/packages/SystemUI/res/values-ka/strings_tv.xml index 0dc1e10cdc9f..081978125ee3 100644 --- a/packages/SystemUI/res/values-ka/strings_tv.xml +++ b/packages/SystemUI/res/values-ka/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN დაკავშირებულია"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN გათიშულია"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>-ის მიერ"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"შეტყობინებები"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"შეტყობინებები არ არის"</string> </resources> diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml index df86e8a4774c..b9c54cc81a2d 100644 --- a/packages/SystemUI/res/values-kk/strings.xml +++ b/packages/SystemUI/res/values-kk/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Скриншот сақталды"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Скриншотты көру үшін түртіңіз"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Скриншот сақталмады"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Скриншот сақталуы үшін, құрылғы құлпын ашу керек."</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Қайта скриншот жасап көріңіз"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Жадтағы шектеулі бос орынға байланысты скриншот сақталмайды"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Қолданба немесе ұйым скриншоттар түсіруге рұқсат етпейді"</string> diff --git a/packages/SystemUI/res/values-kk/strings_tv.xml b/packages/SystemUI/res/values-kk/strings_tv.xml index cc15978b5076..768e3ac19316 100644 --- a/packages/SystemUI/res/values-kk/strings_tv.xml +++ b/packages/SystemUI/res/values-kk/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN қосылған"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ажыратылған"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> арқылы жалғанған"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Хабарландырулар"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Хабарландырулар жоқ"</string> </resources> diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml index e559c1951c50..d293c0d7c02e 100644 --- a/packages/SystemUI/res/values-km/strings.xml +++ b/packages/SystemUI/res/values-km/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"បានរក្សាទុករូបថតអេក្រង់"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"ចុចដើម្បីមើលរូបថតអេក្រង់របស់អ្នក"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"មិនអាចរក្សាទុករូបថតអេក្រង់បានទេ"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ត្រូវតែដោះសោឧបករណ៍ជាមុនសិន ទើបអាចរក្សាទុករូបថតអេក្រង់បាន"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"សាកល្បងថតរូបថតអេក្រង់ម្តងទៀត"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"មិនអាចរក្សាទុករូបថតអេក្រង់បានទេ ដោយសារទំហំផ្ទុកមានកម្រិតទាប"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ការថតរូបអេក្រង់មិនត្រូវបានអនុញ្ញាតដោយកម្មវិធីនេះ ឬស្ថាប័នរបស់អ្នក"</string> diff --git a/packages/SystemUI/res/values-km/strings_tv.xml b/packages/SystemUI/res/values-km/strings_tv.xml index f415a66658de..0dec2d65e5bf 100644 --- a/packages/SystemUI/res/values-km/strings_tv.xml +++ b/packages/SystemUI/res/values-km/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ត្រូវបានភ្ជាប់"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ត្រូវបានផ្ដាច់"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"តាមរយៈ <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"ការជូនដំណឹង"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"គ្មានការជូនដំណឹងទេ"</string> </resources> diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml index f1210804841e..a906a39288c6 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ಅನ್ನು ಉಳಿಸಲಾಗಿದೆ"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ಶಾಟ್ ವೀಕ್ಷಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ಅನ್ನು ಉಳಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ಉಳಿಸುವ ಮೊದಲು ಸಾಧನವನ್ನು ಅನ್ಲಾಕ್ ಮಾಡಬೇಕು"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ಸ್ಕ್ರೀನ್ಶಾಟ್ ಅನ್ನು ಪುನಃ ತೆಗೆದುಕೊಳ್ಳಲು ಪ್ರಯತ್ನಿಸಿ"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"ಪರಿಮಿತ ಸಂಗ್ರಹಣೆ ಸ್ಥಳದ ಕಾರಣದಿಂದಾಗಿ ಸ್ಕ್ರೀನ್ಶಾಟ್ ಉಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ಅಪ್ಲಿಕೇಶನ್ ಅಥವಾ ಸಂಸ್ಥೆಯು ಸ್ಕ್ರೀನ್ಶಾಟ್ಗಳನ್ನು ತೆಗೆಯುವುದನ್ನು ಅನುಮತಿಸುವುದಿಲ್ಲ"</string> @@ -935,7 +936,7 @@ <string name="notification_channel_general" msgid="4384774889645929705">"ಸಾಮಾನ್ಯ ಸಂದೇಶಗಳು"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"ಸಂಗ್ರಹಣೆ"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"ಸುಳಿವುಗಳು"</string> - <string name="instant_apps" msgid="8337185853050247304">"ಇನ್ಸ್ಟಂಟ್ ಆ್ಯಪ್ಗಳು"</string> + <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> ರನ್ ಆಗುತ್ತಿದೆ"</string> <string name="instant_apps_message" msgid="6112428971833011754">"ಇನ್ಸ್ಟಾಲ್ ಮಾಡದೆ ಆ್ಯಪ್ ತೆರೆಯಲಾಗಿದೆ."</string> <string name="instant_apps_message_with_help" msgid="1816952263531203932">"ಇನ್ಸ್ಟಾಲ್ ಮಾಡದೆ ಆ್ಯಪ್ ತೆರೆಯಲಾಗಿದೆ. ಇನ್ನಷ್ಟು ತಿಳಿಯಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string> diff --git a/packages/SystemUI/res/values-kn/strings_tv.xml b/packages/SystemUI/res/values-kn/strings_tv.xml index a9359639f573..ef10e3a2a664 100644 --- a/packages/SystemUI/res/values-kn/strings_tv.xml +++ b/packages/SystemUI/res/values-kn/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ಕನೆಕ್ಟ್ ಮಾಡಲಾಗಿದೆ"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ಕನೆಕ್ಷನ್ ಕಡಿತಗೊಂಡಿದೆ"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> ಮೂಲಕ"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"ಅಧಿಸೂಚನೆಗಳು"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"ಯಾವುದೇ ಅಧಿಸೂಚನೆಗಳಿಲ್ಲ"</string> </resources> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index 6db40c192aea..adedb88a59c6 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"스크린샷 저장됨"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"스크린샷을 확인하려면 탭하세요"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"스크린샷을 저장할 수 없음"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"스크린샷을 저장하려면 기기를 잠금 해제해야 합니다."</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"스크린샷을 다시 찍어 보세요."</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"저장용량이 부족하여 스크린샷을 저장할 수 없습니다"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"앱이나 조직에서 스크린샷 촬영을 허용하지 않습니다."</string> diff --git a/packages/SystemUI/res/values-ko/strings_tv.xml b/packages/SystemUI/res/values-ko/strings_tv.xml index 8c3a8ea65de2..f9c723a3b33b 100644 --- a/packages/SystemUI/res/values-ko/strings_tv.xml +++ b/packages/SystemUI/res/values-ko/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN에 연결됨"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN 연결이 해제됨"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>에 연결됨"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"알림"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"알림 없음"</string> </resources> diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml index 8a06ed67e2f8..92b98fb80939 100644 --- a/packages/SystemUI/res/values-ky/strings.xml +++ b/packages/SystemUI/res/values-ky/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Скриншот сакталды"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Скриншотуңузду көрүү үчүн таптап коюңуз"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Скриншот сакталган жок"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Скриншотту сактоо үчүн түзмөктүн кулпусун ачуу керек"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Скриншотту кайра тартып көрүңүз"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Сактагычта бош орун аз болгондуктан, скриншот сакталбай жатат"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Скриншот тартууга колдонмо же ишканаңыз тыюу салган."</string> diff --git a/packages/SystemUI/res/values-ky/strings_tv.xml b/packages/SystemUI/res/values-ky/strings_tv.xml index 3be657c78b2c..1dba865803d2 100644 --- a/packages/SystemUI/res/values-ky/strings_tv.xml +++ b/packages/SystemUI/res/values-ky/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN туташтырылды"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ажыратылды"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> аркылуу"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Билдирмелер"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Билдирме жок"</string> </resources> diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml index b92c2c17e7f9..aa3bc8829f30 100644 --- a/packages/SystemUI/res/values-lo/strings.xml +++ b/packages/SystemUI/res/values-lo/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"ບັນທຶກຮູບໜ້າຈໍໄວ້ແລ້ວ"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"ແຕະເພື່ອເບິ່ງພາບຖ່າຍໜ້າຈໍຂອງທ່ານ"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"ບໍ່ສາມາດບັນທຶກຮູບໜ້າຈໍໄດ້"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ຈະຕ້ອງປົດລັອກອຸປະກອນກ່ອນບັນທຶກຮູບໜ້າຈໍ"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ກະລຸນາລອງຖ່າຍຮູບໜ້າຈໍອີກຄັ້ງ"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"ບໍ່ສາມາດຖ່າຍຮູບໜ້າຈໍໄດ້ເນື່ອງຈາກພື້ນທີ່ຈັດເກັບຂໍ້ມູນມີຈຳກັດ"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ແອັບ ຫຼື ອົງກອນຂອງທ່ານບໍ່ອະນຸຍາດໃຫ້ຖ່າຍຮູບໜ້າຈໍ"</string> diff --git a/packages/SystemUI/res/values-lo/strings_tv.xml b/packages/SystemUI/res/values-lo/strings_tv.xml index 445e56229bf9..a45fb45cc76f 100644 --- a/packages/SystemUI/res/values-lo/strings_tv.xml +++ b/packages/SystemUI/res/values-lo/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"ເຊື່ອມຕໍ່ VPN ແລ້ວ"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"ຕັດການເຊື່ອມຕໍ່ VPN ແລ້ວ"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"ຜ່ານ <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"ການແຈ້ງເຕືອນ"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"ບໍ່ມີການແຈ້ງເຕືອນ"</string> </resources> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index cac9cf1dbc92..c40c5c9c269d 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Ekrano kopija išsaugota"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Palieskite, kad peržiūrėtumėte ekrano kopiją"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Ekrano kopijos išsaugoti nepavyko"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Įrenginys turi būti atrakintas, kad būtų galima išsaugoti ekrano kopiją"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Pabandykite padaryti ekrano kopiją dar kartą"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Negalima išsaugoti ekrano kopijos dėl ribotos saugyklos vietos"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Jūsų organizacijoje arba naudojant šią programą neleidžiama daryti ekrano kopijų"</string> diff --git a/packages/SystemUI/res/values-lt/strings_tv.xml b/packages/SystemUI/res/values-lt/strings_tv.xml index c749cdfbe22c..8c329f961b5c 100644 --- a/packages/SystemUI/res/values-lt/strings_tv.xml +++ b/packages/SystemUI/res/values-lt/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN prijungtas"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN atjungtas"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Per „<xliff:g id="VPN_APP">%1$s</xliff:g>“"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Pranešimai"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nėra jokių pranešimų"</string> </resources> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index da8adb46000b..85b272a575c3 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Ekrānuzņēmums saglabāts"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Pieskarieties, lai skatītu ekrānuzņēmumu."</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Ekrānuzņēmumu neizdevās saglabāt."</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Lai varētu saglabāt ekrānuzņēmumu, ierīcei ir jābūt atbloķētai."</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Mēģiniet izveidot jaunu ekrānuzņēmumu."</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Nevar saglabāt ekrānuzņēmumu, jo krātuvē nepietiek vietas."</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Lietotne vai jūsu organizācija neatļauj veikt ekrānuzņēmumus."</string> diff --git a/packages/SystemUI/res/values-lv/strings_tv.xml b/packages/SystemUI/res/values-lv/strings_tv.xml index f752439165b4..758d28cddc82 100644 --- a/packages/SystemUI/res/values-lv/strings_tv.xml +++ b/packages/SystemUI/res/values-lv/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"Savienojums ar VPN ir izveidots."</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Savienojums ar VPN ir pārtraukts."</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Izmantojot: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Paziņojumi"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nav paziņojumu"</string> </resources> diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml index 2416dbde4408..bbcf93c7d18e 100644 --- a/packages/SystemUI/res/values-mk/strings.xml +++ b/packages/SystemUI/res/values-mk/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Сликата од екранот е зачувана"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Допрете за да ја видите сликата од екранот"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Не може да се зачува слика од екранот"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Уредот мора да биде отклучен за да може да се зачува слика од екранот"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Повторно обидете се да направите слика од екранот"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Сликата од екранот не може да се зачува поради ограничена меморија"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Апликацијата или вашата организација не дозволува снимање слики од екранот"</string> diff --git a/packages/SystemUI/res/values-mk/strings_tv.xml b/packages/SystemUI/res/values-mk/strings_tv.xml index 947281341e30..0dfbd79de131 100644 --- a/packages/SystemUI/res/values-mk/strings_tv.xml +++ b/packages/SystemUI/res/values-mk/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN е поврзана"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN е исклучена"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Преку <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Известувања"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Нема известувања"</string> </resources> diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml index 4d77fcd4054f..b4db453df156 100644 --- a/packages/SystemUI/res/values-ml/strings.xml +++ b/packages/SystemUI/res/values-ml/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"സ്ക്രീൻഷോട്ട് സംരക്ഷിച്ചു"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"സ്ക്രീൻഷോട്ട് കാണാൻ ടാപ്പ് ചെയ്യുക"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"സ്ക്രീൻഷോട്ട് സംരക്ഷിക്കാനായില്ല"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"സ്ക്രീൻഷോട്ട് സംരക്ഷിക്കുന്നതിന് മുമ്പ് ഉപകരണം അൺലോക്ക് ചെയ്തിരിക്കണം"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"സ്ക്രീൻഷോട്ട് എടുക്കാൻ വീണ്ടും ശ്രമിക്കുക"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"സ്റ്റോറേജ് ഇടം പരിമിതമായതിനാൽ സ്ക്രീൻഷോട്ട് സംരക്ഷിക്കാനാകുന്നില്ല"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"സ്ക്രീൻഷോട്ടുകൾ എടുക്കുന്നത് ആപ്പോ നിങ്ങളുടെ സ്ഥാപനമോ അനുവദിക്കുന്നില്ല"</string> @@ -935,7 +936,7 @@ <string name="notification_channel_general" msgid="4384774889645929705">"പൊതുവായ സന്ദേശങ്ങൾ"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"സ്റ്റോറേജ്"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"സൂചനകൾ"</string> - <string name="instant_apps" msgid="8337185853050247304">"ഇൻസ്റ്റന്റ് ആപ്പ്"</string> + <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> റണ് ചെയ്യുന്നു"</string> <string name="instant_apps_message" msgid="6112428971833011754">"ഇൻസ്റ്റാൾ ചെയ്യാതെ ആപ്പ് തുറന്നു."</string> <string name="instant_apps_message_with_help" msgid="1816952263531203932">"ഇൻസ്റ്റാൾ ചെയ്യാതെ ആപ്പ് തുറന്നു. കൂടുതലറിയാൻ ടാപ്പ് ചെയ്യുക."</string> diff --git a/packages/SystemUI/res/values-ml/strings_tv.xml b/packages/SystemUI/res/values-ml/strings_tv.xml index fe7979665edd..70cced8e810c 100644 --- a/packages/SystemUI/res/values-ml/strings_tv.xml +++ b/packages/SystemUI/res/values-ml/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN കണക്റ്റ് ചെയ്തു"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN വിച്ഛേദിച്ചു"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> വഴി"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"അറിയിപ്പുകൾ"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"അറിയിപ്പുകൾ ഒന്നുമില്ല"</string> </resources> diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml index 0d605c11cd1d..6a96a5019c36 100644 --- a/packages/SystemUI/res/values-mn/strings.xml +++ b/packages/SystemUI/res/values-mn/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Дэлгэцээс дарсан зургийг хадгалсан"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Дэлгэцээс дарсан зургийг харах бол товшино уу"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Дэлгэцээс дарсан зургийг хадгалж чадсангүй"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Дэлгэцийн агшныг хадгалах боломжтой болохоос өмнө төхөөрөмжийн түгжээг тайлах ёстой"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Дэлгэцийн зургийг дахин дарж үзнэ үү"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Сангийн багтаамж бага байгаа тул дэлгэцээс дарсан зургийг хадгалах боломжгүй байна"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Таны апп, байгууллагад дэлгэцийн зураг авахыг зөвшөөрдөггүй"</string> diff --git a/packages/SystemUI/res/values-mn/strings_tv.xml b/packages/SystemUI/res/values-mn/strings_tv.xml index 9ec66d1bf26f..221d8ae058f9 100644 --- a/packages/SystemUI/res/values-mn/strings_tv.xml +++ b/packages/SystemUI/res/values-mn/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN холбогдсон"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN салсан"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>-р"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Мэдэгдэл"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Мэдэгдэл байхгүй байна"</string> </resources> diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml index a487a6377ed5..a667ab7cd52f 100644 --- a/packages/SystemUI/res/values-mr/strings.xml +++ b/packages/SystemUI/res/values-mr/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"स्क्रीनशॉट सेव्ह केला"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"तुमचा स्क्रीनशॉट पाहण्यासाठी टॅप करा"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"स्क्रीनशॉट सेव्ह करू शकलो नाही"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"स्क्रीनशॉट सेव्ह करण्याआधी डिव्हाइस अनलॉक करणे आवश्यक आहे"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"स्क्रीनशॉट पुन्हा घेण्याचा प्रयत्न करा"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"मर्यादित स्टोरेज जागेमुळे स्क्रीनशॉट सेव्ह करू शकत नाही"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"अॅप किंवा आपल्या संस्थेद्वारे स्क्रीनशॉट घेण्याची अनुमती नाही"</string> @@ -935,7 +936,7 @@ <string name="notification_channel_general" msgid="4384774889645929705">"सर्वसाधारण मेसेज"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"स्टोरेज"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"सूचना"</string> - <string name="instant_apps" msgid="8337185853050247304">"इन्सटंट अॅप्स"</string> + <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> रन होत आहे"</string> <string name="instant_apps_message" msgid="6112428971833011754">"इंस्टॉल केल्याशिवाय अॅप उघडले."</string> <string name="instant_apps_message_with_help" msgid="1816952263531203932">"इंस्टॉल केल्याशिवाय अॅप उघडले. अधिक जाणून घेण्यासाठी टॅप करा."</string> diff --git a/packages/SystemUI/res/values-mr/strings_tv.xml b/packages/SystemUI/res/values-mr/strings_tv.xml index 791a4fd0c802..ac0cad132fd0 100644 --- a/packages/SystemUI/res/values-mr/strings_tv.xml +++ b/packages/SystemUI/res/values-mr/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN कनेक्ट केले"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN डिस्कनेक्ट केले"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> द्वारे"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"सूचना"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"सूचना नाहीत"</string> </resources> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index 8f426ede9b75..86565902910e 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Tangkapan skrin disimpan"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Ketik untuk melihat tangkapan skrin anda"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Tidak dapat menyimpan tangkapan skrin"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Peranti mesti dibuka kunci sebelum tangkapan skrin dapat disimpan"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Cuba ambil tangkapan skrin sekali lagi"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Tidak dapat menyimpan tangkapan skrin kerana ruang storan terhad"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Pengambilan tangkapan skrin tidak dibenarkan oleh apl atau organisasi anda"</string> diff --git a/packages/SystemUI/res/values-ms/strings_tv.xml b/packages/SystemUI/res/values-ms/strings_tv.xml index 65c8068d0505..46e345efc16b 100644 --- a/packages/SystemUI/res/values-ms/strings_tv.xml +++ b/packages/SystemUI/res/values-ms/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN telah disambungkan"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN diputuskan sambungan"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Melalui <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Pemberitahuan"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Tiada Pemberitahuan"</string> </resources> diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml index 9d8ffc93fae0..5b5531d06b2b 100644 --- a/packages/SystemUI/res/values-my/strings.xml +++ b/packages/SystemUI/res/values-my/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"ဖန်သားပြင်ဓာတ်ပုံကို သိမ်းပြီးပါပြီ"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"ဖန်သားပြင်ဓာတ်ပုံကို ကြည့်ရန် တို့ပါ"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"မျက်နှာပြင်ပုံကို သိမ်း၍မရပါ"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ဖန်သားပြင်ဓာတ်ပုံကို မသိမ်းမီ စက်ပစ္စည်းကို လော့ခ်ဖွင့်ထားရမည်"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"မျက်နှာပြင်ပုံကို ထပ်ရိုက်ကြည့်ပါ"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"သိုလှောင်ခန်းနေရာ အကန့်အသတ်ရှိသောကြောင့် ဖန်သားပြင်ဓာတ်ပုံကို သိမ်းဆည်း၍မရပါ"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ဖန်သားပြင်ဓာတ်ပုံရိုက်ကူးခြင်းကို ဤအက်ပ် သို့မဟုတ် သင်၏အဖွဲ့အစည်းက ခွင့်မပြုပါ"</string> diff --git a/packages/SystemUI/res/values-my/strings_tv.xml b/packages/SystemUI/res/values-my/strings_tv.xml index c07b9a596b06..268c5540ef5b 100644 --- a/packages/SystemUI/res/values-my/strings_tv.xml +++ b/packages/SystemUI/res/values-my/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ချိတ်ဆက်ထားသည်"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ချိတ်ဆက်မှုမရှိပါ"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> မှတစ်ဆင့်"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"အကြောင်းကြားချက်များ"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"အကြောင်းကြားချက်များ မရှိပါ"</string> </resources> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index 1d30e2bf89bd..6b0568df9f35 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Skjermdumpen er lagret"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Trykk for å se skjermdumpen"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Kunne ikke lagre skjermdump"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Enheten må være låst opp før skjermdumpen kan lagres"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Prøv å ta skjermdump på nytt"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Kan ikke lagre skjermdumpen på grunn av begrenset lagringsplass"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Appen eller organisasjonen din tillater ikke at du tar skjermdumper"</string> diff --git a/packages/SystemUI/res/values-nb/strings_tv.xml b/packages/SystemUI/res/values-nb/strings_tv.xml index 6346519c3823..c5767dd94c03 100644 --- a/packages/SystemUI/res/values-nb/strings_tv.xml +++ b/packages/SystemUI/res/values-nb/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN er tilkoblet"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN er frakoblet"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Varsler"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Ingen varsler"</string> </resources> diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml index 881be66c00c2..f72808f61348 100644 --- a/packages/SystemUI/res/values-ne/strings.xml +++ b/packages/SystemUI/res/values-ne/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"स्क्रिनसट सुरक्षित गरियो"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"आफ्नो स्क्रिनसट हेर्न ट्याप गर्नुहोस्"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"स्क्रिनसट सुरक्षित गर्न सकिएन"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"यन्त्र अनलक गरेपछि मात्र स्क्रिनसट सुरक्षित गर्न सकिन्छ"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"स्क्रिनसट फेरि लिएर हेर्नुहोस्"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"भण्डारण ठाउँ सीमित भएका कारण स्क्रिनसट सुरक्षित गर्न सकिएन"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"उक्त एप वा तपाईंको संगठनले स्क्रिनसटहरू लिन दिँदैन"</string> diff --git a/packages/SystemUI/res/values-ne/strings_tv.xml b/packages/SystemUI/res/values-ne/strings_tv.xml index 00cc10aadf8a..925f7b76c12e 100644 --- a/packages/SystemUI/res/values-ne/strings_tv.xml +++ b/packages/SystemUI/res/values-ne/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN कनेक्ट गरिएको छ"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN डिस्कनेक्ट गरिएको छ"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> मार्फत"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"सूचनाहरू"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"कुनै पनि सूचना छैन"</string> </resources> diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml index 8cc747bf04d6..d0aef6fe2e65 100644 --- a/packages/SystemUI/res/values-night/colors.xml +++ b/packages/SystemUI/res/values-night/colors.xml @@ -44,11 +44,8 @@ <color name="notification_section_clear_all_btn_color">@color/GM2_grey_500</color> <color name="notification_channel_dialog_separator">@color/GM2_grey_700</color> - <!-- The color of the background in the top part of QSCustomizer --> - <color name="qs_customize_background">@color/GM2_grey_900</color> - <!-- The color of the background in the bottom part of QSCustomizer --> - <color name="qs_customize_decoration">@color/GM2_grey_800</color> + <color name="qs_customize_decoration">@color/GM2_grey_900</color> <!-- The color of the background in the separated list of the Global Actions menu --> <color name="global_actions_separated_background">@color/GM2_grey_900</color> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index 6bed66bb171e..aa738c495754 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Screenshot opgeslagen"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Tik om je screenshot te bekijken"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Kan screenshot niet opslaan"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Je moet het apparaat ontgrendelen voordat het screenshot kan worden opgeslagen"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Probeer opnieuw een screenshot te maken"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Kan screenshot niet opslaan vanwege beperkte opslagruimte"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Het maken van screenshots wordt niet toegestaan door de app of je organisatie"</string> diff --git a/packages/SystemUI/res/values-nl/strings_tv.xml b/packages/SystemUI/res/values-nl/strings_tv.xml index 11f70b4dfe94..22d3b8806bbd 100644 --- a/packages/SystemUI/res/values-nl/strings_tv.xml +++ b/packages/SystemUI/res/values-nl/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"Verbinding met VPN"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Geen verbinding met VPN"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Meldingen"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Geen meldingen"</string> </resources> diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml index a809da3d2fe2..7e3406746c5e 100644 --- a/packages/SystemUI/res/values-or/strings.xml +++ b/packages/SystemUI/res/values-or/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"ସ୍କ୍ରୀନଶଟ୍ ସେଭ୍ ହୋଇଛି"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"ସ୍କ୍ରୀନଶଟ୍ ଦେଖିବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"ସ୍କ୍ରୀନ୍ଶଟ୍ ସେଭ୍ କରିହେବ ନାହିଁ"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ସ୍କ୍ରିନସଟ୍ ସେଭ୍ କରିବା ପୂର୍ବରୁ ଡିଭାଇସକୁ ଅନଲକ୍ କରାଯିବା ଆବଶ୍ୟକ"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ପୁଣିଥରେ ସ୍କ୍ରୀନ୍ଶଟ୍ ନେବାକୁ ଚେଷ୍ଟା କରନ୍ତୁ"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"ସୀମିତ ଷ୍ଟୋରେଜ୍ ସ୍ପେସ୍ ହେତୁ ସ୍କ୍ରୀନଶଟ୍ ସେଭ୍ ହୋଇପାରିବ ନାହିଁ"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ଆପ୍ କିମ୍ବା ସଂସ୍ଥା ଦ୍ୱାରା ସ୍କ୍ରୀନଶଟ୍ ନେବାକୁ ଅନୁମତି ଦିଆଯାଇ ନାହିଁ"</string> @@ -935,7 +936,7 @@ <string name="notification_channel_general" msgid="4384774889645929705">"ସାଧାରଣ ମେସେଜ୍"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"ଷ୍ଟୋରେଜ୍"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"ହିଣ୍ଟ"</string> - <string name="instant_apps" msgid="8337185853050247304">"ଇନଷ୍ଟାଣ୍ଟ ଆପ୍"</string> + <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> ଚାଲୁଛି"</string> <string name="instant_apps_message" msgid="6112428971833011754">"ଇନ୍ଷ୍ଟଲ୍ ନହୋଇ ଆପ୍ ଖୋଲିଛି।"</string> <string name="instant_apps_message_with_help" msgid="1816952263531203932">"ଇନ୍ଷ୍ଟଲ୍ ନହୋଇ ଆପ୍ ଖୋଲିଛି। ଅଧିକ ଜାଣିବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ।"</string> diff --git a/packages/SystemUI/res/values-or/strings_tv.xml b/packages/SystemUI/res/values-or/strings_tv.xml index f436babfa20a..707c49e183c7 100644 --- a/packages/SystemUI/res/values-or/strings_tv.xml +++ b/packages/SystemUI/res/values-or/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ସଂଯୋଗ କରାଯାଇଛି"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ବିଚ୍ଛିନ୍ନ କରାଯାଇଛି"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> ମାଧ୍ୟମରେ"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"କୌଣସି ବିଜ୍ଞପ୍ତି ନାହିଁ"</string> </resources> diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index d9a68281eb73..ca4b6ad2cffb 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"ਆਪਣਾ ਸਕ੍ਰੀਨਸ਼ਾਟ ਦੇਖਣ ਲਈ ਟੈਪ ਕਰੋ"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਿਆ"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਨੂੰ ਰੱਖਿਅਤ ਕੀਤੇ ਜਾਣ ਤੋਂ ਪਹਿਲਾਂ ਡੀਵਾਈਸ ਨੂੰ ਅਣਲਾਕ ਕੀਤਾ ਹੋਣਾ ਲਾਜ਼ਮੀ ਹੈ"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ਸਕ੍ਰੀਨਸ਼ਾਟ ਦੁਬਾਰਾ ਲੈ ਕੇ ਦੇਖੋ"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"ਸੀਮਿਤ ਸਟੋਰੇਜ ਹੋਣ ਕਾਰਨ ਸਕ੍ਰੀਨਸ਼ਾਟ ਰੱਖਿਅਤ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ਐਪ ਜਾਂ ਤੁਹਾਡੀ ਸੰਸਥਾ ਵੱਲੋਂ ਸਕ੍ਰੀਨਸ਼ਾਟ ਲੈਣ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਦਿੱਤੀ ਗਈ ਹੈ"</string> @@ -935,7 +936,7 @@ <string name="notification_channel_general" msgid="4384774889645929705">"ਆਮ ਸੁਨੇਹੇ"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"ਸਟੋਰੇਜ"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"ਸੰਕੇਤ"</string> - <string name="instant_apps" msgid="8337185853050247304">"ਤਤਕਾਲ ਐਪਾਂ"</string> + <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> ਚੱਲ ਰਹੀ ਹੈ"</string> <string name="instant_apps_message" msgid="6112428971833011754">"ਸਥਾਪਤ ਕੀਤੇ ਬਿਨਾਂ ਐਪ ਖੋਲ੍ਹੀ ਗਈ।"</string> <string name="instant_apps_message_with_help" msgid="1816952263531203932">"ਸਥਾਪਤ ਕੀਤੇ ਬਿਨਾਂ ਐਪ ਖੋਲ੍ਹੀ ਗਈ। ਹੋਰ ਜਾਣਨ ਲਈ ਟੈਪ ਕਰੋ।"</string> diff --git a/packages/SystemUI/res/values-pa/strings_tv.xml b/packages/SystemUI/res/values-pa/strings_tv.xml index d10daa85da5a..c0761942b2ee 100644 --- a/packages/SystemUI/res/values-pa/strings_tv.xml +++ b/packages/SystemUI/res/values-pa/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ਕਨੈਕਟ ਹੈ"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ਡਿਸਕਨੈਕਟ ਹੈ"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> ਰਾਹੀਂ"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"ਸੂਚਨਾਵਾਂ"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"ਕੋਈ ਸੂਚਨਾ ਨਹੀਂ"</string> </resources> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index 3e944b5f7317..142a507dfd58 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Zrzut ekranu został zapisany"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Kliknij, by zobaczyć zrzut ekranu"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Nie udało się zapisać zrzutu ekranu"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Przed zapisaniem zrzutu ekranu musisz odblokować urządzenie"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Spróbuj jeszcze raz wykonać zrzut ekranu"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Nie można zapisać zrzutu ekranu, bo brakuje miejsca w pamięci"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Nie możesz wykonać zrzutu ekranu, bo nie zezwala na to aplikacja lub Twoja organizacja."</string> diff --git a/packages/SystemUI/res/values-pl/strings_tv.xml b/packages/SystemUI/res/values-pl/strings_tv.xml index d83391e01b57..e63aadee9d65 100644 --- a/packages/SystemUI/res/values-pl/strings_tv.xml +++ b/packages/SystemUI/res/values-pl/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"Połączono z VPN"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Rozłączono z VPN"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Przez: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Powiadomienia"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Brak powiadomień"</string> </resources> diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml index d058eddbcf36..82139f525c44 100644 --- a/packages/SystemUI/res/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Captura de tela salva"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Toque para ver sua captura de tela"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Falha ao salvar a captura de tela"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Para que a captura de tela seja salva, o dispositivo precisa ser desbloqueado"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Tente fazer a captura de tela novamente"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Não é possível salvar a captura de tela, porque não há espaço suficiente"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"O app ou a organização não permitem capturas de tela"</string> diff --git a/packages/SystemUI/res/values-pt-rBR/strings_tv.xml b/packages/SystemUI/res/values-pt-rBR/strings_tv.xml index 49b923d076b7..2ea81526feed 100644 --- a/packages/SystemUI/res/values-pt-rBR/strings_tv.xml +++ b/packages/SystemUI/res/values-pt-rBR/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"A VPN está conectada"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"A VPN está desconectada"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificações"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nenhuma notificação"</string> </resources> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index dcaf46027b2c..61cc9137a9db 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Captura de ecrã guardada"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Toque para ver a captura de ecrã."</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Não foi possível guardar a captura de ecrã"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"É necessário desbloquear o dispositivo para guardar a captura de ecrã"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Experimente voltar a efetuar a captura de ecrã."</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Não é possível guardar a captura de ecrã devido a espaço de armazenamento limitado."</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"A app ou a sua entidade não permitem tirar capturas de ecrã"</string> diff --git a/packages/SystemUI/res/values-pt-rPT/strings_tv.xml b/packages/SystemUI/res/values-pt-rPT/strings_tv.xml index a36a1a92d882..8ce3e307c659 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings_tv.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"A VPN está ligada"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"A VPN está desligada"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Através de <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificações"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Sem notificações"</string> </resources> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index d058eddbcf36..82139f525c44 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Captura de tela salva"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Toque para ver sua captura de tela"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Falha ao salvar a captura de tela"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Para que a captura de tela seja salva, o dispositivo precisa ser desbloqueado"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Tente fazer a captura de tela novamente"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Não é possível salvar a captura de tela, porque não há espaço suficiente"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"O app ou a organização não permitem capturas de tela"</string> diff --git a/packages/SystemUI/res/values-pt/strings_tv.xml b/packages/SystemUI/res/values-pt/strings_tv.xml index 49b923d076b7..2ea81526feed 100644 --- a/packages/SystemUI/res/values-pt/strings_tv.xml +++ b/packages/SystemUI/res/values-pt/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"A VPN está conectada"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"A VPN está desconectada"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificações"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nenhuma notificação"</string> </resources> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index 81caf56e4939..123d6721e5b8 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Captură de ecran salvată"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Atingeți pentru a vedea captura de ecran"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Nu s-a putut salva captura de ecran"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Pentru a salva captura de ecran, trebuie să deblocați dispozitivul"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Încercați să faceți din nou o captură de ecran"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Captura de ecran nu poate fi salvată din cauza spațiului de stocare limitat"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Crearea capturilor de ecran nu este permisă de aplicație sau de organizația dvs."</string> diff --git a/packages/SystemUI/res/values-ro/strings_tv.xml b/packages/SystemUI/res/values-ro/strings_tv.xml index 69a31383a6cc..c64a492c59e4 100644 --- a/packages/SystemUI/res/values-ro/strings_tv.xml +++ b/packages/SystemUI/res/values-ro/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN este conectat"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN este deconectat"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Prin <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Notificări"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Nicio notificare"</string> </resources> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index bf5e6047a525..03f1dfc831b0 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Скриншот сохранен"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Нажмите, чтобы увидеть скриншот."</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Не удалось сохранить скриншот"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Чтобы сохранить скриншот, разблокируйте устройство."</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Попробуйте сделать скриншот снова."</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Не удалось сохранить скриншот: недостаточно места."</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Не удалось сделать скриншот: нет разрешения от приложения или организации."</string> diff --git a/packages/SystemUI/res/values-ru/strings_tv.xml b/packages/SystemUI/res/values-ru/strings_tv.xml index bd8855bb1b56..e08ade3bc065 100644 --- a/packages/SystemUI/res/values-ru/strings_tv.xml +++ b/packages/SystemUI/res/values-ru/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN-подключение установлено"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN-подключение отключено"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Отправлено через <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Уведомления"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Уведомлений нет."</string> </resources> diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml index c855be3dd624..f5e2e706e5d3 100644 --- a/packages/SystemUI/res/values-si/strings.xml +++ b/packages/SystemUI/res/values-si/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"තිර රුව සුරකින ලදී"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"ඔබගේ තිර රුව බැලීමට තට්ටු කරන්න"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"තිර රුව සුරැකිය නොහැකි විය"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"තිර රුව සුරැකීමට පෙර උපාංගය අගුලු හැරිය යුතුය"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"තිර රුව නැවත ගැනීමට උත්සාහ කරන්න"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"සීමිත ගබඩා ඉඩ නිසා තිර රුව සුරැකිය නොහැකිය"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"තිර රූ ගැනීමට යෙදුම හෝ ඔබගේ සංවිධානය ඉඩ නොදේ"</string> diff --git a/packages/SystemUI/res/values-si/strings_tv.xml b/packages/SystemUI/res/values-si/strings_tv.xml index a04d166ebea3..3067be345c7d 100644 --- a/packages/SystemUI/res/values-si/strings_tv.xml +++ b/packages/SystemUI/res/values-si/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN සම්බන්ධිතයි"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN විසන්ධි කර ඇත"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> හරහා"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"දැනුම්දීම්"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"දැනුම්දීම් නැත"</string> </resources> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index c2a94be4ad2d..22673b94ee07 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Snímka obrazovky bola uložená"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Klepnutím zobrazíte snímku obrazovky"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Snímku obrazovky sa nepodarilo uložiť"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Pred uložením snímky obrazovky je potrebné zariadenie odomknúť"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Skúste snímku urobiť znova"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Snímka obrazovky sa nedá uložiť z dôvodu nedostatku miesta v úložisku"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Vytváranie snímok obrazovky je zakázané aplikáciou alebo vašou organizáciou"</string> diff --git a/packages/SystemUI/res/values-sk/strings_tv.xml b/packages/SystemUI/res/values-sk/strings_tv.xml index 3b8fcc836c66..b37648da0e7d 100644 --- a/packages/SystemUI/res/values-sk/strings_tv.xml +++ b/packages/SystemUI/res/values-sk/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"Sieť VPN je pripojená"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Sieť VPN je odpojená"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Cez: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Upozornenia"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Žiadne upozornenia"</string> </resources> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index 5828d659efb4..42a961ceead7 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Posnetek zaslona je shranjen"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Dotaknite se, če si želite ogledati posnetek zaslona"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Posnetka zaslona ni bilo mogoče shraniti"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Pred shranjevanjem posnetka zaslona morate odkleniti napravo"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Poskusite znova ustvariti posnetek zaslona"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Shranjevanje posnetka zaslona ni mogoče zaradi omejenega prostora za shranjevanje"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Aplikacija ali vaša organizacija ne dovoljuje posnetkov zaslona"</string> diff --git a/packages/SystemUI/res/values-sl/strings_tv.xml b/packages/SystemUI/res/values-sl/strings_tv.xml index af5d75db1a56..57d70c0c3ecb 100644 --- a/packages/SystemUI/res/values-sl/strings_tv.xml +++ b/packages/SystemUI/res/values-sl/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"Povezava z navideznim zasebnim omrežjem je vzpostavljena"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Povezava z navideznim zasebnim omrežjem je prekinjena"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Prek storitve <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Obvestila"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Ni obvestil"</string> </resources> diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml index 297ebc6e6a3c..19438233c5a3 100644 --- a/packages/SystemUI/res/values-sq/strings.xml +++ b/packages/SystemUI/res/values-sq/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Pamja e ekranit u ruajt"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Trokit për të parë pamjen e ekranit"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Pamja e ekranit nuk mund të ruhej"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Pajisja duhet të shkyçet para se të mund të ruhet pamja e ekranit"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Provo ta nxjerrësh përsëri pamjen e ekranit"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Pamja e ekranit nuk mund të ruhet për shkak të hapësirës ruajtëse të kufizuar"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Nxjerrja e pamjeve të ekranit nuk lejohet nga aplikacioni ose organizata jote."</string> diff --git a/packages/SystemUI/res/values-sq/strings_tv.xml b/packages/SystemUI/res/values-sq/strings_tv.xml index 713130f30879..fb74e38b4f38 100644 --- a/packages/SystemUI/res/values-sq/strings_tv.xml +++ b/packages/SystemUI/res/values-sq/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN-ja është e lidhur"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN-ja është shkëputur"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Nëpërmjet <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Njoftimet"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Asnjë njoftim"</string> </resources> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index f9262b0e48be..50bbff217bac 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Снимак екрана је сачуван"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Додирните да бисте видели снимак екрана"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Чување снимка екрана није успело"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Уређај мора да буде откључан да би снимак екрана могао да се сачува"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Пробајте да поново направите снимак екрана"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Чување снимка екрана није успело због ограниченог меморијског простора"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Апликација или организација не дозвољавају прављење снимака екрана"</string> diff --git a/packages/SystemUI/res/values-sr/strings_tv.xml b/packages/SystemUI/res/values-sr/strings_tv.xml index 77f842c5d1fd..59151da2677f 100644 --- a/packages/SystemUI/res/values-sr/strings_tv.xml +++ b/packages/SystemUI/res/values-sr/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN је повезан"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Веза са VPN-ом је прекинута"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Преко: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Обавештења"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Нема обавештења"</string> </resources> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index 3401294139da..1aba0e335d59 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Skärmdumpen har sparats"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Visa skärmdumpen genom att trycka här"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Det gick inte att spara skärmdumpen"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Skärmdumpen kan bara sparas om enheten är upplåst"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Testa att ta en skärmdump igen"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Det går inte att spara skärmdumpen eftersom lagringsutrymmet inte räcker"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Appen eller organisationen tillåter inte att du tar skärmdumpar"</string> diff --git a/packages/SystemUI/res/values-sv/strings_tv.xml b/packages/SystemUI/res/values-sv/strings_tv.xml index 141aabf207aa..d7261e6b1445 100644 --- a/packages/SystemUI/res/values-sv/strings_tv.xml +++ b/packages/SystemUI/res/values-sv/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN är anslutet"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN är frånkopplat"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Aviseringar"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Inga aviseringar"</string> </resources> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index 4cf09c775c20..f02cc912d2de 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Imehifadhi picha ya skrini"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Gusa ili utazame picha ya skrini uliyohifadhi"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Imeshindwa kuhifadhi picha ya skrini"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Ni sharti ufungue kifaa kabla ya kuhifadhi picha ya skrini"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Jaribu kupiga picha ya skrini tena"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Imeshindwa kuhifadhi picha ya skrini kwa sababu nafasi haitoshi"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Programu au shirika lako halikuruhusu kupiga picha za skrini"</string> diff --git a/packages/SystemUI/res/values-sw/strings_tv.xml b/packages/SystemUI/res/values-sw/strings_tv.xml index 9dd37ce63bb3..8f6880d4bd0b 100644 --- a/packages/SystemUI/res/values-sw/strings_tv.xml +++ b/packages/SystemUI/res/values-sw/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN imeunganishwa"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN imeondolewa"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Kupitia <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Arifa"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Hakuna Arifa"</string> </resources> diff --git a/packages/SystemUI/res/values-sw600dp/config.xml b/packages/SystemUI/res/values-sw600dp/config.xml index be66320975d9..d886f00cf028 100644 --- a/packages/SystemUI/res/values-sw600dp/config.xml +++ b/packages/SystemUI/res/values-sw600dp/config.xml @@ -32,4 +32,7 @@ <!-- orientation of the dead zone when touches have recently occurred elsewhere on screen --> <integer name="navigation_bar_deadzone_orientation">0</integer> + <!-- Whether wallet view is shown in landscape / seascape orientations --> + <bool name="global_actions_show_landscape_wallet_view">true</bool> + </resources> diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml index fdf4e3b1b796..3be73ba8df25 100644 --- a/packages/SystemUI/res/values-sw600dp/dimens.xml +++ b/packages/SystemUI/res/values-sw600dp/dimens.xml @@ -94,4 +94,11 @@ <!-- Text size for user name in user switcher --> <dimen name="kg_user_switcher_text_size">18sp</dimen> + + <!-- TODO(himanshujaju) - add comments --> + <dimen name="global_actions_wallet_top_margin">5dp</dimen> + <dimen name="controls_header_bottom_margin">12dp</dimen> + <dimen name="controls_top_margin">24dp</dimen> + + <dimen name="global_actions_grid_item_layout_height">80dp</dimen> </resources> diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml index 5d29c91998bf..a9a3b07a1389 100644 --- a/packages/SystemUI/res/values-ta/strings.xml +++ b/packages/SystemUI/res/values-ta/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"ஸ்கிரீன்ஷாட் சேமிக்கப்பட்டது"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"ஸ்கிரீன்ஷாட்டைப் பார்க்க, தட்டவும்"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"ஸ்கிரீன் ஷாட்டைச் சேமிக்க முடியவில்லை"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ஸ்கிரீன்ஷாட் சேமிக்கப்படுவதற்கு முன்பு சாதனம் அன்லாக் செய்யப்பட வேண்டும்"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ஸ்கிரீன் ஷாட்டை மீண்டும் எடுக்க முயலவும்"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"போதுமான சேமிப்பிடம் இல்லாததால் ஸ்கிரீன்ஷாட்டைச் சேமிக்க முடியவில்லை"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ஸ்கிரீன் ஷாட்டுகளை எடுப்பதை, ஆப்ஸ் அல்லது உங்கள் நிறுவனம் அனுமதிக்கவில்லை"</string> @@ -935,7 +936,7 @@ <string name="notification_channel_general" msgid="4384774889645929705">"பொதுச் செய்திகள்"</string> <string name="notification_channel_storage" msgid="2720725707628094977">"சேமிப்பிடம்"</string> <string name="notification_channel_hints" msgid="7703783206000346876">"குறிப்புகள்"</string> - <string name="instant_apps" msgid="8337185853050247304">"இன்ஸ்டண்ட் ஆப்ஸ்"</string> + <string name="instant_apps" msgid="8337185853050247304">"Instant Apps"</string> <string name="instant_apps_title" msgid="8942706782103036910">"<xliff:g id="APP">%1$s</xliff:g> இயங்குகிறது"</string> <string name="instant_apps_message" msgid="6112428971833011754">"நிறுவ வேண்டிய தேவையில்லாமல் ஆப்ஸ் திறக்கப்பட்டது."</string> <string name="instant_apps_message_with_help" msgid="1816952263531203932">"நிறுவ வேண்டிய தேவையில்லாமல் ஆப்ஸ் திறக்கப்பட்டது. மேலும் அறியத் தட்டவும்."</string> diff --git a/packages/SystemUI/res/values-ta/strings_tv.xml b/packages/SystemUI/res/values-ta/strings_tv.xml index 04832016cf67..9c62d8cf7b96 100644 --- a/packages/SystemUI/res/values-ta/strings_tv.xml +++ b/packages/SystemUI/res/values-ta/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN இணைக்கப்பட்டது"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN துண்டிக்கப்பட்டது"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> வழியாக"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"அறிவிப்புகள்"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"அறிவிப்புகள் எதுவுமில்லை"</string> </resources> diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index 5fed052d9f5b..7e7dc374af20 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"స్క్రీన్షాట్ సేవ్ చేయబడింది"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"మీ స్క్రీన్షాట్ను వీక్షించడానికి నొక్కండి"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"స్క్రీన్షాట్ని సేవ్ చేయడం సాధ్యం కాలేదు"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"స్క్రీన్షాట్ సేవ్ అవ్వకముందే పరికరం అన్లాక్ చేయబడాలి"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"స్క్రీన్షాట్ తీయడానికి మళ్లీ ప్రయత్నించండి"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"నిల్వ స్థలం పరిమితంగా ఉన్న కారణంగా స్క్రీన్షాట్ను సేవ్ చేయడం సాధ్యపడదు"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"స్క్రీన్షాట్లు తీయడానికి యాప్ లేదా మీ సంస్థ అనుమతించలేదు"</string> diff --git a/packages/SystemUI/res/values-te/strings_tv.xml b/packages/SystemUI/res/values-te/strings_tv.xml index 67fb678466cb..50f4b4531eb7 100644 --- a/packages/SystemUI/res/values-te/strings_tv.xml +++ b/packages/SystemUI/res/values-te/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN కనెక్ట్ చేయబడింది"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN డిస్కనెక్ట్ చేయబడింది"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> ద్వారా"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"నోటిఫికేషన్లు"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"నోటిఫికేషన్లు లేవు"</string> </resources> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index ffa84d3531ee..a18ec8acecf8 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"บันทึกภาพหน้าจอแล้ว"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"แตะเพื่อดูภาพหน้าจอ"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"บันทึกภาพหน้าจอไม่ได้"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"ต้องปลดล็อกอุปกรณ์ก่อนจึงจะบันทึกภาพหน้าจอได้"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"ลองบันทึกภาพหน้าจออีกครั้ง"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"บันทึกภาพหน้าจอไม่ได้เนื่องจากพื้นที่เก็บข้อมูลมีจำกัด"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"แอปหรือองค์กรของคุณไม่อนุญาตให้จับภาพหน้าจอ"</string> diff --git a/packages/SystemUI/res/values-th/strings_tv.xml b/packages/SystemUI/res/values-th/strings_tv.xml index 4a9144b227fa..072482176363 100644 --- a/packages/SystemUI/res/values-th/strings_tv.xml +++ b/packages/SystemUI/res/values-th/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"เชื่อมต่อ VPN แล้ว"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"ยกเลิกการเชื่อมต่อ VPN แล้ว"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"ผ่าน <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"การแจ้งเตือน"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"ไม่มีการแจ้งเตือน"</string> </resources> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index b8cdef1979ad..a68f5adfb446 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Na-save ang screenshot"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"I-tap upang tingnan ang iyong screenshot"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Hindi ma-save ang screenshot"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Dapat naka-unlock ang device bago ma-save ang screenshot"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Subukang kumuhang muli ng screenshot"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Hindi ma-save ang screenshot dahil sa limitadong espasyo ng storage"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Hindi pinahihintulutan ng app o ng iyong organisasyon ang pagkuha ng mga screenshot"</string> diff --git a/packages/SystemUI/res/values-tl/strings_tv.xml b/packages/SystemUI/res/values-tl/strings_tv.xml index 3489503652ea..8dcc22f2d36b 100644 --- a/packages/SystemUI/res/values-tl/strings_tv.xml +++ b/packages/SystemUI/res/values-tl/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"Nakakonekta ang VPN"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Nakadiskonekta ang VPN"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Sa pamamagitan ng <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Mga Notification"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Walang Notification"</string> </resources> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index 74666b2ec0c3..d0d343cea159 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Ekran görüntüsü kaydedildi"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Ekran görüntünüzü görmek için dokunun"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Ekran görüntüsü kaydedilemedi"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Ekran görüntüsünün kaydedilebilmesi için cihazın kilidi açık olmalıdır"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Tekrar ekran görüntüsü almayı deneyin"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Depolama alanı sınırlı olduğundan ekran görüntüsü kaydedilemiyor"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Uygulama veya kuruluşunuz, ekran görüntüsü alınmasına izin vermiyor."</string> diff --git a/packages/SystemUI/res/values-tr/strings_tv.xml b/packages/SystemUI/res/values-tr/strings_tv.xml index bfb1ae24c890..babd460a1375 100644 --- a/packages/SystemUI/res/values-tr/strings_tv.xml +++ b/packages/SystemUI/res/values-tr/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN bağlandı"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN bağlantısı kesildi"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> yoluyla"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Bildirimler"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Bildirim Yok"</string> </resources> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index 2737ce892f71..26bc66277d4e 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -28,7 +28,7 @@ <string name="battery_low_percent_format" msgid="4276661262843170964">"Залишилося <xliff:g id="PERCENTAGE">%s</xliff:g>"</string> <string name="battery_low_percent_format_hybrid" msgid="3985614339605686167">"На основі використання залишилося <xliff:g id="PERCENTAGE">%1$s</xliff:g> – близько <xliff:g id="TIME">%2$s</xliff:g>"</string> <string name="battery_low_percent_format_hybrid_short" msgid="5917433188456218857">"Залишилося <xliff:g id="PERCENTAGE">%1$s</xliff:g> – близько <xliff:g id="TIME">%2$s</xliff:g>"</string> - <string name="battery_low_percent_format_saver_started" msgid="4968468824040940688">"Залишилося <xliff:g id="PERCENTAGE">%s</xliff:g>. Увімкнено режим економії заряду акумулятора."</string> + <string name="battery_low_percent_format_saver_started" msgid="4968468824040940688">"Залишилося <xliff:g id="PERCENTAGE">%s</xliff:g>. Увімкнено режим енергозбереження."</string> <string name="invalid_charger" msgid="4370074072117767416">"Не вдається зарядити через USB. Використовуйте зарядний пристрій, який входить у комплект пристрою."</string> <string name="invalid_charger_title" msgid="938685362320735167">"Не вдається зарядити через USB"</string> <string name="invalid_charger_text" msgid="2339310107232691577">"Використовуйте зарядний пристрій, який входить у комплект пристрою"</string> @@ -36,7 +36,7 @@ <string name="battery_saver_confirmation_title" msgid="1234998463717398453">"Увімкнути режим енергозбереження?"</string> <string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"Про режим енергозбереження"</string> <string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"Увімкнути"</string> - <string name="battery_saver_start_action" msgid="4553256017945469937">"Увімкнути режим економії заряду акумулятора"</string> + <string name="battery_saver_start_action" msgid="4553256017945469937">"Увімкнути режим енергозбереження"</string> <string name="status_bar_settings_settings_button" msgid="534331565185171556">"Налаштування"</string> <string name="status_bar_settings_wifi_button" msgid="7243072479837270946">"Wi-Fi"</string> <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Автообертання екрана"</string> @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Знімок екрана збережено"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Торкніться, щоб переглянути знімок екрана"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Не вдалося зберегти знімок екрана"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Щоб зберегти знімок екрана, розблокуйте пристрій"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Спробуйте зробити знімок екрана ще раз"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Не вдалося зберегти знімок екрана через обмежений обсяг пам’яті"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Додаток або адміністратор вашої організації не дозволяють робити знімки екрана"</string> @@ -509,7 +510,7 @@ <string name="user_remove_user_remove" msgid="8387386066949061256">"Видалити"</string> <string name="battery_saver_notification_title" msgid="8419266546034372562">"Режим енергозбереження ввімкнено"</string> <string name="battery_saver_notification_text" msgid="2617841636449016951">"Знижується продуктивність і обмежуються фонові дані"</string> - <string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Вимкнути режим економії заряду акумулятора"</string> + <string name="battery_saver_notification_action_text" msgid="6022091913807026887">"Вимкнути режим енергозбереження"</string> <string name="media_projection_dialog_text" msgid="1755705274910034772">"Додаток <xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> матиме доступ до всієї інформації, яка з\'являється на екрані або відтворюється на пристрої під час запису чи трансляції, зокрема до паролів, інформації про платежі, фотографій, повідомлень і аудіофайлів."</string> <string name="media_projection_dialog_service_text" msgid="958000992162214611">"Сервіс, що надає цю функцію, матиме доступ до всієї інформації, яка з\'являється на екрані або відтворюється на пристрої під час запису чи трансляції, зокрема до паролів, інформації про платежі, фотографій, повідомлень і аудіофайлів."</string> <string name="media_projection_dialog_service_title" msgid="2888507074107884040">"Почати запис або трансляцію?"</string> @@ -975,11 +976,11 @@ <string name="slice_permission_checkbox" msgid="4242888137592298523">"Дозволити додатку <xliff:g id="APP">%1$s</xliff:g> показувати фрагменти будь-якого додатка"</string> <string name="slice_permission_allow" msgid="6340449521277951123">"Дозволити"</string> <string name="slice_permission_deny" msgid="6870256451658176895">"Заборонити"</string> - <string name="auto_saver_title" msgid="6873691178754086596">"Торкніться, щоб увімкнути автоматичний режим економії заряду акумулятора"</string> + <string name="auto_saver_title" msgid="6873691178754086596">"Торкніться, щоб налаштувати режим енергозбереження"</string> <string name="auto_saver_text" msgid="3214960308353838764">"Вмикати, коли заряд акумулятора закінчується"</string> <string name="no_auto_saver_action" msgid="7467924389609773835">"Ні, дякую"</string> <string name="auto_saver_enabled_title" msgid="4294726198280286333">"Автоматичний перехід у режим енергозбереження ввімкнено"</string> - <string name="auto_saver_enabled_text" msgid="7889491183116752719">"Режим економії заряду акумулятора вмикається автоматично, коли рівень заряду нижчий за <xliff:g id="PERCENTAGE">%d</xliff:g>%%."</string> + <string name="auto_saver_enabled_text" msgid="7889491183116752719">"Режим енергозбереження вмикається автоматично, коли рівень заряду нижчий за <xliff:g id="PERCENTAGE">%d</xliff:g>%%."</string> <string name="open_saver_setting_action" msgid="2111461909782935190">"Налаштування"</string> <string name="auto_saver_okay_action" msgid="7815925750741935386">"OK"</string> <string name="heap_dump_tile_name" msgid="2464189856478823046">"Dump SysUI Heap"</string> diff --git a/packages/SystemUI/res/values-uk/strings_tv.xml b/packages/SystemUI/res/values-uk/strings_tv.xml index 4a4cac92e6c1..170b06805355 100644 --- a/packages/SystemUI/res/values-uk/strings_tv.xml +++ b/packages/SystemUI/res/values-uk/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"Мережу VPN під\'єднано"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Мережу VPN від\'єднано"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Через <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Сповіщення"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Немає сповіщень"</string> </resources> diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml index 7488323b00c0..53072498974c 100644 --- a/packages/SystemUI/res/values-ur/strings.xml +++ b/packages/SystemUI/res/values-ur/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"اسکرین شاٹ محفوظ ہو گیا"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"اپنا اسکرین شاٹ دیکھنے کیلئے تھپتھپائیں"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"اسکرین شاٹ کو محفوظ نہیں کیا جا سکا"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"اسکرین شاٹ محفوظ کرنے سے پہلے آلے کو غیر مقفل کرنا ضروری ہے"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"دوبارہ اسکرین شاٹ لینے کی کوشش کریں"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"اسٹوریج کی محدود جگہ کی وجہ سے اسکرین شاٹ کو محفوظ نہیں کیا جا سکتا"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ایپ یا آپ کی تنظیم کی جانب سے اسکرین شاٹس لینے کی اجازت نہیں ہے"</string> diff --git a/packages/SystemUI/res/values-ur/strings_tv.xml b/packages/SystemUI/res/values-ur/strings_tv.xml index 20d3a587af48..fbaa3f628bf3 100644 --- a/packages/SystemUI/res/values-ur/strings_tv.xml +++ b/packages/SystemUI/res/values-ur/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN منسلک ہے"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN غیر منسلک ہے"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"بذریعہ <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"اطلاعات"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"کوئی اطلاع نہیں ہے"</string> </resources> diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml index 997197da19cb..b2ba26d6b92e 100644 --- a/packages/SystemUI/res/values-uz/strings.xml +++ b/packages/SystemUI/res/values-uz/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Skrinshot saqlandi"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Skrinshotni ochish uchun bosing"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Skrinshot saqlanmadi"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Skrinshotni saqlashdan oldin qurilma qulflanmagan boʻlishi lozim"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Qayta skrinshot olib ko‘ring"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Xotirada joy kamligi uchun skrinshot saqlanmadi"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Ilova yoki tashkilotingiz skrinshot olishni taqiqlagan"</string> @@ -778,7 +779,7 @@ </plurals> <string name="battery_panel_title" msgid="5931157246673665963">"Batareya sarfi"</string> <string name="battery_detail_charging_summary" msgid="8821202155297559706">"Quvvat tejash rejimidan quvvatlash vaqtida foydalanib bo‘lmaydi"</string> - <string name="battery_detail_switch_title" msgid="6940976502957380405">"Quvvat tejash rejimi"</string> + <string name="battery_detail_switch_title" msgid="6940976502957380405">"Quvvat tejash"</string> <string name="battery_detail_switch_summary" msgid="3668748557848025990">"Unumdorlik pasayadi va fonda internetdan foydalanish cheklanadi"</string> <string name="keyboard_key_button_template" msgid="8005673627272051429">"<xliff:g id="NAME">%1$s</xliff:g> tugmasi"</string> <string name="keyboard_key_home" msgid="3734400625170020657">"Bosh ekran"</string> diff --git a/packages/SystemUI/res/values-uz/strings_tv.xml b/packages/SystemUI/res/values-uz/strings_tv.xml index fc4ecd34873f..f4b4b0853e69 100644 --- a/packages/SystemUI/res/values-uz/strings_tv.xml +++ b/packages/SystemUI/res/values-uz/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ulandi"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN uzildi"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> orqali"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Bildirishnomalar"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Bildirishnomalar yoʻq"</string> </resources> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index 1acdbb51c859..a5d490041516 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Đã lưu ảnh chụp màn hình"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Nhấn để xem ảnh chụp màn hình của bạn"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Không thể lưu ảnh chụp màn hình"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Bạn phải mở khóa thiết bị để chúng tôi có thể lưu ảnh chụp màn hình"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Hãy thử chụp lại màn hình"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Không thể lưu ảnh chụp màn hình do giới hạn dung lượng bộ nhớ"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Ứng dụng hoặc tổ chức của bạn không cho phép chụp ảnh màn hình"</string> diff --git a/packages/SystemUI/res/values-vi/strings_tv.xml b/packages/SystemUI/res/values-vi/strings_tv.xml index 98697fd93204..3dfc8c186205 100644 --- a/packages/SystemUI/res/values-vi/strings_tv.xml +++ b/packages/SystemUI/res/values-vi/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN đã được kết nối"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN đã bị ngắt kết nối"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Thông qua <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Thông báo"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Không có thông báo"</string> </resources> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index 68630bba8212..10873c5ca125 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"已保存屏幕截图"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"点按即可查看您的屏幕截图"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"无法保存屏幕截图"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"必须先解锁设备,然后才能保存屏幕截图"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"请再次尝试截屏"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"由于存储空间有限,无法保存屏幕截图"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"此应用或您所在的单位不允许进行屏幕截图"</string> diff --git a/packages/SystemUI/res/values-zh-rCN/strings_tv.xml b/packages/SystemUI/res/values-zh-rCN/strings_tv.xml index 169d98a538ed..1e599cabcd0b 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings_tv.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN 已连接"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN 已断开连接"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"通过“<xliff:g id="VPN_APP">%1$s</xliff:g>”"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"通知"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"没有通知"</string> </resources> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index ddf60fb56e20..9abcf109d9f9 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"螢幕擷取畫面已儲存"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"輕按即可查看螢幕擷取畫面"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"無法儲存螢幕擷取畫面"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"必須先解鎖裝置,才能儲存螢幕截圖"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"請再嘗試拍攝螢幕擷取畫面"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"由於儲存空間有限,因此無法儲存螢幕擷取畫面"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"應用程式或您的機構不允許擷取螢幕畫面"</string> diff --git a/packages/SystemUI/res/values-zh-rHK/strings_tv.xml b/packages/SystemUI/res/values-zh-rHK/strings_tv.xml index 858185186365..92b176261f7b 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings_tv.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN 已連線"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN 已中斷連線"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"透過 <xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"通知"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"沒有通知"</string> </resources> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index 85aae2e9453b..a33146bd57e3 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"螢幕截圖已儲存"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"輕觸即可查看螢幕截圖"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"無法儲存螢幕截圖"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"必須先解鎖裝置,才能儲存螢幕截圖"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"請再次嘗試拍攝螢幕截圖"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"由於儲存空間有限,因此無法儲存螢幕截圖"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"這個應用程式或貴機構不允許擷取螢幕畫面"</string> diff --git a/packages/SystemUI/res/values-zh-rTW/strings_tv.xml b/packages/SystemUI/res/values-zh-rTW/strings_tv.xml index fcb16b79c3ad..db0781acf3b5 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings_tv.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN 已連線"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN 連線已中斷"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"透過「<xliff:g id="VPN_APP">%1$s</xliff:g>」"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"通知"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"沒有通知"</string> </resources> diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index ca87d975e42e..5c8b6cd4d5df 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -83,6 +83,7 @@ <string name="screenshot_saved_title" msgid="8893267638659083153">"Isithombe-skrini silondoloziwe"</string> <string name="screenshot_saved_text" msgid="7778833104901642442">"Thepha ukuze ubuke isithombe-skrini sakho"</string> <string name="screenshot_failed_title" msgid="3259148215671936891">"Ayikwazanga ukulondoloza isithombe-skrini"</string> + <string name="screenshot_failed_to_save_user_locked_text" msgid="6156607948256936920">"Idivayisi kufanele ivulwe ngaphambi kokuthi isithombe-skrini singalondolozwa"</string> <string name="screenshot_failed_to_save_unknown_text" msgid="1506621600548684129">"Zama ukuthatha isithombe-skrini futhi"</string> <string name="screenshot_failed_to_save_text" msgid="8344173457344027501">"Ayikwazi ukulondoloza isithombe-skrini ngenxa yesikhala sesitoreji esikhawulelwe"</string> <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Ukuthatha izithombe-skrini akuvunyelwe uhlelo lokusebenza noma inhlangano yakho"</string> diff --git a/packages/SystemUI/res/values-zu/strings_tv.xml b/packages/SystemUI/res/values-zu/strings_tv.xml index 5cb6c1d1796e..a9b759766078 100644 --- a/packages/SystemUI/res/values-zu/strings_tv.xml +++ b/packages/SystemUI/res/values-zu/strings_tv.xml @@ -24,4 +24,6 @@ <string name="notification_vpn_connected" msgid="3891023882833274730">"I-VPN ixhunyiwe"</string> <string name="notification_vpn_disconnected" msgid="7150747626448044843">"I-VPN inqanyuliwe"</string> <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Nge-<xliff:g id="VPN_APP">%1$s</xliff:g>"</string> + <string name="tv_notification_panel_title" msgid="5311050946506276154">"Izaziso"</string> + <string name="tv_notification_panel_no_notifications" msgid="9115191912267270678">"Azikho Izaziso"</string> </resources> diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml index 78d92c4b47e2..897e3902b55c 100644 --- a/packages/SystemUI/res/values/attrs.xml +++ b/packages/SystemUI/res/values/attrs.xml @@ -161,5 +161,11 @@ <attr name="sensorPressureCoefficient" format="float"/> <attr name="sensorTouchAreaCoefficient" format="float"/> </declare-styleable> + + <declare-styleable name="AlphaTintDrawableWrapper"> + <attr name="android:tint" /> + <attr name="android:drawable" /> + <attr name="android:alpha" /> + </declare-styleable> </resources> diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index c51e0bf2c31b..9731d786eb7f 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -35,8 +35,7 @@ <color name="status_bar_clock_color">#FFFFFFFF</color> <color name="qs_user_detail_icon_muted">#FFFFFFFF</color> <!-- not so muted after all --> <color name="qs_tile_disabled_color">#9E9E9E</color> <!-- 38% black --> - <color name="qs_customize_background">@color/GM2_grey_50</color> - <color name="qs_customize_decoration">@color/GM2_grey_100</color> + <color name="qs_customize_decoration">@color/GM2_grey_300</color> <!-- The color of the background in the separated list of the Global Actions menu --> <color name="global_actions_separated_background">#F5F5F5</color> @@ -257,6 +256,8 @@ <color name="control_enabled_heat_foreground">#FF8B66</color> <color name="control_enabled_default_foreground">@color/GM2_blue_300</color> <color name="control_enabled_cool_foreground">@color/GM2_blue_300</color> + <color name="control_thumbnail_tint">#33000000</color> + <color name="control_thumbnail_shadow_color">@*android:color/black</color> <!-- Docked misalignment message --> <color name="misalignment_text_color">#F28B82</color> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 880dd378e390..101124ec2a2e 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -24,10 +24,6 @@ certain GPU's and thus can be turned off with only minimal visual impact. --> <bool name="config_notifications_round_rect_clipping">true</bool> - <!-- Control whether status bar should distinguish HSPA data icon form UMTS - data icon on devices --> - <bool name="config_hspa_data_distinguishable">false</bool> - <!-- Component to be used as the status bar service. Must implement the IStatusBar interface. This name is in the ComponentName flattened format (package/class) --> <string name="config_statusBarComponent" translatable="false">com.android.systemui.statusbar.phone.StatusBar</string> @@ -56,9 +52,6 @@ <!-- Show phone (voice) signal strength instead of data in mobile RSSI. --> <bool name="config_showPhoneRSSIForData">false</bool> - <!-- When true, show 1/2G networks as 3G. --> - <bool name="config_showMin3G">false</bool> - <!-- Show rotation lock toggle in System UI--> <bool name="config_showRotationLock">true</bool> @@ -358,7 +351,7 @@ <bool name="config_showNotificationGear">true</bool> <!-- Whether or not a background should be drawn behind a notification. --> - <bool name="config_drawNotificationBackground">true</bool> + <bool name="config_drawNotificationBackground">false</bool> <!-- Whether or the notifications can be shown and dismissed with a drag. --> <bool name="config_enableNotificationShadeDrag">true</bool> @@ -570,4 +563,7 @@ <bool name="config_showNotificationForUnknownBatteryState">false</bool> <!-- content URL in a notification when ACTION_BATTERY_CHANGED.EXTRA_PRESENT field is false --> <string translatable="false" name="config_batteryStateUnknownUrl"></string> + + <!-- Whether wallet view is shown in landscape / seascape orientations --> + <bool name="global_actions_show_landscape_wallet_view">false</bool> </resources> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index a9601336c6e2..e1f7e7e56726 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -1005,6 +1005,7 @@ <dimen name="global_actions_grid_vertical_padding">3dp</dimen> <dimen name="global_actions_grid_horizontal_padding">3dp</dimen> + <dimen name="global_actions_grid_item_layout_height">98dp</dimen> <dimen name="global_actions_grid_item_side_margin">5dp</dimen> <dimen name="global_actions_grid_item_vertical_margin">4dp</dimen> <dimen name="global_actions_grid_item_width">64dp</dimen> @@ -1269,6 +1270,10 @@ <dimen name="controls_app_divider_height">2dp</dimen> <dimen name="controls_app_divider_side_margin">32dp</dimen> + <item name="controls_thumbnail_shadow_x" type="dimen" format="float">2.0</item> + <item name="controls_thumbnail_shadow_y" type="dimen" format="float">2.0</item> + <item name="controls_thumbnail_shadow_radius" type="dimen" format="float">2.0</item> + <dimen name="controls_card_margin">@dimen/control_base_item_margin</dimen> <item name="control_card_elevation" type="dimen" format="float">15</item> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 7989b7a08fc8..6fa4aa116aa4 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -450,28 +450,6 @@ <!-- Content description of the battery when battery state is unknown for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_battery_unknown">Battery percentage unknown.</string> - <!-- Content description of the phone signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> - <string name="accessibility_no_phone">No phone.</string> - <!-- Content description of the phone signal when it is one bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> - <string name="accessibility_phone_one_bar">Phone one bar.</string> - <!-- Content description of the phone signal when it is two bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> - <string name="accessibility_phone_two_bars">Phone two bars.</string> - <!-- Content description of the phone signal when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> - <string name="accessibility_phone_three_bars">Phone three bars.</string> - <!-- Content description of the phone signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> - <string name="accessibility_phone_signal_full">Phone signal full.</string> - - <!-- Content description of the data signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> - <string name="accessibility_no_data">No data.</string> - <!-- Content description of the data signal when it is one bar for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> - <string name="accessibility_data_one_bar">Data one bar.</string> - <!-- Content description of the data signal when it is two bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> - <string name="accessibility_data_two_bars">Data two bars.</string> - <!-- Content description of the data signal when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> - <string name="accessibility_data_three_bars">Data three bars.</string> - <!-- Content description of the data signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> - <string name="accessibility_data_signal_full">Data signal full.</string> - <!-- Content description of the wifi label showing what we are connected to. [CHAR LIMIT=NONE] --> <string name="accessibility_wifi_name">Connected to <xliff:g id="wifi" example="Home Network">%s</xliff:g>.</string> @@ -493,11 +471,6 @@ <!-- Content description of the WiMAX signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_wimax_signal_full">WiMAX signal full.</string> - <!-- Content description of the Ethernet connection when disconnected for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> - <string name="accessibility_ethernet_disconnected">Ethernet disconnected.</string> - <!-- Content description of the Ethernet connection when connected for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> - <string name="accessibility_ethernet_connected">Ethernet connected.</string> - <!-- Content description of an item with no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_no_signal">No signal.</string> <!-- Content description of an item with no signal and no connection for accessibility (not shown on the screen) [CHAR LIMIT=NONE] --> @@ -522,54 +495,16 @@ <!-- Content description of an item that is connecting for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_desc_connecting">Connecting.</string> - <!-- Content description of the data connection type GPRS. [CHAR LIMIT=NONE] --> - <string name="data_connection_gprs">GPRS</string> - <!-- Content description of the data connection type HSPA and its variants. [CHAR LIMIT=NONE] --> <string name="data_connection_hspa">HSPA</string> - <!-- Content description of the data connection type 3G. [CHAR LIMIT=NONE] --> - <string name="data_connection_3g">3G</string> - - <!-- Content description of the data connection type 3.5G. [CHAR LIMIT=NONE] --> - <string name="data_connection_3_5g">H</string> - - <!-- Content description of the data connection type 3.5G+. [CHAR LIMIT=NONE] --> - <string name="data_connection_3_5g_plus">H+</string> - - <!-- Content description of the data connection type 4G . [CHAR LIMIT=NONE] --> - <string name="data_connection_4g">4G</string> - - <!-- Content description of the data connection type 4G+. [CHAR LIMIT=NONE] --> - <string name="data_connection_4g_plus">4G+</string> - - <!-- Content description of the data connection type LTE. [CHAR LIMIT=NONE] --> - <string name="data_connection_lte">LTE</string> - - <!-- Content description of the data connection type LTE+. [CHAR LIMIT=NONE] --> - <string name="data_connection_lte_plus">LTE+</string> - <!-- Content description of the data connection type 5Ge. [CHAR LIMIT=NONE] --> <string name="data_connection_5ge" translatable="false">5Ge</string> - <!-- Content description of the data connection type 5Ge with HTML styling. DO NOT TRANSLATE [CHAR LIMIT=NONE] --> - <string name="data_connection_5ge_html" translate="false"> <i>5G <small>E</small></i> </string> - - <!-- Content description of the data connection type 5G. [CHAR LIMIT=NONE] --> - <string name="data_connection_5g" translatable="false">5G</string> - - <!-- Content description of the data connection type 5G+. [CHAR LIMIT=NONE] --> - <string name="data_connection_5g_plus" translatable="false">5G+</string> - - <!-- Content description of the data connection type CDMA. [CHAR LIMIT=NONE] --> - <string name="data_connection_cdma">1X</string> <!-- Content description of the roaming data connection type. [CHAR LIMIT=NONE] --> <string name="data_connection_roaming">Roaming</string> - <!-- Content description of the data connection type Edge. [CHAR LIMIT=NONE] --> - <string name="data_connection_edge">EDGE</string> - <!-- Content description of the data connection type WiFi for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_data_connection_wifi">Wi-Fi</string> @@ -582,12 +517,6 @@ <!-- Content description of the cell data being enabled. [CHAR LIMIT=NONE] --> <string name="accessibility_cell_data_on">Mobile Data On</string> - <!-- Content description of the cell data being disabled. [CHAR LIMIT=NONE] --> - <string name="cell_data_off_content_description">Mobile data off</string> - - <!-- Content description of the cell data for not default subscription. [CHAR LIMIT=NONE] --> - <string name="not_default_data_content_description">Not set to use data</string> - <!-- Content description of the cell data being disabled but shortened. [CHAR LIMIT=20] --> <string name="cell_data_off">Off</string> @@ -603,9 +532,6 @@ <!-- Content description of the no sim icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_no_sims">No SIM card.</string> - <!-- Content description of the carrier network changing icon. [CHAR LIMIT=NONE] --> - <string name="carrier_network_change_mode">Carrier network changing</string> - <!-- Content description of button to open battery details icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_battery_details">Open battery details</string> @@ -1876,6 +1802,18 @@ <!-- [CHAR LIMIT=150] Notification Importance title: automatic importance level summary --> <string name="notification_channel_summary_automatic">Have the system determine if this notification should make sound or vibration</string> + <!-- [CHAR LIMIT=150] Notification Importance title: automatic importance level summary (alerted) --> + <string name="notification_channel_summary_automatic_alerted"><b>Status:</b> Promoted to Default</string> + + <!-- [CHAR LIMIT=150] Notification Importance title: automatic importance level summary (silenced) --> + <string name="notification_channel_summary_automatic_silenced"><b>Status:</b> Demoted to Silent</string> + + <!-- [CHAR LIMIT=150] Notification Importance title: automatic importance level summary (promoted) --> + <string name="notification_channel_summary_automatic_promoted"><b>Status:</b> Ranked Higher</string> + + <!-- [CHAR LIMIT=150] Notification Importance title: automatic importance level summary (demoted) --> + <string name="notification_channel_summary_automatic_demoted"><b>Status:</b> Ranked Lower</string> + <!-- [CHAR LIMIT=150] Notification Importance title: important conversation level summary --> <string name="notification_channel_summary_priority">Shows at top of conversation section, appears as floating bubble, displays profile picture on lock screen</string> @@ -1922,11 +1860,13 @@ <string name="notification_appops_ok">OK</string> <!-- Notification Inline controls: describes how the notification was adjusted [CHAR_LIMIT=NONE] --> - <string name="feedback_silenced">This notification was silenced by the system.</string> + <string name="feedback_alerted">This notification was automatically <b>promoted to Default</b> by the system.</string> + <!-- Notification Inline controls: describes how the notification was adjusted [CHAR_LIMIT=NONE] --> + <string name="feedback_silenced">This notification was automatically <b>demoted to Silent</b> by the system.</string> <!-- Notification Inline controls: describes how the notification was adjusted [CHAR_LIMIT=NONE] --> - <string name="feedback_promoted">This notification was promoted by the system.</string> + <string name="feedback_promoted">This notification was automatically <b>ranked higher</b> in your shade.</string> <!-- Notification Inline controls: describes how the notification was adjusted [CHAR_LIMIT=NONE] --> - <string name="feedback_demoted">This notification was demoted by the system.</string> + <string name="feedback_demoted">This notification was automatically <b>ranked lower</b> in your shade.</string> <!-- Notification Inline controls: prompts the user for feedback [CHAR_LIMIT=NONE] --> <string name="feedback_prompt">Was this correct?</string> <!-- Notification Inline controls: responds to user provided feedback [CHAR_LIMIT=NONE] --> diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/BitmapUtil.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/BitmapUtil.java index b79fcbd43972..325bcfc622d7 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/BitmapUtil.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/BitmapUtil.java @@ -81,6 +81,7 @@ public final class BitmapUtil { HardwareBuffer buffer = bundle.getParcelable(KEY_BUFFER); ParcelableColorSpace colorSpace = bundle.getParcelable(KEY_COLOR_SPACE); - return Bitmap.wrapHardwareBuffer(Objects.requireNonNull(buffer), colorSpace); + return Bitmap.wrapHardwareBuffer(Objects.requireNonNull(buffer), + colorSpace.getColorSpace()); } } 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 611c4b766b4e..fa2f8b97b039 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 @@ -137,4 +137,15 @@ public class RecentsAnimationControllerCompat { return false; } } + + /** + * @see IRecentsAnimationController#detachNavigationBarFromApp + */ + public void detachNavigationBarFromApp() { + try { + mAnimationController.detachNavigationBarFromApp(); + } catch (RemoteException e) { + Log.e(TAG, "Failed to detach the navigation bar from app", e); + } + } }
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java deleted file mode 100644 index c0f8cae607ca..000000000000 --- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui; - -import android.annotation.NonNull; -import android.app.Notification; -import android.os.Handler; -import android.os.Looper; -import android.util.ArraySet; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.systemui.statusbar.NotificationInteractionTracker; -import com.android.systemui.statusbar.NotificationLifetimeExtender; -import com.android.systemui.statusbar.notification.collection.NotificationEntry; -import com.android.systemui.util.time.SystemClock; - -import javax.inject.Inject; - -/** - * Extends the lifetime of foreground notification services such that they show for at least - * five seconds - */ -public class ForegroundServiceLifetimeExtender implements NotificationLifetimeExtender { - - private static final String TAG = "FGSLifetimeExtender"; - @VisibleForTesting - static final int MIN_FGS_TIME_MS = 5000; - - private NotificationSafeToRemoveCallback mNotificationSafeToRemoveCallback; - private ArraySet<NotificationEntry> mManagedEntries = new ArraySet<>(); - private Handler mHandler = new Handler(Looper.getMainLooper()); - private final SystemClock mSystemClock; - private final NotificationInteractionTracker mInteractionTracker; - - @Inject - public ForegroundServiceLifetimeExtender( - NotificationInteractionTracker interactionTracker, - SystemClock systemClock) { - mSystemClock = systemClock; - mInteractionTracker = interactionTracker; - } - - @Override - public void setCallback(@NonNull NotificationSafeToRemoveCallback callback) { - mNotificationSafeToRemoveCallback = callback; - } - - @Override - public boolean shouldExtendLifetime(@NonNull NotificationEntry entry) { - if ((entry.getSbn().getNotification().flags - & Notification.FLAG_FOREGROUND_SERVICE) == 0) { - return false; - } - - // Entry has triggered a HUN or some other interruption, therefore it has been seen and the - // interrupter might be retaining it anyway. - if (entry.hasInterrupted()) { - return false; - } - - boolean hasInteracted = mInteractionTracker.hasUserInteractedWith(entry.getKey()); - long aliveTime = mSystemClock.uptimeMillis() - entry.getCreationTime(); - return aliveTime < MIN_FGS_TIME_MS && !hasInteracted; - } - - @Override - public boolean shouldExtendLifetimeForPendingNotification( - @NonNull NotificationEntry entry) { - return shouldExtendLifetime(entry); - } - - @Override - public void setShouldManageLifetime( - @NonNull NotificationEntry entry, boolean shouldManage) { - if (!shouldManage) { - mManagedEntries.remove(entry); - return; - } - - mManagedEntries.add(entry); - - Runnable r = () -> { - if (mManagedEntries.contains(entry)) { - mManagedEntries.remove(entry); - if (mNotificationSafeToRemoveCallback != null) { - mNotificationSafeToRemoveCallback.onSafeToRemove(entry.getKey()); - } - } - }; - long delayAmt = MIN_FGS_TIME_MS - - (mSystemClock.uptimeMillis() - entry.getCreationTime()); - mHandler.postDelayed(r, delayAmt); - } -} - diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java index d6cb1142061d..04e26d36f0a5 100644 --- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java +++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java @@ -50,7 +50,6 @@ public class ForegroundServiceNotificationListener { ForegroundServiceController foregroundServiceController, NotificationEntryManager notificationEntryManager, NotifPipeline notifPipeline, - ForegroundServiceLifetimeExtender fgsLifetimeExtender, SystemClock systemClock) { mContext = context; mForegroundServiceController = foregroundServiceController; @@ -78,7 +77,6 @@ public class ForegroundServiceNotificationListener { removeNotification(entry.getSbn()); } }); - mEntryManager.addNotificationLifetimeExtender(fgsLifetimeExtender); notifPipeline.addCollectionListener(new NotifCollectionListener() { @Override diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java index 6b4e8bdef72a..08262defbdee 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java @@ -106,7 +106,7 @@ public class SystemUIFactory { // components that shouldn't be run in the test environment builder = prepareSysUIComponentBuilder(builder, mWMComponent) .setPip(mWMComponent.getPip()) - .setSplitScreen(mWMComponent.getSplitScreen()) + .setLegacySplitScreen(mWMComponent.getLegacySplitScreen()) .setOneHanded(mWMComponent.getOneHanded()) .setBubbles(mWMComponent.getBubbles()) .setHideDisplayCutout(mWMComponent.getHideDisplayCutout()) @@ -117,7 +117,7 @@ public class SystemUIFactory { // is separating this logic into newly creating SystemUITestsFactory. builder = prepareSysUIComponentBuilder(builder, mWMComponent) .setPip(Optional.ofNullable(null)) - .setSplitScreen(Optional.ofNullable(null)) + .setLegacySplitScreen(Optional.ofNullable(null)) .setOneHanded(Optional.ofNullable(null)) .setBubbles(Optional.ofNullable(null)) .setHideDisplayCutout(Optional.ofNullable(null)) diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java index 267debc7dc2d..edc3216e0b81 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java @@ -149,7 +149,7 @@ class MagnificationModeSwitch { } switch (event.getAction()) { case MotionEvent.ACTION_DOWN: - mImageView.animate().cancel(); + stopFadeOutAnimation(); mLastDown.set(event.getRawX(), event.getRawY()); mLastDrag.set(event.getRawX(), event.getRawY()); return true; @@ -217,13 +217,18 @@ class MagnificationModeSwitch { AccessibilityManager.FLAG_CONTENT_ICONS | AccessibilityManager.FLAG_CONTENT_CONTROLS); } + // Refresh the time slot of the fade-out task whenever this method is called. + stopFadeOutAnimation(); + mImageView.postOnAnimationDelayed(mFadeOutAnimationTask, mUiTimeout); + } + + private void stopFadeOutAnimation() { + mImageView.removeCallbacks(mFadeOutAnimationTask); if (mIsFadeOutAnimating) { mImageView.animate().cancel(); mImageView.setAlpha(1f); + mIsFadeOutAnimating = false; } - // Refresh the time slot of the fade-out task whenever this method is called. - mImageView.removeCallbacks(mFadeOutAnimationTask); - mImageView.postOnAnimationDelayed(mFadeOutAnimationTask, mUiTimeout); } void onConfigurationChanged(int configDiff) { diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java index 0fd47654ebb9..c289ca2173be 100644 --- a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java @@ -438,7 +438,8 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon } @Override - public void onOpNoted(int code, int uid, String packageName, int result) { + public void onOpNoted(int code, int uid, String packageName, + @AppOpsManager.OpFlags int flags, @AppOpsManager.Mode int result) { if (DEBUG) { Log.w(TAG, "Noted op: " + code + " with result " + AppOpsManager.MODE_NAMES[result] + " for package " + packageName); diff --git a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java index e24a513437ea..e78057f5bd71 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java @@ -23,7 +23,6 @@ import android.net.Uri; import android.os.Build; import android.util.IndentingPrintWriter; import android.util.Log; -import android.view.MotionEvent; import androidx.annotation.NonNull; @@ -33,10 +32,12 @@ import com.android.systemui.dagger.qualifiers.TestHarness; import com.android.systemui.dock.DockManager; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.util.sensors.ThresholdSensor; +import com.android.systemui.util.time.SystemClock; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayDeque; +import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Locale; @@ -63,6 +64,8 @@ public class BrightLineFalsingManager implements FalsingManager { private final DockManager mDockManager; private final SingleTapClassifier mSingleTapClassifier; private final DoubleTapClassifier mDoubleTapClassifier; + private final HistoryTracker mHistoryTracker; + private final SystemClock mSystemClock; private final boolean mTestHarness; private final MetricsLogger mMetricsLogger; private int mIsFalseTouchCalls; @@ -85,6 +88,17 @@ public class BrightLineFalsingManager implements FalsingManager { } }; + private final FalsingDataProvider.GestureCompleteListener mGestureCompleteListener = + new FalsingDataProvider.GestureCompleteListener() { + @Override + public void onGestureComplete() { + mHistoryTracker.addResults( + mClassifiers.stream().map(FalsingClassifier::classifyGesture) + .collect(Collectors.toCollection(ArrayList::new)), + mSystemClock.uptimeMillis()); + } + }; + private boolean mPreviousResult = false; @Inject @@ -92,6 +106,7 @@ public class BrightLineFalsingManager implements FalsingManager { DockManager dockManager, MetricsLogger metricsLogger, @Named(BRIGHT_LINE_GESTURE_CLASSIFERS) Set<FalsingClassifier> classifiers, SingleTapClassifier singleTapClassifier, DoubleTapClassifier doubleTapClassifier, + HistoryTracker historyTracker, SystemClock systemClock, @TestHarness boolean testHarness) { mDataProvider = falsingDataProvider; mDockManager = dockManager; @@ -99,9 +114,12 @@ public class BrightLineFalsingManager implements FalsingManager { mClassifiers = classifiers; mSingleTapClassifier = singleTapClassifier; mDoubleTapClassifier = doubleTapClassifier; + mHistoryTracker = historyTracker; + mSystemClock = systemClock; mTestHarness = testHarness; mDataProvider.addSessionListener(mSessionListener); + mDataProvider.addGestureCompleteListener(mGestureCompleteListener); } @Override @@ -119,21 +137,22 @@ public class BrightLineFalsingManager implements FalsingManager { mPreviousResult = !mTestHarness && !mDataProvider.isJustUnlockedWithFace() && !mDockManager.isDocked() && mClassifiers.stream().anyMatch(falsingClassifier -> { - boolean result = falsingClassifier.isFalseTouch(); - if (result) { + FalsingClassifier.Result result = falsingClassifier.classifyGesture( + mHistoryTracker.falsePenalty(), mHistoryTracker.falseConfidence()); + if (result.isFalse()) { logInfo(String.format( (Locale) null, "{classifier=%s, interactionType=%d}", falsingClassifier.getClass().getName(), mDataProvider.getInteractionType())); - String reason = falsingClassifier.getReason(); + String reason = result.getReason(); if (reason != null) { logInfo(reason); } } else { logDebug(falsingClassifier.getClass().getName() + ": false"); } - return result; + return result.isFalse(); }); logDebug("Is false touch? " + mPreviousResult); @@ -159,10 +178,12 @@ public class BrightLineFalsingManager implements FalsingManager { @Override public boolean isFalseTap(boolean robustCheck) { - if (!mSingleTapClassifier.isTap(mDataProvider.getRecentMotionEvents())) { + FalsingClassifier.Result singleTapResult = + mSingleTapClassifier.isTap(mDataProvider.getRecentMotionEvents()); + if (singleTapResult.isFalse()) { logInfo(String.format( (Locale) null, "{classifier=%s}", mSingleTapClassifier.getClass().getName())); - String reason = mSingleTapClassifier.getReason(); + String reason = singleTapResult.getReason(); if (reason != null) { logInfo(reason); } @@ -179,23 +200,16 @@ public class BrightLineFalsingManager implements FalsingManager { @Override public boolean isFalseDoubleTap() { - boolean result = mDoubleTapClassifier.isFalseTouch(); - if (result) { + FalsingClassifier.Result result = mDoubleTapClassifier.classifyGesture(); + if (result.isFalse()) { logInfo(String.format( (Locale) null, "{classifier=%s}", mDoubleTapClassifier.getClass().getName())); - String reason = mDoubleTapClassifier.getReason(); + String reason = result.getReason(); if (reason != null) { logInfo(reason); } } - return result; - } - - @Override - public void onTouchEvent(MotionEvent motionEvent, int width, int height) { - // TODO: some of these classifiers might allow us to abort early, meaning we don't have to - // make these calls. - mClassifiers.forEach((classifier) -> classifier.onTouchEvent(motionEvent)); + return result.isFalse(); } @Override @@ -271,6 +285,8 @@ public class BrightLineFalsingManager implements FalsingManager { @Override public void cleanup() { mDataProvider.removeSessionListener(mSessionListener); + mDataProvider.removeGestureCompleteListener(mGestureCompleteListener); + mClassifiers.forEach(FalsingClassifier::cleanup); } static void logDebug(String msg) { diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DiagonalClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/DiagonalClassifier.java index 92dd8b74e959..bbb937176f59 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/DiagonalClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/DiagonalClassifier.java @@ -62,17 +62,16 @@ class DiagonalClassifier extends FalsingClassifier { VERTICAL_ANGLE_RANGE); } - @Override - boolean isFalseTouch() { + Result calculateFalsingResult(double historyPenalty, double historyConfidence) { float angle = getAngle(); if (angle == Float.MAX_VALUE) { // Unknown angle - return false; + return Result.passed(0); } if (getInteractionType() == LEFT_AFFORDANCE || getInteractionType() == RIGHT_AFFORDANCE) { - return false; + return Result.passed(0); } float minAngle = DIAGONAL - mHorizontalAngleRange; @@ -82,15 +81,15 @@ class DiagonalClassifier extends FalsingClassifier { maxAngle = DIAGONAL + mVerticalAngleRange; } - return angleBetween(angle, minAngle, maxAngle) + boolean falsed = angleBetween(angle, minAngle, maxAngle) || angleBetween(angle, minAngle + NINETY_DEG, maxAngle + NINETY_DEG) || angleBetween(angle, minAngle - NINETY_DEG, maxAngle - NINETY_DEG) || angleBetween(angle, minAngle + ONE_HUNDRED_EIGHTY_DEG, maxAngle + ONE_HUNDRED_EIGHTY_DEG); + return falsed ? Result.falsed(0.5f, getReason()) : Result.passed(0.5); } - @Override - String getReason() { + private String getReason() { return String.format( (Locale) null, "{angle=%f, vertical=%s}", diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java index 50d55f6f6028..4cb5aa2cce37 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/DistanceClassifier.java @@ -123,7 +123,6 @@ class DistanceClassifier extends FalsingClassifier { } VelocityTracker velocityTracker = VelocityTracker.obtain(); - for (MotionEvent motionEvent : motionEvents) { velocityTracker.addMovement(motionEvent); } @@ -148,11 +147,11 @@ class DistanceClassifier extends FalsingClassifier { } @Override - public boolean isFalseTouch() { - return !getPassedFlingThreshold(); + Result calculateFalsingResult(double historyPenalty, double historyConfidence) { + return !getPassedFlingThreshold() + ? Result.falsed(0.5, getReason()) : Result.passed(0.5); } - @Override String getReason() { DistanceVectors distanceVectors = getDistances(); @@ -170,10 +169,10 @@ class DistanceClassifier extends FalsingClassifier { mVerticalSwipeThresholdPx); } - boolean isLongSwipe() { + Result isLongSwipe() { boolean longSwipe = getPassedDistanceThreshold(); logDebug("Is longSwipe? " + longSwipe); - return longSwipe; + return longSwipe ? Result.passed(0.5) : Result.falsed(0.5, getReason()); } private boolean getPassedDistanceThreshold() { diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DoubleTapClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/DoubleTapClassifier.java index 1c8f4208edba..64576a97ddb2 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/DoubleTapClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/DoubleTapClassifier.java @@ -36,8 +36,6 @@ public class DoubleTapClassifier extends FalsingClassifier { private final float mDoubleTapSlop; private final long mDoubleTapTimeMs; - private StringBuilder mReason = new StringBuilder(); - @Inject DoubleTapClassifier(FalsingDataProvider dataProvider, SingleTapClassifier singleTapClassifier, @Named(DOUBLE_TAP_TOUCH_SLOP) float doubleTapSlop, @@ -49,32 +47,34 @@ public class DoubleTapClassifier extends FalsingClassifier { } @Override - boolean isFalseTouch() { + Result calculateFalsingResult(double historyPenalty, double historyConfidence) { List<MotionEvent> secondTapEvents = getRecentMotionEvents(); Queue<? extends List<MotionEvent>> historicalEvents = getHistoricalEvents(); List<MotionEvent> firstTapEvents = historicalEvents.peek(); - mReason = new StringBuilder(); + StringBuilder reason = new StringBuilder(); if (firstTapEvents == null) { - mReason.append("Only one gesture recorded"); - return true; + return Result.falsed(1, "Only one gesture recorded"); } - return !isDoubleTap(firstTapEvents, secondTapEvents, mReason); + return !isDoubleTap(firstTapEvents, secondTapEvents, reason) + ? Result.falsed(0.5, reason.toString()) : Result.passed(0.5); } /** Returns true if the two supplied lists of {@link MotionEvent}s look like a double-tap. */ public boolean isDoubleTap(List<MotionEvent> firstEvents, List<MotionEvent> secondEvents, StringBuilder reason) { - if (!mSingleTapClassifier.isTap(firstEvents)) { - reason.append("First gesture is not a tap. ").append(mSingleTapClassifier.getReason()); + Result firstTap = mSingleTapClassifier.isTap(firstEvents); + if (firstTap.isFalse()) { + reason.append("First gesture is not a tap. ").append(firstTap.getReason()); return false; } - if (!mSingleTapClassifier.isTap(secondEvents)) { - reason.append("Second gesture is not a tap. ").append(mSingleTapClassifier.getReason()); + Result secondTap = mSingleTapClassifier.isTap(secondEvents); + if (secondTap.isFalse()) { + reason.append("Second gesture is not a tap. ").append(secondTap.getReason()); return false; } @@ -106,9 +106,4 @@ public class DoubleTapClassifier extends FalsingClassifier { return true; } - - @Override - String getReason() { - return mReason.toString(); - } } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingClassifier.java index 82575c3e639e..dbfeacfa91c4 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingClassifier.java @@ -29,8 +29,11 @@ import java.util.Queue; public abstract class FalsingClassifier { private final FalsingDataProvider mDataProvider; + private final FalsingDataProvider.MotionEventListener mMotionEventListener = this::onTouchEvent; + FalsingClassifier(FalsingDataProvider dataProvider) { mDataProvider = dataProvider; + mDataProvider.addMotionEventListener(mMotionEventListener); } List<MotionEvent> getRecentMotionEvents() { @@ -89,6 +92,10 @@ public abstract class FalsingClassifier { return mDataProvider.getInteractionType(); } + void cleanup() { + mDataProvider.removeMotionEventListener(mMotionEventListener); + } + /** * Called whenever a MotionEvent occurs. * @@ -113,17 +120,32 @@ public abstract class FalsingClassifier { void onSessionEnded() {}; /** - * Returns true if the data captured so far looks like a false touch. + * Returns whether a gesture looks like a false touch. + * + * See also {@link #classifyGesture(double, double)}. */ - abstract boolean isFalseTouch(); + Result classifyGesture() { + return calculateFalsingResult(0, 0); + } /** - * Give the classifier a chance to log more details about why it triggered. + * Returns whether a gesture looks like a false touch, with the option to consider history. + * + * Unlike the parameter-less version of this method, this method allows the classifier to take + * history into account, penalizing or boosting confidence in a gesture based on recent results. * - * This should only be called after a call to {@link #isFalseTouch()}, and only if - * {@link #isFalseTouch()} returns true; + * See also {@link #classifyGesture()}. */ - abstract String getReason(); + Result classifyGesture(double historyPenalty, double historyConfidence) { + return calculateFalsingResult(historyPenalty, historyConfidence); + } + + /** + * Calculate a result based on available data. + * + * When passed a historyConfidence of 0, the history penalty should be wholly ignored. + */ + abstract Result calculateFalsingResult(double historyPenalty, double historyConfidence); /** */ public static void logDebug(String msg) { @@ -139,4 +161,48 @@ public abstract class FalsingClassifier { public static void logError(String msg) { BrightLineFalsingManager.logError(msg); } + + /** + * A Falsing result that encapsulates the boolean result along with confidence and a reason. + */ + static class Result { + private final boolean mFalsed; + private final double mConfidence; + private final String mReason; + + /** + * See {@link #falsed(double, String)} abd {@link #passed(double)}. + */ + private Result(boolean falsed, double confidence, String reason) { + mFalsed = falsed; + mConfidence = confidence; + mReason = reason; + } + + public boolean isFalse() { + return mFalsed; + } + + public double getConfidence() { + return mConfidence; + } + + public String getReason() { + return mReason; + } + + /** + * Construct a "falsed" result indicating that a gesture should be treated as accidental. + */ + static Result falsed(double confidence, String reason) { + return new Result(true, confidence, reason); + } + + /** + * Construct a "passed" result indicating that a gesture should be allowed. + */ + static Result passed(double confidence) { + return new Result(false, confidence, null); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollector.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollector.java index c05ce93f0c13..fe47162a1d4e 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollector.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollector.java @@ -113,7 +113,7 @@ public interface FalsingCollector { void onBouncerHidden(); /** */ - void onTouchEvent(MotionEvent ev, int width, int height); + void onTouchEvent(MotionEvent ev); /** */ void cleanup(); diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java index a5691118261a..fd059898f7a6 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorFake.java @@ -143,7 +143,7 @@ public class FalsingCollectorFake implements FalsingCollector { } @Override - public void onTouchEvent(MotionEvent ev, int width, int height) { + public void onTouchEvent(MotionEvent ev) { } @Override diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java index 3547392512a7..4c11ecf66956 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java @@ -244,9 +244,8 @@ class FalsingCollectorImpl implements FalsingCollector { } @Override - public void onTouchEvent(MotionEvent ev, int width, int height) { + public void onTouchEvent(MotionEvent ev) { mFalsingDataProvider.onMotionEvent(ev); - mFalsingManager.onTouchEvent(ev, width, height); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java index 009b311f2363..deb9e6dc442c 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java @@ -50,6 +50,8 @@ public class FalsingDataProvider { private final float mXdpi; private final float mYdpi; private final List<SessionListener> mSessionListeners = new ArrayList<>(); + private final List<MotionEventListener> mMotionEventListeners = new ArrayList<>(); + private final List<GestureCompleteListener> mGestuerCompleteListeners = new ArrayList<>(); private @Classifier.InteractionType int mInteractionType; private final Deque<TimeLimitedMotionEventBuffer> mExtendedMotionEvents = new LinkedList<>(); @@ -97,6 +99,8 @@ public class FalsingDataProvider { FalsingClassifier.logDebug("Size: " + mRecentMotionEvents.size()); + mMotionEventListeners.forEach(listener -> listener.onMotionEvent(motionEvent)); + mDirty = true; } @@ -321,6 +325,26 @@ public class FalsingDataProvider { mSessionListeners.remove(listener); } + /** Register a {@link MotionEventListener}. */ + public void addMotionEventListener(MotionEventListener listener) { + mMotionEventListeners.add(listener); + } + + /** Unegister a {@link MotionEventListener}. */ + public void removeMotionEventListener(MotionEventListener listener) { + mMotionEventListeners.remove(listener); + } + + /** Register a {@link GestureCompleteListener}. */ + public void addGestureCompleteListener(GestureCompleteListener listener) { + mGestuerCompleteListeners.add(listener); + } + + /** Unregister a {@link GestureCompleteListener}. */ + public void removeGestureCompleteListener(GestureCompleteListener listener) { + mGestuerCompleteListeners.remove(listener); + } + void onSessionStarted() { mSessionListeners.forEach(SessionListener::onSessionStarted); } @@ -353,4 +377,16 @@ public class FalsingDataProvider { /** Called when the lock screen exits and falsing-tracking ends. */ void onSessionEnded(); } + + /** Callback for receiving {@link android.view.MotionEvent}s as they are reported. */ + public interface MotionEventListener { + /** */ + void onMotionEvent(MotionEvent ev); + } + + /** Callback to be alerted when the current gesture ends. */ + public interface GestureCompleteListener { + /** */ + void onGestureComplete(); + } } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java index 32d27bcc01a6..d4d8d06b081b 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerFake.java @@ -17,7 +17,6 @@ package com.android.systemui.classifier; import android.net.Uri; -import android.view.MotionEvent; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.plugins.FalsingManager; @@ -117,11 +116,6 @@ public class FalsingManagerFake implements FalsingManager { } @Override - public void onTouchEvent(MotionEvent ev, int width, int height) { - - } - - @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java index d4f58c324d39..cbec0576e449 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java @@ -19,7 +19,6 @@ package com.android.systemui.classifier; import android.content.Context; import android.net.Uri; import android.provider.DeviceConfig; -import android.view.MotionEvent; import androidx.annotation.NonNull; @@ -162,11 +161,6 @@ public class FalsingManagerProxy implements FalsingManager, Dumpable { } @Override - public void onTouchEvent(MotionEvent ev, int width, int height) { - mInternalFalsingManager.onTouchEvent(ev, width, height); - } - - @Override public void onProximityEvent(ThresholdSensor.ThresholdSensorEvent proximityEvent) { mInternalFalsingManager.onProximityEvent(proximityEvent); } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/HistoryTracker.java b/packages/SystemUI/src/com/android/systemui/classifier/HistoryTracker.java new file mode 100644 index 000000000000..8bd94a122707 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/classifier/HistoryTracker.java @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.classifier; + +import com.android.systemui.dagger.SysUISingleton; +import com.android.systemui.plugins.FalsingManager; +import com.android.systemui.util.time.SystemClock; + +import java.util.Collection; +import java.util.concurrent.DelayQueue; +import java.util.concurrent.Delayed; +import java.util.concurrent.TimeUnit; + +import javax.inject.Inject; + +/** + * A stateful class for tracking recent {@link FalsingManager} results. + * + * Can return a "penalty" based on recent gestures that may make it harder or easier to + * unlock a phone, as well as a "confidence" relating to how consistent recent falsing results + * have been. + */ +@SysUISingleton +public class HistoryTracker { + private static final double HISTORY_DECAY = 0.8f; + private static final long DECAY_INTERVAL_MS = 100; + // We expire items once their decay factor is below 0.001. + private static final double MINIMUM_SCORE = 0.001; + private static final long TOTAL_DECAY_TIME_MS = + DECAY_INTERVAL_MS * (long) (Math.log(MINIMUM_SCORE) / Math.log(HISTORY_DECAY)); + private final SystemClock mSystemClock; + + DelayQueue<CombinedResult> mResults = new DelayQueue<>(); + + @Inject + HistoryTracker(SystemClock systemClock) { + mSystemClock = systemClock; + } + + /** + * Returns how much the HistoryClassifier thinks the past events indicate pocket dialing. + * + * A result of 0 means that all prior gestures succeeded or there is no data to + * calculate a score with. Use {@link #falseConfidence()} to differentiate between the + * two cases. + * + * A result of 1 means that all prior gestures were very obviously false. The current gesture + * might be valid, but it should have a high-bar to be classified as such. + * + * See also {@link #falseConfidence()}. + */ + double falsePenalty() { + //noinspection StatementWithEmptyBody + while (mResults.poll() != null) { + // Empty out the expired results. + } + + if (mResults.isEmpty()) { + return 0; + } + + long nowMs = mSystemClock.uptimeMillis(); + return mResults.stream() + .map(result -> result.getDecayedScore(nowMs)) + .reduce(0.0, Double::sum) / mResults.size(); + } + + /** + * Returns how confident the HistoryClassifier is in its own score. + * + * A result of 0.0 means that there are no data to make a calculation with. The HistoryTracker's + * results have nothing to add and should not be considered. + * + * A result of 0.5 means that the data are not consistent with each other, sometimes falsing + * sometimes not. + * + * A result of 1 means that there are ample, fresh data to act upon that is all consistent + * with each other. + * + * See als {@link #falsePenalty()}. + */ + double falseConfidence() { + //noinspection StatementWithEmptyBody + while (mResults.poll() != null) { + // Empty out the expired results. + } + + // Our confidence is 1 - the population stddev. Smaller stddev == higher confidence. + if (mResults.isEmpty()) { + return 0; + } + + double mean = mResults.stream() + .map(CombinedResult::getScore) + .reduce(0.0, Double::sum) / mResults.size(); + + double stddev = Math.sqrt( + mResults.stream() + .map(result -> Math.pow(result.getScore() - mean, 2)) + .reduce(0.0, Double::sum) / mResults.size()); + + return 1 - stddev; + } + + void addResults(Collection<FalsingClassifier.Result> results, long uptimeMillis) { + double finalScore = 0; + for (FalsingClassifier.Result result : results) { + // A confidence of 1 adds either 0 for non-falsed or 1 for falsed. + // A confidence of 0 adds 0.5. + finalScore += (result.isFalse() ? .5 : -.5) * result.getConfidence() + 0.5; + } + + finalScore /= results.size(); + + //noinspection StatementWithEmptyBody + while (mResults.poll() != null) { + // Empty out the expired results. + } + + mResults.add(new CombinedResult(uptimeMillis, finalScore)); + } + + /** + * Represents a falsing score combing all the classifiers together. + * + * Can "decay" over time, such that older results contribute less. Once they drop below + * a certain threshold, the {@link #getDelay(TimeUnit)} method will return <= 0, indicating + * that this result can be discarded. + */ + private class CombinedResult implements Delayed { + + private final long mExpiryMs; + private final double mScore; + + CombinedResult(long uptimeMillis, double score) { + mExpiryMs = uptimeMillis + TOTAL_DECAY_TIME_MS; + mScore = score; + } + + double getDecayedScore(long nowMs) { + long remainingTimeMs = mExpiryMs - nowMs; + long decayedTimeMs = TOTAL_DECAY_TIME_MS - remainingTimeMs; + double timeIntervals = (double) decayedTimeMs / DECAY_INTERVAL_MS; + return mScore * Math.pow(HISTORY_DECAY, timeIntervals); + } + + double getScore() { + return mScore; + } + + @Override + public long getDelay(TimeUnit unit) { + return unit.convert(mExpiryMs - mSystemClock.uptimeMillis(), TimeUnit.MILLISECONDS); + } + + @Override + public int compareTo(Delayed o) { + long ourDelay = getDelay(TimeUnit.MILLISECONDS); + long otherDelay = o.getDelay(TimeUnit.MILLISECONDS); + return Long.compare(ourDelay, otherDelay); + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java index 0565165e1e8d..cd399fe15de1 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/PointerCountClassifier.java @@ -56,20 +56,21 @@ class PointerCountClassifier extends FalsingClassifier { } @Override - public boolean isFalseTouch() { + Result calculateFalsingResult(double historyPenalty, double historyConfidence) { int interactionType = getInteractionType(); - if (interactionType == QUICK_SETTINGS || interactionType == NOTIFICATION_DRAG_DOWN) { - return mMaxPointerCount > MAX_ALLOWED_POINTERS_SWIPE_DOWN; - } - return mMaxPointerCount > MAX_ALLOWED_POINTERS; + int allowedPointerCount = + (interactionType == QUICK_SETTINGS || interactionType == NOTIFICATION_DRAG_DOWN) + ? MAX_ALLOWED_POINTERS_SWIPE_DOWN : MAX_ALLOWED_POINTERS; + + return mMaxPointerCount > allowedPointerCount + ? Result.falsed(1, getReason(allowedPointerCount)) : Result.passed(0); } - @Override - String getReason() { + private String getReason(int allowedPointerCount) { return String.format( (Locale) null, "{pointersObserved=%d, threshold=%d}", mMaxPointerCount, - MAX_ALLOWED_POINTERS); + allowedPointerCount); } } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java index 6e73fc06de4c..9ee85986c53c 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/ProximityClassifier.java @@ -33,7 +33,7 @@ import javax.inject.Inject; /** * False touch if proximity sensor is covered for more than a certain percentage of the gesture. * - * This classifer is essentially a no-op for QUICK_SETTINGS, as we assume the sensor may be + * This classifier is essentially a no-op for QUICK_SETTINGS, as we assume the sensor may be * covered when swiping from the top. */ class ProximityClassifier extends FalsingClassifier { @@ -112,28 +112,29 @@ class ProximityClassifier extends FalsingClassifier { } @Override - public boolean isFalseTouch() { + Result calculateFalsingResult(double historyPenalty, double historyConfidence) { if (getInteractionType() == QUICK_SETTINGS) { - return false; + return Result.passed(0); } logInfo("Percent of gesture in proximity: " + mPercentNear); if (mPercentNear > mPercentCoveredThreshold) { - return !mDistanceClassifier.isLongSwipe(); + Result longSwipeResult = mDistanceClassifier.isLongSwipe(); + return longSwipeResult.isFalse() + ? Result.falsed(0.5, getReason(longSwipeResult)) : Result.passed(0.5); } - return false; + return Result.passed(0.5); } - @Override - String getReason() { + private String getReason(Result longSwipeResult) { return String.format( (Locale) null, "{percentInProximity=%f, threshold=%f, distanceClassifier=%s}", mPercentNear, mPercentCoveredThreshold, - mDistanceClassifier.getReason()); + longSwipeResult.getReason()); } /** diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SingleTapClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/SingleTapClassifier.java index 6b7a1413bc74..f2622ec4e6e9 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/SingleTapClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/SingleTapClassifier.java @@ -30,7 +30,6 @@ import javax.inject.Named; */ public class SingleTapClassifier extends FalsingClassifier { private final float mTouchSlop; - private String mReason; @Inject SingleTapClassifier(FalsingDataProvider dataProvider, @@ -40,36 +39,31 @@ public class SingleTapClassifier extends FalsingClassifier { } @Override - boolean isFalseTouch() { - return !isTap(getRecentMotionEvents()); + Result calculateFalsingResult(double historyPenalty, double historyConfidence) { + return isTap(getRecentMotionEvents()); } /** Given a list of {@link android.view.MotionEvent}'s, returns true if the look like a tap. */ - public boolean isTap(List<MotionEvent> motionEvents) { + public Result isTap(List<MotionEvent> motionEvents) { float downX = motionEvents.get(0).getX(); float downY = motionEvents.get(0).getY(); for (MotionEvent event : motionEvents) { + String reason; if (Math.abs(event.getX() - downX) >= mTouchSlop) { - mReason = "dX too big for a tap: " + reason = "dX too big for a tap: " + Math.abs(event.getX() - downX) + "vs " + mTouchSlop; - return false; + return Result.falsed(0.5, reason); } else if (Math.abs(event.getY() - downY) >= mTouchSlop) { - mReason = "dY too big for a tap: " + reason = "dY too big for a tap: " + Math.abs(event.getY() - downY) + "vs " + mTouchSlop; - return false; + return Result.falsed(0.5, reason); } } - mReason = ""; - return true; - } - - @Override - String getReason() { - return mReason; + return Result.passed(0); } } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java index 711a0fc0f478..d470d6297170 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/TypeClassifier.java @@ -38,32 +38,40 @@ public class TypeClassifier extends FalsingClassifier { } @Override - public boolean isFalseTouch() { + Result calculateFalsingResult(double historyPenalty, double historyConfidence) { boolean vertical = isVertical(); boolean up = isUp(); boolean right = isRight(); + boolean wrongDirection = true; switch (getInteractionType()) { case QUICK_SETTINGS: case PULSE_EXPAND: case NOTIFICATION_DRAG_DOWN: - return !vertical || up; + wrongDirection = !vertical || up; + break; case NOTIFICATION_DISMISS: - return vertical; + wrongDirection = vertical; + break; case UNLOCK: case BOUNCER_UNLOCK: - return !vertical || !up; + wrongDirection = !vertical || !up; + break; case LEFT_AFFORDANCE: // Swiping from the bottom left corner for camera or similar. - return !right || !up; + wrongDirection = !right || !up; + break; case RIGHT_AFFORDANCE: // Swiping from the bottom right corner for camera or similar. - return right || !up; + wrongDirection = right || !up; + break; default: - return true; + wrongDirection = true; + break; } + + return wrongDirection ? Result.falsed(1, getReason()) : Result.passed(0.5); } - @Override - String getReason() { + private String getReason() { return String.format("{vertical=%s, up=%s, right=%s}", isVertical(), isUp(), isRight()); } } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java index 383dda498b49..2bfb2186191b 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/ZigZagClassifier.java @@ -84,7 +84,7 @@ class ZigZagClassifier extends FalsingClassifier { } @Override - boolean isFalseTouch() { + Result calculateFalsingResult(double historyPenalty, double historyConfidence) { List<MotionEvent> motionEvents = getRecentMotionEvents(); // Rotate horizontal gestures to be horizontal between their first and last point. // Rotate vertical gestures to be vertical between their first and last point. @@ -95,7 +95,7 @@ class ZigZagClassifier extends FalsingClassifier { // For vertical lines, the difference in the y direction should be small. if (motionEvents.size() < 3) { - return false; + return Result.passed(0); } List<Point> rotatedPoints; @@ -155,11 +155,11 @@ class ZigZagClassifier extends FalsingClassifier { logDebug("Straightness Deviance: (" + devianceX + "," + devianceY + ") vs " + "(" + maxXDeviance + "," + maxYDeviance + ")"); - return devianceX > maxXDeviance || devianceY > maxYDeviance; + return devianceX > maxXDeviance || devianceY > maxYDeviance + ? Result.falsed(0.5, getReason()) : Result.passed(0.5); } - @Override - String getReason() { + private String getReason() { return String.format( (Locale) null, "{devianceX=%f, maxDevianceX=%s, devianceY=%s, maxDevianceY=%s}", diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt index 0e4f68431c16..9d92a40beec4 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt @@ -37,6 +37,7 @@ import android.service.controls.templates.ControlTemplate import android.service.controls.templates.RangeTemplate import android.service.controls.templates.StatelessTemplate import android.service.controls.templates.TemperatureControlTemplate +import android.service.controls.templates.ThumbnailTemplate import android.service.controls.templates.ToggleRangeTemplate import android.service.controls.templates.ToggleTemplate import android.util.MathUtils @@ -87,8 +88,11 @@ class ControlViewHolder( ): KClass<out Behavior> { return when { status != Control.STATUS_OK -> StatusBehavior::class - deviceType == DeviceTypes.TYPE_CAMERA -> TouchBehavior::class template == ControlTemplate.NO_TEMPLATE -> TouchBehavior::class + template is ThumbnailTemplate -> ThumbnailBehavior::class + + // Required for legacy support, or where cameras do not use the new template + deviceType == DeviceTypes.TYPE_CAMERA -> TouchBehavior::class template is ToggleTemplate -> ToggleBehavior::class template is StatelessTemplate -> TouchBehavior::class template is ToggleRangeTemplate -> ToggleRangeBehavior::class @@ -105,7 +109,7 @@ class ControlViewHolder( private var statusAnimator: Animator? = null private val baseLayer: GradientDrawable val icon: ImageView = layout.requireViewById(R.id.icon) - private val status: TextView = layout.requireViewById(R.id.status) + val status: TextView = layout.requireViewById(R.id.status) private var nextStatusText: CharSequence = "" val title: TextView = layout.requireViewById(R.id.title) val subtitle: TextView = layout.requireViewById(R.id.subtitle) @@ -132,7 +136,6 @@ class ControlViewHolder( val ld = layout.getBackground() as LayerDrawable ld.mutate() clipLayer = ld.findDrawableByLayerId(R.id.clip_layer) as ClipDrawable - clipLayer.alpha = ALPHA_DISABLED baseLayer = ld.findDrawableByLayerId(R.id.background) as GradientDrawable // needed for marquee to start status.setSelected(true) @@ -315,7 +318,9 @@ class ControlViewHolder( ) } - (clipLayer.getDrawable() as GradientDrawable).apply { + clipLayer.getDrawable().apply { + clipLayer.alpha = ALPHA_DISABLED + val newBaseColor = if (behavior is ToggleRangeBehavior) { ColorUtils.blendARGB(bg, newClipColor, toggleBackgroundIntensity) } else { @@ -323,15 +328,25 @@ class ControlViewHolder( } stateAnimator?.cancel() if (animated) { - val oldColor = color?.defaultColor ?: newClipColor + val oldColor = if (this is GradientDrawable) { + this.color?.defaultColor ?: newClipColor + } else { + newClipColor + } val oldBaseColor = baseLayer.color?.defaultColor ?: newBaseColor val oldAlpha = layout.alpha + + // Animate both alpha and background colors. Only animate colors for + // GradientDrawables and not static images as used for the ThumbnailTemplate. stateAnimator = ValueAnimator.ofInt(clipLayer.alpha, newAlpha).apply { addUpdateListener { alpha = it.animatedValue as Int - setColor(ColorUtils.blendARGB(oldColor, newClipColor, it.animatedFraction)) - baseLayer.setColor(ColorUtils.blendARGB(oldBaseColor, - newBaseColor, it.animatedFraction)) + if (this is GradientDrawable) { + this.setColor(ColorUtils.blendARGB(oldColor, newClipColor, + it.animatedFraction)) + } + baseLayer.setColor(ColorUtils.blendARGB(oldBaseColor, newBaseColor, + it.animatedFraction)) layout.alpha = MathUtils.lerp(oldAlpha, 1f, it.animatedFraction) } addListener(object : AnimatorListenerAdapter() { @@ -345,7 +360,9 @@ class ControlViewHolder( } } else { alpha = newAlpha - setColor(newClipColor) + if (this is GradientDrawable) { + this.setColor(newClipColor) + } baseLayer.setColor(newBaseColor) layout.alpha = 1f } diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt index 3f17a4fefd7e..ad2b785ea5c5 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt @@ -92,7 +92,9 @@ private val deviceColorMap = mapOf<Int, Pair<Int, Int>>( (THERMOSTAT_RANGE + TemperatureControlTemplate.MODE_COOL) to Pair(R.color.thermo_cool_foreground, R.color.control_enabled_thermo_cool_background), DeviceTypes.TYPE_LIGHT - to Pair(R.color.light_foreground, R.color.control_enabled_light_background) + to Pair(R.color.light_foreground, R.color.control_enabled_light_background), + DeviceTypes.TYPE_CAMERA + to Pair(R.color.camera_foreground, R.color.control_enabled_default_background) ).withDefault { Pair(R.color.control_foreground, R.color.control_enabled_default_background) } diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ThumbnailBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ThumbnailBehavior.kt new file mode 100644 index 000000000000..c2168aa8d9d9 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ThumbnailBehavior.kt @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.controls.ui + +import android.graphics.BlendMode +import android.graphics.BlendModeColorFilter +import android.graphics.drawable.ClipDrawable +import android.graphics.drawable.LayerDrawable +import android.view.View +import android.service.controls.Control +import android.service.controls.templates.ThumbnailTemplate +import android.util.TypedValue + +import com.android.systemui.R +import com.android.systemui.controls.ui.ControlViewHolder.Companion.MAX_LEVEL +import com.android.systemui.controls.ui.ControlViewHolder.Companion.MIN_LEVEL + +/** + * Supports display of static images on the background of the tile. When marked active, the title + * and subtitle will not be visible. To be used with {@link Thumbnailtemplate} only. + */ +class ThumbnailBehavior : Behavior { + lateinit var template: ThumbnailTemplate + lateinit var control: Control + lateinit var cvh: ControlViewHolder + private var shadowOffsetX: Float = 0f + private var shadowOffsetY: Float = 0f + private var shadowRadius: Float = 0f + private var shadowColor: Int = 0 + + private val enabled: Boolean + get() = template.isActive() + + override fun initialize(cvh: ControlViewHolder) { + this.cvh = cvh + + val outValue = TypedValue() + cvh.context.resources.getValue(R.dimen.controls_thumbnail_shadow_x, outValue, true) + shadowOffsetX = outValue.getFloat() + + cvh.context.resources.getValue(R.dimen.controls_thumbnail_shadow_y, outValue, true) + shadowOffsetY = outValue.getFloat() + + cvh.context.resources.getValue(R.dimen.controls_thumbnail_shadow_radius, outValue, true) + shadowRadius = outValue.getFloat() + + shadowColor = cvh.context.resources.getColor(R.color.control_thumbnail_shadow_color) + cvh.layout.setOnClickListener(View.OnClickListener() { + cvh.controlActionCoordinator.touch(cvh, template.getTemplateId(), control) + }) + } + + override fun bind(cws: ControlWithState, colorOffset: Int) { + this.control = cws.control!! + cvh.setStatusText(control.getStatusText()) + template = control.getControlTemplate() as ThumbnailTemplate + + val ld = cvh.layout.getBackground() as LayerDrawable + val clipLayer = ld.findDrawableByLayerId(R.id.clip_layer) as ClipDrawable + + clipLayer.setLevel(if (enabled) MAX_LEVEL else MIN_LEVEL) + + if (template.isActive()) { + cvh.title.visibility = View.INVISIBLE + cvh.subtitle.visibility = View.INVISIBLE + cvh.status.setShadowLayer(shadowOffsetX, shadowOffsetY, shadowRadius, shadowColor) + + cvh.bgExecutor.execute { + val drawable = template.getThumbnail().loadDrawable(cvh.context) + cvh.uiExecutor.execute { + val radius = cvh.context.getResources() + .getDimensionPixelSize(R.dimen.control_corner_radius).toFloat() + clipLayer.setDrawable(CornerDrawable(drawable, radius)) + clipLayer.setColorFilter(BlendModeColorFilter(cvh.context.resources + .getColor(R.color.control_thumbnail_tint), BlendMode.LUMINOSITY)) + cvh.applyRenderInfo(enabled, colorOffset) + } + } + } else { + cvh.title.visibility = View.VISIBLE + cvh.subtitle.visibility = View.VISIBLE + cvh.status.setShadowLayer(0f, 0f, 0f, shadowColor) + } + + cvh.applyRenderInfo(enabled, colorOffset) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java index 275bfaa1023c..f22fa326ee9d 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java @@ -82,7 +82,7 @@ import com.android.systemui.statusbar.policy.NetworkController; import com.android.systemui.theme.ThemeOverlayApplier; import com.android.systemui.util.leak.LeakDetector; import com.android.wm.shell.pip.Pip; -import com.android.wm.shell.splitscreen.SplitScreen; +import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import java.util.Optional; import java.util.concurrent.Executor; @@ -213,7 +213,7 @@ public class DependencyProvider { BroadcastDispatcher broadcastDispatcher, CommandQueue commandQueue, Optional<Pip> pipOptional, - Optional<SplitScreen> splitScreenOptional, + Optional<LegacySplitScreen> splitScreenOptional, Optional<Recents> recentsOptional, Lazy<StatusBar> statusBarLazy, ShadeController shadeController, diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java index f9f68e22d022..926062b1623f 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java @@ -30,7 +30,7 @@ import com.android.wm.shell.bubbles.Bubbles; import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout; import com.android.wm.shell.onehanded.OneHanded; import com.android.wm.shell.pip.Pip; -import com.android.wm.shell.splitscreen.SplitScreen; +import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import java.util.Optional; @@ -59,7 +59,7 @@ public interface SysUIComponent { Builder setPip(Optional<Pip> p); @BindsInstance - Builder setSplitScreen(Optional<SplitScreen> s); + Builder setLegacySplitScreen(Optional<LegacySplitScreen> s); @BindsInstance Builder setAppPairs(Optional<AppPairs> s); diff --git a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java index ec8c7da3ebf6..a1bde589d5c1 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java @@ -24,7 +24,7 @@ import com.android.wm.shell.bubbles.Bubbles; import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout; import com.android.wm.shell.onehanded.OneHanded; import com.android.wm.shell.pip.Pip; -import com.android.wm.shell.splitscreen.SplitScreen; +import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import java.util.Optional; @@ -69,7 +69,7 @@ public interface WMComponent { Optional<Pip> getPip(); @WMSingleton - Optional<SplitScreen> getSplitScreen(); + Optional<LegacySplitScreen> getLegacySplitScreen(); @WMSingleton Optional<AppPairs> getAppPairs(); diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java index f470a6b55b76..c26cc4466c6d 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java @@ -298,6 +298,22 @@ public class DozeLog implements Dumpable { mLogger.logDozeSuppressed(suppressedState); } + /** + * Appends new AOD sreen brightness to logs + * @param brightness display brightness setting + */ + public void traceDozeScreenBrightness(int brightness) { + mLogger.logDozeScreenBrightness(brightness); + } + + /** + * Appends new AOD dimming scrim opacity to logs + * @param scrimOpacity + */ + public void traceSetAodDimmingScrim(float scrimOpacity) { + mLogger.logSetAodDimmingScrim((long) scrimOpacity); + } + private class SummaryStats { private int mCount; diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt b/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt index 0c9e14352946..fddefae6f5b6 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt @@ -226,6 +226,22 @@ class DozeLogger @Inject constructor( "Doze state suppressed, state=$str1" }) } + + fun logDozeScreenBrightness(brightness: Int) { + buffer.log(TAG, INFO, { + int1 = brightness + }, { + "Doze screen brightness set, brightness=$int1" + }) + } + + fun logSetAodDimmingScrim(scrimOpacity: Long) { + buffer.log(TAG, INFO, { + long1 = scrimOpacity + }, { + "Doze aod dimming scrim opacity set, opacity=$long1" + }) + } } private const val TAG = "DozeLog" diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java index ebfce661c9af..c542e5b07d9b 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java @@ -34,6 +34,7 @@ import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; import android.text.TextUtils; +import android.util.IndentingPrintWriter; import android.util.Log; import android.view.Display; @@ -79,6 +80,7 @@ public class DozeSensors { private long mDebounceFrom; private boolean mSettingRegistered; private boolean mListening; + private boolean mListeningTouchScreenSensors; @VisibleForTesting public enum DozeSensorsUiEvent implements UiEventLogger.UiEventEnum { @@ -232,22 +234,25 @@ public class DozeSensors { /** * If sensors should be registered and sending signals. */ - public void setListening(boolean listen) { - if (mListening == listen) { + public void setListening(boolean listen, boolean includeTouchScreenSensors) { + if (mListening == listen && mListeningTouchScreenSensors == includeTouchScreenSensors) { return; } mListening = listen; + mListeningTouchScreenSensors = includeTouchScreenSensors; updateListening(); } /** * Registers/unregisters sensors based on internal state. */ - public void updateListening() { + private void updateListening() { boolean anyListening = false; for (TriggerSensor s : mSensors) { - s.setListening(mListening); - if (mListening) { + boolean listen = mListening + && (!s.mRequiresTouchscreen || mListeningTouchScreenSensors); + s.setListening(listen); + if (listen) { anyListening = true; } } @@ -319,10 +324,14 @@ public class DozeSensors { /** Dump current state */ public void dump(PrintWriter pw) { + pw.println("mListening=" + mListening); + pw.println("mListeningTouchScreenSensors=" + mListeningTouchScreenSensors); + IndentingPrintWriter idpw = new IndentingPrintWriter(pw); + idpw.increaseIndent(); for (TriggerSensor s : mSensors) { - pw.println(" Sensor: " + s.toString()); + idpw.println("Sensor: " + s.toString()); } - pw.println(" ProxSensor: " + mProximitySensor.toString()); + idpw.println("ProxSensor: " + mProximitySensor.toString()); } /** diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java index 6888d1ad6063..c617f3d751d0 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java @@ -29,6 +29,7 @@ import android.metrics.LogMaker; import android.os.SystemClock; import android.os.UserHandle; import android.text.format.Formatter; +import android.util.IndentingPrintWriter; import android.util.Log; import android.view.Display; @@ -434,15 +435,12 @@ public class DozeTriggers implements DozeMachine.Part { break; case DOZE_PULSE_DONE: mDozeSensors.requestTemporaryDisable(); - // A pulse will temporarily disable sensors that require a touch screen. - // Let's make sure that they are re-enabled when the pulse is over. - mDozeSensors.updateListening(); break; case FINISH: mBroadcastReceiver.unregister(mBroadcastDispatcher); mDozeHost.removeCallback(mHostCallback); mDockManager.removeListener(mDockEventListener); - mDozeSensors.setListening(false); + mDozeSensors.setListening(false, false); mDozeSensors.setProxListening(false); mWantSensors = false; mWantProx = false; @@ -450,20 +448,16 @@ public class DozeTriggers implements DozeMachine.Part { break; default: } + mDozeSensors.setListening(mWantSensors, mWantTouchScreenSensors); } @Override public void onScreenState(int state) { mDozeSensors.onScreenState(state); - if (state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND - || state == Display.STATE_OFF) { - mDozeSensors.setProxListening(mWantProx); - mDozeSensors.setListening(mWantSensors); - mDozeSensors.setTouchscreenSensorsListening(mWantTouchScreenSensors); - } else { - mDozeSensors.setProxListening(false); - mDozeSensors.setListening(mWantSensors); - } + mDozeSensors.setProxListening(mWantProx && (state == Display.STATE_DOZE + || state == Display.STATE_DOZE_SUSPEND + || state == Display.STATE_OFF)); + mDozeSensors.setListening(mWantSensors, mWantTouchScreenSensors); } private void checkTriggersAtInit() { @@ -539,7 +533,9 @@ public class DozeTriggers implements DozeMachine.Part { pw.println(" pulsePending=" + mPulsePending); pw.println("DozeSensors:"); - mDozeSensors.dump(pw); + IndentingPrintWriter idpw = new IndentingPrintWriter(pw); + idpw.increaseIndent(); + mDozeSensors.dump(idpw); } private class TriggerReceiver extends BroadcastReceiver { diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java index 9c90510099a2..ad4c44767995 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java @@ -50,6 +50,7 @@ import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.UserInfo; import android.content.res.ColorStateList; +import android.content.res.Configuration; import android.content.res.Resources; import android.database.ContentObserver; import android.graphics.Color; @@ -256,6 +257,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, private UserContextProvider mUserContextProvider; @VisibleForTesting boolean mShowLockScreenCardsAndControls = false; + private int mSmallestScreenWidthDp; @VisibleForTesting public enum GlobalActionsEvent implements UiEventLogger.UiEventEnum { @@ -344,6 +346,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, mSysUiState = sysUiState; mMainHandler = handler; mUserContextProvider = userContextProvider; + mSmallestScreenWidthDp = mContext.getResources().getConfiguration().smallestScreenWidthDp; // receive broadcasts IntentFilter filter = new IntentFilter(); @@ -760,6 +763,15 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, } } + @Override + public void onConfigChanged(Configuration newConfig) { + if (mDialog != null && mDialog.isShowing() + && (newConfig.smallestScreenWidthDp != mSmallestScreenWidthDp)) { + mSmallestScreenWidthDp = newConfig.smallestScreenWidthDp; + mDialog.refreshDialog(); + } + } + public void destroy() { mConfigurationController.removeCallback(this); } @@ -2230,6 +2242,9 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, return; } + boolean isLandscapeWalletViewShown = mContext.getResources().getBoolean( + com.android.systemui.R.bool.global_actions_show_landscape_wallet_view); + int rotation = RotationUtils.getRotation(mContext); boolean rotationLocked = RotationPolicy.isRotationLocked(mContext); if (rotation != RotationUtils.ROTATION_NONE) { @@ -2246,6 +2261,10 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, mGlobalActionsLayout.post(() -> RotationPolicy.setRotationLockAtAngle( mContext, false, RotationUtils.ROTATION_NONE)); + + if (!isLandscapeWalletViewShown) { + return; + } } } else { if (!rotationLocked) { @@ -2253,44 +2272,48 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, mResetOrientationData = new ResetOrientationData(); mResetOrientationData.locked = false; } + } - // Lock to portrait, so the user doesn't accidentally hide the panel. + boolean shouldLockRotation = !isLandscapeWalletViewShown; + if (rotationLocked != shouldLockRotation) { + // Locks the screen to portrait if the landscape / seascape orientation does not + // show the wallet view, so the user doesn't accidentally hide the panel. // This call is posted so that the rotation does not change until post-layout, // otherwise onConfigurationChanged() may not get invoked. mGlobalActionsLayout.post(() -> RotationPolicy.setRotationLockAtAngle( - mContext, true, RotationUtils.ROTATION_NONE)); + mContext, shouldLockRotation, RotationUtils.ROTATION_NONE)); } + } - // Disable rotation suggestions, if enabled - setRotationSuggestionsEnabled(false); - - FrameLayout panelContainer = - findViewById(com.android.systemui.R.id.global_actions_wallet); - FrameLayout.LayoutParams panelParams = - new FrameLayout.LayoutParams( - FrameLayout.LayoutParams.MATCH_PARENT, - FrameLayout.LayoutParams.MATCH_PARENT); - if (!mControlsAvailable) { - panelParams.topMargin = mContext.getResources().getDimensionPixelSize( - com.android.systemui.R.dimen.global_actions_wallet_top_margin); - } - View walletView = mWalletViewController.getPanelContent(); - panelContainer.addView(walletView, panelParams); - // Smooth transitions when wallet is resized, which can happen when a card is added - ViewGroup root = findViewById(com.android.systemui.R.id.global_actions_grid_root); - if (root != null) { - walletView.addOnLayoutChangeListener((v, l, t, r, b, ol, ot, or, ob) -> { - int oldHeight = ob - ot; - int newHeight = b - t; - if (oldHeight > 0 && oldHeight != newHeight) { - TransitionSet transition = new AutoTransition() - .setDuration(250) - .setOrdering(TransitionSet.ORDERING_TOGETHER); - TransitionManager.beginDelayedTransition(root, transition); - } - }); - } + // Disable rotation suggestions, if enabled + setRotationSuggestionsEnabled(false); + + FrameLayout panelContainer = + findViewById(com.android.systemui.R.id.global_actions_wallet); + FrameLayout.LayoutParams panelParams = + new FrameLayout.LayoutParams( + FrameLayout.LayoutParams.MATCH_PARENT, + FrameLayout.LayoutParams.MATCH_PARENT); + if (!mControlsAvailable) { + panelParams.topMargin = mContext.getResources().getDimensionPixelSize( + com.android.systemui.R.dimen.global_actions_wallet_top_margin); + } + View walletView = mWalletViewController.getPanelContent(); + panelContainer.addView(walletView, panelParams); + // Smooth transitions when wallet is resized, which can happen when a card is added + ViewGroup root = findViewById(com.android.systemui.R.id.global_actions_grid_root); + if (root != null) { + walletView.addOnLayoutChangeListener((v, l, t, r, b, ol, ot, or, ob) -> { + int oldHeight = ob - ot; + int newHeight = b - t; + if (oldHeight > 0 && oldHeight != newHeight) { + TransitionSet transition = new AutoTransition() + .setDuration(250) + .setOrdering(TransitionSet.ORDERING_TOGETHER); + TransitionManager.beginDelayedTransition(root, transition); + } + }); } } 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 eb86128a82a5..9e2538977fab 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java @@ -24,6 +24,7 @@ import android.graphics.drawable.Drawable; import android.graphics.drawable.Icon; import android.media.MediaMetadata; import android.media.MediaRoute2Info; +import android.media.MediaRouter2Manager; import android.media.RoutingSessionInfo; import android.media.session.MediaController; import android.media.session.MediaSessionManager; @@ -76,6 +77,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback { private final List<MediaDevice> mGroupMediaDevices = new CopyOnWriteArrayList<>(); private final boolean mAboveStatusbar; private final NotificationEntryManager mNotificationEntryManager; + private final MediaRouter2Manager mRouterManager; @VisibleForTesting final List<MediaDevice> mMediaDevices = new CopyOnWriteArrayList<>(); @@ -104,6 +106,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback { mLocalMediaManager = new LocalMediaManager(mContext, lbm, imm, packageName); mMetricLogger = new MediaOutputMetricLogger(mContext, mPackageName); mUiEventLogger = uiEventLogger; + mRouterManager = MediaRouter2Manager.getInstance(mContext); } void start(@NonNull Callback cb) { @@ -134,6 +137,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback { mLocalMediaManager.stopScan(); mLocalMediaManager.registerCallback(this); mLocalMediaManager.startScan(); + mRouterManager.startScan(); } void stop() { @@ -144,6 +148,9 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback { mLocalMediaManager.unregisterCallback(this); mLocalMediaManager.stopScan(); } + if (mRouterManager != null) { + mRouterManager.stopScan(); + } mMediaDevices.clear(); } diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java index b6ca77b73df7..f7a4aca4ebb1 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java @@ -137,7 +137,7 @@ import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.wm.shell.pip.Pip; -import com.android.wm.shell.splitscreen.SplitScreen; +import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import java.io.PrintWriter; import java.util.List; @@ -181,7 +181,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, private final BroadcastDispatcher mBroadcastDispatcher; private final CommandQueue mCommandQueue; private final Optional<Pip> mPipOptional; - private final Optional<SplitScreen> mSplitScreenOptional; + private final Optional<LegacySplitScreen> mSplitScreenOptional; private final Optional<Recents> mRecentsOptional; private final SystemActions mSystemActions; private final Handler mHandler; @@ -409,7 +409,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, BroadcastDispatcher broadcastDispatcher, CommandQueue commandQueue, Optional<Pip> pipOptional, - Optional<SplitScreen> splitScreenOptional, + Optional<LegacySplitScreen> splitScreenOptional, Optional<Recents> recentsOptional, Lazy<StatusBar> statusBarLazy, ShadeController shadeController, NotificationRemoteInputManager notificationRemoteInputManager, @@ -697,7 +697,7 @@ public class NavigationBar implements View.OnAttachStateChangeListener, } if (mStartingQuickSwitchRotation == -1 || mSplitScreenOptional - .map(SplitScreen::isDividerVisible).orElse(false)) { + .map(LegacySplitScreen::isDividerVisible).orElse(false)) { // Hide the secondary home handle if we are in multiwindow since apps in multiwindow // aren't allowed to set the display orientation resetSecondaryHandle(); diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java index f7f34003be87..461ab3aeb3c3 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java @@ -65,7 +65,7 @@ import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.wm.shell.pip.Pip; -import com.android.wm.shell.splitscreen.SplitScreen; +import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -98,7 +98,7 @@ public class NavigationBarController implements Callbacks, private final BroadcastDispatcher mBroadcastDispatcher; private final CommandQueue mCommandQueue; private final Optional<Pip> mPipOptional; - private final Optional<SplitScreen> mSplitScreenOptional; + private final Optional<LegacySplitScreen> mSplitScreenOptional; private final Optional<Recents> mRecentsOptional; private final Lazy<StatusBar> mStatusBarLazy; private final ShadeController mShadeController; @@ -133,7 +133,7 @@ public class NavigationBarController implements Callbacks, BroadcastDispatcher broadcastDispatcher, CommandQueue commandQueue, Optional<Pip> pipOptional, - Optional<SplitScreen> splitScreenOptional, + Optional<LegacySplitScreen> splitScreenOptional, Optional<Recents> recentsOptional, Lazy<StatusBar> statusBarLazy, ShadeController shadeController, diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java index 4c3ac404a49e..d6f079993846 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java @@ -93,7 +93,7 @@ import com.android.systemui.statusbar.phone.LightBarTransitionsController; import com.android.systemui.statusbar.phone.NotificationPanelViewController; import com.android.systemui.statusbar.phone.StatusBar; import com.android.wm.shell.pip.Pip; -import com.android.wm.shell.splitscreen.SplitScreen; +import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import java.io.PrintWriter; import java.util.function.Consumer; @@ -1289,8 +1289,8 @@ public class NavigationBarView extends FrameLayout implements return super.onApplyWindowInsets(insets); } - void registerDockedListener(SplitScreen splitScreen) { - splitScreen.registerInSplitScreenListener(mDockedListener); + void registerDockedListener(LegacySplitScreen legacySplitScreen) { + legacySplitScreen.registerInSplitScreenListener(mDockedListener); } void registerPipExclusionBoundsChangeListener(Pip pip) { diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java index dddd39b17209..bc9500a68a52 100644 --- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java +++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java @@ -21,7 +21,6 @@ import android.app.PendingIntent; import android.app.people.ConversationChannel; import android.app.people.IPeopleManager; import android.app.people.PeopleSpaceTile; -import android.appwidget.AppWidgetHost; import android.appwidget.AppWidgetManager; import android.content.Context; import android.content.Intent; @@ -120,8 +119,7 @@ public class PeopleSpaceUtils { e -> e.getValue().getId().equals(shortcutId)).findFirst(); if (!entry.isPresent() || shortcutId == null) { if (DEBUG) Log.d(TAG, "Matching conversation not found for shortcut ID"); - AppWidgetHost host = new AppWidgetHost(context, 0); - host.deleteAppWidgetId(appWidgetId); + //TODO: Delete app widget id when crash is fixed (b/175486868) continue; } PeopleSpaceTile tile = entry.get().getValue(); diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt index 87ffbd465109..b2c2aa309811 100644 --- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt +++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt @@ -262,8 +262,11 @@ class PrivacyItemController @Inject constructor( privacyList = emptyList() return } - val list = currentUserIds.flatMap { appOpsController.getActiveAppOpsForUser(it) } - .mapNotNull { toPrivacyItem(it) }.distinct() + val list = appOpsController.getActiveAppOpsForUser(UserHandle.USER_ALL).filter { + UserHandle.getUserId(it.uid) in currentUserIds || + it.code == AppOpsManager.OP_PHONE_CALL_MICROPHONE || + it.code == AppOpsManager.OP_PHONE_CALL_CAMERA + }.mapNotNull { toPrivacyItem(it) }.distinct() logger.logUpdatedPrivacyItemsList( list.joinToString(separator = ", ", transform = PrivacyItem::toLog)) privacyList = list diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java index c89f8e58f980..6074ef6156c3 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java @@ -252,11 +252,9 @@ public class QuickQSPanel extends QSPanel { final int availableWidth = getMeasuredWidth() - getPaddingStart() - getPaddingEnd(); final int leftoverWhitespace = availableWidth - maxTiles * mCellWidth; - final int smallestHorizontalMarginNeeded; - smallestHorizontalMarginNeeded = leftoverWhitespace / Math.max(1, maxTiles - 1); - if (smallestHorizontalMarginNeeded > 0){ - mCellMarginHorizontal = smallestHorizontalMarginNeeded; + if (leftoverWhitespace > 0) { + mCellMarginHorizontal = leftoverWhitespace / Math.max(1, maxTiles); mColumns = maxTiles; } else{ mColumns = mCellWidth == 0 ? 1 : @@ -266,7 +264,7 @@ public class QuickQSPanel extends QSPanel { mCellMarginHorizontal = (availableWidth - mCellWidth) / 2; } else { mCellMarginHorizontal = - (availableWidth - mColumns * mCellWidth) / (mColumns - 1); + (availableWidth - mColumns * mCellWidth) / mColumns; } } @@ -310,7 +308,8 @@ public class QuickQSPanel extends QSPanel { // Only one column/tile. Use the margin to center the tile. return getPaddingStart() + mCellMarginHorizontal; } - return getPaddingStart() + column * (mCellWidth + mCellMarginHorizontal); + return getPaddingStart() + mCellMarginHorizontal / 2 + + column * (mCellWidth + mCellMarginHorizontal); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java index ad275f1fa6ab..39b92dc4f662 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java +++ b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java @@ -116,9 +116,11 @@ public class QSCarrier extends LinearLayout { return TextUtils.equals(typeContentDescription, mContext.getString(R.string.data_connection_no_internet)) || TextUtils.equals(typeContentDescription, - mContext.getString(R.string.cell_data_off_content_description)) + mContext.getString( + com.android.settingslib.R.string.cell_data_off_content_description)) || TextUtils.equals(typeContentDescription, - mContext.getString(R.string.not_default_data_content_description)); + mContext.getString( + com.android.settingslib.R.string.not_default_data_content_description)); } public void setCarrierText(CharSequence text) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java index 5c683f24a8f1..ef501c8efc2a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileBaseView.java @@ -133,7 +133,7 @@ public class QSTileBaseView extends com.android.systemui.plugins.qs.QSTileView { mColorActive = Utils.getColorAttrDefaultColor(context, android.R.attr.colorAccent); mColorDisabled = Utils.getDisabled(context, - Utils.getColorAttrDefaultColor(context, android.R.attr.textColorTertiary)); + Utils.getColorAttrDefaultColor(context, android.R.attr.colorControlActivated)); mColorInactive = Utils.getColorAttrDefaultColor(context, android.R.attr.textColorSecondary); setPadding(0, 0, 0, 0); diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java index c27b0473f16c..6d9d587bc729 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java +++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java @@ -95,7 +95,7 @@ import com.android.wm.shell.onehanded.OneHanded; import com.android.wm.shell.onehanded.OneHandedEvents; import com.android.wm.shell.pip.Pip; import com.android.wm.shell.pip.PipAnimationController; -import com.android.wm.shell.splitscreen.SplitScreen; +import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -130,7 +130,7 @@ public class OverviewProxyService extends CurrentUserTracker implements private final Context mContext; private final Optional<Pip> mPipOptional; private final Optional<Lazy<StatusBar>> mStatusBarOptionalLazy; - private final Optional<SplitScreen> mSplitScreenOptional; + private final Optional<LegacySplitScreen> mSplitScreenOptional; private SysUiState mSysUiState; private final Handler mHandler; private final Lazy<NavigationBarController> mNavBarControllerLazy; @@ -636,7 +636,7 @@ public class OverviewProxyService extends CurrentUserTracker implements NavigationModeController navModeController, NotificationShadeWindowController statusBarWinController, SysUiState sysUiState, Optional<Pip> pipOptional, - Optional<SplitScreen> splitScreenOptional, + Optional<LegacySplitScreen> splitScreenOptional, Optional<Lazy<StatusBar>> statusBarOptionalLazy, Optional<OneHanded> oneHandedOptional, BroadcastDispatcher broadcastDispatcher) { diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java index 6c4f8083788a..53ff1dfd277b 100644 --- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java +++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java @@ -17,6 +17,9 @@ package com.android.systemui.settings.brightness; import android.content.Context; +import android.graphics.drawable.ClipDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.LayerDrawable; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; @@ -27,6 +30,7 @@ import android.widget.SeekBar; import androidx.annotation.Nullable; import com.android.settingslib.RestrictedLockUtils; +import com.android.settingslib.Utils; import com.android.systemui.R; import com.android.systemui.statusbar.policy.BrightnessMirrorController; import com.android.systemui.util.ViewController; @@ -269,14 +273,45 @@ public class BrightnessSlider private BrightnessSlider fromTree(ViewGroup root, boolean useMirror) { BrightnessSliderView v = root.requireViewById(R.id.brightness_slider); + + // TODO(175026098) Workaround. Remove when b/175026098 is fixed + applyTheme(v); + return new BrightnessSlider(root, v, useMirror); } /** Get the layout to inflate based on what slider to use */ - public int getLayout() { + private int getLayout() { return mSettings.useThickSlider() ? R.layout.quick_settings_brightness_dialog_thick : R.layout.quick_settings_brightness_dialog; } + + private LayerDrawable findProgressClippableDrawable(BrightnessSliderView v) { + SeekBar b = v.requireViewById(R.id.slider); + if (b.getProgressDrawable() instanceof LayerDrawable) { + Drawable progress = ((LayerDrawable) b.getProgressDrawable()) + .findDrawableByLayerId(com.android.internal.R.id.progress); + if (progress instanceof ClipDrawable) { + Drawable inner = ((ClipDrawable) progress).getDrawable(); + if (inner instanceof LayerDrawable) { + return (LayerDrawable) inner; + } + } + } + return null; + } + + private void applyTheme(BrightnessSliderView v) { + LayerDrawable layer = findProgressClippableDrawable(v); + if (layer != null) { + layer.findDrawableByLayerId(R.id.slider_foreground).setTintList( + Utils.getColorAttr(v.getContext(), + com.android.internal.R.attr.colorControlActivated)); + layer.findDrawableByLayerId(R.id.slider_icon).setTintList( + Utils.getColorAttr(v.getContext(), + com.android.internal.R.attr.colorBackground)); + } + } } } diff --git a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java index 6202057b9ef1..993343808ee9 100644 --- a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java +++ b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java @@ -26,8 +26,8 @@ import android.view.WindowManagerGlobal; import com.android.internal.policy.DividerSnapAlgorithm; import com.android.systemui.SystemUI; import com.android.systemui.dagger.SysUISingleton; -import com.android.wm.shell.splitscreen.DividerView; -import com.android.wm.shell.splitscreen.SplitScreen; +import com.android.wm.shell.legacysplitscreen.DividerView; +import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import java.util.Optional; @@ -41,7 +41,7 @@ public class ShortcutKeyDispatcher extends SystemUI implements ShortcutKeyServiceProxy.Callbacks { private static final String TAG = "ShortcutKeyDispatcher"; - private final Optional<SplitScreen> mSplitScreenOptional; + private final Optional<LegacySplitScreen> mSplitScreenOptional; private ShortcutKeyServiceProxy mShortcutKeyServiceProxy = new ShortcutKeyServiceProxy(this); private IWindowManager mWindowManagerService = WindowManagerGlobal.getWindowManagerService(); @@ -55,7 +55,7 @@ public class ShortcutKeyDispatcher extends SystemUI protected final long SC_DOCK_RIGHT = META_MASK | KeyEvent.KEYCODE_RIGHT_BRACKET; @Inject - public ShortcutKeyDispatcher(Context context, Optional<SplitScreen> splitScreenOptional) { + public ShortcutKeyDispatcher(Context context, Optional<LegacySplitScreen> splitScreenOptional) { super(context); mSplitScreenOptional = splitScreenOptional; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java index 9bd34ad1937f..4b6d66eef56d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java @@ -484,8 +484,8 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle stack.push(notificationChildren.get(i)); } } - - row.showFeedbackIcon(mAssistantFeedbackController.showFeedbackIndicator(entry)); + row.showFeedbackIcon(mAssistantFeedbackController.showFeedbackIndicator(entry), + mAssistantFeedbackController.getFeedbackImageResource(entry)); row.setLastAudiblyAlertedMs(entry.getLastAudiblyAlertedMs()); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java index 87a3f0755ec5..a350c5d8cd77 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/AssistantFeedbackController.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.notification; import static android.service.notification.NotificationListenerService.Ranking; +import android.app.NotificationManager; import android.content.ContentResolver; import android.content.Context; import android.database.ContentObserver; @@ -29,6 +30,7 @@ import android.provider.Settings; import androidx.annotation.Nullable; +import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.statusbar.notification.collection.NotificationEntry; @@ -47,6 +49,12 @@ public class AssistantFeedbackController extends ContentObserver { = Settings.Global.getUriFor(Settings.Global.NOTIFICATION_FEEDBACK_ENABLED); private ContentResolver mResolver; + public static final int STATUS_UNCHANGED = 0; + public static final int STATUS_ALERTED = 1; + public static final int STATUS_SILENCED = 2; + public static final int STATUS_PROMOTED = 3; + public static final int STATUS_DEMOTED = 4; + private boolean mFeedbackEnabled; /** Injected constructor */ @@ -81,16 +89,88 @@ public class AssistantFeedbackController extends ContentObserver { } /** - * Determines whether to show feedback indicator. The feedback indicator will be shown if - * {@link #isFeedbackEnabled()} is enabled and assistant has changed this notification's rank or - * importance. + * Get the feedback status according to assistant's adjustments * * @param entry Notification Entry to show feedback for */ - public boolean showFeedbackIndicator(NotificationEntry entry) { + public int getFeedbackStatus(NotificationEntry entry) { + if (!isFeedbackEnabled()) { + return STATUS_UNCHANGED; + } Ranking ranking = entry.getRanking(); - return isFeedbackEnabled() - && (ranking.getImportance() != ranking.getChannel().getImportance() - || ranking.getRankingAdjustment() != Ranking.RANKING_UNCHANGED); + int oldImportance = ranking.getChannel().getImportance(); + int newImportance = ranking.getImportance(); + if (oldImportance < NotificationManager.IMPORTANCE_DEFAULT + && newImportance >= NotificationManager.IMPORTANCE_DEFAULT) { + return STATUS_ALERTED; + } else if (oldImportance >= NotificationManager.IMPORTANCE_DEFAULT + && newImportance < NotificationManager.IMPORTANCE_DEFAULT) { + return STATUS_SILENCED; + } else if (oldImportance < newImportance + || ranking.getRankingAdjustment() == ranking.RANKING_PROMOTED) { + return STATUS_PROMOTED; + } else if (oldImportance > newImportance + || ranking.getRankingAdjustment() == ranking.RANKING_DEMOTED) { + return STATUS_DEMOTED; + } else { + return STATUS_UNCHANGED; + } + } + + /** + * Determines whether to show feedback indicator. The feedback indicator will be shown + * if {@link #isFeedbackEnabled()} is enabled and assistant has changed this notification's rank + * or importance. + * + * @param entry Notification Entry to show feedback for + */ + public boolean showFeedbackIndicator(NotificationEntry entry) { + return getFeedbackStatus(entry) != STATUS_UNCHANGED; + } + + /** + * Get the feedback indicator image resource according to assistant's changes on this + * notification's rank or importance. + * + * @param entry Notification Entry to show feedback for + */ + public int getFeedbackImageResource(NotificationEntry entry) { + int feedbackStatus = getFeedbackStatus(entry); + switch (feedbackStatus) { + case STATUS_ALERTED: + return R.drawable.ic_feedback_alerted; + case STATUS_SILENCED: + return R.drawable.ic_feedback_silenced; + case STATUS_PROMOTED: + return R.drawable.ic_feedback_uprank; + case STATUS_DEMOTED: + return R.drawable.ic_feedback_downrank; + default: + return 0; + } + } + + /** + * Get the inline settings description resource according to assistant's changes on this + * notification's rank or importance. + * + * @param entry Notification Entry to show feedback for + */ + public int getInlineDescriptionResource(NotificationEntry entry) { + int feedbackStatus = getFeedbackStatus(entry); + switch (feedbackStatus) { + case STATUS_ALERTED: + return com.android.systemui.R.string.notification_channel_summary_automatic_alerted; + case STATUS_SILENCED: + return com.android.systemui.R.string + .notification_channel_summary_automatic_silenced; + case STATUS_PROMOTED: + return com.android.systemui.R.string + .notification_channel_summary_automatic_promoted; + case STATUS_DEMOTED: + return com.android.systemui.R.string.notification_channel_summary_automatic_demoted; + default: + return com.android.systemui.R.string.notification_channel_summary_automatic; + } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java index 1f9bc77b0b2f..e58ea7b8b5f3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java @@ -59,7 +59,7 @@ import com.android.systemui.dagger.qualifiers.UiBackground; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.NotificationChannels; -import com.android.wm.shell.splitscreen.SplitScreen; +import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import java.util.List; import java.util.Optional; @@ -82,11 +82,11 @@ public class InstantAppNotifier extends SystemUI private final CommandQueue mCommandQueue; private boolean mDockedStackExists; private KeyguardStateController mKeyguardStateController; - private final Optional<SplitScreen> mSplitScreenOptional; + private final Optional<LegacySplitScreen> mSplitScreenOptional; @Inject public InstantAppNotifier(Context context, CommandQueue commandQueue, - @UiBackground Executor uiBgExecutor, Optional<SplitScreen> splitScreenOptional) { + @UiBackground Executor uiBgExecutor, Optional<LegacySplitScreen> splitScreenOptional) { super(context); mSplitScreenOptional = splitScreenOptional; mCommandQueue = commandQueue; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java index c7ac40346ce1..998ae9e55313 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java @@ -30,12 +30,8 @@ import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner; -import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender; import com.android.systemui.util.concurrency.DelayableExecutor; -import java.util.HashMap; -import java.util.Map; - import javax.inject.Inject; /** @@ -75,9 +71,6 @@ public class AppOpsCoordinator implements Coordinator { public void attach(NotifPipeline pipeline) { mNotifPipeline = pipeline; - // extend the lifetime of foreground notification services to show for at least 5 seconds - mNotifPipeline.addNotificationLifetimeExtender(mForegroundLifetimeExtender); - // filter out foreground service notifications that aren't necessary anymore mNotifPipeline.addPreGroupFilter(mNotifFilter); @@ -119,64 +112,6 @@ public class AppOpsCoordinator implements Coordinator { }; /** - * 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 10118e4733ba..11b829c4b4e8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -1672,12 +1672,12 @@ public class ExpandableNotificationRow extends ActivatableNotificationView requestLayout(); } - public void showFeedbackIcon(boolean show) { + public void showFeedbackIcon(boolean show, int resId) { if (mIsSummaryWithChildren) { - mChildrenContainer.showFeedbackIcon(show); + mChildrenContainer.showFeedbackIcon(show, resId); } - mPrivateLayout.showFeedbackIcon(show); - mPublicLayout.showFeedbackIcon(show); + mPrivateLayout.showFeedbackIcon(show, resId); + mPublicLayout.showFeedbackIcon(show, resId); } /** Sets the last time the notification being displayed audibly alerted the user. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java index 2ff43d002f3a..85f556fa733c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java @@ -54,7 +54,8 @@ public abstract class ExpandableOutlineView extends ExpandableView { R.id.bottom_roundess_animator_end_tag, R.id.bottom_roundess_animator_start_tag); private static final AnimationProperties ROUNDNESS_PROPERTIES = - new AnimationProperties().setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD); + new AnimationProperties().setDuration( + StackStateAnimator.ANIMATION_DURATION_CORNER_RADIUS); private static final Path EMPTY_PATH = new Path(); private final Rect mOutlineRect = new Rect(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java index 73e080423d40..ba03d01b20b0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java @@ -69,6 +69,7 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable { private float mContentTranslation; protected boolean mLastInSection; protected boolean mFirstInSection; + boolean mIsBeingSwiped; public ExpandableView(Context context, AttributeSet attrs) { super(context, attrs); @@ -173,6 +174,14 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable { return false; } + public void setIsBeingSwiped(boolean swiped) { + mIsBeingSwiped = swiped; + } + + public boolean isBeingSwiped() { + return mIsBeingSwiped; + } + public boolean isHeadsUpAnimatingAway() { return false; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FeedbackInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FeedbackInfo.java index 149ee8c05348..35f35615e1c1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FeedbackInfo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FeedbackInfo.java @@ -16,10 +16,6 @@ package com.android.systemui.statusbar.notification.row; -import static android.app.NotificationManager.IMPORTANCE_DEFAULT; -import static android.service.notification.NotificationListenerService.Ranking.RANKING_DEMOTED; -import static android.service.notification.NotificationListenerService.Ranking.RANKING_PROMOTED; - import android.annotation.SuppressLint; import android.app.Notification; import android.content.Context; @@ -30,6 +26,7 @@ import android.os.Bundle; import android.os.RemoteException; import android.service.notification.NotificationListenerService; import android.service.notification.StatusBarNotification; +import android.text.Html; import android.util.AttributeSet; import android.util.Log; import android.view.View; @@ -138,30 +135,30 @@ public class FeedbackInfo extends LinearLayout implements NotificationGuts.GutsC no.setVisibility(View.VISIBLE); yes.setOnClickListener(this::positiveFeedback); no.setOnClickListener(this::negativeFeedback); - prompt.setText(getPrompt()); + prompt.setText(Html.fromHtml(getPrompt())); } @SuppressLint("DefaultLocale") private String getPrompt() { StringBuilder sb = new StringBuilder(); - int oldImportance = mRanking.getChannel().getImportance(); - int newImportance = mRanking.getImportance(); - int ranking = mRanking.getRankingAdjustment(); + int status = mFeedbackController.getFeedbackStatus(mEntry); if (DEBUG) { sb.append(String.format( "[DEBUG]: oldImportance=%d, newImportance=%d, ranking=%d\n\n", mRanking.getChannel().getImportance(), mRanking.getImportance(), mRanking.getRankingAdjustment())); } - if (oldImportance >= IMPORTANCE_DEFAULT && newImportance < IMPORTANCE_DEFAULT) { - sb.append(mContext.getString(R.string.feedback_silenced)); - } else if (newImportance > oldImportance || ranking == RANKING_PROMOTED) { - sb.append(mContext.getString(R.string.feedback_promoted)); - } else if (newImportance < oldImportance || ranking == RANKING_DEMOTED) { - sb.append(mContext.getString(R.string.feedback_demoted)); + if (status == mFeedbackController.STATUS_ALERTED) { + sb.append(mContext.getText(R.string.feedback_alerted)); + } else if (status == mFeedbackController.STATUS_SILENCED) { + sb.append(mContext.getText(R.string.feedback_silenced)); + } else if (status == mFeedbackController.STATUS_PROMOTED) { + sb.append(mContext.getText(R.string.feedback_promoted)); + } else if (status == mFeedbackController.STATUS_DEMOTED) { + sb.append(mContext.getText(R.string.feedback_demoted)); } sb.append(" "); - sb.append(mContext.getString(R.string.feedback_prompt)); + sb.append(mContext.getText(R.string.feedback_prompt)); return sb.toString(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java index 74e6c003041e..475f627d8649 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java @@ -1586,15 +1586,15 @@ public class NotificationContentView extends FrameLayout { return null; } - public void showFeedbackIcon(boolean show) { + public void showFeedbackIcon(boolean show, int resId) { if (mContractedChild != null) { - mContractedWrapper.showFeedbackIcon(show); + mContractedWrapper.showFeedbackIcon(show, resId); } if (mExpandedChild != null) { - mExpandedWrapper.showFeedbackIcon(show); + mExpandedWrapper.showFeedbackIcon(show, resId); } if (mHeadsUpChild != null) { - mHeadsUpWrapper.showFeedbackIcon(show); + mHeadsUpWrapper.showFeedbackIcon(show, resId); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java index c4f009815ba6..2fd17a587612 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java @@ -378,7 +378,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx mDeviceProvisionedController.isDeviceProvisioned(), row.getIsNonblockable(), mHighPriorityProvider.isHighPriority(row.getEntry()), - mAssistantFeedbackController.isFeedbackEnabled()); + mAssistantFeedbackController); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java index 6ff5ed1bceae..d12d98ecc62b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java @@ -41,6 +41,7 @@ import android.metrics.LogMaker; import android.os.Handler; import android.os.RemoteException; import android.service.notification.StatusBarNotification; +import android.text.Html; import android.text.TextUtils; import android.transition.ChangeBounds; import android.transition.Fade; @@ -60,6 +61,7 @@ import com.android.internal.logging.UiEventLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.Dependency; import com.android.systemui.R; +import com.android.systemui.statusbar.notification.AssistantFeedbackController; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import java.lang.annotation.Retention; @@ -96,6 +98,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G private PackageManager mPm; private MetricsLogger mMetricsLogger; private ChannelEditorDialogController mChannelEditorDialogController; + private AssistantFeedbackController mAssistantFeedbackController; private String mPackageName; private String mAppName; @@ -200,12 +203,13 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G boolean isDeviceProvisioned, boolean isNonblockable, boolean wasShownHighPriority, - boolean showAutomaticSetting) + AssistantFeedbackController assistantFeedbackController) throws RemoteException { mINotificationManager = iNotificationManager; mMetricsLogger = Dependency.get(MetricsLogger.class); mOnUserInteractionCallback = onUserInteractionCallback; mChannelEditorDialogController = channelEditorDialogController; + mAssistantFeedbackController = assistantFeedbackController; mPackageName = pkg; mUniqueChannelsInRow = uniqueChannelsInRow; mNumUniqueChannelsInRow = uniqueChannelsInRow.size(); @@ -222,7 +226,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G mAppUid = mSbn.getUid(); mDelegatePkg = mSbn.getOpPkg(); mIsDeviceProvisioned = isDeviceProvisioned; - mShowAutomaticSetting = showAutomaticSetting; + mShowAutomaticSetting = mAssistantFeedbackController.isFeedbackEnabled(); mUiEventLogger = uiEventLogger; int numTotalChannels = mINotificationManager.getNumNotificationChannelsForPackage( @@ -280,6 +284,8 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G View automatic = findViewById(R.id.automatic); if (mShowAutomaticSetting) { + mAutomaticDescriptionView.setText(Html.fromHtml(mContext.getText( + mAssistantFeedbackController.getInlineDescriptionResource(mEntry)).toString())); automatic.setVisibility(VISIBLE); automatic.setOnClickListener(mOnAutomatic); } else { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java index 7c5d4a3efee7..152527f3d76a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java @@ -29,6 +29,7 @@ import android.view.ViewGroup; import android.view.ViewGroup.MarginLayoutParams; import android.view.animation.Interpolator; import android.view.animation.PathInterpolator; +import android.widget.ImageButton; import android.widget.ImageView; import android.widget.TextView; @@ -131,8 +132,11 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper { /** Shows or hides feedback indicator */ @Override - public void showFeedbackIcon(boolean show) { + public void showFeedbackIcon(boolean show, int resId) { mFeedbackIcon.setVisibility(show ? View.VISIBLE : View.GONE); + if (show && mFeedbackIcon instanceof ImageButton) { + ((ImageButton) mFeedbackIcon).setImageResource(resId); + } } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java index 2d706a48e90d..04cbe87c1e82 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java @@ -103,7 +103,7 @@ public abstract class NotificationViewWrapper implements TransformableView { /** * Shows or hides feedback icon. */ - public void showFeedbackIcon(boolean show) { + public void showFeedbackIcon(boolean show, int resId) { } public void onReinflated() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java index 885048df13f1..c5dd3c771da1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java @@ -42,8 +42,6 @@ public class AmbientState { private final SectionProvider mSectionProvider; private int mScrollY; - private int mAnchorViewIndex; - private int mAnchorViewY; private boolean mDimmed; private ActivatableNotificationView mActivatedChild; private float mOverScrollTopAmount; @@ -140,27 +138,6 @@ public class AmbientState { } /** - * Index of the child view whose Y position on screen is returned by {@link #getAnchorViewY()}. - * Other views are laid out outwards from this view in both directions. - */ - public int getAnchorViewIndex() { - return mAnchorViewIndex; - } - - public void setAnchorViewIndex(int anchorViewIndex) { - mAnchorViewIndex = anchorViewIndex; - } - - /** Current Y position of the view at {@link #getAnchorViewIndex()}. */ - public int getAnchorViewY() { - return mAnchorViewY; - } - - public void setAnchorViewY(int anchorViewY) { - mAnchorViewY = anchorViewY; - } - - /** * @param dimmed Whether we are in a dimmed state (on the lockscreen), where the backgrounds are * translucent and everything is scaled back a bit. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java index 601fc197cfa6..a56ae7d21952 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java @@ -1300,12 +1300,12 @@ public class NotificationChildrenContainer extends ViewGroup { /** * Shows or hides feedback icon. */ - public void showFeedbackIcon(boolean show) { + public void showFeedbackIcon(boolean show, int resId) { if (mNotificationHeaderWrapper != null) { - mNotificationHeaderWrapper.showFeedbackIcon(show); + mNotificationHeaderWrapper.showFeedbackIcon(show, resId); } if (mNotificationHeaderWrapperLowPriority != null) { - mNotificationHeaderWrapperLowPriority.showFeedbackIcon(show); + mNotificationHeaderWrapperLowPriority.showFeedbackIcon(show, resId); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java index f9d7c1f056ae..31600710057b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java @@ -67,7 +67,7 @@ public class NotificationRoundnessManager { } } - private boolean updateViewWithoutCallback(ExpandableView view, + boolean updateViewWithoutCallback(ExpandableView view, boolean animate) { float topRoundness = getRoundness(view, true /* top */); float bottomRoundness = getRoundness(view, false /* top */); @@ -107,7 +107,9 @@ public class NotificationRoundnessManager { } private float getRoundness(ExpandableView view, boolean top) { - if ((view.isPinned() || view.isHeadsUpAnimatingAway()) && !mExpanded) { + if ((view.isPinned() + || view.isBeingSwiped() + || (view.isHeadsUpAnimatingAway()) && !mExpanded)) { return 1.0f; } if (isFirstInSection(view, true /* include first section */) && top) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt index 4f7e14ba4a4c..6c8cdf67d974 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt @@ -73,7 +73,6 @@ class NotificationSectionsManager @Inject internal constructor( private lateinit var parent: NotificationStackScrollLayout private var initialized = false - private var onClearSilentNotifsClickListener: View.OnClickListener? = null @VisibleForTesting val silentHeaderView: SectionHeaderView? @@ -441,11 +440,6 @@ class NotificationSectionsManager @Inject internal constructor( } } - /** Listener for when the "clear all" button is clicked on the gentle notification header. */ - fun setOnClearSilentNotifsClickListener(listener: View.OnClickListener) { - onClearSilentNotifsClickListener = listener - } - fun setHeaderForegroundColor(@ColorInt color: Int) { peopleHeaderView?.setForegroundColor(color) silentHeaderView?.setForegroundColor(color) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 4487142e8907..0dc824f04e74 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -19,7 +19,6 @@ package com.android.systemui.statusbar.notification.stack; import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_SCROLL_FLING; import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters; import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_SILENT; -import static com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.ANCHOR_SCROLLING; import static com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_SWIPE; import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT; @@ -164,9 +163,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable private float mExpandedHeight; private int mOwnScrollY; - - private View mScrollAnchorView; - private int mScrollAnchorViewY; private int mMaxLayoutHeight; private VelocityTracker mVelocityTracker; @@ -387,7 +383,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } } }; - private PorterDuffXfermode mSrcMode = new PorterDuffXfermode(PorterDuff.Mode.SRC); private boolean mPulsing; private boolean mScrollable; private View mForcedScroll; @@ -423,9 +418,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable private int mCachedBackgroundColor; private boolean mHeadsUpGoingAwayAnimationsAllowed = true; private Runnable mReflingAndAnimateScroll = () -> { - if (ANCHOR_SCROLLING) { - maybeReflingScroller(); - } animateScroll(); }; private int mCornerRadius; @@ -480,23 +472,12 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable private final ScrollAdapter mScrollAdapter = new ScrollAdapter() { @Override public boolean isScrolledToTop() { - if (ANCHOR_SCROLLING) { - updateScrollAnchor(); - // TODO: once we're recycling this will need to check the adapter position of the - // child - return mScrollAnchorView == getFirstChildNotGone() && mScrollAnchorViewY >= 0; - } else { - return mOwnScrollY == 0; - } + return mOwnScrollY == 0; } @Override public boolean isScrolledToBottom() { - if (ANCHOR_SCROLLING) { - return getMaxPositiveScrollAmount() <= 0; - } else { - return mOwnScrollY >= getScrollRange(); - } + return mOwnScrollY >= getScrollRange(); } @Override @@ -519,12 +500,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable mSectionsManager = notificationSectionsManager; mSectionsManager.initialize(this, LayoutInflater.from(context)); - mSectionsManager.setOnClearSilentNotifsClickListener(v -> { - // Leave the shade open if there will be other notifs left over to clear - final boolean closeShade = - !mController.hasActiveClearableNotifications(ROWS_HIGH_PRIORITY); - clearNotifications(ROWS_GENTLE, closeShade); - }); mSections = mSectionsManager.createSectionsForBuckets(); mAmbientState = new AmbientState(context, mSectionsManager); @@ -665,30 +640,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } } - @Override - public void draw(Canvas canvas) { - super.draw(canvas); - - if (DEBUG && ANCHOR_SCROLLING) { - if (mScrollAnchorView instanceof ExpandableNotificationRow) { - canvas.drawRect(0, - mScrollAnchorView.getTranslationY(), - getWidth(), - mScrollAnchorView.getTranslationY() - + ((ExpandableNotificationRow) mScrollAnchorView).getActualHeight(), - mDebugPaint); - canvas.drawText(Integer.toString(mScrollAnchorViewY), getWidth() - 200, - mScrollAnchorView.getTranslationY() + 30, mDebugPaint); - int y = (int) mShelf.getTranslationY(); - canvas.drawLine(0, y, getWidth(), y, mDebugPaint); - } - canvas.drawText(Integer.toString(getMaxNegativeScrollAmount()), getWidth() - 100, - getTopPadding() + 30, mDebugPaint); - canvas.drawText(Integer.toString(getMaxPositiveScrollAmount()), getWidth() - 100, - getHeight() - 30, mDebugPaint); - } - } - @ShadeViewRefactor(RefactorComponent.DECORATOR) private void drawBackground(Canvas canvas) { int lockScreenLeft = mSidePaddings; @@ -823,13 +774,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable if (!mShouldDrawNotificationBackground) { return; } - final boolean newFlowHideShelf = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.SHOW_NEW_NOTIF_DISMISS, 1 /* on by default */) == 1; - if (newFlowHideShelf) { - mBackgroundPaint.setColor(Color.TRANSPARENT); - invalidate(); - return; - } // Interpolate between semi-transparent notification panel background color // and white AOD separator. float colorInterpolation = MathUtils.smoothStep(0.4f /* start */, 1f /* end */, @@ -996,10 +940,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable mListener = listener; } - public void setScrollAnchorView(View scrollAnchorView) { - mScrollAnchorView = scrollAnchorView; - } - @ShadeViewRefactor(RefactorComponent.LAYOUT_ALGORITHM) private void setMaxLayoutHeight(int maxLayoutHeight) { mMaxLayoutHeight = maxLayoutHeight; @@ -1030,12 +970,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable mAmbientState.setCurrentScrollVelocity(mScroller.isFinished() ? 0 : mScroller.getCurrVelocity()); - if (ANCHOR_SCROLLING) { - mAmbientState.setAnchorViewIndex(indexOfChild(mScrollAnchorView)); - mAmbientState.setAnchorViewY(mScrollAnchorViewY); - } else { - mAmbientState.setScrollY(mOwnScrollY); - } + mAmbientState.setScrollY(mOwnScrollY); mStackScrollAlgorithm.resetViewStates(mAmbientState, getSpeedBumpIndex()); if (!isCurrentlyAnimating() && !mNeedsAnimation) { applyCurrentState(); @@ -1081,18 +1016,16 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable if (mChildrenToAddAnimated.isEmpty()) { return; } - if (!ANCHOR_SCROLLING) { - for (int i = 0; i < getChildCount(); i++) { - ExpandableView child = (ExpandableView) getChildAt(i); - if (mChildrenToAddAnimated.contains(child)) { - final int startingPosition = getPositionInLinearLayout(child); - final int childHeight = getIntrinsicHeight(child) + mPaddingBetweenElements; - if (startingPosition < mOwnScrollY) { - // This child starts off screen, so let's keep it offscreen to keep the - // others visible - - setOwnScrollY(mOwnScrollY + childHeight); - } + for (int i = 0; i < getChildCount(); i++) { + ExpandableView child = (ExpandableView) getChildAt(i); + if (mChildrenToAddAnimated.contains(child)) { + final int startingPosition = getPositionInLinearLayout(child); + final int childHeight = getIntrinsicHeight(child) + mPaddingBetweenElements; + if (startingPosition < mOwnScrollY) { + // This child starts off screen, so let's keep it offscreen to keep the + // others visible + + setOwnScrollY(mOwnScrollY + childHeight); } } } @@ -1110,17 +1043,11 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable int positionInLinearLayout = getPositionInLinearLayout(expandableView); int targetScroll = targetScrollForView(expandableView, positionInLinearLayout); int outOfViewScroll = positionInLinearLayout + expandableView.getIntrinsicHeight(); - - if (ANCHOR_SCROLLING) { - // TODO - } else { - targetScroll = Math.max(0, Math.min(targetScroll, getScrollRange())); - - // Only apply the scroll if we're scrolling the view upwards, or the view is so - // far up that it is not visible anymore. - if (mOwnScrollY < targetScroll || outOfViewScroll < mOwnScrollY) { - setOwnScrollY(targetScroll); - } + targetScroll = Math.max(0, Math.min(targetScroll, getScrollRange())); + // Only apply the scroll if we're scrolling the view upwards, or the view is so + // far up that it is not visible anymore. + if (mOwnScrollY < targetScroll || outOfViewScroll < mOwnScrollY) { + setOwnScrollY(targetScroll); } } } @@ -1155,13 +1082,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable @ShadeViewRefactor(RefactorComponent.COORDINATOR) private void clampScrollPosition() { - if (ANCHOR_SCROLLING) { - // TODO - } else { - int scrollRange = getScrollRange(); - if (scrollRange < mOwnScrollY) { - setOwnScrollY(scrollRange); - } + int scrollRange = getScrollRange(); + if (scrollRange < mOwnScrollY) { + setOwnScrollY(scrollRange); } } @@ -1425,12 +1348,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } @ShadeViewRefactor(RefactorComponent.ADAPTER) - public int getFirstItemMinHeight() { - final ExpandableView firstChild = getFirstChildNotGone(); - return firstChild != null ? firstChild.getMinHeight() : mCollapsedSize; - } - - @ShadeViewRefactor(RefactorComponent.ADAPTER) public void setQsContainer(ViewGroup qsContainer) { mQsContainer = qsContainer; } @@ -1454,36 +1371,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } @ShadeViewRefactor(RefactorComponent.COORDINATOR) - public ExpandableView getClosestChildAtRawPosition(float touchX, float touchY) { - getLocationOnScreen(mTempInt2); - float localTouchY = touchY - mTempInt2[1]; - - ExpandableView closestChild = null; - float minDist = Float.MAX_VALUE; - - // find the view closest to the location, accounting for GONE views - final int count = getChildCount(); - for (int childIdx = 0; childIdx < count; childIdx++) { - ExpandableView slidingChild = (ExpandableView) getChildAt(childIdx); - if (slidingChild.getVisibility() == GONE - || slidingChild instanceof StackScrollerDecorView) { - continue; - } - float childTop = slidingChild.getTranslationY(); - float top = childTop + slidingChild.getClipTopAmount(); - float bottom = childTop + slidingChild.getActualHeight() - - slidingChild.getClipBottomAmount(); - - float dist = Math.min(Math.abs(top - localTouchY), Math.abs(bottom - localTouchY)); - if (dist < minDist) { - closestChild = slidingChild; - minDist = dist; - } - } - return closestChild; - } - - @ShadeViewRefactor(RefactorComponent.COORDINATOR) private ExpandableView getChildAtPosition(float touchX, float touchY) { return getChildAtPosition( touchX, touchY, true /* requireMinHeight */, true /* ignoreDecors */); @@ -1559,21 +1446,17 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) public boolean scrollTo(View v) { ExpandableView expandableView = (ExpandableView) v; - if (ANCHOR_SCROLLING) { - // TODO - } else { - int positionInLinearLayout = getPositionInLinearLayout(v); - int targetScroll = targetScrollForView(expandableView, positionInLinearLayout); - int outOfViewScroll = positionInLinearLayout + expandableView.getIntrinsicHeight(); - - // Only apply the scroll if we're scrolling the view upwards, or the view is so far up - // that it is not visible anymore. - if (mOwnScrollY < targetScroll || outOfViewScroll < mOwnScrollY) { - mScroller.startScroll(mScrollX, mOwnScrollY, 0, targetScroll - mOwnScrollY); - mDontReportNextOverScroll = true; - animateScroll(); - return true; - } + int positionInLinearLayout = getPositionInLinearLayout(v); + int targetScroll = targetScrollForView(expandableView, positionInLinearLayout); + int outOfViewScroll = positionInLinearLayout + expandableView.getIntrinsicHeight(); + + // Only apply the scroll if we're scrolling the view upwards, or the view is so far up + // that it is not visible anymore. + if (mOwnScrollY < targetScroll || outOfViewScroll < mOwnScrollY) { + mScroller.startScroll(mScrollX, mOwnScrollY, 0, targetScroll - mOwnScrollY); + mDontReportNextOverScroll = true; + animateScroll(); + return true; } return false; } @@ -1600,20 +1483,16 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable mWaterfallTopInset = cutout.getWaterfallInsets().top; } - if (ANCHOR_SCROLLING) { - // TODO - } else { - int range = getScrollRange(); - if (mOwnScrollY > range) { - // HACK: We're repeatedly getting staggered insets here while the IME is - // animating away. To work around that we'll wait until things have settled. - removeCallbacks(mReclamp); - postDelayed(mReclamp, 50); - } else if (mForcedScroll != null) { - // The scroll was requested before we got the actual inset - in case we need - // to scroll up some more do so now. - scrollTo(mForcedScroll); - } + int range = getScrollRange(); + if (mOwnScrollY > range) { + // HACK: We're repeatedly getting staggered insets here while the IME is + // animating away. To work around that we'll wait until things have settled. + removeCallbacks(mReclamp); + postDelayed(mReclamp, 50); + } else if (mForcedScroll != null) { + // The scroll was requested before we got the actual inset - in case we need + // to scroll up some more do so now. + scrollTo(mForcedScroll); } return insets; } @@ -1622,12 +1501,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable private Runnable mReclamp = new Runnable() { @Override public void run() { - if (ANCHOR_SCROLLING) { - // TODO - } else { - int range = getScrollRange(); - mScroller.startScroll(mScrollX, mOwnScrollY, 0, range - mOwnScrollY); - } + int range = getScrollRange(); + mScroller.startScroll(mScrollX, mOwnScrollY, 0, range - mOwnScrollY); mDontReportNextOverScroll = true; mDontClampNextScroll = true; animateScroll(); @@ -1701,39 +1576,20 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } // Top overScroll might not grab all scrolling motion, // we have to scroll as well. - if (ANCHOR_SCROLLING) { - float scrollAmount = newTopAmount < 0 ? -newTopAmount : 0.0f; - // TODO: once we're recycling this will need to check the adapter position of the child - ExpandableView lastRow = getLastRowNotGone(); - if (lastRow != null && !lastRow.isInShelf()) { - float distanceToMax = Math.max(0, getMaxPositiveScrollAmount()); - if (scrollAmount > distanceToMax) { - float currentBottomPixels = getCurrentOverScrolledPixels(false); - // We overScroll on the bottom - setOverScrolledPixels(currentBottomPixels + (scrollAmount - distanceToMax), - false /* onTop */, - false /* animate */); - mScrollAnchorViewY -= distanceToMax; - scrollAmount = 0f; - } - } - return scrollAmount; - } else { - float scrollAmount = newTopAmount < 0 ? -newTopAmount : 0.0f; - float newScrollY = mOwnScrollY + scrollAmount; - if (newScrollY > range) { - if (!mExpandedInThisMotion) { - float currentBottomPixels = getCurrentOverScrolledPixels(false); - // We overScroll on the bottom - setOverScrolledPixels(currentBottomPixels + newScrollY - range, - false /* onTop */, - false /* animate */); - } - setOwnScrollY(range); - scrollAmount = 0.0f; + float scrollAmount = newTopAmount < 0 ? -newTopAmount : 0.0f; + float newScrollY = mOwnScrollY + scrollAmount; + if (newScrollY > range) { + if (!mExpandedInThisMotion) { + float currentBottomPixels = getCurrentOverScrolledPixels(false); + // We overScroll on the bottom + setOverScrolledPixels(currentBottomPixels + newScrollY - range, + false /* onTop */, + false /* animate */); } - return scrollAmount; + setOwnScrollY(range); + scrollAmount = 0.0f; } + return scrollAmount; } /** @@ -1754,37 +1610,18 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } // Bottom overScroll might not grab all scrolling motion, // we have to scroll as well. - if (ANCHOR_SCROLLING) { - float scrollAmount = newBottomAmount < 0 ? newBottomAmount : 0.0f; - // TODO: once we're recycling this will need to check the adapter position of the child - ExpandableView firstChild = getFirstChildNotGone(); - float top = firstChild.getTranslationY(); - float distanceToTop = mScrollAnchorView.getTranslationY() - top - mScrollAnchorViewY; - if (distanceToTop < -scrollAmount) { - float currentTopPixels = getCurrentOverScrolledPixels(true); - // We overScroll on the top - setOverScrolledPixels(currentTopPixels + (-scrollAmount - distanceToTop), - true /* onTop */, - false /* animate */); - mScrollAnchorView = firstChild; - mScrollAnchorViewY = 0; - scrollAmount = 0f; - } - return scrollAmount; - } else { - float scrollAmount = newBottomAmount < 0 ? newBottomAmount : 0.0f; - float newScrollY = mOwnScrollY + scrollAmount; - if (newScrollY < 0) { - float currentTopPixels = getCurrentOverScrolledPixels(true); - // We overScroll on the top - setOverScrolledPixels(currentTopPixels - newScrollY, - true /* onTop */, - false /* animate */); - setOwnScrollY(0); - scrollAmount = 0.0f; - } - return scrollAmount; + float scrollAmount = newBottomAmount < 0 ? newBottomAmount : 0.0f; + float newScrollY = mOwnScrollY + scrollAmount; + if (newScrollY < 0) { + float currentTopPixels = getCurrentOverScrolledPixels(true); + // We overScroll on the top + setOverScrolledPixels(currentTopPixels - newScrollY, + true /* onTop */, + false /* animate */); + setOwnScrollY(0); + scrollAmount = 0.0f; } + return scrollAmount; } @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER) @@ -1819,42 +1656,23 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER) private void animateScroll() { if (mScroller.computeScrollOffset()) { - if (ANCHOR_SCROLLING) { - int oldY = mLastScrollerY; - int y = mScroller.getCurrY(); - int deltaY = y - oldY; - if (deltaY != 0) { - int maxNegativeScrollAmount = getMaxNegativeScrollAmount(); - int maxPositiveScrollAmount = getMaxPositiveScrollAmount(); - if ((maxNegativeScrollAmount < 0 && deltaY < maxNegativeScrollAmount) - || (maxPositiveScrollAmount > 0 && deltaY > maxPositiveScrollAmount)) { - // This frame takes us into overscroll, so set the max overscroll based on - // the current velocity - setMaxOverScrollFromCurrentVelocity(); - } - customOverScrollBy(deltaY, oldY, 0, (int) mMaxOverScroll); - mLastScrollerY = y; + int oldY = mOwnScrollY; + int y = mScroller.getCurrY(); + + if (oldY != y) { + int range = getScrollRange(); + if (y < 0 && oldY >= 0 || y > range && oldY <= range) { + // This frame takes us into overscroll, so set the max overscroll based on + // the current velocity + setMaxOverScrollFromCurrentVelocity(); } - } else { - int oldY = mOwnScrollY; - int y = mScroller.getCurrY(); - - if (oldY != y) { - int range = getScrollRange(); - if (y < 0 && oldY >= 0 || y > range && oldY <= range) { - // This frame takes us into overscroll, so set the max overscroll based on - // the current velocity - setMaxOverScrollFromCurrentVelocity(); - } - if (mDontClampNextScroll) { - range = Math.max(range, oldY); - } - customOverScrollBy(y - oldY, oldY, range, - (int) (mMaxOverScroll)); + if (mDontClampNextScroll) { + range = Math.max(range, oldY); } + customOverScrollBy(y - oldY, oldY, range, + (int) (mMaxOverScroll)); } - postOnAnimation(mReflingAndAnimateScroll); } else { mDontClampNextScroll = false; @@ -1877,9 +1695,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable * * This method performs the determination of whether we're exceeding the overscroll and clamps * the scroll amount if so. The actual scrolling/overscrolling happens in - * {@link #onCustomOverScrolled(int, boolean)} (absolute scrolling) or - * {@link #onCustomOverScrolledBy(int, boolean)} (anchor scrolling). - * + * {@link #onCustomOverScrolled(int, boolean)} * @param deltaY The (signed) number of pixels to scroll. * @param scrollY The current scroll position (absolute scrolling only). * @param scrollRangeY The maximum allowable scroll position (absolute scrolling only). @@ -1887,44 +1703,20 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable */ @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER) private void customOverScrollBy(int deltaY, int scrollY, int scrollRangeY, int maxOverScrollY) { - if (ANCHOR_SCROLLING) { - boolean clampedY = false; - if (deltaY < 0) { - int maxScrollAmount = getMaxNegativeScrollAmount(); - if (maxScrollAmount > Integer.MIN_VALUE) { - maxScrollAmount -= maxOverScrollY; - if (deltaY < maxScrollAmount) { - deltaY = maxScrollAmount; - clampedY = true; - } - } - } else { - int maxScrollAmount = getMaxPositiveScrollAmount(); - if (maxScrollAmount < Integer.MAX_VALUE) { - maxScrollAmount += maxOverScrollY; - if (deltaY > maxScrollAmount) { - deltaY = maxScrollAmount; - clampedY = true; - } - } - } - onCustomOverScrolledBy(deltaY, clampedY); - } else { - int newScrollY = scrollY + deltaY; - final int top = -maxOverScrollY; - final int bottom = maxOverScrollY + scrollRangeY; - - boolean clampedY = false; - if (newScrollY > bottom) { - newScrollY = bottom; - clampedY = true; - } else if (newScrollY < top) { - newScrollY = top; - clampedY = true; - } + int newScrollY = scrollY + deltaY; + final int top = -maxOverScrollY; + final int bottom = maxOverScrollY + scrollRangeY; - onCustomOverScrolled(newScrollY, clampedY); + boolean clampedY = false; + if (newScrollY > bottom) { + newScrollY = bottom; + clampedY = true; + } else if (newScrollY < top) { + newScrollY = top; + clampedY = true; } + + onCustomOverScrolled(newScrollY, clampedY); } /** @@ -2043,35 +1835,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } /** - * Scrolls by the given delta, overscrolling if needed. If called during a fling and the delta - * would cause us to exceed the provided maximum overscroll, springs back instead. - * - * @param deltaY The (signed) number of pixels to scroll. - * @param clampedY Whether this value was clamped by the calling method, meaning we've reached - * the overscroll limit. - */ - private void onCustomOverScrolledBy(int deltaY, boolean clampedY) { - assert ANCHOR_SCROLLING; - mScrollAnchorViewY -= deltaY; - // Treat animating scrolls differently; see #computeScroll() for why. - if (!mScroller.isFinished()) { - if (clampedY) { - springBack(); - } else { - float overScrollTop = getCurrentOverScrollAmount(true /* top */); - if (mScrollAdapter.isScrolledToTop() && mScrollAnchorViewY > 0) { - notifyOverscrollTopListener(mScrollAnchorViewY, - isRubberbanded(true /* onTop */)); - } else { - notifyOverscrollTopListener(overScrollTop, isRubberbanded(true /* onTop */)); - } - } - } - updateScrollAnchor(); - updateOnScrollChange(); - } - - /** * Scrolls to the given position, overscrolling if needed. If called during a fling and the * position exceeds the provided maximum overscroll, springs back instead. * @@ -2081,7 +1844,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable */ @ShadeViewRefactor(RefactorComponent.COORDINATOR) private void onCustomOverScrolled(int scrollY, boolean clampedY) { - assert !ANCHOR_SCROLLING; // Treat animating scrolls differently; see #computeScroll() for why. if (!mScroller.isFinished()) { setOwnScrollY(scrollY); @@ -2106,45 +1868,25 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable */ @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER) private void springBack() { - if (ANCHOR_SCROLLING) { - boolean overScrolledTop = mScrollAdapter.isScrolledToTop() && mScrollAnchorViewY > 0; - int maxPositiveScrollAmount = getMaxPositiveScrollAmount(); - boolean overscrolledBottom = maxPositiveScrollAmount < 0; - if (overScrolledTop || overscrolledBottom) { - float newAmount; - if (overScrolledTop) { - newAmount = mScrollAnchorViewY; - mScrollAnchorViewY = 0; - mDontReportNextOverScroll = true; - } else { - newAmount = -maxPositiveScrollAmount; - mScrollAnchorViewY -= maxPositiveScrollAmount; - } - setOverScrollAmount(newAmount, overScrolledTop, false); - setOverScrollAmount(0.0f, overScrolledTop, true); - mScroller.forceFinished(true); - } - } else { - int scrollRange = getScrollRange(); - boolean overScrolledTop = mOwnScrollY <= 0; - boolean overScrolledBottom = mOwnScrollY >= scrollRange; - if (overScrolledTop || overScrolledBottom) { - boolean onTop; - float newAmount; - if (overScrolledTop) { - onTop = true; - newAmount = -mOwnScrollY; - setOwnScrollY(0); - mDontReportNextOverScroll = true; - } else { - onTop = false; - newAmount = mOwnScrollY - scrollRange; - setOwnScrollY(scrollRange); - } - setOverScrollAmount(newAmount, onTop, false); - setOverScrollAmount(0.0f, onTop, true); - mScroller.forceFinished(true); + int scrollRange = getScrollRange(); + boolean overScrolledTop = mOwnScrollY <= 0; + boolean overScrolledBottom = mOwnScrollY >= scrollRange; + if (overScrolledTop || overScrolledBottom) { + boolean onTop; + float newAmount; + if (overScrolledTop) { + onTop = true; + newAmount = -mOwnScrollY; + setOwnScrollY(0); + mDontReportNextOverScroll = true; + } else { + onTop = false; + newAmount = mOwnScrollY - scrollRange; + setOwnScrollY(scrollRange); } + setOverScrollAmount(newAmount, onTop, false); + setOverScrollAmount(0.0f, onTop, true); + mScroller.forceFinished(true); } } @@ -2183,25 +1925,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } /** - * @return the child before the given view which has visibility unequal to GONE - */ - @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) - public ExpandableView getViewBeforeView(ExpandableView view) { - ExpandableView previousView = null; - int childCount = getChildCount(); - for (int i = 0; i < childCount; i++) { - View child = getChildAt(i); - if (child == view) { - return previousView; - } - if (child.getVisibility() != View.GONE) { - previousView = (ExpandableView) child; - } - } - return null; - } - - /** * @return The first child which has visibility unequal to GONE which is currently below the * given translationY or equal to it. */ @@ -2334,8 +2057,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable ExpandableView current, int visibleIndex ) { - return mStackScrollAlgorithm.getGapHeightForChild(mSectionsManager, - mAmbientState.getAnchorViewIndex(), visibleIndex, current, + return mStackScrollAlgorithm.getGapHeightForChild(mSectionsManager, visibleIndex, current, previous); } @@ -2566,21 +2288,13 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable float topAmount = getCurrentOverScrollAmount(true); float bottomAmount = getCurrentOverScrollAmount(false); if (velocityY < 0 && topAmount > 0) { - if (ANCHOR_SCROLLING) { - mScrollAnchorViewY += topAmount; - } else { - setOwnScrollY(mOwnScrollY - (int) topAmount); - } + setOwnScrollY(mOwnScrollY - (int) topAmount); mDontReportNextOverScroll = true; setOverScrollAmount(0, true, false); mMaxOverScroll = Math.abs(velocityY) / 1000f * getRubberBandFactor(true /* onTop */) * mOverflingDistance + topAmount; } else if (velocityY > 0 && bottomAmount > 0) { - if (ANCHOR_SCROLLING) { - mScrollAnchorViewY -= bottomAmount; - } else { - setOwnScrollY((int) (mOwnScrollY + bottomAmount)); - } + setOwnScrollY((int) (mOwnScrollY + bottomAmount)); setOverScrollAmount(0, false, false); mMaxOverScroll = Math.abs(velocityY) / 1000f * getRubberBandFactor(false /* onTop */) * mOverflingDistance @@ -2589,139 +2303,19 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable // it will be set once we reach the boundary mMaxOverScroll = 0.0f; } - if (ANCHOR_SCROLLING) { - flingScroller(velocityY); - } else { - int scrollRange = getScrollRange(); - int minScrollY = Math.max(0, scrollRange); - if (mExpandedInThisMotion) { - minScrollY = Math.min(minScrollY, mMaxScrollAfterExpand); - } - mScroller.fling(mScrollX, mOwnScrollY, 1, velocityY, 0, 0, 0, minScrollY, 0, - mExpandedInThisMotion && mOwnScrollY >= 0 ? 0 : Integer.MAX_VALUE / 2); + int scrollRange = getScrollRange(); + int minScrollY = Math.max(0, scrollRange); + if (mExpandedInThisMotion) { + minScrollY = Math.min(minScrollY, mMaxScrollAfterExpand); } + mScroller.fling(mScrollX, mOwnScrollY, 1, velocityY, 0, 0, 0, minScrollY, 0, + mExpandedInThisMotion && mOwnScrollY >= 0 ? 0 : Integer.MAX_VALUE / 2); animateScroll(); } } /** - * Flings the overscroller with the given velocity (anchor-based scrolling). - * - * Because anchor-based scrolling can't track the current scroll position, the overscroller is - * always started at startY = 0, and we interpret the positions it computes as relative to the - * start of the scroll. - */ - private void flingScroller(int velocityY) { - assert ANCHOR_SCROLLING; - mIsScrollerBoundSet = false; - maybeFlingScroller(velocityY, true /* always fling */); - } - - private void maybeFlingScroller(int velocityY, boolean alwaysFling) { - assert ANCHOR_SCROLLING; - // Attempt to determine the maximum amount to scroll before we reach the end. - // If the first view is not materialized (for an upwards scroll) or the last view is either - // not materialized or is pinned to the shade (for a downwards scroll), we don't know this - // amount, so we do an unbounded fling and rely on {@link #maybeReflingScroller()} to update - // the scroller once we approach the start/end of the list. - int minY = Integer.MIN_VALUE; - int maxY = Integer.MAX_VALUE; - if (velocityY < 0) { - minY = getMaxNegativeScrollAmount(); - if (minY > Integer.MIN_VALUE) { - mIsScrollerBoundSet = true; - } - } else { - maxY = getMaxPositiveScrollAmount(); - if (maxY < Integer.MAX_VALUE) { - mIsScrollerBoundSet = true; - } - } - if (mIsScrollerBoundSet || alwaysFling) { - mLastScrollerY = 0; - // x velocity is set to 1 to avoid overscroller bug - mScroller.fling(0, 0, 1, velocityY, 0, 0, minY, maxY, 0, - mExpandedInThisMotion - && !mScrollAdapter.isScrolledToTop() ? 0 : Integer.MAX_VALUE / 2); - } - } - - /** - * Returns the maximum number of pixels we can scroll in the positive direction (downwards) - * before reaching the bottom of the list (discounting overscroll). - * - * If the return value is negative then we have overscrolled; this is a transient state which - * should immediately be handled by adjusting the anchor position and adding the extra space to - * the bottom overscroll amount. - * - * If we don't know how many pixels we have left to scroll (because the last row has not been - * materialized, or it's in the shelf so it doesn't have its "natural" position), we return - * {@link Integer#MAX_VALUE}. - */ - private int getMaxPositiveScrollAmount() { - assert ANCHOR_SCROLLING; - // TODO: once we're recycling we need to check the adapter position of the last child. - ExpandableNotificationRow lastRow = getLastRowNotGone(); - if (mScrollAnchorView != null && lastRow != null && !lastRow.isInShelf()) { - // distance from bottom of last child to bottom of notifications area is: - // distance from bottom of last child - return (int) (lastRow.getTranslationY() + lastRow.getActualHeight() - // to top of anchor view - - mScrollAnchorView.getTranslationY() - // plus distance from anchor view to top of notifications area - + mScrollAnchorViewY - // minus height of notifications area. - - (mMaxLayoutHeight - getIntrinsicPadding() - mFooterView.getActualHeight())); - } else { - return Integer.MAX_VALUE; - } - } - - /** - * Returns the maximum number of pixels (as a negative number) we can scroll in the negative - * direction (upwards) before reaching the top of the list (discounting overscroll). - * - * If the return value is positive then we have overscrolled; this is a transient state which - * should immediately be handled by adjusting the anchor position and adding the extra space to - * the top overscroll amount. - * - * If we don't know how many pixels we have left to scroll (because the first row has not been - * materialized), we return {@link Integer#MIN_VALUE}. - */ - private int getMaxNegativeScrollAmount() { - assert ANCHOR_SCROLLING; - // TODO: once we're recycling we need to check the adapter position of the first child. - ExpandableView firstChild = getFirstChildNotGone(); - if (mScrollAnchorView != null && firstChild != null) { - // distance from top of first child to top of notifications area is: - // distance from top of anchor view - return (int) -(mScrollAnchorView.getTranslationY() - // to top of first child - - firstChild.getTranslationY() - // minus distance from top of anchor view to top of notifications area. - - mScrollAnchorViewY); - } else { - return Integer.MIN_VALUE; - } - } - - /** - * During a fling, if we were unable to set the bounds of the fling due to the top/bottom view - * not being materialized or being pinned to the shelf, we need to check on every frame if we're - * able to set the bounds. If we are, we fling the scroller again with the newly computed - * bounds. - */ - private void maybeReflingScroller() { - if (!mIsScrollerBoundSet) { - // Because mScroller is a flywheel scroller, we fling with the minimum possible - // velocity to establish direction, so as not to perceptibly affect the velocity. - maybeFlingScroller((int) Math.signum(mScroller.getCurrVelocity()), - false /* alwaysFling */); - } - } - - /** * @return Whether a fling performed on the top overscroll edge lead to the expanded * overScroll view (i.e QS). */ @@ -2990,38 +2584,17 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable */ @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER) private void updateScrollStateForRemovedChild(ExpandableView removedChild) { - if (ANCHOR_SCROLLING) { - if (removedChild == mScrollAnchorView) { - ExpandableView firstChild = getFirstChildNotGone(); - if (firstChild != null) { - mScrollAnchorView = firstChild; - } else { - mScrollAnchorView = mShelf; - } - // Adjust anchor view Y by the distance between the old and new anchors - // so that there's no visible change. - mScrollAnchorViewY += - mScrollAnchorView.getTranslationY() - removedChild.getTranslationY(); - } - updateScrollAnchor(); - // TODO: once we're recycling this will need to check the adapter position of the child - if (mScrollAnchorView == getFirstChildNotGone() && mScrollAnchorViewY > 0) { - mScrollAnchorViewY = 0; - } - updateOnScrollChange(); - } else { - final int startingPosition = getPositionInLinearLayout(removedChild); - final int childHeight = getIntrinsicHeight(removedChild) + mPaddingBetweenElements; - final int endPosition = startingPosition + childHeight; - if (endPosition <= mOwnScrollY) { - // This child is fully scrolled of the top, so we have to deduct its height from the - // scrollPosition - setOwnScrollY(mOwnScrollY - childHeight); - } else if (startingPosition < mOwnScrollY) { - // This child is currently being scrolled into, set the scroll position to the - // start of this child - setOwnScrollY(startingPosition); - } + final int startingPosition = getPositionInLinearLayout(removedChild); + final int childHeight = getIntrinsicHeight(removedChild) + mPaddingBetweenElements; + final int endPosition = startingPosition + childHeight; + if (endPosition <= mOwnScrollY) { + // This child is fully scrolled of the top, so we have to deduct its height from the + // scrollPosition + setOwnScrollY(mOwnScrollY - childHeight); + } else if (startingPosition < mOwnScrollY) { + // This child is currently being scrolled into, set the scroll position to the + // start of this child + setOwnScrollY(startingPosition); } } @@ -3115,15 +2688,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable if (child instanceof ExpandableNotificationRow) { ((ExpandableNotificationRow) child).setDismissRtl(mDismissRtl); } - if (ANCHOR_SCROLLING) { - // TODO: once we're recycling this will need to check the adapter position of the child - if (child == getFirstChildNotGone() - && (mScrollAdapter.isScrolledToTop() || !mIsExpanded)) { - // New child was added at the top while we're scrolled to the top; - // make it the new anchor view so that we stay at the top. - mScrollAnchorView = child; - } - } } @ShadeViewRefactor(RefactorComponent.COORDINATOR) @@ -3581,24 +3145,17 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable final float vscroll = event.getAxisValue(MotionEvent.AXIS_VSCROLL); if (vscroll != 0) { final int delta = (int) (vscroll * getVerticalScrollFactor()); - if (ANCHOR_SCROLLING) { - mScrollAnchorViewY -= delta; - updateScrollAnchor(); - clampScrollPosition(); - updateOnScrollChange(); - } else { - final int range = getScrollRange(); - int oldScrollY = mOwnScrollY; - int newScrollY = oldScrollY - delta; - if (newScrollY < 0) { - newScrollY = 0; - } else if (newScrollY > range) { - newScrollY = range; - } - if (newScrollY != oldScrollY) { - setOwnScrollY(newScrollY); - return true; - } + final int range = getScrollRange(); + int oldScrollY = mOwnScrollY; + int newScrollY = oldScrollY - delta; + if (newScrollY < 0) { + newScrollY = 0; + } else if (newScrollY > range) { + newScrollY = range; + } + if (newScrollY != oldScrollY) { + setOwnScrollY(newScrollY); + return true; } } } @@ -3676,13 +3233,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable mLastMotionY = y; float scrollAmount; int range; - if (ANCHOR_SCROLLING) { - range = 0; // unused in the methods it's being passed to - } else { - range = getScrollRange(); - if (mExpandedInThisMotion) { - range = Math.min(range, mMaxScrollAfterExpand); - } + range = getScrollRange(); + if (mExpandedInThisMotion) { + range = Math.min(range, mMaxScrollAfterExpand); } if (deltaY < 0) { scrollAmount = overScrollDown(deltaY); @@ -3727,13 +3280,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable onOverScrollFling(false, initialVelocity); } } else { - if (ANCHOR_SCROLLING) { - // TODO - } else { - if (mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0, - getScrollRange())) { - animateScroll(); - } + if (mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0, + getScrollRange())) { + animateScroll(); } } } @@ -3745,13 +3294,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable break; case MotionEvent.ACTION_CANCEL: if (mIsBeingDragged && getChildCount() > 0) { - if (ANCHOR_SCROLLING) { - // TODO - } else { - if (mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0, - getScrollRange())) { - animateScroll(); - } + if (mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0, + getScrollRange())) { + animateScroll(); } mActivePointerId = INVALID_POINTER; endDrag(); @@ -3970,12 +3515,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable setIsBeingDragged(false); mActivePointerId = INVALID_POINTER; recycleVelocityTracker(); - if (ANCHOR_SCROLLING) { - // TODO - } else { - if (mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0, getScrollRange())) { - animateScroll(); - } + if (mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0, getScrollRange())) { + animateScroll(); } break; case MotionEvent.ACTION_POINTER_UP: @@ -4050,20 +3591,16 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: // fall through case android.R.id.accessibilityActionScrollUp: - if (ANCHOR_SCROLLING) { - // TODO - } else { - final int viewportHeight = - getHeight() - mPaddingBottom - mTopPadding - mPaddingTop - - mShelf.getIntrinsicHeight(); - final int targetScrollY = Math.max(0, - Math.min(mOwnScrollY + direction * viewportHeight, getScrollRange())); - if (targetScrollY != mOwnScrollY) { - mScroller.startScroll(mScrollX, mOwnScrollY, 0, - targetScrollY - mOwnScrollY); - animateScroll(); - return true; - } + final int viewportHeight = + getHeight() - mPaddingBottom - mTopPadding - mPaddingTop + - mShelf.getIntrinsicHeight(); + final int targetScrollY = Math.max(0, + Math.min(mOwnScrollY + direction * viewportHeight, getScrollRange())); + if (targetScrollY != mOwnScrollY) { + mScroller.startScroll(mScrollX, mOwnScrollY, 0, + targetScrollY - mOwnScrollY); + animateScroll(); + return true; } break; } @@ -4166,14 +3703,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER) void resetScrollPosition() { mScroller.abortAnimation(); - if (ANCHOR_SCROLLING) { - // TODO: once we're recycling this will need to modify the adapter position instead - mScrollAnchorView = getFirstChildNotGone(); - mScrollAnchorViewY = 0; - updateOnScrollChange(); - } else { - setOwnScrollY(0); - } + setOwnScrollY(0); } @ShadeViewRefactor(RefactorComponent.COORDINATOR) @@ -4262,13 +3792,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable layoutEnd -= mShelf.getIntrinsicHeight() + mPaddingBetweenElements; } if (endPosition > layoutEnd) { - if (ANCHOR_SCROLLING) { - mScrollAnchorViewY -= (endPosition - layoutEnd); - updateScrollAnchor(); - updateOnScrollChange(); - } else { - setOwnScrollY((int) (mOwnScrollY + endPosition - layoutEnd)); - } + setOwnScrollY((int) (mOwnScrollY + endPosition - layoutEnd)); mDisallowScrollingInThisMotion = true; } } @@ -4765,12 +4289,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable super.onInitializeAccessibilityEventInternal(event); event.setScrollable(mScrollable); event.setMaxScrollX(mScrollX); - if (ANCHOR_SCROLLING) { - // TODO - } else { - event.setScrollY(mOwnScrollY); - event.setMaxScrollY(getScrollRange()); - } + event.setScrollY(mOwnScrollY); + event.setMaxScrollY(getScrollRange()); } @Override @@ -4955,7 +4475,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable @ShadeViewRefactor(RefactorComponent.COORDINATOR) private void setOwnScrollY(int ownScrollY) { - assert !ANCHOR_SCROLLING; if (ownScrollY != mOwnScrollY) { // We still want to call the normal scrolled changed for accessibility reasons onScrollChanged(mScrollX, ownScrollY, mScrollX, mOwnScrollY); @@ -4969,51 +4488,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable requestChildrenUpdate(); } - private void updateScrollAnchor() { - int anchorIndex = indexOfChild(mScrollAnchorView); - // If the anchor view has been scrolled off the top, move to the next view. - while (mScrollAnchorViewY < 0) { - View nextAnchor = null; - for (int i = anchorIndex + 1; i < getChildCount(); i++) { - View child = getChildAt(i); - if (child.getVisibility() != View.GONE - && child instanceof ExpandableNotificationRow) { - anchorIndex = i; - nextAnchor = child; - break; - } - } - if (nextAnchor == null) { - break; - } - mScrollAnchorViewY += - (int) (nextAnchor.getTranslationY() - mScrollAnchorView.getTranslationY()); - mScrollAnchorView = nextAnchor; - } - // If the view above the anchor view is fully visible, make it the anchor view. - while (anchorIndex > 0 && mScrollAnchorViewY > 0) { - View prevAnchor = null; - for (int i = anchorIndex - 1; i >= 0; i--) { - View child = getChildAt(i); - if (child.getVisibility() != View.GONE - && child instanceof ExpandableNotificationRow) { - anchorIndex = i; - prevAnchor = child; - break; - } - } - if (prevAnchor == null) { - break; - } - float distanceToPreviousAnchor = - mScrollAnchorView.getTranslationY() - prevAnchor.getTranslationY(); - if (distanceToPreviousAnchor < mScrollAnchorViewY) { - mScrollAnchorViewY -= (int) distanceToPreviousAnchor; - mScrollAnchorView = prevAnchor; - } - } - } - @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) public void setShelfController(NotificationShelfController notificationShelfController) { int index = -1; @@ -5026,9 +4500,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable mAmbientState.setShelf(mShelf); mStateAnimator.setShelf(mShelf); notificationShelfController.bind(mAmbientState, mController); - if (ANCHOR_SCROLLING) { - mScrollAnchorView = mShelf; - } } @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) @@ -5496,7 +4967,13 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable mSwipedOutViews.add(v); } - void onSwipeBegin() { + void onSwipeBegin(View v) { + if (v instanceof ExpandableView) { + ExpandableView ev = (ExpandableView) v; + ev.setIsBeingSwiped(true); + mController.getNoticationRoundessManager() + .updateViewWithoutCallback(ev, true /* animate */); + } requestDisallowInterceptTouchEvent(true); updateFirstAndLastBackgroundViews(); updateContinuousShadowDrawing(); @@ -5504,7 +4981,13 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable requestChildrenUpdate(); } - void onSwipeEnd() { + void onSwipeEnd(View v) { + if (v instanceof ExpandableView) { + ExpandableView ev = (ExpandableView) v; + ev.setIsBeingSwiped(false); + mController.getNoticationRoundessManager() + .updateViewWithoutCallback(ev, true /* animate */); + } updateFirstAndLastBackgroundViews(); } @@ -5631,15 +5114,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable mSectionsManager.updateSectionBoundaries(reason); } - boolean isSilkDismissEnabled() { - return Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.SHOW_NEW_NOTIF_DISMISS, 1 /* enabled by default */) == 1; - } - void updateContinuousBackgroundDrawing() { - if (isSilkDismissEnabled()) { - return; - } boolean continuousBackground = !mAmbientState.isFullyAwake() && mSwipeHelper.isSwiping(); if (continuousBackground != mContinuousBackgroundUpdate) { @@ -6166,11 +5641,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable public void expansionStateChanged(boolean isExpanding) { mExpandingNotification = isExpanding; if (!mExpandedInThisMotion) { - if (ANCHOR_SCROLLING) { - // TODO - } else { - mMaxScrollAfterExpand = mOwnScrollY; - } + mMaxScrollAfterExpand = mOwnScrollY; mExpandedInThisMotion = true; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java index c2d030b132db..e332f18ce183 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java @@ -395,7 +395,7 @@ public class NotificationStackScrollLayoutController { if (mView.getDismissAllInProgress()) { return; } - mView.onSwipeEnd(); + mView.onSwipeEnd(view); if (view instanceof ExpandableNotificationRow) { ExpandableNotificationRow row = (ExpandableNotificationRow) view; if (row.isHeadsUp()) { @@ -450,12 +450,12 @@ public class NotificationStackScrollLayoutController { @Override public void onBeginDrag(View v) { mFalsingCollector.onNotificationStartDismissing(); - mView.onSwipeBegin(); + mView.onSwipeBegin(v); } @Override public void onChildSnappedBack(View animView, float targetLeft) { - mView.onSwipeEnd(); + mView.onSwipeEnd(animView); if (animView instanceof ExpandableNotificationRow) { ExpandableNotificationRow row = (ExpandableNotificationRow) animView; if (row.isPinned() && !canChildBeDismissed(row) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java index d85baa9f1b93..2c206b1c3f45 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java @@ -45,8 +45,6 @@ import java.util.List; */ public class StackScrollAlgorithm { - static final boolean ANCHOR_SCROLLING = false; - private static final String LOG_TAG = "StackScrollAlgorithm"; private final ViewGroup mHostView; @@ -229,10 +227,6 @@ public class StackScrollAlgorithm { scrollY = Math.max(0, scrollY); state.scrollY = (int) (scrollY + bottomOverScroll); - if (ANCHOR_SCROLLING) { - state.anchorViewY = (int) (ambientState.getAnchorViewY() - bottomOverScroll); - } - //now init the visible children and update paddings int childCount = hostView.getChildCount(); state.visibleChildren.clear(); @@ -240,11 +234,6 @@ public class StackScrollAlgorithm { int notGoneIndex = 0; ExpandableView lastView = null; for (int i = 0; i < childCount; i++) { - if (ANCHOR_SCROLLING) { - if (i == ambientState.getAnchorViewIndex()) { - state.anchorViewIndex = state.visibleChildren.size(); - } - } ExpandableView v = (ExpandableView) hostView.getChildAt(i); if (v.getVisibility() != View.GONE) { if (v == ambientState.getShelf()) { @@ -293,26 +282,12 @@ public class StackScrollAlgorithm { */ private void updatePositionsForState(StackScrollAlgorithmState algorithmState, AmbientState ambientState) { - if (ANCHOR_SCROLLING) { - float currentYPosition = algorithmState.anchorViewY; - int childCount = algorithmState.visibleChildren.size(); - for (int i = algorithmState.anchorViewIndex; i < childCount; i++) { - currentYPosition = updateChild(i, algorithmState, ambientState, currentYPosition, - false /* reverse */); - } - currentYPosition = algorithmState.anchorViewY; - for (int i = algorithmState.anchorViewIndex - 1; i >= 0; i--) { - currentYPosition = updateChild(i, algorithmState, ambientState, currentYPosition, - true /* reverse */); - } - } else { - // The y coordinate of the current child. - float currentYPosition = -algorithmState.scrollY; - int childCount = algorithmState.visibleChildren.size(); - for (int i = 0; i < childCount; i++) { - currentYPosition = updateChild(i, algorithmState, ambientState, currentYPosition, - false /* reverse */); - } + // The y coordinate of the current child. + float currentYPosition = -algorithmState.scrollY; + int childCount = algorithmState.visibleChildren.size(); + for (int i = 0; i < childCount; i++) { + currentYPosition = updateChild(i, algorithmState, ambientState, currentYPosition, + false /* reverse */); } } @@ -343,7 +318,7 @@ public class StackScrollAlgorithm { ExpandableView previousChild = i > 0 ? algorithmState.visibleChildren.get(i - 1) : null; final boolean applyGapHeight = childNeedsGapHeight( - ambientState.getSectionProvider(), algorithmState.anchorViewIndex, i, + ambientState.getSectionProvider(), i, child, previousChild); ExpandableViewState childViewState = child.getViewState(); childViewState.location = ExpandableViewState.LOCATION_UNKNOWN; @@ -409,7 +384,6 @@ public class StackScrollAlgorithm { * Get the gap height needed for before a view * * @param sectionProvider the sectionProvider used to understand the sections - * @param anchorViewIndex the anchorView index when anchor scrolling, can be 0 if not * @param visibleIndex the visible index of this view in the list * @param child the child asked about * @param previousChild the child right before it or null if none @@ -417,12 +391,11 @@ public class StackScrollAlgorithm { */ public float getGapHeightForChild( SectionProvider sectionProvider, - int anchorViewIndex, int visibleIndex, View child, View previousChild) { - if (childNeedsGapHeight(sectionProvider, anchorViewIndex, visibleIndex, child, + if (childNeedsGapHeight(sectionProvider, visibleIndex, child, previousChild)) { return mGapHeight; } else { @@ -434,7 +407,6 @@ public class StackScrollAlgorithm { * Does a given child need a gap, i.e spacing before a view? * * @param sectionProvider the sectionProvider used to understand the sections - * @param anchorViewIndex the anchorView index when anchor scrolling, can be 0 if not * @param visibleIndex the visible index of this view in the list * @param child the child asked about * @param previousChild the child right before it or null if none @@ -442,16 +414,12 @@ public class StackScrollAlgorithm { */ private boolean childNeedsGapHeight( SectionProvider sectionProvider, - int anchorViewIndex, int visibleIndex, View child, View previousChild) { boolean needsGapHeight = sectionProvider.beginsSection(child, previousChild) && visibleIndex > 0; - if (ANCHOR_SCROLLING) { - needsGapHeight &= visibleIndex != anchorViewIndex; - } return needsGapHeight; } @@ -537,7 +505,6 @@ public class StackScrollAlgorithm { // To check if the row need to do translation according to scroll Y // heads up show full of row's content and any scroll y indicate that the // translationY need to move up the HUN. - // TODO: fix this check for anchor scrolling. if (!mIsExpanded && isTopEntry && ambientState.getScrollY() > 0) { childState.yTranslation -= ambientState.getScrollY(); } @@ -701,14 +668,6 @@ public class StackScrollAlgorithm { */ public int scrollY; - /** The index of the anchor view (anchor scrolling). */ - public int anchorViewIndex; - - /** - * The Y position, relative to the top of the screen, of the anchor view (anchor scrolling). - */ - public int anchorViewY; - /** * The children from the host view which are not gone. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java index d4add958ad1f..66a48f16b624 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java @@ -42,6 +42,7 @@ import java.util.Stack; public class StackStateAnimator { public static final int ANIMATION_DURATION_STANDARD = 360; + public static final int ANIMATION_DURATION_CORNER_RADIUS = 200; public static final int ANIMATION_DURATION_WAKEUP = 500; public static final int ANIMATION_DURATION_GO_TO_FULL_SHADE = 448; public static final int ANIMATION_DURATION_APPEAR_DISAPPEAR = 464; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java index a5667bb513e0..e1eaf3c17357 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java @@ -390,17 +390,17 @@ public final class DozeServiceHost implements DozeHost { } @Override - public void setDozeScreenBrightness(int value) { - mNotificationShadeWindowController.setDozeScreenBrightness(value); + public void setDozeScreenBrightness(int brightness) { + mDozeLog.traceDozeScreenBrightness(brightness); + mNotificationShadeWindowController.setDozeScreenBrightness(brightness); } @Override public void setAodDimmingScrim(float scrimOpacity) { + mDozeLog.traceSetAodDimmingScrim(scrimOpacity); mScrimController.setAodFrontScrimAlpha(scrimOpacity); } - - @Override public void prepareForGentleSleep(Runnable onDisplayOffCallback) { if (mPendingScreenOffCallback != null) { 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 547a3705266a..6bdc303b4786 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java @@ -37,6 +37,7 @@ import androidx.annotation.Nullable; import com.android.internal.logging.nano.MetricsProto; import com.android.internal.widget.LockPatternUtils; +import com.android.keyguard.KeyguardSecurityModel; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.settingslib.Utils; @@ -78,6 +79,7 @@ public class LockscreenLockIconController { private final KeyguardStateController mKeyguardStateController; private final Resources mResources; private final HeadsUpManagerPhone mHeadsUpManagerPhone; + private final KeyguardSecurityModel mKeyguardSecurityModel; private boolean mKeyguardShowing; private boolean mKeyguardJustShown; private boolean mBlockUpdates; @@ -326,7 +328,8 @@ public class LockscreenLockIconController { @Nullable DockManager dockManager, KeyguardStateController keyguardStateController, @Main Resources resources, - HeadsUpManagerPhone headsUpManagerPhone) { + HeadsUpManagerPhone headsUpManagerPhone, + KeyguardSecurityModel keyguardSecurityModel) { mLockscreenGestureLogger = lockscreenGestureLogger; mKeyguardUpdateMonitor = keyguardUpdateMonitor; mLockPatternUtils = lockPatternUtils; @@ -341,6 +344,7 @@ public class LockscreenLockIconController { mKeyguardStateController = keyguardStateController; mResources = resources; mHeadsUpManagerPhone = headsUpManagerPhone; + mKeyguardSecurityModel = keyguardSecurityModel; mKeyguardIndicationController.setLockIconController(this); } @@ -541,13 +545,20 @@ public class LockscreenLockIconController { * @return true if the visibility changed */ private boolean updateIconVisibility() { + if (mLockIcon == null) { + return false; + } + if (mKeyguardUpdateMonitor.isUdfpsEnrolled()) { boolean changed = mLockIcon.getVisibility() == GONE; mLockIcon.setVisibility(GONE); return changed; } + boolean onAodOrDocked = mStatusBarStateController.isDozing() || mDocked; - boolean invisible = onAodOrDocked || mWakeAndUnlockRunning || mShowingLaunchAffordance; + boolean invisible = onAodOrDocked || mWakeAndUnlockRunning || mShowingLaunchAffordance + || (mKeyguardSecurityModel.getSecurityMode(KeyguardUpdateMonitor.getCurrentUser()) + == KeyguardSecurityModel.SecurityMode.None); boolean fingerprintOrBypass = mFingerprintUnlock || mKeyguardBypassController.getBypassEnabled(); if (fingerprintOrBypass && !mBouncerShowingScrimmed) { @@ -559,11 +570,6 @@ public class LockscreenLockIconController { invisible = true; } } - - if (mLockIcon == null) { - return false; - } - return mLockIcon.updateIconVisibility(!invisible); } 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 01a729235eda..8d3b12868dd7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -1140,6 +1140,7 @@ public class NotificationPanelViewController extends PanelViewController { if (isFullyCollapsed()) { expand(true /* animate */); } else { + traceQsJank(true /* startTracing */, false /* wasCancelled */); flingSettings(0 /* velocity */, FLING_EXPAND); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java index 9ea402d4e6df..d074e64d337e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java @@ -652,7 +652,7 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW pw.println(TAG + ":"); pw.println(" mKeyguardDisplayMode=" + mKeyguardDisplayMode); pw.println(mCurrentState); - mNotificationShadeView.getViewRootImpl().dump(" ", fd, pw, args); + mNotificationShadeView.getViewRootImpl().dump(" ", pw); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java index ba4fbb871b97..2ac9f301a89a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java @@ -238,7 +238,7 @@ public class NotificationShadeWindowViewController { if (mTouchCancelled || mExpandAnimationRunning || mExpandAnimationPending) { return false; } - mFalsingCollector.onTouchEvent(ev, mView.getWidth(), mView.getHeight()); + mFalsingCollector.onTouchEvent(ev); mGestureDetector.onTouchEvent(ev); if (mBrightnessMirror != null && mBrightnessMirror.getVisibility() == View.VISIBLE) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java index 5a01f471d0cd..8ed971087508 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java @@ -862,6 +862,8 @@ public abstract class PanelViewController { mView.getViewTreeObserver().removeOnGlobalLayoutListener(this); if (mAnimateAfterExpanding) { notifyExpandingStarted(); + InteractionJankMonitor.getInstance().begin( + CUJ_NOTIFICATION_SHADE_EXPAND_COLLAPSE); fling(0, true /* expand */); } else { setExpandedFraction(1f); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 9ebde53bb38b..a18d87c30196 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -234,7 +234,7 @@ import com.android.systemui.statusbar.policy.UserSwitcherController; import com.android.systemui.volume.VolumeComponent; import com.android.systemui.wmshell.BubblesManager; import com.android.wm.shell.bubbles.Bubbles; -import com.android.wm.shell.splitscreen.SplitScreen; +import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -394,7 +394,7 @@ public class StatusBar extends SystemUI implements DemoMode, private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy; private final Provider<StatusBarComponent.Builder> mStatusBarComponentBuilder; private final PluginManager mPluginManager; - private final Optional<SplitScreen> mSplitScreenOptional; + private final Optional<LegacySplitScreen> mSplitScreenOptional; private final StatusBarNotificationActivityStarter.Builder mStatusBarNotificationActivityStarterBuilder; private final ShadeController mShadeController; @@ -738,7 +738,7 @@ public class StatusBar extends SystemUI implements DemoMode, CommandQueue commandQueue, Provider<StatusBarComponent.Builder> statusBarComponentBuilder, PluginManager pluginManager, - Optional<SplitScreen> splitScreenOptional, + Optional<LegacySplitScreen> splitScreenOptional, LightsOutNotifController lightsOutNotifController, StatusBarNotificationActivityStarter.Builder statusBarNotificationActivityStarterBuilder, @@ -1568,14 +1568,14 @@ public class StatusBar extends SystemUI implements DemoMode, return false; } - final SplitScreen splitScreen = mSplitScreenOptional.get(); - if (splitScreen.isDividerVisible()) { - if (splitScreen.isMinimized() && !splitScreen.isHomeStackResizable()) { + final LegacySplitScreen legacySplitScreen = mSplitScreenOptional.get(); + if (legacySplitScreen.isDividerVisible()) { + if (legacySplitScreen.isMinimized() && !legacySplitScreen.isHomeStackResizable()) { // Undocking from the minimized state is not supported return false; } - splitScreen.onUndockingTask(); + legacySplitScreen.onUndockingTask(); if (metricsUndockAction != -1) { mMetricsLogger.action(metricsUndockAction); } @@ -1587,7 +1587,7 @@ public class StatusBar extends SystemUI implements DemoMode, return false; } - if (splitScreen.splitPrimaryTask()) { + if (legacySplitScreen.splitPrimaryTask()) { if (metricsDockAction != -1) { mMetricsLogger.action(metricsDockAction); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java index 2aa3f37ccf11..26e19596b577 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java @@ -100,7 +100,7 @@ import com.android.systemui.statusbar.policy.UserSwitcherController; import com.android.systemui.volume.VolumeComponent; import com.android.systemui.wmshell.BubblesManager; import com.android.wm.shell.bubbles.Bubbles; -import com.android.wm.shell.splitscreen.SplitScreen; +import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import java.util.Optional; import java.util.concurrent.Executor; @@ -181,7 +181,7 @@ public interface StatusBarPhoneModule { CommandQueue commandQueue, Provider<StatusBarComponent.Builder> statusBarComponentBuilder, PluginManager pluginManager, - Optional<SplitScreen> splitScreenOptional, + Optional<LegacySplitScreen> splitScreenOptional, LightsOutNotifController lightsOutNotifController, StatusBarNotificationActivityStarter.Builder statusBarNotificationActivityStarterBuilder, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java index d8710bf85a6c..8c67072a15d9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java @@ -37,7 +37,6 @@ import com.android.settingslib.fuelgauge.BatterySaverUtils; import com.android.settingslib.fuelgauge.Estimate; import com.android.settingslib.utils.PowerUtil; import com.android.systemui.broadcast.BroadcastDispatcher; -import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.demomode.DemoMode; @@ -49,13 +48,10 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; -import javax.inject.Inject; - /** * Default implementation of a {@link BatteryController}. This controller monitors for battery * level change events that are broadcasted by the system. */ -@SysUISingleton public class BatteryControllerImpl extends BroadcastReceiver implements BatteryController { private static final String TAG = "BatteryController"; @@ -89,7 +85,6 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC private boolean mFetchingEstimate = false; @VisibleForTesting - @Inject public BatteryControllerImpl( Context context, EnhancedEstimates enhancedEstimates, @@ -155,8 +150,11 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC mChangeCallbacks.add(cb); } if (!mHasReceivedBattery) return; + + // Make sure new callbacks get the correct initial state cb.onBatteryLevelChanged(mLevel, mPluggedIn, mCharging); cb.onPowerSaveChanged(mPowerSave); + cb.onBatteryUnknownStateChanged(mStateUnknown); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java index 4fbf5ff3d35f..2eff04eb66f6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EthernetSignalController.java @@ -18,6 +18,9 @@ package com.android.systemui.statusbar.policy; import android.content.Context; import android.net.NetworkCapabilities; +import com.android.settingslib.AccessibilityContentDescriptions; +import com.android.settingslib.SignalIcon.IconGroup; +import com.android.settingslib.SignalIcon.State; import com.android.systemui.statusbar.policy.NetworkController.IconState; import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; @@ -25,7 +28,7 @@ import java.util.BitSet; public class EthernetSignalController extends - SignalController<SignalController.State, SignalController.IconGroup> { + SignalController<State, IconGroup> { public EthernetSignalController(Context context, CallbackHandler callbackHandler, NetworkControllerImpl networkController) { @@ -57,7 +60,7 @@ public class EthernetSignalController extends } @Override - public SignalController.State cleanState() { - return new SignalController.State(); + public State cleanState() { + return new State(); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java index 49be648755c3..947b91825f29 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java @@ -15,6 +15,10 @@ */ package com.android.systemui.statusbar.policy; +import static com.android.settingslib.mobile.MobileMappings.getDefaultIcons; +import static com.android.settingslib.mobile.MobileMappings.getIconKey; +import static com.android.settingslib.mobile.MobileMappings.mapIconSets; + import android.content.Context; import android.content.Intent; import android.database.ContentObserver; @@ -22,10 +26,8 @@ import android.net.NetworkCapabilities; import android.os.Handler; import android.os.Looper; import android.provider.Settings.Global; -import android.telephony.Annotation; import android.telephony.CellSignalStrength; import android.telephony.CellSignalStrengthCdma; -import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.SignalStrength; import android.telephony.SubscriptionInfo; @@ -37,38 +39,37 @@ import android.text.TextUtils; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; +import com.android.settingslib.SignalIcon.MobileIconGroup; +import com.android.settingslib.SignalIcon.MobileState; import com.android.settingslib.Utils; import com.android.settingslib.graph.SignalDrawable; +import com.android.settingslib.mobile.MobileMappings.Config; +import com.android.settingslib.mobile.MobileStatusTracker; +import com.android.settingslib.mobile.MobileStatusTracker.SubscriptionDefaults; +import com.android.settingslib.mobile.TelephonyIcons; import com.android.settingslib.net.SignalStrengthUtil; import com.android.systemui.R; import com.android.systemui.statusbar.policy.NetworkController.IconState; import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; -import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config; -import com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults; import java.io.PrintWriter; import java.util.BitSet; -import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; -import java.util.concurrent.Executor; - -public class MobileSignalController extends SignalController< - MobileSignalController.MobileState, MobileSignalController.MobileIconGroup> { +/** + * Monitors the mobile signal changes and update the SysUI icons. + */ +public class MobileSignalController extends SignalController<MobileState, MobileIconGroup> { private final TelephonyManager mPhone; private final SubscriptionDefaults mDefaults; private final String mNetworkNameDefault; private final String mNetworkNameSeparator; private final ContentObserver mObserver; - @VisibleForTesting - final PhoneStateListener mPhoneStateListener; // Save entire info for logging, we only use the id. final SubscriptionInfo mSubscriptionInfo; - // @VisibleForDemoMode - final Map<String, MobileIconGroup> mNetworkToIconLookup; + Map<String, MobileIconGroup> mNetworkToIconLookup; // Since some pieces of the phone state are interdependent we store it locally, // this could potentially become part of MobileState for simplification/complication @@ -83,6 +84,9 @@ public class MobileSignalController extends SignalController< private Config mConfig; @VisibleForTesting boolean mInflateSignalStrengths = false; + private MobileStatusTracker.Callback mCallback; + @VisibleForTesting + MobileStatusTracker mMobileStatusTracker; // TODO: Reduce number of vars passed in, if we have the NetworkController, probably don't // need listener lists anymore. @@ -93,18 +97,17 @@ public class MobileSignalController extends SignalController< super("MobileSignalController(" + info.getSubscriptionId() + ")", context, NetworkCapabilities.TRANSPORT_CELLULAR, callbackHandler, networkController); - mNetworkToIconLookup = new HashMap<>(); mConfig = config; mPhone = phone; mDefaults = defaults; mSubscriptionInfo = info; - mPhoneStateListener = new MobilePhoneStateListener((new Handler(receiverLooper))::post); mNetworkNameSeparator = getTextIfExists(R.string.status_bar_network_name_separator) .toString(); mNetworkNameDefault = getTextIfExists( com.android.internal.R.string.lockscreen_carrier_default).toString(); - mapIconSets(); + mNetworkToIconLookup = mapIconSets(mConfig); + mDefaultIcons = getDefaultIcons(mConfig); String networkName = info.getCarrierName() != null ? info.getCarrierName().toString() : mNetworkNameDefault; @@ -112,20 +115,38 @@ public class MobileSignalController extends SignalController< mLastState.networkNameData = mCurrentState.networkNameData = networkName; mLastState.enabled = mCurrentState.enabled = hasMobileData; mLastState.iconGroup = mCurrentState.iconGroup = mDefaultIcons; - // Get initial data sim state. - updateDataSim(); mObserver = new ContentObserver(new Handler(receiverLooper)) { @Override public void onChange(boolean selfChange) { updateTelephony(); } }; + mCallback = new MobileStatusTracker.Callback() { + @Override + public void onMobileStatusChanged(boolean updateTelephony, + MobileStatusTracker.MobileStatus mobileStatus) { + if (Log.isLoggable(mTag, Log.DEBUG)) { + Log.d(mTag, "onMobileStatusChanged=" + + " updateTelephony=" + updateTelephony + + " mobileStatus=" + mobileStatus.toString()); + } + updateMobileStatus(mobileStatus); + if (updateTelephony) { + updateTelephony(); + } else { + notifyListenersIfNecessary(); + } + } + }; + mMobileStatusTracker = new MobileStatusTracker(mPhone, receiverLooper, + info, mDefaults, mCallback); } public void setConfiguration(Config config) { mConfig = config; updateInflateSignalStrength(); - mapIconSets(); + mNetworkToIconLookup = mapIconSets(mConfig); + mDefaultIcons = getDefaultIcons(mConfig); updateTelephony(); } @@ -157,15 +178,7 @@ public class MobileSignalController extends SignalController< * Start listening for phone state changes. */ public void registerListener() { - mPhone.listen(mPhoneStateListener, - PhoneStateListener.LISTEN_SERVICE_STATE - | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS - | PhoneStateListener.LISTEN_CALL_STATE - | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE - | PhoneStateListener.LISTEN_DATA_ACTIVITY - | PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE - | PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE - | PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED); + mMobileStatusTracker.setListening(true); mContext.getContentResolver().registerContentObserver(Global.getUriFor(Global.MOBILE_DATA), true, mObserver); mContext.getContentResolver().registerContentObserver(Global.getUriFor( @@ -177,145 +190,10 @@ public class MobileSignalController extends SignalController< * Stop listening for phone state changes. */ public void unregisterListener() { - mPhone.listen(mPhoneStateListener, 0); + mMobileStatusTracker.setListening(false); mContext.getContentResolver().unregisterContentObserver(mObserver); } - /** - * Produce a mapping of data network types to icon groups for simple and quick use in - * updateTelephony. - */ - private void mapIconSets() { - mNetworkToIconLookup.clear(); - - mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EVDO_0), - TelephonyIcons.THREE_G); - mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EVDO_A), - TelephonyIcons.THREE_G); - mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EVDO_B), - TelephonyIcons.THREE_G); - mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EHRPD), - TelephonyIcons.THREE_G); - if (mConfig.show4gFor3g) { - mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_UMTS), - TelephonyIcons.FOUR_G); - } else { - mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_UMTS), - TelephonyIcons.THREE_G); - } - mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_TD_SCDMA), - TelephonyIcons.THREE_G); - - if (!mConfig.showAtLeast3G) { - mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_UNKNOWN), - TelephonyIcons.UNKNOWN); - mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EDGE), - TelephonyIcons.E); - mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_CDMA), - TelephonyIcons.ONE_X); - mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_1xRTT), - TelephonyIcons.ONE_X); - - mDefaultIcons = TelephonyIcons.G; - } else { - mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_UNKNOWN), - TelephonyIcons.THREE_G); - mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EDGE), - TelephonyIcons.THREE_G); - mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_CDMA), - TelephonyIcons.THREE_G); - mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_1xRTT), - TelephonyIcons.THREE_G); - mDefaultIcons = TelephonyIcons.THREE_G; - } - - MobileIconGroup hGroup = TelephonyIcons.THREE_G; - MobileIconGroup hPlusGroup = TelephonyIcons.THREE_G; - if (mConfig.show4gFor3g) { - hGroup = TelephonyIcons.FOUR_G; - hPlusGroup = TelephonyIcons.FOUR_G; - } else if (mConfig.hspaDataDistinguishable) { - hGroup = TelephonyIcons.H; - hPlusGroup = TelephonyIcons.H_PLUS; - } - - mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_HSDPA), hGroup); - mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_HSUPA), hGroup); - mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_HSPA), hGroup); - mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_HSPAP), hPlusGroup); - - if (mConfig.show4gForLte) { - mNetworkToIconLookup.put(toIconKey( - TelephonyManager.NETWORK_TYPE_LTE), - TelephonyIcons.FOUR_G); - if (mConfig.hideLtePlus) { - mNetworkToIconLookup.put(toDisplayIconKey( - TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA), - TelephonyIcons.FOUR_G); - } else { - mNetworkToIconLookup.put(toDisplayIconKey( - TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA), - TelephonyIcons.FOUR_G_PLUS); - } - } else { - mNetworkToIconLookup.put(toIconKey( - TelephonyManager.NETWORK_TYPE_LTE), - TelephonyIcons.LTE); - if (mConfig.hideLtePlus) { - mNetworkToIconLookup.put(toDisplayIconKey( - TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA), - TelephonyIcons.LTE); - } else { - mNetworkToIconLookup.put(toDisplayIconKey( - TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA), - TelephonyIcons.LTE_PLUS); - } - } - mNetworkToIconLookup.put(toIconKey( - TelephonyManager.NETWORK_TYPE_IWLAN), - TelephonyIcons.WFC); - mNetworkToIconLookup.put(toDisplayIconKey( - TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO), - TelephonyIcons.LTE_CA_5G_E); - mNetworkToIconLookup.put(toDisplayIconKey( - TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA), - TelephonyIcons.NR_5G); - mNetworkToIconLookup.put(toDisplayIconKey( - TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE), - TelephonyIcons.NR_5G_PLUS); - mNetworkToIconLookup.put(toIconKey( - TelephonyManager.NETWORK_TYPE_NR), - TelephonyIcons.NR_5G); - } - - private String getIconKey() { - if (mTelephonyDisplayInfo.getOverrideNetworkType() - == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE) { - return toIconKey(mTelephonyDisplayInfo.getNetworkType()); - } else { - return toDisplayIconKey(mTelephonyDisplayInfo.getOverrideNetworkType()); - } - } - - private String toIconKey(@Annotation.NetworkType int networkType) { - return Integer.toString(networkType); - } - - private String toDisplayIconKey(@Annotation.OverrideNetworkType int displayNetworkType) { - switch (displayNetworkType) { - case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA: - return toIconKey(TelephonyManager.NETWORK_TYPE_LTE) + "_CA"; - case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO: - return toIconKey(TelephonyManager.NETWORK_TYPE_LTE) + "_CA_Plus"; - case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA: - return toIconKey(TelephonyManager.NETWORK_TYPE_NR); - case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE: - return toIconKey(TelephonyManager.NETWORK_TYPE_NR) + "_Plus"; - default: - return "unsupported"; - } - } - private void updateInflateSignalStrength() { mInflateSignalStrengths = SignalStrengthUtil.shouldInflateSignalStrength(mContext, mSubscriptionInfo.getSubscriptionId()); @@ -361,7 +239,7 @@ public class MobileSignalController extends SignalController< MobileIconGroup icons = getIcons(); String contentDescription = getTextIfExists(getContentDescription()).toString(); - CharSequence dataContentDescriptionHtml = getTextIfExists(icons.mDataContentDescription); + CharSequence dataContentDescriptionHtml = getTextIfExists(icons.dataContentDescription); //TODO: Hacky // The data content description can sometimes be shown in a text view and might come to us @@ -385,7 +263,7 @@ public class MobileSignalController extends SignalController< CharSequence description = null; // Only send data sim callbacks to QS. if (mCurrentState.dataSim) { - qsTypeIcon = (showDataIcon || mConfig.alwaysShowDataRatIcon) ? icons.mQsDataType : 0; + qsTypeIcon = (showDataIcon || mConfig.alwaysShowDataRatIcon) ? icons.qsDataType : 0; qsIcon = new IconState(mCurrentState.enabled && !mCurrentState.isEmergency, getQsCurrentIconId(), contentDescription); description = mCurrentState.isEmergency ? null : mCurrentState.networkName; @@ -397,10 +275,10 @@ public class MobileSignalController extends SignalController< && !mCurrentState.carrierNetworkChangeMode && mCurrentState.activityOut; showDataIcon &= mCurrentState.isDefault || dataDisabled; - int typeIcon = (showDataIcon || mConfig.alwaysShowDataRatIcon) ? icons.mDataType : 0; + int typeIcon = (showDataIcon || mConfig.alwaysShowDataRatIcon) ? icons.dataType : 0; callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon, activityIn, activityOut, dataContentDescription, dataContentDescriptionHtml, - description, icons.mIsWide, mSubscriptionInfo.getSubscriptionId(), + description, icons.isWide, mSubscriptionInfo.getSubscriptionId(), mCurrentState.roaming); } @@ -521,13 +399,24 @@ public class MobileSignalController extends SignalController< return CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN; } + private void updateMobileStatus(MobileStatusTracker.MobileStatus mobileStatus) { + mCurrentState.activityIn = mobileStatus.activityIn; + mCurrentState.activityOut = mobileStatus.activityOut; + mCurrentState.dataSim = mobileStatus.dataSim; + mCurrentState.carrierNetworkChangeMode = mobileStatus.carrierNetworkChangeMode; + mDataState = mobileStatus.dataState; + mServiceState = mobileStatus.serviceState; + mSignalStrength = mobileStatus.signalStrength; + mTelephonyDisplayInfo = mobileStatus.telephonyDisplayInfo; + } + /** * Updates the current state based on mServiceState, mSignalStrength, mDataState, * mTelephonyDisplayInfo, and mSimState. It should be called any time one of these is updated. * This will call listeners if necessary. */ private final void updateTelephony() { - if (DEBUG) { + if (Log.isLoggable(mTag, Log.DEBUG)) { Log.d(mTag, "updateTelephonySignalStrength: hasService=" + Utils.isInService(mServiceState) + " ss=" + mSignalStrength + " displayInfo=" + mTelephonyDisplayInfo); @@ -542,7 +431,7 @@ public class MobileSignalController extends SignalController< } } - String iconKey = getIconKey(); + String iconKey = getIconKey(mTelephonyDisplayInfo); if (mNetworkToIconLookup.get(iconKey) != null) { mCurrentState.iconGroup = mNetworkToIconLookup.get(iconKey); } else { @@ -621,156 +510,4 @@ public class MobileSignalController extends SignalController< pw.println(" mInflateSignalStrengths=" + mInflateSignalStrengths + ","); pw.println(" isDataDisabled=" + isDataDisabled() + ","); } - - class MobilePhoneStateListener extends PhoneStateListener { - public MobilePhoneStateListener(Executor executor) { - super(executor); - } - - @Override - public void onSignalStrengthsChanged(SignalStrength signalStrength) { - if (DEBUG) { - Log.d(mTag, "onSignalStrengthsChanged signalStrength=" + signalStrength + - ((signalStrength == null) ? "" : (" level=" + signalStrength.getLevel()))); - } - mSignalStrength = signalStrength; - updateTelephony(); - } - - @Override - public void onServiceStateChanged(ServiceState state) { - if (DEBUG) { - Log.d(mTag, "onServiceStateChanged voiceState=" + state.getState() - + " dataState=" + state.getDataRegistrationState()); - } - mServiceState = state; - updateTelephony(); - } - - @Override - public void onDataConnectionStateChanged(int state, int networkType) { - if (DEBUG) { - Log.d(mTag, "onDataConnectionStateChanged: state=" + state - + " type=" + networkType); - } - mDataState = state; - updateTelephony(); - } - - @Override - public void onDataActivity(int direction) { - if (DEBUG) { - Log.d(mTag, "onDataActivity: direction=" + direction); - } - setActivity(direction); - } - - @Override - public void onCarrierNetworkChange(boolean active) { - if (DEBUG) { - Log.d(mTag, "onCarrierNetworkChange: active=" + active); - } - mCurrentState.carrierNetworkChangeMode = active; - updateTelephony(); - } - - @Override - public void onActiveDataSubscriptionIdChanged(int subId) { - if (DEBUG) Log.d(mTag, "onActiveDataSubscriptionIdChanged: subId=" + subId); - updateDataSim(); - updateTelephony(); - } - - @Override - public void onDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo) { - if (DEBUG) { - Log.d(mTag, "onDisplayInfoChanged: telephonyDisplayInfo=" + telephonyDisplayInfo); - } - mTelephonyDisplayInfo = telephonyDisplayInfo; - updateTelephony(); - } - } - - static class MobileIconGroup extends SignalController.IconGroup { - final int mDataContentDescription; // mContentDescriptionDataType - final int mDataType; - final boolean mIsWide; - final int mQsDataType; - - public MobileIconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc, - int sbNullState, int qsNullState, int sbDiscState, int qsDiscState, - int discContentDesc, int dataContentDesc, int dataType, boolean isWide) { - super(name, sbIcons, qsIcons, contentDesc, sbNullState, qsNullState, sbDiscState, - qsDiscState, discContentDesc); - mDataContentDescription = dataContentDesc; - mDataType = dataType; - mIsWide = isWide; - mQsDataType = dataType; // TODO: remove this field - } - } - - static class MobileState extends SignalController.State { - String networkName; - String networkNameData; - boolean dataSim; - boolean dataConnected; - boolean isEmergency; - boolean airplaneMode; - boolean carrierNetworkChangeMode; - boolean isDefault; - boolean userSetup; - boolean roaming; - boolean defaultDataOff; // Tracks the on/off state of the defaultDataSubscription - - @Override - public void copyFrom(State s) { - super.copyFrom(s); - MobileState state = (MobileState) s; - dataSim = state.dataSim; - networkName = state.networkName; - networkNameData = state.networkNameData; - dataConnected = state.dataConnected; - isDefault = state.isDefault; - isEmergency = state.isEmergency; - airplaneMode = state.airplaneMode; - carrierNetworkChangeMode = state.carrierNetworkChangeMode; - userSetup = state.userSetup; - roaming = state.roaming; - defaultDataOff = state.defaultDataOff; - } - - @Override - protected void toString(StringBuilder builder) { - super.toString(builder); - builder.append(','); - builder.append("dataSim=").append(dataSim).append(','); - builder.append("networkName=").append(networkName).append(','); - builder.append("networkNameData=").append(networkNameData).append(','); - builder.append("dataConnected=").append(dataConnected).append(','); - builder.append("roaming=").append(roaming).append(','); - builder.append("isDefault=").append(isDefault).append(','); - builder.append("isEmergency=").append(isEmergency).append(','); - builder.append("airplaneMode=").append(airplaneMode).append(','); - builder.append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode) - .append(','); - builder.append("userSetup=").append(userSetup).append(','); - builder.append("defaultDataOff=").append(defaultDataOff); - } - - @Override - public boolean equals(Object o) { - return super.equals(o) - && Objects.equals(((MobileState) o).networkName, networkName) - && Objects.equals(((MobileState) o).networkNameData, networkNameData) - && ((MobileState) o).dataSim == dataSim - && ((MobileState) o).dataConnected == dataConnected - && ((MobileState) o).isEmergency == isEmergency - && ((MobileState) o).airplaneMode == airplaneMode - && ((MobileState) o).carrierNetworkChangeMode == carrierNetworkChangeMode - && ((MobileState) o).userSetup == userSetup - && ((MobileState) o).isDefault == isDefault - && ((MobileState) o).roaming == roaming - && ((MobileState) o).defaultDataOff == defaultDataOff; - } - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java index 62b922e23532..0ca2b4a96759 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java @@ -30,7 +30,6 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Configuration; -import android.content.res.Resources; import android.net.ConnectivityManager; import android.net.Network; import android.net.NetworkCapabilities; @@ -40,7 +39,6 @@ import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.Looper; -import android.os.PersistableBundle; import android.provider.Settings; import android.telephony.CarrierConfigManager; import android.telephony.CellSignalStrength; @@ -59,6 +57,9 @@ import androidx.annotation.NonNull; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.settingslib.mobile.MobileMappings.Config; +import com.android.settingslib.mobile.MobileStatusTracker.SubscriptionDefaults; +import com.android.settingslib.mobile.TelephonyIcons; import com.android.settingslib.net.DataUsageController; import com.android.systemui.Dumpable; import com.android.systemui.R; @@ -391,7 +392,6 @@ public class NetworkControllerImpl extends BroadcastReceiver } } }); - updateMobileControllers(); // Initial setup of emergency information. Handled as if we had received a sticky broadcast @@ -1201,59 +1201,4 @@ public class NetworkControllerImpl extends BroadcastReceiver registerListeners(); } }; - - public static class SubscriptionDefaults { - public int getDefaultVoiceSubId() { - return SubscriptionManager.getDefaultVoiceSubscriptionId(); - } - - public int getDefaultDataSubId() { - return SubscriptionManager.getDefaultDataSubscriptionId(); - } - - public int getActiveDataSubId() { - return SubscriptionManager.getActiveDataSubscriptionId(); - } - } - - @VisibleForTesting - static class Config { - boolean showAtLeast3G = false; - boolean show4gFor3g = false; - boolean alwaysShowCdmaRssi = false; - boolean show4gForLte = false; - boolean hideLtePlus = false; - boolean hspaDataDistinguishable; - boolean alwaysShowDataRatIcon = false; - - static Config readConfig(Context context) { - Config config = new Config(); - Resources res = context.getResources(); - - config.showAtLeast3G = res.getBoolean(R.bool.config_showMin3G); - config.alwaysShowCdmaRssi = - res.getBoolean(com.android.internal.R.bool.config_alwaysUseCdmaRssi); - config.hspaDataDistinguishable = - res.getBoolean(R.bool.config_hspa_data_distinguishable); - - CarrierConfigManager configMgr = (CarrierConfigManager) - context.getSystemService(Context.CARRIER_CONFIG_SERVICE); - // Handle specific carrier config values for the default data SIM - int defaultDataSubId = SubscriptionManager.from(context) - .getDefaultDataSubscriptionId(); - PersistableBundle b = configMgr.getConfigForSubId(defaultDataSubId); - if (b != null) { - config.alwaysShowDataRatIcon = b.getBoolean( - CarrierConfigManager.KEY_ALWAYS_SHOW_DATA_RAT_ICON_BOOL); - config.show4gForLte = b.getBoolean( - CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL); - config.show4gFor3g = b.getBoolean( - CarrierConfigManager.KEY_SHOW_4G_FOR_3G_DATA_ICON_BOOL); - config.hideLtePlus = b.getBoolean( - CarrierConfigManager.KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL); - } - - return config; - } - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java index 3a456918a49b..a05fe1f1b0c2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java @@ -21,18 +21,21 @@ import android.annotation.NonNull; import android.content.Context; import android.util.Log; +import com.android.settingslib.SignalIcon.IconGroup; +import com.android.settingslib.SignalIcon.State; import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; import java.io.PrintWriter; -import java.text.SimpleDateFormat; import java.util.BitSet; /** * Common base class for handling signal for both wifi and mobile data. + * + * @param <T> State of the SysUI controller. + * @param <I> Icon groups of the SysUI controller for a given State. */ -public abstract class SignalController<T extends SignalController.State, - I extends SignalController.IconGroup> { +public abstract class SignalController<T extends State, I extends IconGroup> { // Save the previous SignalController.States of all SignalControllers for dumps. static final boolean RECORD_HISTORY = true; // If RECORD_HISTORY how many to save, must be a power of 2. @@ -124,11 +127,11 @@ public abstract class SignalController<T extends SignalController.State, */ public int getQsCurrentIconId() { if (mCurrentState.connected) { - return getIcons().mQsIcons[mCurrentState.inetCondition][mCurrentState.level]; + return getIcons().qsIcons[mCurrentState.inetCondition][mCurrentState.level]; } else if (mCurrentState.enabled) { - return getIcons().mQsDiscState; + return getIcons().qsDiscState; } else { - return getIcons().mQsNullState; + return getIcons().qsNullState; } } @@ -137,11 +140,11 @@ public abstract class SignalController<T extends SignalController.State, */ public int getCurrentIconId() { if (mCurrentState.connected) { - return getIcons().mSbIcons[mCurrentState.inetCondition][mCurrentState.level]; + return getIcons().sbIcons[mCurrentState.inetCondition][mCurrentState.level]; } else if (mCurrentState.enabled) { - return getIcons().mSbDiscState; + return getIcons().sbDiscState; } else { - return getIcons().mSbNullState; + return getIcons().sbNullState; } } @@ -151,9 +154,9 @@ public abstract class SignalController<T extends SignalController.State, */ public int getContentDescription() { if (mCurrentState.connected) { - return getIcons().mContentDesc[mCurrentState.level]; + return getIcons().contentDesc[mCurrentState.level]; } else { - return getIcons().mDiscContentDesc; + return getIcons().discContentDesc; } } @@ -216,108 +219,4 @@ public abstract class SignalController<T extends SignalController.State, * Generate a blank T. */ protected abstract T cleanState(); - - /* - * Holds icons for a given state. Arrays are generally indexed as inet - * state (full connectivity or not) first, and second dimension as - * signal strength. - */ - static class IconGroup { - final int[][] mSbIcons; - final int[][] mQsIcons; - final int[] mContentDesc; - final int mSbNullState; - final int mQsNullState; - final int mSbDiscState; - final int mQsDiscState; - final int mDiscContentDesc; - // For logging. - final String mName; - - public IconGroup(String name, int[][] sbIcons, int[][] qsIcons, int[] contentDesc, - int sbNullState, int qsNullState, int sbDiscState, int qsDiscState, - int discContentDesc) { - mName = name; - mSbIcons = sbIcons; - mQsIcons = qsIcons; - mContentDesc = contentDesc; - mSbNullState = sbNullState; - mQsNullState = qsNullState; - mSbDiscState = sbDiscState; - mQsDiscState = qsDiscState; - mDiscContentDesc = discContentDesc; - } - - @Override - public String toString() { - return "IconGroup(" + mName + ")"; - } - } - - static class State { - // No locale as it's only used for logging purposes - private static SimpleDateFormat sSDF = new SimpleDateFormat("MM-dd HH:mm:ss.SSS"); - boolean connected; - boolean enabled; - boolean activityIn; - boolean activityOut; - int level; - IconGroup iconGroup; - int inetCondition; - int rssi; // Only for logging. - - // Not used for comparison, just used for logging. - long time; - - public void copyFrom(State state) { - connected = state.connected; - enabled = state.enabled; - level = state.level; - iconGroup = state.iconGroup; - inetCondition = state.inetCondition; - activityIn = state.activityIn; - activityOut = state.activityOut; - rssi = state.rssi; - time = state.time; - } - - @Override - public String toString() { - if (time != 0) { - StringBuilder builder = new StringBuilder(); - toString(builder); - return builder.toString(); - } else { - return "Empty " + getClass().getSimpleName(); - } - } - - protected void toString(StringBuilder builder) { - builder.append("connected=").append(connected).append(',') - .append("enabled=").append(enabled).append(',') - .append("level=").append(level).append(',') - .append("inetCondition=").append(inetCondition).append(',') - .append("iconGroup=").append(iconGroup).append(',') - .append("activityIn=").append(activityIn).append(',') - .append("activityOut=").append(activityOut).append(',') - .append("rssi=").append(rssi).append(',') - .append("lastModified=").append(sSDF.format(time)); - } - - @Override - public boolean equals(Object o) { - if (!o.getClass().equals(getClass())) { - return false; - } - State other = (State) o; - return other.connected == connected - && other.enabled == enabled - && other.level == level - && other.inetCondition == inetCondition - && other.iconGroup == iconGroup - && other.activityIn == activityIn - && other.activityOut == activityOut - && other.rssi == rssi; - } - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java index e7f84a55eb5f..34c78813d11a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java @@ -102,8 +102,7 @@ public class SmartReplyView extends ViewGroup { mHeightUpperLimit = NotificationUtils.getFontScaledHeight(mContext, R.dimen.smart_reply_button_max_height); - mCurrentBackgroundColor = context.getColor(R.color.smart_reply_button_background); - mDefaultBackgroundColor = mCurrentBackgroundColor; + mDefaultBackgroundColor = context.getColor(R.color.smart_reply_button_background); mDefaultTextColor = mContext.getColor(R.color.smart_reply_button_text); mDefaultTextColorDarkBg = mContext.getColor(R.color.smart_reply_button_text_dark_bg); mDefaultStrokeColor = mContext.getColor(R.color.smart_reply_button_stroke); @@ -142,8 +141,9 @@ public class SmartReplyView extends ViewGroup { mSingleToDoubleLineButtonWidthIncrease = 2 * (doubleLineButtonPaddingHorizontal - singleLineButtonPaddingHorizontal); - mBreakIterator = BreakIterator.getLineInstance(); + + setBackgroundTintColor(mDefaultBackgroundColor); reallocateCandidateButtonQueueForSqueezing(); } @@ -182,7 +182,7 @@ public class SmartReplyView extends ViewGroup { public void resetSmartSuggestions(View newSmartReplyContainer) { mSmartReplyContainer = newSmartReplyContainer; removeAllViews(); - mCurrentBackgroundColor = mDefaultBackgroundColor; + setBackgroundTintColor(mDefaultBackgroundColor); } /** Add buttons to the {@link SmartReplyView} */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java index 4ae96651b570..82ce4c87e300 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java @@ -28,6 +28,9 @@ import android.net.wifi.WifiManager; import android.text.TextUtils; import com.android.internal.annotations.VisibleForTesting; +import com.android.settingslib.AccessibilityContentDescriptions; +import com.android.settingslib.SignalIcon.IconGroup; +import com.android.settingslib.SignalIcon.State; import com.android.settingslib.wifi.WifiStatusTracker; import com.android.systemui.R; import com.android.systemui.statusbar.policy.NetworkController.IconState; @@ -36,7 +39,7 @@ import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; import java.util.Objects; public class WifiSignalController extends - SignalController<WifiSignalController.WifiState, SignalController.IconGroup> { + SignalController<WifiSignalController.WifiState, IconGroup> { private final boolean mHasMobileDataFeature; private final WifiStatusTracker mWifiTracker; @@ -156,7 +159,7 @@ public class WifiSignalController extends } } - static class WifiState extends SignalController.State { + static class WifiState extends State { String ssid; boolean isTransient; boolean isDefault; diff --git a/packages/SystemUI/src/com/android/systemui/util/AlphaTintDrawableWrapper.java b/packages/SystemUI/src/com/android/systemui/util/AlphaTintDrawableWrapper.java new file mode 100644 index 000000000000..79a197d9d409 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/util/AlphaTintDrawableWrapper.java @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.util; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.res.ColorStateList; +import android.content.res.Resources; +import android.content.res.Resources.Theme; +import android.content.res.TypedArray; +import android.graphics.drawable.DrawableWrapper; +import android.util.AttributeSet; + +import com.android.systemui.R; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; + +/** + * An extension of {@link DrawableWrapper} that supports alpha and tint XML properties. + * + * {@link DrawableWrapper} supports setting these properties programmatically, but doesn't expose + * corresponding XML properties for some reason. This class allows to set these values in the XML, + * supporting theming. + * + * This class should only be used in XML. + * + * @attr ref android.R.styleable#DrawableWrapper_drawable + * @attr ref R.styleable#AlphaTintDrawableWrapper_tint + * @attr ref R.styleable#AlphaTintDrawableWrapper_alpha + */ +public class AlphaTintDrawableWrapper extends DrawableWrapper { + private ColorStateList mTint; + private int[] mThemeAttrs; + + /** No-arg constructor used by drawable inflation. */ + public AlphaTintDrawableWrapper() { + super(null); + } + + @Override + public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser, + @NonNull AttributeSet attrs, @Nullable Theme theme) + throws XmlPullParserException, IOException { + final TypedArray a = obtainAttributes(r, theme, attrs, + R.styleable.AlphaTintDrawableWrapper); + + super.inflate(r, parser, attrs, theme); + + mThemeAttrs = a.extractThemeAttrs(); + updateStateFromTypedArray(a); + a.recycle(); + + applyTint(); + } + + @Override + public void applyTheme(Theme t) { + super.applyTheme(t); + + if (mThemeAttrs != null) { + final TypedArray a = t.resolveAttributes(mThemeAttrs, + R.styleable.AlphaTintDrawableWrapper); + updateStateFromTypedArray(a); + a.recycle(); + } + + // Ensure tint is reapplied after applying the theme to ensure this drawables' + // tint overrides the underlying drawables' tint. + applyTint(); + } + + @Override + public boolean canApplyTheme() { + return (mThemeAttrs != null && mThemeAttrs.length > 0) || super.canApplyTheme(); + } + + private void updateStateFromTypedArray(@NonNull TypedArray a) { + if (a.hasValue(R.styleable.AlphaTintDrawableWrapper_android_drawable)) { + setDrawable(a.getDrawable(R.styleable.AlphaTintDrawableWrapper_android_drawable)); + } + if (a.hasValue(R.styleable.AlphaTintDrawableWrapper_android_tint)) { + mTint = a.getColorStateList(R.styleable.AlphaTintDrawableWrapper_android_tint); + } + if (a.hasValue(R.styleable.AlphaTintDrawableWrapper_android_alpha)) { + float alpha = a.getFloat(R.styleable.AlphaTintDrawableWrapper_android_alpha, 1); + setAlpha(Math.round(alpha * 255)); + } + } + + private void applyTint() { + if (getDrawable() != null && mTint != null) { + getDrawable().mutate().setTintList(mTint); + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java index 8dea5b5a19a3..125b5d4c7b8d 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java @@ -36,7 +36,7 @@ import com.android.wm.shell.pip.tv.PipControlsView; import com.android.wm.shell.pip.tv.PipControlsViewController; import com.android.wm.shell.pip.tv.PipNotification; import com.android.wm.shell.pip.tv.TvPipMenuController; -import com.android.wm.shell.splitscreen.SplitScreen; +import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import java.util.Optional; @@ -120,7 +120,7 @@ public abstract class TvPipModule { PipBoundsState pipBoundsState, PipBoundsAlgorithm pipBoundsAlgorithm, PipSurfaceTransactionHelper pipSurfaceTransactionHelper, - Optional<SplitScreen> splitScreenOptional, DisplayController displayController, + Optional<LegacySplitScreen> splitScreenOptional, DisplayController displayController, PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer) { return new PipTaskOrganizer(context, pipBoundsState, pipBoundsAlgorithm, tvMenuController, pipSurfaceTransactionHelper, splitScreenOptional, diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java index 06f1522a7256..765fd32f7cd2 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java @@ -29,8 +29,8 @@ import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.SystemWindows; import com.android.wm.shell.common.TaskStackListenerImpl; import com.android.wm.shell.common.TransactionPool; -import com.android.wm.shell.splitscreen.SplitScreen; -import com.android.wm.shell.splitscreen.SplitScreenController; +import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; +import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController; import java.util.concurrent.Executor; @@ -54,12 +54,12 @@ public class TvWMShellModule { @WMSingleton @Provides - static SplitScreen provideSplitScreen(Context context, + static LegacySplitScreen provideSplitScreen(Context context, DisplayController displayController, SystemWindows systemWindows, DisplayImeController displayImeController, @Main Handler handler, TransactionPool transactionPool, ShellTaskOrganizer shellTaskOrganizer, SyncTransactionQueue syncQueue, TaskStackListenerImpl taskStackListener) { - return new SplitScreenController(context, displayController, systemWindows, + return new LegacySplitScreenController(context, displayController, systemWindows, displayImeController, handler, transactionPool, shellTaskOrganizer, syncQueue, taskStackListener); } diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java index 2a18f3c550ed..08194291ce2f 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java @@ -61,7 +61,7 @@ import com.android.wm.shell.onehanded.OneHandedGestureHandler.OneHandedGestureEv import com.android.wm.shell.onehanded.OneHandedTransitionCallback; import com.android.wm.shell.pip.Pip; import com.android.wm.shell.protolog.ShellProtoLogImpl; -import com.android.wm.shell.splitscreen.SplitScreen; +import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -93,7 +93,7 @@ public final class WMShell extends SystemUI private final ScreenLifecycle mScreenLifecycle; private final SysUiState mSysUiState; private final Optional<Pip> mPipOptional; - private final Optional<SplitScreen> mSplitScreenOptional; + private final Optional<LegacySplitScreen> mSplitScreenOptional; private final Optional<OneHanded> mOneHandedOptional; private final Optional<HideDisplayCutout> mHideDisplayCutoutOptional; private final ProtoTracer mProtoTracer; @@ -112,7 +112,7 @@ public final class WMShell extends SystemUI ScreenLifecycle screenLifecycle, SysUiState sysUiState, Optional<Pip> pipOptional, - Optional<SplitScreen> splitScreenOptional, + Optional<LegacySplitScreen> splitScreenOptional, Optional<OneHanded> oneHandedOptional, Optional<HideDisplayCutout> hideDisplayCutoutOptional, ProtoTracer protoTracer, @@ -190,7 +190,7 @@ public final class WMShell extends SystemUI } @VisibleForTesting - void initSplitScreen(SplitScreen splitScreen) { + void initSplitScreen(LegacySplitScreen legacySplitScreen) { mSplitScreenKeyguardCallback = new KeyguardUpdateMonitorCallback() { @Override public void onKeyguardVisibilityChanged(boolean showing) { @@ -198,7 +198,7 @@ public final class WMShell extends SystemUI // above everything, it is actually transparent except for notifications, so // we still need to hide any surfaces that are below it. // TODO(b/148906453): Figure out keyguard dismiss animation for divider view. - splitScreen.onKeyguardVisibilityChanged(showing); + legacySplitScreen.onKeyguardVisibilityChanged(showing); } }; mKeyguardUpdateMonitor.registerCallback(mSplitScreenKeyguardCallback); diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java index 71a883d20988..c57d52e3f8e9 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java @@ -37,6 +37,7 @@ import com.android.wm.shell.FullscreenTaskListener; import com.android.wm.shell.ShellCommandHandler; import com.android.wm.shell.ShellInit; import com.android.wm.shell.ShellTaskOrganizer; +import com.android.wm.shell.Transitions; import com.android.wm.shell.WindowManagerShellWrapper; import com.android.wm.shell.apppairs.AppPairs; import com.android.wm.shell.bubbles.BubbleController; @@ -56,8 +57,6 @@ import com.android.wm.shell.common.annotations.ShellMainThread; import com.android.wm.shell.draganddrop.DragAndDropController; import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout; import com.android.wm.shell.hidedisplaycutout.HideDisplayCutoutController; -import com.android.wm.shell.letterbox.LetterboxConfigController; -import com.android.wm.shell.letterbox.LetterboxTaskListener; import com.android.wm.shell.onehanded.OneHanded; import com.android.wm.shell.onehanded.OneHandedController; import com.android.wm.shell.pip.Pip; @@ -66,7 +65,7 @@ import com.android.wm.shell.pip.PipSurfaceTransactionHelper; import com.android.wm.shell.pip.PipUiEventLogger; import com.android.wm.shell.pip.phone.PipAppOpsListener; import com.android.wm.shell.pip.phone.PipTouchHandler; -import com.android.wm.shell.splitscreen.SplitScreen; +import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import java.util.Optional; import java.util.concurrent.TimeUnit; @@ -170,17 +169,17 @@ public abstract class WMShellBaseModule { static ShellInit provideShellInit(DisplayImeController displayImeController, DragAndDropController dragAndDropController, ShellTaskOrganizer shellTaskOrganizer, - Optional<SplitScreen> splitScreenOptional, + Optional<LegacySplitScreen> legacySplitScreenOptional, Optional<AppPairs> appPairsOptional, - LetterboxTaskListener letterboxTaskListener, - FullscreenTaskListener fullscreenTaskListener) { + FullscreenTaskListener fullscreenTaskListener, + Transitions transitions) { return new ShellInit(displayImeController, dragAndDropController, shellTaskOrganizer, - splitScreenOptional, + legacySplitScreenOptional, appPairsOptional, - letterboxTaskListener, - fullscreenTaskListener); + fullscreenTaskListener, + transitions); } /** @@ -191,15 +190,13 @@ public abstract class WMShellBaseModule { @Provides static Optional<ShellCommandHandler> provideShellCommandHandler( ShellTaskOrganizer shellTaskOrganizer, - Optional<SplitScreen> splitScreenOptional, + Optional<LegacySplitScreen> legacySplitScreenOptional, Optional<Pip> pipOptional, Optional<OneHanded> oneHandedOptional, Optional<HideDisplayCutout> hideDisplayCutout, - Optional<AppPairs> appPairsOptional, - LetterboxConfigController letterboxConfigController) { - return Optional.of(new ShellCommandHandler(shellTaskOrganizer, splitScreenOptional, - pipOptional, oneHandedOptional, hideDisplayCutout, appPairsOptional, - letterboxConfigController)); + Optional<AppPairs> appPairsOptional) { + return Optional.of(new ShellCommandHandler(shellTaskOrganizer, legacySplitScreenOptional, + pipOptional, oneHandedOptional, hideDisplayCutout, appPairsOptional)); } @WMSingleton @@ -278,12 +275,9 @@ public abstract class WMShellBaseModule { @WMSingleton @Provides - static ShellTaskOrganizer provideShellTaskOrganizer(SyncTransactionQueue syncQueue, - @ShellMainThread ShellExecutor shellMainExecutor, - @ShellAnimationThread ShellExecutor shellAnimationExecutor, - TransactionPool transactionPool, Context context) { - return new ShellTaskOrganizer(syncQueue, transactionPool, shellMainExecutor, - shellAnimationExecutor, context); + static ShellTaskOrganizer provideShellTaskOrganizer(@ShellMainThread ShellExecutor mainExecutor, + Context context) { + return new ShellTaskOrganizer(mainExecutor, context); } @WMSingleton @@ -293,7 +287,7 @@ public abstract class WMShellBaseModule { } @BindsOptionalOf - abstract SplitScreen optionalSplitScreen(); + abstract LegacySplitScreen optionalLegacySplitScreen(); @BindsOptionalOf abstract AppPairs optionalAppPairs(); @@ -338,16 +332,9 @@ public abstract class WMShellBaseModule { @WMSingleton @Provides - static LetterboxTaskListener provideLetterboxTaskListener( - SyncTransactionQueue syncQueue, - LetterboxConfigController letterboxConfigController, - WindowManager windowManager) { - return new LetterboxTaskListener(syncQueue, letterboxConfigController, windowManager); - } - - @WMSingleton - @Provides - static LetterboxConfigController provideLetterboxConfigController(Context context) { - return new LetterboxConfigController(context); + static Transitions provideTransitions(ShellTaskOrganizer organizer, TransactionPool pool, + @ShellMainThread ShellExecutor mainExecutor, + @ShellAnimationThread ShellExecutor animExecutor) { + return new Transitions(organizer, pool, mainExecutor, animExecutor); } } diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java index 281b1aa9ad7b..3399a0bfc72e 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java @@ -46,8 +46,8 @@ import com.android.wm.shell.pip.phone.PhonePipMenuController; import com.android.wm.shell.pip.phone.PipAppOpsListener; import com.android.wm.shell.pip.phone.PipController; import com.android.wm.shell.pip.phone.PipTouchHandler; -import com.android.wm.shell.splitscreen.SplitScreen; -import com.android.wm.shell.splitscreen.SplitScreenController; +import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; +import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController; import java.util.Optional; import java.util.concurrent.Executor; @@ -72,12 +72,12 @@ public class WMShellModule { @WMSingleton @Provides - static SplitScreen provideSplitScreen(Context context, + static LegacySplitScreen provideLegacySplitScreen(Context context, DisplayController displayController, SystemWindows systemWindows, DisplayImeController displayImeController, @Main Handler handler, TransactionPool transactionPool, ShellTaskOrganizer shellTaskOrganizer, SyncTransactionQueue syncQueue, TaskStackListenerImpl taskStackListener) { - return new SplitScreenController(context, displayController, systemWindows, + return new LegacySplitScreenController(context, displayController, systemWindows, displayImeController, handler, transactionPool, shellTaskOrganizer, syncQueue, taskStackListener); } @@ -145,7 +145,7 @@ public class WMShellModule { PipBoundsAlgorithm pipBoundsAlgorithm, PhonePipMenuController menuPhoneController, PipSurfaceTransactionHelper pipSurfaceTransactionHelper, - Optional<SplitScreen> splitScreenOptional, DisplayController displayController, + Optional<LegacySplitScreen> splitScreenOptional, DisplayController displayController, PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer) { return new PipTaskOrganizer(context, pipBoundsState, pipBoundsAlgorithm, menuPhoneController, pipSurfaceTransactionHelper, splitScreenOptional, diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java index e967a5d607eb..6c3b37edbd15 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java @@ -24,10 +24,7 @@ import static junit.framework.TestCase.fail; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -54,8 +51,6 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; import com.android.systemui.util.time.FakeSystemClock; -import junit.framework.Assert; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -84,8 +79,7 @@ public class ForegroundServiceControllerTest extends SysuiTestCase { MockitoAnnotations.initMocks(this); mFsc = new ForegroundServiceController(mAppOpsController, mMainHandler); mListener = new ForegroundServiceNotificationListener( - mContext, mFsc, mEntryManager, mNotifPipeline, - mock(ForegroundServiceLifetimeExtender.class), mClock); + mContext, mFsc, mEntryManager, mNotifPipeline, mClock); ArgumentCaptor<NotificationEntryListener> entryListenerCaptor = ArgumentCaptor.forClass(NotificationEntryListener.class); verify(mEntryManager).addNotificationEntryListener( diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceNotificationListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceNotificationListenerTest.java deleted file mode 100644 index 9a40421a353f..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceNotificationListenerTest.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui; - -import static com.android.systemui.ForegroundServiceLifetimeExtender.MIN_FGS_TIME_MS; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import android.app.Notification; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import com.android.systemui.statusbar.NotificationInteractionTracker; -import com.android.systemui.statusbar.notification.collection.NotificationEntry; -import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; -import com.android.systemui.util.time.FakeSystemClock; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -@RunWith(AndroidJUnit4.class) -@SmallTest -public class ForegroundServiceNotificationListenerTest extends SysuiTestCase { - private ForegroundServiceLifetimeExtender mExtender; - private NotificationEntry mEntry; - private Notification mNotif; - private final FakeSystemClock mClock = new FakeSystemClock(); - - @Mock - private NotificationInteractionTracker mInteractionTracker; - - @Before - public void setup() { - MockitoAnnotations.initMocks(this); - mExtender = new ForegroundServiceLifetimeExtender(mInteractionTracker, mClock); - - mNotif = new Notification.Builder(mContext, "") - .setSmallIcon(R.drawable.ic_person) - .setContentTitle("Title") - .setContentText("Text") - .build(); - - mEntry = new NotificationEntryBuilder() - .setCreationTime(mClock.uptimeMillis()) - .setNotification(mNotif) - .build(); - } - - /** - * ForegroundServiceLifetimeExtenderTest - */ - @Test - public void testShouldExtendLifetime_should_foreground() { - // Extend the lifetime of a FGS notification iff it has not been visible - // for the minimum time - mNotif.flags |= Notification.FLAG_FOREGROUND_SERVICE; - - // No time has elapsed, keep showing - assertTrue(mExtender.shouldExtendLifetime(mEntry)); - } - - @Test - public void testShouldExtendLifetime_shouldNot_foreground() { - mNotif.flags |= Notification.FLAG_FOREGROUND_SERVICE; - - // Entry was created at mClock.uptimeMillis(), advance it MIN_FGS_TIME_MS + 1 - mClock.advanceTime(MIN_FGS_TIME_MS + 1); - assertFalse(mExtender.shouldExtendLifetime(mEntry)); - } - - @Test - public void testShouldExtendLifetime_shouldNot_notForeground() { - mNotif.flags = 0; - - // Entry was created at mClock.uptimeMillis(), advance it MIN_FGS_TIME_MS + 1 - mClock.advanceTime(MIN_FGS_TIME_MS + 1); - assertFalse(mExtender.shouldExtendLifetime(mEntry)); - } - - @Test - public void testShouldExtendLifetime_shouldNot_interruped() { - // GIVEN a notification that would trigger lifetime extension - mNotif.flags |= Notification.FLAG_FOREGROUND_SERVICE; - - // GIVEN the notification has alerted - mEntry.setInterruption(); - - // THEN the notification does not need to have its lifetime extended by this extender - assertFalse(mExtender.shouldExtendLifetime(mEntry)); - } -} diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java index 0451d45a628b..96f3c156c978 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java @@ -33,6 +33,7 @@ import static junit.framework.Assert.assertNotNull; import static org.hamcrest.CoreMatchers.hasItems; import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; @@ -91,6 +92,7 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { private MagnificationModeSwitch mMagnificationModeSwitch; private View.OnTouchListener mTouchListener; private List<MotionEvent> mMotionEvents = new ArrayList<>(); + private Runnable mFadeOutAnimation; @Before public void setUp() throws Exception { @@ -119,6 +121,7 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { event.recycle(); } mMotionEvents.clear(); + mFadeOutAnimation = null; } @Test @@ -164,15 +167,9 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { } @Test - public void showMagnificationButton_windowMode_verifyAnimationEndAction() { - // Execute the runnable immediately to run the animation. - doAnswer((invocation) -> { - final Runnable action = invocation.getArgument(0); - action.run(); - return null; - }).when(mSpyImageView).postOnAnimationDelayed(any(Runnable.class), anyLong()); - + public void showMagnificationButton_windowModeAndFadingOut_verifyAnimationEndAction() { mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW); + executeFadeOutAnimation(); // Verify the end action after fade-out. final ArgumentCaptor<Runnable> endActionCaptor = ArgumentCaptor.forClass(Runnable.class); @@ -207,9 +204,6 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { final long downTime = SystemClock.uptimeMillis(); mTouchListener.onTouch(mSpyImageView, obtainMotionEvent(downTime, 0, ACTION_DOWN, 100, 100)); - - verify(mViewPropertyAnimator).cancel(); - resetAndStubMockImageViewAndAnimator(); mTouchListener.onTouch(mSpyImageView, obtainMotionEvent(downTime, downTime, ACTION_UP, 100, 100)); @@ -218,6 +212,31 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { } @Test + public void sendDownEvent_fullscreenMode_fadeOutAnimationIsNull() { + mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); + resetAndStubMockImageViewAndAnimator(); + + final long downTime = SystemClock.uptimeMillis(); + mTouchListener.onTouch(mSpyImageView, + obtainMotionEvent(downTime, 0, ACTION_DOWN, 100, 100)); + + assertNull(mFadeOutAnimation); + } + + @Test + public void sendDownEvent_fullscreenModeAndFadingOut_cancelAnimation() { + mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); + executeFadeOutAnimation(); + resetAndStubMockImageViewAndAnimator(); + + final long downTime = SystemClock.uptimeMillis(); + mTouchListener.onTouch(mSpyImageView, + obtainMotionEvent(downTime, 0, ACTION_DOWN, 100, 100)); + + verify(mViewPropertyAnimator).cancel(); + } + + @Test public void performDragging_showMagnificationButton_updateViewLayout() { mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN); resetAndStubMockImageViewAndAnimator(); @@ -229,7 +248,6 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { final long downTime = SystemClock.uptimeMillis(); mTouchListener.onTouch(mSpyImageView, obtainMotionEvent( downTime, 0, ACTION_DOWN, 100, 100)); - verify(mViewPropertyAnimator).cancel(); mTouchListener.onTouch(mSpyImageView, obtainMotionEvent(downTime, downTime, ACTION_MOVE, 100 + offset, @@ -384,6 +402,16 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { return null; }).when(mSpyImageView).post(any(Runnable.class)); doReturn(mViewPropertyAnimator).when(mSpyImageView).animate(); + doAnswer((invocation) -> { + mFadeOutAnimation = invocation.getArgument(0); + return null; + }).when(mSpyImageView).postOnAnimationDelayed(any(Runnable.class), anyLong()); + doAnswer((invocation) -> { + if (mFadeOutAnimation == invocation.getArgument(0)) { + mFadeOutAnimation = null; + } + return null; + }).when(mSpyImageView).removeCallbacks(any(Runnable.class)); } private void resetAndStubMockAnimator() { @@ -412,4 +440,10 @@ public class MagnificationModeSwitchTest extends SysuiTestCase { mMotionEvents.add(event); return event; } + + private void executeFadeOutAnimation() { + assertNotNull(mFadeOutAnimation); + mFadeOutAnimation.run(); + mFadeOutAnimation = null; + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java index ade329011b7d..02143a750cae 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java @@ -150,7 +150,7 @@ public class AppOpsControllerTest extends SysuiTestCase { mController.onOpActiveChanged( AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true); mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, - AppOpsManager.MODE_ALLOWED); + AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED); mTestableLooper.processAllMessages(); verify(mCallback).onActiveStateChanged(AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true); @@ -204,7 +204,8 @@ public class AppOpsControllerTest extends SysuiTestCase { mController.onOpActiveChanged(AppOpsManager.OP_CAMERA, TEST_UID, TEST_PACKAGE_NAME, true); mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, - TEST_UID, TEST_PACKAGE_NAME, AppOpsManager.MODE_ALLOWED); + TEST_UID, TEST_PACKAGE_NAME, AppOpsManager.OP_FLAG_SELF, + AppOpsManager.MODE_ALLOWED); assertEquals(3, mController.getActiveAppOps().size()); } @@ -215,7 +216,8 @@ public class AppOpsControllerTest extends SysuiTestCase { mController.onOpActiveChanged(AppOpsManager.OP_CAMERA, TEST_UID_OTHER, TEST_PACKAGE_NAME, true); mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, - TEST_UID, TEST_PACKAGE_NAME, AppOpsManager.MODE_ALLOWED); + TEST_UID, TEST_PACKAGE_NAME, AppOpsManager.OP_FLAG_SELF, + AppOpsManager.MODE_ALLOWED); assertEquals(2, mController.getActiveAppOpsForUser(UserHandle.getUserId(TEST_UID)).size()); assertEquals(1, @@ -246,7 +248,7 @@ public class AppOpsControllerTest extends SysuiTestCase { public void opNotedScheduledForRemoval() { mController.setBGHandler(mMockHandler); mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, - AppOpsManager.MODE_ALLOWED); + AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED); verify(mMockHandler).scheduleRemoval(any(AppOpItem.class), anyLong()); } @@ -258,7 +260,7 @@ public class AppOpsControllerTest extends SysuiTestCase { mController.onOpActiveChanged(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, true); mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, - AppOpsManager.MODE_ALLOWED); + AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED); assertFalse(mController.getActiveAppOps().isEmpty()); mController.setListening(false); @@ -272,9 +274,9 @@ public class AppOpsControllerTest extends SysuiTestCase { mController.setBGHandler(mMockHandler); mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, - AppOpsManager.MODE_ALLOWED); + AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED); mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, - AppOpsManager.MODE_ALLOWED); + AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED); // Only one post to notify subscribers verify(mMockHandler, times(1)).post(any()); @@ -288,9 +290,9 @@ public class AppOpsControllerTest extends SysuiTestCase { mController.setBGHandler(mMockHandler); mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, - AppOpsManager.MODE_ALLOWED); + AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED); mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, - AppOpsManager.MODE_ALLOWED); + AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED); // Only one post to notify subscribers verify(mMockHandler, times(2)).scheduleRemoval(any(), anyLong()); @@ -308,7 +310,7 @@ public class AppOpsControllerTest extends SysuiTestCase { AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, true); mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, - AppOpsManager.MODE_ALLOWED); + AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED); // Check that we "scheduled" the removal. Don't actually schedule until we are ready to // process messages at a later time. @@ -337,7 +339,7 @@ public class AppOpsControllerTest extends SysuiTestCase { mController.addCallback(new int[]{AppOpsManager.OP_FINE_LOCATION}, mCallback); mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, - AppOpsManager.MODE_ALLOWED); + AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED); mController.onOpActiveChanged( AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, true); @@ -366,7 +368,7 @@ public class AppOpsControllerTest extends SysuiTestCase { mController.addCallback(new int[]{AppOpsManager.OP_FINE_LOCATION}, mCallback); mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, - AppOpsManager.MODE_ALLOWED); + AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED); mController.onOpActiveChanged( AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, true); @@ -384,7 +386,7 @@ public class AppOpsControllerTest extends SysuiTestCase { AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, true); mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, - AppOpsManager.MODE_ALLOWED); + AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED); mTestableLooper.processAllMessages(); verify(mCallback).onActiveStateChanged( diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java index 19f0a15c8936..8c547b127da2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java @@ -20,6 +20,8 @@ import static com.android.systemui.util.mockito.KotlinMockitoHelpersKt.any; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.anyDouble; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -31,15 +33,19 @@ import androidx.test.filters.SmallTest; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.testing.FakeMetricsLogger; import com.android.systemui.SysuiTestCase; +import com.android.systemui.classifier.FalsingDataProvider.GestureCompleteListener; import com.android.systemui.dock.DockManagerFake; +import com.android.systemui.util.time.FakeSystemClock; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.ArrayList; +import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -62,16 +68,25 @@ public class BrightLineClassifierTest extends SysuiTestCase { @Mock private FalsingClassifier mClassifierB; private final List<MotionEvent> mMotionEventList = new ArrayList<>(); + @Mock + private HistoryTracker mHistoryTracker; + private FakeSystemClock mSystemClock = new FakeSystemClock(); + + private final FalsingClassifier.Result mFalsedResult = FalsingClassifier.Result.falsed(1, ""); + private final FalsingClassifier.Result mPassedResult = FalsingClassifier.Result.passed(1); @Before public void setup() { MockitoAnnotations.initMocks(this); + when(mClassifierA.classifyGesture(anyDouble(), anyDouble())).thenReturn(mPassedResult); + when(mClassifierB.classifyGesture(anyDouble(), anyDouble())).thenReturn(mPassedResult); mClassifiers.add(mClassifierA); mClassifiers.add(mClassifierB); when(mFalsingDataProvider.isDirty()).thenReturn(true); when(mFalsingDataProvider.getRecentMotionEvents()).thenReturn(mMotionEventList); mBrightLineFalsingManager = new BrightLineFalsingManager(mFalsingDataProvider, mDockManager, - mMetricsLogger, mClassifiers, mSingleTapClassfier, mDoubleTapClassifier, false); + mMetricsLogger, mClassifiers, mSingleTapClassfier, mDoubleTapClassifier, + mHistoryTracker, mSystemClock, false); } @Test @@ -98,20 +113,20 @@ public class BrightLineClassifierTest extends SysuiTestCase { @Test public void testIsFalseTouch_ClassifierARejects() { - when(mClassifierA.isFalseTouch()).thenReturn(true); + when(mClassifierA.classifyGesture(anyDouble(), anyDouble())).thenReturn(mFalsedResult); assertThat(mBrightLineFalsingManager.isFalseTouch(0)).isTrue(); } @Test public void testIsFalseTouch_ClassifierBRejects() { - when(mClassifierB.isFalseTouch()).thenReturn(true); + when(mClassifierB.classifyGesture(anyDouble(), anyDouble())).thenReturn(mFalsedResult); assertThat(mBrightLineFalsingManager.isFalseTouch(0)).isTrue(); } @Test public void testIsFalseTouch_FaceAuth() { // Even when the classifiers report a false, we should allow. - when(mClassifierA.isFalseTouch()).thenReturn(true); + when(mClassifierA.classifyGesture(anyDouble(), anyDouble())).thenReturn(mPassedResult); when(mFalsingDataProvider.isJustUnlockedWithFace()).thenReturn(true); assertThat(mBrightLineFalsingManager.isFalseTouch(0)).isFalse(); @@ -120,7 +135,7 @@ public class BrightLineClassifierTest extends SysuiTestCase { @Test public void testIsFalseTouch_Docked() { // Even when the classifiers report a false, we should allow. - when(mClassifierA.isFalseTouch()).thenReturn(true); + when(mClassifierA.classifyGesture(anyDouble(), anyDouble())).thenReturn(mPassedResult); mDockManager.setIsDocked(true); assertThat(mBrightLineFalsingManager.isFalseTouch(0)).isFalse(); @@ -128,37 +143,51 @@ public class BrightLineClassifierTest extends SysuiTestCase { @Test public void testIsFalseTap_BasicCheck() { - when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(false); + when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(mFalsedResult); assertThat(mBrightLineFalsingManager.isFalseTap(false)).isTrue(); - when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(true); + when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(mPassedResult); assertThat(mBrightLineFalsingManager.isFalseTap(false)).isFalse(); } @Test public void testIsFalseTap_RobustCheck_NoFaceAuth() { - when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(true); + when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(mPassedResult); mFalsingDataProvider.setJustUnlockedWithFace(false); assertThat(mBrightLineFalsingManager.isFalseTap(true)).isTrue(); } @Test public void testIsFalseTap_RobustCheck_FaceAuth() { - when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(true); + when(mSingleTapClassfier.isTap(mMotionEventList)).thenReturn(mPassedResult); when(mFalsingDataProvider.isJustUnlockedWithFace()).thenReturn(true); assertThat(mBrightLineFalsingManager.isFalseTap(true)).isFalse(); } @Test public void testIsFalseDoubleTap() { - when(mDoubleTapClassifier.isFalseTouch()).thenReturn(false); + when(mDoubleTapClassifier.classifyGesture()).thenReturn(mPassedResult); assertThat(mBrightLineFalsingManager.isFalseDoubleTap()).isFalse(); - when(mDoubleTapClassifier.isFalseTouch()).thenReturn(true); + when(mDoubleTapClassifier.classifyGesture()).thenReturn(mFalsedResult); assertThat(mBrightLineFalsingManager.isFalseDoubleTap()).isTrue(); } + + @Test + public void testHistory() { + ArgumentCaptor<GestureCompleteListener> gestureCompleteListenerCaptor = + ArgumentCaptor.forClass(GestureCompleteListener.class); + + verify(mFalsingDataProvider).addGestureCompleteListener( + gestureCompleteListenerCaptor.capture()); + + GestureCompleteListener gestureCompleteListener = gestureCompleteListenerCaptor.getValue(); + gestureCompleteListener.onGestureComplete(); + + verify(mHistoryTracker).addResults(any(Collection.class), eq(mSystemClock.uptimeMillis())); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/DiagonalClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/DiagonalClassifierTest.java index 7659db8cc9ef..dafc87133d39 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/DiagonalClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/DiagonalClassifierTest.java @@ -69,93 +69,93 @@ public class DiagonalClassifierTest extends ClassifierTest { @Test public void testPass_UnknownAngle() { when(mDataProvider.getAngle()).thenReturn(Float.MAX_VALUE); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test public void testPass_VerticalSwipe() { when(mDataProvider.getAngle()).thenReturn(UP_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.getAngle()).thenReturn(DOWN_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test public void testPass_MostlyVerticalSwipe() { when(mDataProvider.getAngle()).thenReturn(UP_IN_RADIANS + 2 * FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.getAngle()).thenReturn(UP_IN_RADIANS - 2 * FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.getAngle()).thenReturn(DOWN_IN_RADIANS + 2 * FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.getAngle()).thenReturn(DOWN_IN_RADIANS - 2 * FIVE_DEG_IN_RADIANS * 2); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test public void testPass_BarelyVerticalSwipe() { when(mDataProvider.getAngle()).thenReturn( UP_IN_RADIANS - FORTY_FIVE_DEG_IN_RADIANS + 2 * FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.getAngle()).thenReturn( UP_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS - 2 * FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.getAngle()).thenReturn( DOWN_IN_RADIANS - FORTY_FIVE_DEG_IN_RADIANS + 2 * FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.getAngle()).thenReturn( DOWN_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS - 2 * FIVE_DEG_IN_RADIANS * 2); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test public void testPass_HorizontalSwipe() { when(mDataProvider.getAngle()).thenReturn(RIGHT_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.getAngle()).thenReturn(LEFT_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test public void testPass_MostlyHorizontalSwipe() { when(mDataProvider.getAngle()).thenReturn(RIGHT_IN_RADIANS + 2 * FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.getAngle()).thenReturn(RIGHT_IN_RADIANS - 2 * FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.getAngle()).thenReturn(LEFT_IN_RADIANS + 2 * FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.getAngle()).thenReturn(LEFT_IN_RADIANS - 2 * FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test public void testPass_BarelyHorizontalSwipe() { when(mDataProvider.getAngle()).thenReturn( RIGHT_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS - 2 * FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.getAngle()).thenReturn( LEFT_IN_RADIANS - FORTY_FIVE_DEG_IN_RADIANS + 2 * FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.getAngle()).thenReturn( LEFT_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS - 2 * FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.getAngle()).thenReturn( RIGHT_IN_RADIANS - FORTY_FIVE_DEG_IN_RADIANS + 2 * FIVE_DEG_IN_RADIANS * 2); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -163,12 +163,12 @@ public class DiagonalClassifierTest extends ClassifierTest { when(mDataProvider.getInteractionType()).thenReturn(LEFT_AFFORDANCE); when(mDataProvider.getAngle()).thenReturn( RIGHT_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.getInteractionType()).thenReturn(RIGHT_AFFORDANCE); when(mDataProvider.getAngle()).thenReturn( LEFT_IN_RADIANS - FORTY_FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); // This classifier may return false for other angles, but these are the only // two that actually matter, as affordances generally only travel in these two directions. @@ -182,37 +182,37 @@ public class DiagonalClassifierTest extends ClassifierTest { when(mDataProvider.isVertical()).thenReturn(false); when(mDataProvider.getAngle()).thenReturn( RIGHT_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS - FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.getAngle()).thenReturn( UP_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS + FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.getAngle()).thenReturn( LEFT_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS - FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.getAngle()).thenReturn( DOWN_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS + FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); // Vertical Swipes when(mDataProvider.isVertical()).thenReturn(true); when(mDataProvider.getAngle()).thenReturn( RIGHT_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS + FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.getAngle()).thenReturn( UP_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS - FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.getAngle()).thenReturn( LEFT_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS + FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.getAngle()).thenReturn( DOWN_IN_RADIANS + FORTY_FIVE_DEG_IN_RADIANS - FIVE_DEG_IN_RADIANS); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java index 013fa369e876..f6c14240c8f4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/DistanceClassifierTest.java @@ -51,32 +51,32 @@ public class DistanceClassifierTest extends ClassifierTest { @Test public void testPass_noPointer() { - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test public void testPass_fling() { mClassifier.onTouchEvent(appendDownEvent(1, 1)); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); mClassifier.onTouchEvent(appendMoveEvent(1, 40)); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); mClassifier.onTouchEvent(appendUpEvent(1, 80)); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test public void testFail_flingShort() { mClassifier.onTouchEvent(appendDownEvent(1, 1)); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); mClassifier.onTouchEvent(appendMoveEvent(1, 2)); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); mClassifier.onTouchEvent(appendUpEvent(1, 10)); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -84,26 +84,26 @@ public class DistanceClassifierTest extends ClassifierTest { // These events, in testing, result in a fling that falls just short of the threshold. mClassifier.onTouchEvent(appendDownEvent(1, 1, 1)); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); mClassifier.onTouchEvent(appendMoveEvent(1, 15, 2)); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); mClassifier.onTouchEvent(appendMoveEvent(1, 16, 3)); mClassifier.onTouchEvent(appendMoveEvent(1, 17, 300)); mClassifier.onTouchEvent(appendMoveEvent(1, 18, 301)); mClassifier.onTouchEvent(appendUpEvent(1, 19, 501)); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test public void testPass_swipe() { mClassifier.onTouchEvent(appendDownEvent(1, 1)); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); mClassifier.onTouchEvent(appendMoveEvent(1, mDataProvider.getYdpi() * 3, 3)); mClassifier.onTouchEvent(appendUpEvent(1, mDataProvider.getYdpi() * 3, 300)); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/DoubleTapClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/DoubleTapClassifierTest.java index 4c4108a0cb90..17c2700c5bda 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/DoubleTapClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/DoubleTapClassifierTest.java @@ -55,6 +55,9 @@ public class DoubleTapClassifierTest extends ClassifierTest { private SingleTapClassifier mSingleTapClassifier; private DoubleTapClassifier mClassifier; + private final FalsingClassifier.Result mFalsedResult = FalsingClassifier.Result.falsed(1, ""); + private final FalsingClassifier.Result mPassedResult = FalsingClassifier.Result.passed(1); + @Before public void setup() { super.setup(); @@ -77,17 +80,17 @@ public class DoubleTapClassifierTest extends ClassifierTest { @Test public void testSingleTap() { - when(mSingleTapClassifier.isTap(anyList())).thenReturn(true); + when(mSingleTapClassifier.isTap(anyList())).thenReturn(mFalsedResult); addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, TOUCH_SLOP, 1); - boolean result = mClassifier.isFalseTouch(); + boolean result = mClassifier.classifyGesture().isFalse(); assertThat("Single tap recognized as a valid double tap", result, is(true)); } @Test public void testDoubleTap() { - when(mSingleTapClassifier.isTap(anyList())).thenReturn(true); + when(mSingleTapClassifier.isTap(anyList())).thenReturn(mPassedResult); addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1); @@ -97,13 +100,13 @@ public class DoubleTapClassifierTest extends ClassifierTest { addMotionEvent(2, 2, MotionEvent.ACTION_DOWN, TOUCH_SLOP, TOUCH_SLOP); addMotionEvent(2, 3, MotionEvent.ACTION_UP, TOUCH_SLOP, TOUCH_SLOP); - boolean result = mClassifier.isFalseTouch(); - assertThat(mClassifier.getReason(), result, is(false)); + FalsingClassifier.Result result = mClassifier.classifyGesture(); + assertThat(result.getReason(), result.isFalse(), is(false)); } @Test public void testBadFirstTap() { - when(mSingleTapClassifier.isTap(anyList())).thenReturn(false, true); + when(mSingleTapClassifier.isTap(anyList())).thenReturn(mPassedResult, mFalsedResult); addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1); @@ -113,13 +116,13 @@ public class DoubleTapClassifierTest extends ClassifierTest { addMotionEvent(2, 2, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(2, 3, MotionEvent.ACTION_UP, 1, 1); - boolean result = mClassifier.isFalseTouch(); + boolean result = mClassifier.classifyGesture().isFalse(); assertThat("Bad first touch allowed", result, is(true)); } @Test public void testBadSecondTap() { - when(mSingleTapClassifier.isTap(anyList())).thenReturn(true, false); + when(mSingleTapClassifier.isTap(anyList())).thenReturn(mFalsedResult, mPassedResult); addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1); @@ -129,13 +132,13 @@ public class DoubleTapClassifierTest extends ClassifierTest { addMotionEvent(2, 2, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(2, 3, MotionEvent.ACTION_UP, 1, 1); - boolean result = mClassifier.isFalseTouch(); + boolean result = mClassifier.classifyGesture().isFalse(); assertThat("Bad second touch allowed", result, is(true)); } @Test public void testBadTouchSlop() { - when(mSingleTapClassifier.isTap(anyList())).thenReturn(true); + when(mSingleTapClassifier.isTap(anyList())).thenReturn(mFalsedResult); addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1); @@ -145,13 +148,13 @@ public class DoubleTapClassifierTest extends ClassifierTest { addMotionEvent(2, 2, MotionEvent.ACTION_DOWN, TOUCH_SLOP + 1, TOUCH_SLOP); addMotionEvent(2, 3, MotionEvent.ACTION_UP, TOUCH_SLOP, TOUCH_SLOP + 1); - boolean result = mClassifier.isFalseTouch(); + boolean result = mClassifier.classifyGesture().isFalse(); assertThat("Sloppy second touch allowed", result, is(true)); } @Test public void testBadTouchSlow() { - when(mSingleTapClassifier.isTap(anyList())).thenReturn(true); + when(mSingleTapClassifier.isTap(anyList())).thenReturn(mFalsedResult); addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1); @@ -163,7 +166,7 @@ public class DoubleTapClassifierTest extends ClassifierTest { addMotionEvent(DOUBLE_TAP_TIMEOUT_MS + 1, DOUBLE_TAP_TIMEOUT_MS + 2, MotionEvent.ACTION_UP, 1, 1); - boolean result = mClassifier.isFalseTouch(); + boolean result = mClassifier.classifyGesture().isFalse(); assertThat("Slow second tap allowed", result, is(true)); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/HistoryTrackerTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/HistoryTrackerTest.java new file mode 100644 index 000000000000..01cce3579b0c --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/HistoryTrackerTest.java @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.classifier; + +import static com.google.common.truth.Truth.assertThat; + +import android.testing.AndroidTestingRunner; + +import androidx.test.filters.SmallTest; + +import com.android.systemui.SysuiTestCase; +import com.android.systemui.util.time.FakeSystemClock; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.MockitoAnnotations; + +import java.util.Collections; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +public class HistoryTrackerTest extends SysuiTestCase { + + private FakeSystemClock mSystemClock = new FakeSystemClock(); + + private HistoryTracker mHistoryTracker; + + @Before + public void setup() { + MockitoAnnotations.initMocks(this); + mHistoryTracker = new HistoryTracker(mSystemClock); + } + + @Test + public void testNoDataNoPenalty() { + assertThat(mHistoryTracker.falsePenalty()).isEqualTo(0); + assertThat(mHistoryTracker.falseConfidence()).isEqualTo(0); + } + + @Test + public void testOneResultFullConfidence() { + addResult(true, 1); + assertThat(mHistoryTracker.falsePenalty()).isEqualTo(1); + assertThat(mHistoryTracker.falseConfidence()).isEqualTo(1); + } + + @Test + public void testMultipleResultsSameTimestamp() { + addResult(true, 1); + addResult(false, 1); + + assertThat(mHistoryTracker.falsePenalty()).isEqualTo(0.5); + assertThat(mHistoryTracker.falseConfidence()).isEqualTo(0.5); + } + + @Test + public void testMultipleConfidences() { + addResult(true, 1); + addResult(true, 0); + + assertThat(mHistoryTracker.falsePenalty()).isEqualTo(0.75); + assertThat(mHistoryTracker.falseConfidence()).isEqualTo(.75); + } + + @Test + public void testDecay() { + addResult(true, 1); + + assertThat(mHistoryTracker.falsePenalty()).isEqualTo(1); + assertThat(mHistoryTracker.falseConfidence()).isEqualTo(1); + + mSystemClock.advanceTime(1000); + + assertThat(mHistoryTracker.falsePenalty()).isWithin(0.01).of(0.1); + assertThat(mHistoryTracker.falseConfidence()).isEqualTo(1); + } + + @Test + public void testMultipleResultsDifferentTimestamp() { + addResult(true, 1); + mSystemClock.advanceTime(1000); + addResult(false, .5); + + assertThat(mHistoryTracker.falsePenalty()).isWithin(0.01).of(0.17); + assertThat(mHistoryTracker.falseConfidence()).isEqualTo(0.625); + } + + @Test + public void testCompleteDecay() { + addResult(true, 1); + + assertThat(mHistoryTracker.falsePenalty()).isEqualTo(1); + assertThat(mHistoryTracker.falseConfidence()).isEqualTo(1); + + mSystemClock.advanceTime(2999); + + assertThat(mHistoryTracker.falsePenalty()).isGreaterThan(0); + assertThat(mHistoryTracker.falseConfidence()).isEqualTo(1); + + mSystemClock.advanceTime(1); + + assertThat(mHistoryTracker.falsePenalty()).isEqualTo(0); + assertThat(mHistoryTracker.falseConfidence()).isEqualTo(0); + } + + private void addResult(boolean falsed, double confidence) { + mHistoryTracker.addResults(Collections.singletonList( + falsed + ? FalsingClassifier.Result.falsed(confidence, "test") + : FalsingClassifier.Result.passed(confidence)), + mSystemClock.uptimeMillis()); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/PointerCountClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/PointerCountClassifierTest.java index ee289b5b922d..76802f4de14f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/PointerCountClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/PointerCountClassifierTest.java @@ -50,13 +50,13 @@ public class PointerCountClassifierTest extends ClassifierTest { @Test public void testPass_noPointer() { - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test public void testPass_singlePointer() { mClassifier.onTouchEvent(appendDownEvent(1, 1)); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -72,7 +72,7 @@ public class PointerCountClassifierTest extends ClassifierTest { 0, 0); mClassifier.onTouchEvent(motionEvent); motionEvent.recycle(); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -89,6 +89,6 @@ public class PointerCountClassifierTest extends ClassifierTest { mClassifier.onTouchEvent(motionEvent); motionEvent.recycle(); getDataProvider().setInteractionType(QUICK_SETTINGS); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/ProximityClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/ProximityClassifierTest.java index 38b025f675ee..ba8ca9abc2d7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/ProximityClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/ProximityClassifierTest.java @@ -50,12 +50,16 @@ public class ProximityClassifierTest extends ClassifierTest { private DistanceClassifier mDistanceClassifier; private FalsingClassifier mClassifier; + private final FalsingClassifier.Result mFalsedResult = + FalsingClassifier.Result.falsed(1, "test"); + private final FalsingClassifier.Result mPassedResult = FalsingClassifier.Result.passed(1); + @Before public void setup() { super.setup(); MockitoAnnotations.initMocks(this); when(mDataProvider.getInteractionType()).thenReturn(GENERIC); - when(mDistanceClassifier.isLongSwipe()).thenReturn(false); + when(mDistanceClassifier.isLongSwipe()).thenReturn(mFalsedResult); mClassifier = new ProximityClassifier( mDistanceClassifier, mDataProvider, new DeviceConfigProxyFake()); } @@ -69,7 +73,7 @@ public class ProximityClassifierTest extends ClassifierTest { public void testPass_uncovered() { touchDown(); touchUp(10); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -78,7 +82,7 @@ public class ProximityClassifierTest extends ClassifierTest { mClassifier.onProximityEvent(createSensorEvent(true, 1)); mClassifier.onProximityEvent(createSensorEvent(false, 2)); touchUp(20); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -88,7 +92,7 @@ public class ProximityClassifierTest extends ClassifierTest { mClassifier.onProximityEvent(createSensorEvent(true, 1)); mClassifier.onProximityEvent(createSensorEvent(false, 11)); touchUp(10); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -97,7 +101,7 @@ public class ProximityClassifierTest extends ClassifierTest { mClassifier.onProximityEvent(createSensorEvent(true, 1)); mClassifier.onProximityEvent(createSensorEvent(false, 11)); touchUp(10); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -108,7 +112,7 @@ public class ProximityClassifierTest extends ClassifierTest { mClassifier.onProximityEvent(createSensorEvent(true, 96)); mClassifier.onProximityEvent(createSensorEvent(false, 100)); touchUp(100); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -117,8 +121,8 @@ public class ProximityClassifierTest extends ClassifierTest { mClassifier.onProximityEvent(createSensorEvent(true, 1)); mClassifier.onProximityEvent(createSensorEvent(false, 11)); touchUp(10); - when(mDistanceClassifier.isLongSwipe()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(false)); + when(mDistanceClassifier.isLongSwipe()).thenReturn(mPassedResult); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } private void touchDown() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/SingleTapClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/SingleTapClassifierTest.java index 941e12e475f9..62c876f99a15 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/SingleTapClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/SingleTapClassifierTest.java @@ -70,14 +70,14 @@ public class SingleTapClassifierTest extends ClassifierTest { addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, TOUCH_SLOP, 1); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); mMotionEvents.clear(); addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, -TOUCH_SLOP + 2, 1); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @@ -86,14 +86,14 @@ public class SingleTapClassifierTest extends ClassifierTest { addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, TOUCH_SLOP); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); mMotionEvents.clear(); addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, -TOUCH_SLOP + 2); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @@ -102,14 +102,14 @@ public class SingleTapClassifierTest extends ClassifierTest { addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, TOUCH_SLOP + 1, 1); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); mMotionEvents.clear(); addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, -TOUCH_SLOP - 1, 1); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @@ -118,14 +118,14 @@ public class SingleTapClassifierTest extends ClassifierTest { addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, TOUCH_SLOP + 1); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); mMotionEvents.clear(); addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, -TOUCH_SLOP - 1); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -134,7 +134,7 @@ public class SingleTapClassifierTest extends ClassifierTest { addMotionEvent(0, 1, MotionEvent.ACTION_MOVE, 1, TOUCH_SLOP + 1); addMotionEvent(0, 2, MotionEvent.ACTION_UP, 1, 1); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -142,12 +142,12 @@ public class SingleTapClassifierTest extends ClassifierTest { addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, 1); - assertThat(mClassifier.isTap(mMotionEvents), is(true)); + assertThat(mClassifier.isTap(mMotionEvents).isFalse(), is(false)); addMotionEvent(0, 0, MotionEvent.ACTION_DOWN, 1, 1); addMotionEvent(0, 1, MotionEvent.ACTION_UP, 1, TOUCH_SLOP + 1); - assertThat(mClassifier.isTap(mMotionEvents), is(false)); + assertThat(mClassifier.isTap(mMotionEvents).isFalse(), is(true)); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/TypeClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/TypeClassifierTest.java index 6b9bb4fedd16..4a896a8574b9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/TypeClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/TypeClassifierTest.java @@ -61,10 +61,10 @@ public class TypeClassifierTest extends ClassifierTest { when(mDataProvider.isUp()).thenReturn(false); when(mDataProvider.isRight()).thenReturn(false); // right should cause no effect. - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.isRight()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -73,11 +73,11 @@ public class TypeClassifierTest extends ClassifierTest { when(mDataProvider.isVertical()).thenReturn(false); when(mDataProvider.isUp()).thenReturn(false); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.isVertical()).thenReturn(true); when(mDataProvider.isUp()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -87,10 +87,10 @@ public class TypeClassifierTest extends ClassifierTest { when(mDataProvider.isUp()).thenReturn(false); when(mDataProvider.isRight()).thenReturn(false); // right should cause no effect. - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.isRight()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -99,11 +99,11 @@ public class TypeClassifierTest extends ClassifierTest { when(mDataProvider.isVertical()).thenReturn(false); when(mDataProvider.isUp()).thenReturn(false); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.isVertical()).thenReturn(true); when(mDataProvider.isUp()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -113,10 +113,10 @@ public class TypeClassifierTest extends ClassifierTest { when(mDataProvider.isUp()).thenReturn(false); when(mDataProvider.isRight()).thenReturn(false); // right should cause no effect. - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.isRight()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -125,11 +125,11 @@ public class TypeClassifierTest extends ClassifierTest { when(mDataProvider.isVertical()).thenReturn(false); when(mDataProvider.isUp()).thenReturn(false); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.isVertical()).thenReturn(true); when(mDataProvider.isUp()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -139,19 +139,19 @@ public class TypeClassifierTest extends ClassifierTest { when(mDataProvider.isUp()).thenReturn(false); // up and right should cause no effect. when(mDataProvider.isRight()).thenReturn(false); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.isUp()).thenReturn(true); when(mDataProvider.isRight()).thenReturn(false); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.isUp()).thenReturn(false); when(mDataProvider.isRight()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.isUp()).thenReturn(true); when(mDataProvider.isRight()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -161,19 +161,19 @@ public class TypeClassifierTest extends ClassifierTest { when(mDataProvider.isUp()).thenReturn(false); // up and right should cause no effect. when(mDataProvider.isRight()).thenReturn(false); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.isUp()).thenReturn(true); when(mDataProvider.isRight()).thenReturn(false); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.isUp()).thenReturn(false); when(mDataProvider.isRight()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.isUp()).thenReturn(true); when(mDataProvider.isRight()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @@ -185,10 +185,10 @@ public class TypeClassifierTest extends ClassifierTest { when(mDataProvider.isRight()).thenReturn(false); // right should cause no effect. - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.isRight()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -197,15 +197,15 @@ public class TypeClassifierTest extends ClassifierTest { when(mDataProvider.isVertical()).thenReturn(false); when(mDataProvider.isUp()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.isVertical()).thenReturn(true); when(mDataProvider.isUp()).thenReturn(false); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.isVertical()).thenReturn(false); when(mDataProvider.isUp()).thenReturn(false); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -216,10 +216,10 @@ public class TypeClassifierTest extends ClassifierTest { when(mDataProvider.isRight()).thenReturn(false); // right should cause no effect. - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.isRight()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -228,15 +228,15 @@ public class TypeClassifierTest extends ClassifierTest { when(mDataProvider.isVertical()).thenReturn(false); when(mDataProvider.isUp()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.isVertical()).thenReturn(true); when(mDataProvider.isUp()).thenReturn(false); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.isVertical()).thenReturn(false); when(mDataProvider.isUp()).thenReturn(false); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -247,10 +247,10 @@ public class TypeClassifierTest extends ClassifierTest { when(mDataProvider.isVertical()).thenReturn(false); // vertical should cause no effect. - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.isVertical()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -259,15 +259,15 @@ public class TypeClassifierTest extends ClassifierTest { when(mDataProvider.isRight()).thenReturn(false); when(mDataProvider.isUp()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.isRight()).thenReturn(true); when(mDataProvider.isUp()).thenReturn(false); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.isRight()).thenReturn(false); when(mDataProvider.isUp()).thenReturn(false); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -278,10 +278,10 @@ public class TypeClassifierTest extends ClassifierTest { when(mDataProvider.isVertical()).thenReturn(false); // vertical should cause no effect. - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); when(mDataProvider.isVertical()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -290,14 +290,14 @@ public class TypeClassifierTest extends ClassifierTest { when(mDataProvider.isUp()).thenReturn(true); when(mDataProvider.isRight()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.isUp()).thenReturn(false); when(mDataProvider.isRight()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); when(mDataProvider.isUp()).thenReturn(false); when(mDataProvider.isRight()).thenReturn(true); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java index 339dd9e9e6d2..09bee128c673 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/ZigZagClassifierTest.java @@ -51,11 +51,11 @@ public class ZigZagClassifierTest extends ClassifierTest { @Test public void testPass_fewTouchesVertical() { - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); appendMoveEvent(0, 0); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); appendMoveEvent(0, 100); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -63,16 +63,16 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(0, 100); appendMoveEvent(0, 200); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test public void testPass_fewTouchesHorizontal() { - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); appendMoveEvent(0, 0); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); appendMoveEvent(100, 0); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -80,7 +80,7 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(100, 0); appendMoveEvent(200, 0); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @@ -89,7 +89,7 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(0, 100); appendMoveEvent(0, 1); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -97,7 +97,7 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(100, 0); appendMoveEvent(1, 0); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -105,7 +105,7 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(10, 10); appendMoveEvent(20, 20); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -115,7 +115,7 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(5, 100); appendMoveEvent(-5, 200); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -125,7 +125,7 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(100, 5); appendMoveEvent(200, -5); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); } @Test @@ -135,7 +135,7 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(6, 10); appendMoveEvent(-6, 20); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -145,7 +145,7 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(10, 5); appendMoveEvent(20, -5); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -153,25 +153,25 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(100, 5); appendMoveEvent(200, 10); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(100, 0); appendMoveEvent(200, 10); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(100, -10); appendMoveEvent(200, 10); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(100, -10); appendMoveEvent(200, 50); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -179,25 +179,25 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(10, 50); appendMoveEvent(8, 100); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(1, 800); appendMoveEvent(2, 900); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(-10, 600); appendMoveEvent(30, 700); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(40, 100); appendMoveEvent(0, 101); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -205,25 +205,25 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(-10, 50); appendMoveEvent(-24, 100); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(-20, 800); appendMoveEvent(-20, 900); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(30, 600); appendMoveEvent(-10, 700); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(-80, 100); appendMoveEvent(-10, 101); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -231,25 +231,25 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(-120, 10); appendMoveEvent(-200, 20); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(-20, 8); appendMoveEvent(-40, 2); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(-500, -2); appendMoveEvent(-600, 70); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(-80, 100); appendMoveEvent(-100, 1); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -257,25 +257,25 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(-120, -10); appendMoveEvent(-200, -20); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(-20, -8); appendMoveEvent(-40, -2); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(-500, 2); appendMoveEvent(-600, -70); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(-80, -100); appendMoveEvent(-100, -1); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -283,25 +283,25 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(-12, -20); appendMoveEvent(-20, -40); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(-20, -130); appendMoveEvent(-40, -260); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(1, -100); appendMoveEvent(-6, -200); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(-80, -100); appendMoveEvent(-10, -110); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -309,25 +309,25 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(12, -20); appendMoveEvent(20, -40); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(20, -130); appendMoveEvent(40, -260); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(-1, -100); appendMoveEvent(6, -200); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(80, -100); appendMoveEvent(10, -110); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test @@ -335,25 +335,25 @@ public class ZigZagClassifierTest extends ClassifierTest { appendMoveEvent(0, 0); appendMoveEvent(120, -20); appendMoveEvent(200, -40); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(200, -13); appendMoveEvent(400, -30); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(100, 10); appendMoveEvent(600, -20); - assertThat(mClassifier.isFalseTouch(), is(false)); + assertThat(mClassifier.classifyGesture().isFalse(), is(false)); resetDataProvider(); appendMoveEvent(0, 0); appendMoveEvent(80, -100); appendMoveEvent(100, -1); - assertThat(mClassifier.isFalseTouch(), is(true)); + assertThat(mClassifier.classifyGesture().isFalse(), is(true)); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java index 00598814be5a..2320f4ee2b60 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java @@ -31,7 +31,6 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import android.app.AlarmManager; import android.database.ContentObserver; import android.hardware.Sensor; import android.hardware.display.AmbientDisplayConfiguration; @@ -65,8 +64,6 @@ import java.util.function.Consumer; public class DozeSensorsTest extends SysuiTestCase { @Mock - private AlarmManager mAlarmManager; - @Mock private AsyncSensorManager mSensorManager; @Mock private DozeParameters mDozeParameters; @@ -79,8 +76,6 @@ public class DozeSensorsTest extends SysuiTestCase { @Mock private Consumer<Boolean> mProxCallback; @Mock - private AlwaysOnDisplayPolicy mAlwaysOnDisplayPolicy; - @Mock private TriggerSensor mTriggerSensor; @Mock private DozeLog mDozeLog; @@ -115,7 +110,7 @@ public class DozeSensorsTest extends SysuiTestCase { @Test public void testSensorDebounce() { - mDozeSensors.setListening(true); + mDozeSensors.setListening(true, true); mWakeLockScreenListener.onSensorChanged(mock(SensorManagerPlugin.SensorEvent.class)); mTestableLooper.processAllMessages(); @@ -133,7 +128,7 @@ public class DozeSensorsTest extends SysuiTestCase { @Test public void testSetListening_firstTrue_registerSettingsObserver() { verify(mSensorManager, never()).registerListener(any(), any(Sensor.class), anyInt()); - mDozeSensors.setListening(true); + mDozeSensors.setListening(true, true); verify(mTriggerSensor).registerSettingsObserver(any(ContentObserver.class)); } @@ -141,8 +136,8 @@ public class DozeSensorsTest extends SysuiTestCase { @Test public void testSetListening_twiceTrue_onlyRegisterSettingsObserverOnce() { verify(mSensorManager, never()).registerListener(any(), any(Sensor.class), anyInt()); - mDozeSensors.setListening(true); - mDozeSensors.setListening(true); + mDozeSensors.setListening(true, true); + mDozeSensors.setListening(true, true); verify(mTriggerSensor, times(1)).registerSettingsObserver(any(ContentObserver.class)); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java index 4bbba56395f8..27187a85c040 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java @@ -154,6 +154,7 @@ public class DozeTriggersTest extends SysuiTestCase { clearInvocations(mSensors); mTriggers.transitionTo(DozeMachine.State.DOZE_PULSING, DozeMachine.State.DOZE_PULSE_DONE); + mTriggers.transitionTo(DozeMachine.State.DOZE_PULSE_DONE, DozeMachine.State.DOZE_AOD); waitForSensorManager(); verify(mSensors).requestTriggerSensor(any(), eq(mTapSensor)); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java index 32c360f3d2cb..96f46eaaf156 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java @@ -60,7 +60,7 @@ import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.wm.shell.pip.Pip; -import com.android.wm.shell.splitscreen.SplitScreen; +import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import org.junit.After; import org.junit.Before; @@ -98,7 +98,7 @@ public class NavigationBarControllerTest extends SysuiTestCase { mock(BroadcastDispatcher.class), mock(CommandQueue.class), Optional.of(mock(Pip.class)), - Optional.of(mock(SplitScreen.class)), + Optional.of(mock(LegacySplitScreen.class)), Optional.of(mock(Recents.class)), () -> mock(StatusBar.class), mock(ShadeController.class), diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java index 57eac74401dd..851d4862dbbb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java @@ -77,7 +77,7 @@ import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.utils.leaks.LeakCheckedTest; import com.android.wm.shell.pip.Pip; -import com.android.wm.shell.splitscreen.SplitScreen; +import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import org.junit.Before; import org.junit.Rule; @@ -225,7 +225,7 @@ public class NavigationBarTest extends SysuiTestCase { mBroadcastDispatcher, mCommandQueue, Optional.of(mock(Pip.class)), - Optional.of(mock(SplitScreen.class)), + Optional.of(mock(LegacySplitScreen.class)), Optional.of(mock(Recents.class)), () -> mock(StatusBar.class), mock(ShadeController.class), diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt index 3e834986e383..a8b305614a4a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt @@ -343,6 +343,83 @@ class PrivacyItemControllerTest : SysuiTestCase() { assertTrue(values[values.size - 1].contains(expected.toLog())) } + @Test + fun testListRequestedForAllUsers() { + privacyItemController.addCallback(callback) + executor.runAllReady() + verify(appOpsController).getActiveAppOpsForUser(UserHandle.USER_ALL) + } + + @Test + fun testListFilterCurrentUser() { + val otherUser = CURRENT_USER_ID + 1 + val otherUserUid = otherUser * UserHandle.PER_USER_RANGE + `when`(userTracker.userProfiles).thenReturn(listOf(UserInfo(otherUser, "", 0))) + + doReturn(listOf( + AppOpItem(AppOpsManager.OP_COARSE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, 0), + AppOpItem(AppOpsManager.OP_CAMERA, otherUserUid, TEST_PACKAGE_NAME, 0)) + ).`when`(appOpsController).getActiveAppOpsForUser(anyInt()) + + privacyItemController.userTrackerCallback.onUserChanged(otherUser, mContext) + executor.runAllReady() + + privacyItemController.addCallback(callback) + executor.runAllReady() + + verify(callback).onPrivacyItemsChanged(capture(argCaptor)) + + assertEquals(1, argCaptor.value.size) + assertEquals(PrivacyType.TYPE_CAMERA, argCaptor.value[0].privacyType) + assertEquals(otherUserUid, argCaptor.value[0].application.uid) + } + + @Test + fun testAlwaysGetPhoneCameraOps() { + val otherUser = CURRENT_USER_ID + 1 + `when`(userTracker.userProfiles).thenReturn(listOf(UserInfo(otherUser, "", 0))) + + doReturn(listOf( + AppOpItem(AppOpsManager.OP_COARSE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, 0), + AppOpItem(AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, 0), + AppOpItem(AppOpsManager.OP_PHONE_CALL_CAMERA, TEST_UID, TEST_PACKAGE_NAME, 0)) + ).`when`(appOpsController).getActiveAppOpsForUser(anyInt()) + + privacyItemController.userTrackerCallback.onUserChanged(otherUser, mContext) + executor.runAllReady() + + privacyItemController.addCallback(callback) + executor.runAllReady() + + verify(callback).onPrivacyItemsChanged(capture(argCaptor)) + + assertEquals(1, argCaptor.value.size) + assertEquals(PrivacyType.TYPE_CAMERA, argCaptor.value[0].privacyType) + } + + @Test + fun testAlwaysGetPhoneMicOps() { + val otherUser = CURRENT_USER_ID + 1 + `when`(userTracker.userProfiles).thenReturn(listOf(UserInfo(otherUser, "", 0))) + + doReturn(listOf( + AppOpItem(AppOpsManager.OP_COARSE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, 0), + AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, TEST_PACKAGE_NAME, 0), + AppOpItem(AppOpsManager.OP_PHONE_CALL_MICROPHONE, TEST_UID, TEST_PACKAGE_NAME, 0)) + ).`when`(appOpsController).getActiveAppOpsForUser(anyInt()) + + privacyItemController.userTrackerCallback.onUserChanged(otherUser, mContext) + executor.runAllReady() + + privacyItemController.addCallback(callback) + executor.runAllReady() + + verify(callback).onPrivacyItemsChanged(capture(argCaptor)) + + assertEquals(1, argCaptor.value.size) + assertEquals(PrivacyType.TYPE_MICROPHONE, argCaptor.value[0].privacyType) + } + private fun changeMicCamera(value: Boolean?) = changeProperty(MIC_CAMERA, value) private fun changeAll(value: Boolean?) = changeProperty(ALL_INDICATORS, value) diff --git a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.java index 0c3db57f1a2c..b3176ddeaf65 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.java @@ -41,7 +41,7 @@ import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.StatusBar; import com.android.wm.shell.pip.Pip; -import com.android.wm.shell.splitscreen.SplitScreen; +import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import org.junit.Before; import org.junit.Test; @@ -70,7 +70,7 @@ public class OverviewProxyServiceTest extends SysuiTestCase { @Mock private NavigationModeController mMockNavModeController; @Mock private NotificationShadeWindowController mMockStatusBarWinController; @Mock private Optional<Pip> mMockPipOptional; - @Mock private Optional<SplitScreen> mMockSplitScreenOptional; + @Mock private Optional<LegacySplitScreen> mMockSplitScreenOptional; @Mock private Optional<Lazy<StatusBar>> mMockStatusBarOptionalLazy; @Mock private Optional<com.android.wm.shell.onehanded.OneHanded> mMockOneHandedOptional; @Mock private PackageManager mPackageManager; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AssistantFeedbackControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AssistantFeedbackControllerTest.java index fb8c3d9af05c..3f1cf83d7b5c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AssistantFeedbackControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AssistantFeedbackControllerTest.java @@ -25,6 +25,12 @@ import static android.service.notification.NotificationListenerService.Ranking.R import static android.service.notification.NotificationListenerService.Ranking.RANKING_PROMOTED; import static android.service.notification.NotificationListenerService.Ranking.RANKING_UNCHANGED; +import static com.android.systemui.statusbar.notification.AssistantFeedbackController.STATUS_DEMOTED; +import static com.android.systemui.statusbar.notification.AssistantFeedbackController.STATUS_PROMOTED; +import static com.android.systemui.statusbar.notification.AssistantFeedbackController.STATUS_SILENCED; +import static com.android.systemui.statusbar.notification.AssistantFeedbackController.STATUS_UNCHANGED; + +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -40,6 +46,8 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; +import junit.framework.Assert; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -76,28 +84,46 @@ public class AssistantFeedbackControllerTest extends SysuiTestCase { } @Test - public void testShowFeedbackIndicator_settingDisabled() { + public void testFeedback_settingDisabled() { switchSetting(OFF); + assertEquals(STATUS_UNCHANGED, mAssistantFeedbackController.getFeedbackStatus( + getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_DEFAULT, RANKING_UNCHANGED))); assertFalse(mAssistantFeedbackController.showFeedbackIndicator( getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_DEFAULT, RANKING_UNCHANGED))); } @Test - public void testShowFeedbackIndicator_changedImportance() { - assertTrue(mAssistantFeedbackController.showFeedbackIndicator( - getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_HIGH, RANKING_UNCHANGED))); - assertTrue(mAssistantFeedbackController.showFeedbackIndicator( - getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_LOW, RANKING_UNCHANGED))); - assertTrue(mAssistantFeedbackController.showFeedbackIndicator( - getEntry(IMPORTANCE_LOW, IMPORTANCE_MIN, RANKING_UNCHANGED))); + public void testFeedback_changedImportance() { + NotificationEntry entry = getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_HIGH, RANKING_UNCHANGED); + assertEquals(STATUS_PROMOTED, mAssistantFeedbackController.getFeedbackStatus(entry)); + assertTrue(mAssistantFeedbackController.showFeedbackIndicator(entry)); + + entry = getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_LOW, RANKING_UNCHANGED); + assertEquals(STATUS_SILENCED, mAssistantFeedbackController.getFeedbackStatus(entry)); + assertTrue(mAssistantFeedbackController.showFeedbackIndicator(entry)); + + entry = getEntry(IMPORTANCE_LOW, IMPORTANCE_MIN, RANKING_UNCHANGED); + assertEquals(STATUS_DEMOTED, mAssistantFeedbackController.getFeedbackStatus(entry)); + assertTrue(mAssistantFeedbackController.showFeedbackIndicator(entry)); + } + + @Test + public void testFeedback_changedRanking() { + NotificationEntry entry = + getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_DEFAULT, RANKING_PROMOTED); + assertEquals(STATUS_PROMOTED, mAssistantFeedbackController.getFeedbackStatus(entry)); + assertTrue(mAssistantFeedbackController.showFeedbackIndicator(entry)); + + entry = getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_DEFAULT, RANKING_DEMOTED); + assertEquals(STATUS_DEMOTED, mAssistantFeedbackController.getFeedbackStatus(entry)); + assertTrue(mAssistantFeedbackController.showFeedbackIndicator(entry)); } @Test - public void testShowFeedbackIndicator_changedRanking() { - assertTrue(mAssistantFeedbackController.showFeedbackIndicator( - getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_DEFAULT, RANKING_PROMOTED))); - assertTrue(mAssistantFeedbackController.showFeedbackIndicator( - getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_DEFAULT, RANKING_DEMOTED))); + public void testGetFeedbackImageResource_settingDisabled() { + switchSetting(OFF); + Assert.assertEquals(0, mAssistantFeedbackController.getFeedbackImageResource( + getEntry(IMPORTANCE_DEFAULT, IMPORTANCE_DEFAULT, RANKING_UNCHANGED))); } private NotificationEntry getEntry(int oldImportance, int newImportance, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java index b0e17cdab8e4..5fc01ccd96b4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java @@ -629,10 +629,8 @@ public class NotificationEntryManagerTest extends SysuiTestCase { return new Notification.Action.Builder( Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon), "action", - // TODO(b/174935104) Please replace FLAG_MUTABLE_UNAUDITED below - // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"), - PendingIntent.FLAG_MUTABLE_UNAUDITED)).build(); + PendingIntent.FLAG_IMMUTABLE)).build(); } private static class FakeNotificationLifetimeExtender implements NotificationLifetimeExtender { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java index 01b3d8e787e6..241451edf698 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java @@ -233,10 +233,8 @@ public class NotificationEntryTest extends SysuiTestCase { return new Notification.Action.Builder( Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon), title, - // TODO(b/174965424) Please replace FLAG_MUTABLE_UNAUDITED below - // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"), - PendingIntent.FLAG_MUTABLE_UNAUDITED)) + PendingIntent.FLAG_IMMUTABLE)) .setContextual(true) .build(); } @@ -245,10 +243,8 @@ public class NotificationEntryTest extends SysuiTestCase { return new Notification.Action.Builder( Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon), title, - // TODO(b/174965424) Please replace FLAG_MUTABLE_UNAUDITED below - // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"), - PendingIntent.FLAG_MUTABLE_UNAUDITED)).build(); + PendingIntent.FLAG_IMMUTABLE)).build(); } private ArrayList<Notification.Action> createActions(String... titles) { 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 639e791cbf23..09546216183f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java @@ -31,7 +31,6 @@ import static org.mockito.Mockito.when; import android.app.Notification; import android.os.Bundle; import android.os.UserHandle; -import android.service.notification.NotificationListenerService; import android.service.notification.StatusBarNotification; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; @@ -46,7 +45,6 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner; -import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender; import com.android.systemui.util.concurrency.FakeExecutor; import com.android.systemui.util.time.FakeSystemClock; @@ -71,7 +69,6 @@ public class AppOpsCoordinatorTest extends SysuiTestCase { private NotificationEntryBuilder mEntryBuilder; private AppOpsCoordinator mAppOpsCoordinator; private NotifFilter mForegroundFilter; - private NotifLifetimeExtender mForegroundNotifLifetimeExtender; private NotifSectioner mFgsSection; private FakeSystemClock mClock = new FakeSystemClock(); @@ -98,13 +95,6 @@ public class AppOpsCoordinatorTest extends SysuiTestCase { verify(mNotifPipeline, times(1)).addPreGroupFilter(filterCaptor.capture()); mForegroundFilter = filterCaptor.getValue(); - // capture lifetime extender - ArgumentCaptor<NotifLifetimeExtender> lifetimeExtenderCaptor = - ArgumentCaptor.forClass(NotifLifetimeExtender.class); - verify(mNotifPipeline, times(1)).addNotificationLifetimeExtender( - lifetimeExtenderCaptor.capture()); - mForegroundNotifLifetimeExtender = lifetimeExtenderCaptor.getValue(); - mFgsSection = mAppOpsCoordinator.getSectioner(); } @@ -160,55 +150,6 @@ public class AppOpsCoordinatorTest extends SysuiTestCase { } @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/interruption/NotificationInterruptStateProviderImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java index d606316f16ed..60c3bc874235 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java @@ -476,10 +476,8 @@ public class NotificationInterruptStateProviderImplTest extends SysuiTestCase { private NotificationEntry createBubble() { Notification.BubbleMetadata data = new Notification.BubbleMetadata.Builder( - // TODO(b/174970399) Please replace FLAG_MUTABLE_UNAUDITED below - // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. PendingIntent.getActivity(mContext, 0, new Intent(), - PendingIntent.FLAG_MUTABLE_UNAUDITED), + PendingIntent.FLAG_MUTABLE), Icon.createWithResource(mContext.getResources(), R.drawable.android)) .build(); Notification n = new Notification.Builder(getContext(), "a") 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 891179c32315..ca982a64d382 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java @@ -210,7 +210,7 @@ public class ExpandableNotificationRowTest extends SysuiTestCase { // public notification is custom layout - no header mGroupRow.setSensitive(true, true); mGroupRow.setOnFeedbackClickListener(null); - mGroupRow.showFeedbackIcon(false); + mGroupRow.showFeedbackIcon(false, 0); } @Test @@ -224,11 +224,12 @@ public class ExpandableNotificationRowTest extends SysuiTestCase { mGroupRow.setChildrenContainer(mockContainer); final boolean show = true; - mGroupRow.showFeedbackIcon(show); + final int resId = 1; + mGroupRow.showFeedbackIcon(show, resId); - verify(mockContainer, times(1)).showFeedbackIcon(show); - verify(privateLayout, times(1)).showFeedbackIcon(show); - verify(publicLayout, times(1)).showFeedbackIcon(show); + verify(mockContainer, times(1)).showFeedbackIcon(show, resId); + verify(privateLayout, times(1)).showFeedbackIcon(show, resId); + verify(publicLayout, times(1)).showFeedbackIcon(show, resId); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java index 9d87579ee154..53ff957e4016 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/FeedbackInfoTest.java @@ -17,13 +17,13 @@ package com.android.systemui.statusbar.notification.row; import static android.app.NotificationManager.IMPORTANCE_DEFAULT; -import static android.app.NotificationManager.IMPORTANCE_HIGH; -import static android.app.NotificationManager.IMPORTANCE_LOW; -import static android.app.NotificationManager.IMPORTANCE_MIN; -import static android.service.notification.NotificationListenerService.Ranking.RANKING_DEMOTED; -import static android.service.notification.NotificationListenerService.Ranking.RANKING_PROMOTED; import static android.service.notification.NotificationListenerService.Ranking.RANKING_UNCHANGED; +import static com.android.systemui.statusbar.notification.AssistantFeedbackController.STATUS_ALERTED; +import static com.android.systemui.statusbar.notification.AssistantFeedbackController.STATUS_DEMOTED; +import static com.android.systemui.statusbar.notification.AssistantFeedbackController.STATUS_PROMOTED; +import static com.android.systemui.statusbar.notification.AssistantFeedbackController.STATUS_SILENCED; + import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertTrue; @@ -79,6 +79,8 @@ public class FeedbackInfoTest extends SysuiTestCase { private final NotificationGuts mGutsParent = mock(NotificationGuts.class); private final ExpandableNotificationRow mMockNotificationRow = mock(ExpandableNotificationRow.class); + private final AssistantFeedbackController mAssistantFeedbackController = + mock(AssistantFeedbackController.class); private StatusBarNotification mSbn; @Mock @@ -120,7 +122,7 @@ public class FeedbackInfoTest extends SysuiTestCase { public void testBindNotification_SetsTextApplicationName() { when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name"); mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), - mMockNotificationRow, mock(AssistantFeedbackController.class)); + mMockNotificationRow, mAssistantFeedbackController); final TextView textView = mFeedbackInfo.findViewById(R.id.pkg_name); assertTrue(textView.getText().toString().contains("App Name")); } @@ -131,65 +133,60 @@ public class FeedbackInfoTest extends SysuiTestCase { when(mMockPackageManager.getApplicationIcon(any(ApplicationInfo.class))) .thenReturn(iconDrawable); mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), - mMockNotificationRow, mock(AssistantFeedbackController.class)); + mMockNotificationRow, mAssistantFeedbackController); final ImageView iconView = mFeedbackInfo.findViewById(R.id.pkg_icon); assertEquals(iconDrawable, iconView.getDrawable()); } @Test public void testPrompt_silenced() { - mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(IMPORTANCE_DEFAULT, - IMPORTANCE_LOW, RANKING_UNCHANGED), mMockNotificationRow, - mock(AssistantFeedbackController.class)); - TextView prompt = mFeedbackInfo.findViewById(R.id.prompt); - assertEquals("This notification was silenced by the system. Was this correct?", - prompt.getText()); - } - - @Test - public void testPrompt_promoted_importance() { - mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(IMPORTANCE_DEFAULT, - IMPORTANCE_HIGH, RANKING_UNCHANGED), mMockNotificationRow, - mock(AssistantFeedbackController.class)); + when(mAssistantFeedbackController.getFeedbackStatus(any(NotificationEntry.class))) + .thenReturn(STATUS_SILENCED); + mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), mMockNotificationRow, + mAssistantFeedbackController); TextView prompt = mFeedbackInfo.findViewById(R.id.prompt); - assertEquals("This notification was promoted by the system. Was this correct?", - prompt.getText()); + assertEquals("This notification was automatically demoted to Silent by the system. " + + "Was this correct?", prompt.getText().toString()); } @Test - public void testPrompt_promoted_ranking() { - mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(IMPORTANCE_DEFAULT, - IMPORTANCE_DEFAULT, RANKING_PROMOTED), mMockNotificationRow, - mock(AssistantFeedbackController.class)); + public void testPrompt_promoted() { + when(mAssistantFeedbackController.getFeedbackStatus(any(NotificationEntry.class))) + .thenReturn(STATUS_PROMOTED); + mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), mMockNotificationRow, + mAssistantFeedbackController); TextView prompt = mFeedbackInfo.findViewById(R.id.prompt); - assertEquals("This notification was promoted by the system. Was this correct?", - prompt.getText()); + assertEquals("This notification was automatically ranked higher in your shade. " + + "Was this correct?", prompt.getText().toString()); } @Test - public void testPrompt_demoted_importance() { - mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(IMPORTANCE_LOW, - IMPORTANCE_MIN, RANKING_UNCHANGED), mMockNotificationRow, - mock(AssistantFeedbackController.class)); + public void testPrompt_alerted() { + when(mAssistantFeedbackController.getFeedbackStatus(any(NotificationEntry.class))) + .thenReturn(STATUS_ALERTED); + mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), mMockNotificationRow, + mAssistantFeedbackController); TextView prompt = mFeedbackInfo.findViewById(R.id.prompt); - assertEquals("This notification was demoted by the system. Was this correct?", - prompt.getText()); + assertEquals("This notification was automatically promoted to Default by the system. " + + "Was this correct?", + prompt.getText().toString()); } @Test - public void testPrompt_demoted_ranking() { - mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(IMPORTANCE_DEFAULT, - IMPORTANCE_DEFAULT, RANKING_DEMOTED), mMockNotificationRow, - mock(AssistantFeedbackController.class)); + public void testPrompt_demoted() { + when(mAssistantFeedbackController.getFeedbackStatus(any(NotificationEntry.class))) + .thenReturn(STATUS_DEMOTED); + mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), mMockNotificationRow, + mAssistantFeedbackController); TextView prompt = mFeedbackInfo.findViewById(R.id.prompt); - assertEquals("This notification was demoted by the system. Was this correct?", - prompt.getText()); + assertEquals("This notification was automatically ranked lower in your shade. " + + "Was this correct?", prompt.getText().toString()); } @Test public void testPositiveFeedback() { mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), mMockNotificationRow, - mock(AssistantFeedbackController.class)); + mAssistantFeedbackController); final View yes = mFeedbackInfo.findViewById(R.id.yes); yes.performClick(); @@ -206,7 +203,7 @@ public class FeedbackInfoTest extends SysuiTestCase { .thenReturn(true); mFeedbackInfo.bindGuts(mMockPackageManager, mSbn, getEntry(), mMockNotificationRow, - mock(AssistantFeedbackController.class)); + mAssistantFeedbackController); final View no = mFeedbackInfo.findViewById(R.id.no); no.performClick(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java index 2101ea1766a1..377a69dab91b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java @@ -95,7 +95,7 @@ public class NotificationContentViewTest extends SysuiTestCase { mView.setExpandedChild(mockExpanded); mView.setHeadsUpChild(mockHeadsUp); - mView.showFeedbackIcon(true); + mView.showFeedbackIcon(true, 1); verify(mockContracted, times(1)).setVisibility(View.VISIBLE); verify(mockExpanded, times(1)).setVisibility(View.VISIBLE); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java index 1387a63d449f..291b223d72bb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java @@ -213,11 +213,9 @@ public class NotificationConversationInfoTest extends SysuiTestCase { notification, UserHandle.CURRENT, null, 0); mEntry = new NotificationEntryBuilder().setSbn(mSbn).setShortcutInfo(mShortcutInfo).build(); - // TODO(b/175005650) Please replace FLAG_MUTABLE_UNAUDITED below - // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext, BubblesTestActivity.class), - PendingIntent.FLAG_MUTABLE_UNAUDITED); + PendingIntent.FLAG_MUTABLE); mBubbleSbn = new SbnBuilder(mSbn).setBubbleMetadata( new Notification.BubbleMetadata.Builder(bubbleIntent, Icon.createWithResource(mContext, R.drawable.android)).build()) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java index 3000b8b449c3..458a058cc6ec 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java @@ -374,7 +374,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase { eq(false), eq(false), eq(true), /* wasShownHighPriority */ - eq(false) /* showAutomaticSetting */); + eq(mAssistantFeedbackController)); } @Test @@ -408,7 +408,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase { eq(true), eq(false), eq(false), /* wasShownHighPriority */ - eq(false) /* showAutomaticSetting */); + eq(mAssistantFeedbackController)); } @Test @@ -440,7 +440,7 @@ public class NotificationGutsManagerTest extends SysuiTestCase { eq(false), eq(false), eq(false), /* wasShownHighPriority */ - eq(false) /* showAutomaticSetting */); + eq(mAssistantFeedbackController)); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java index 4a2cbccad24d..324f0ac08fad 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java @@ -64,6 +64,7 @@ import com.android.internal.logging.testing.UiEventLoggerFake; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; +import com.android.systemui.statusbar.notification.AssistantFeedbackController; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; @@ -113,6 +114,8 @@ public class NotificationInfoTest extends SysuiTestCase { private OnUserInteractionCallback mOnUserInteractionCallback; @Mock private ChannelEditorDialogController mChannelEditorDialogController; + @Mock + private AssistantFeedbackController mAssistantFeedbackController; @Before public void setUp() throws Exception { @@ -160,6 +163,9 @@ public class NotificationInfoTest extends SysuiTestCase { mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0, new Notification(), UserHandle.CURRENT, null, 0); mEntry = new NotificationEntryBuilder().setSbn(mSbn).build(); + when(mAssistantFeedbackController.isFeedbackEnabled()).thenReturn(false); + when(mAssistantFeedbackController.getInlineDescriptionResource(any())) + .thenReturn(R.string.notification_channel_summary_automatic); } @Test @@ -180,7 +186,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, true, - false); + mAssistantFeedbackController); final TextView textView = mNotificationInfo.findViewById(R.id.pkg_name); assertTrue(textView.getText().toString().contains("App Name")); assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.header).getVisibility()); @@ -206,7 +212,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, true, - false); + mAssistantFeedbackController); final ImageView iconView = mNotificationInfo.findViewById(R.id.pkg_icon); assertEquals(iconDrawable, iconView.getDrawable()); } @@ -228,7 +234,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, true, - false); + mAssistantFeedbackController); final TextView nameView = mNotificationInfo.findViewById(R.id.delegate_name); assertEquals(GONE, nameView.getVisibility()); } @@ -259,7 +265,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, true, - false); + mAssistantFeedbackController); final TextView nameView = mNotificationInfo.findViewById(R.id.delegate_name); assertEquals(VISIBLE, nameView.getVisibility()); assertTrue(nameView.getText().toString().contains("Proxied")); @@ -282,7 +288,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, true, - false); + mAssistantFeedbackController); final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name); assertEquals(GONE, groupNameView.getVisibility()); } @@ -310,7 +316,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, true, - false); + mAssistantFeedbackController); final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name); assertEquals(View.VISIBLE, groupNameView.getVisibility()); assertEquals("Test Group Name", groupNameView.getText()); @@ -333,7 +339,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, true, - false); + mAssistantFeedbackController); final TextView textView = mNotificationInfo.findViewById(R.id.channel_name); assertEquals(TEST_CHANNEL_NAME, textView.getText()); } @@ -355,7 +361,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, true, - false); + mAssistantFeedbackController); final TextView textView = mNotificationInfo.findViewById(R.id.channel_name); assertEquals(GONE, textView.getVisibility()); } @@ -381,7 +387,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, true, - false); + mAssistantFeedbackController); final TextView textView = mNotificationInfo.findViewById(R.id.channel_name); assertEquals(VISIBLE, textView.getVisibility()); } @@ -403,7 +409,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, true, true, - false); + mAssistantFeedbackController); final TextView textView = mNotificationInfo.findViewById(R.id.channel_name); assertEquals(VISIBLE, textView.getVisibility()); } @@ -429,7 +435,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, true, - false); + mAssistantFeedbackController); final View settingsButton = mNotificationInfo.findViewById(R.id.info); settingsButton.performClick(); @@ -454,7 +460,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, true, - false); + mAssistantFeedbackController); final View settingsButton = mNotificationInfo.findViewById(R.id.info); assertTrue(settingsButton.getVisibility() != View.VISIBLE); } @@ -479,7 +485,7 @@ public class NotificationInfoTest extends SysuiTestCase { false, false, true, - false); + mAssistantFeedbackController); final View settingsButton = mNotificationInfo.findViewById(R.id.info); assertTrue(settingsButton.getVisibility() != View.VISIBLE); } @@ -501,7 +507,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, true, - false); + mAssistantFeedbackController); mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, @@ -517,7 +523,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, true, - false); + mAssistantFeedbackController); final View settingsButton = mNotificationInfo.findViewById(R.id.info); assertEquals(View.VISIBLE, settingsButton.getVisibility()); } @@ -542,7 +548,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, true, true, - false); + mAssistantFeedbackController); mNotificationInfo.findViewById(R.id.info).performClick(); // Verify that listener was triggered. @@ -568,7 +574,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, true, - false); + mAssistantFeedbackController); final TextView channelNameView = mNotificationInfo.findViewById(R.id.channel_name); assertEquals(GONE, channelNameView.getVisibility()); @@ -592,7 +598,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, true, - false); + mAssistantFeedbackController); assertEquals(GONE, mNotificationInfo.findViewById( R.id.interruptiveness_settings).getVisibility()); assertEquals(VISIBLE, mNotificationInfo.findViewById( @@ -616,7 +622,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, true, true, - false); + mAssistantFeedbackController); final TextView view = mNotificationInfo.findViewById(R.id.non_configurable_text); assertEquals(View.VISIBLE, view.getVisibility()); assertEquals(mContext.getString(R.string.notification_unblockable_desc), @@ -627,6 +633,7 @@ public class NotificationInfoTest extends SysuiTestCase { @Test public void testBindNotification_automaticIsVisible() throws Exception { + when(mAssistantFeedbackController.isFeedbackEnabled()).thenReturn(true); mNotificationInfo.bindNotification( mMockPackageManager, mMockINotificationManager, @@ -642,7 +649,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, true, - true); + mAssistantFeedbackController); assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.automatic).getVisibility()); assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.automatic_summary).getVisibility()); } @@ -664,13 +671,14 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, true, - false); + mAssistantFeedbackController); assertEquals(GONE, mNotificationInfo.findViewById(R.id.automatic).getVisibility()); assertEquals(GONE, mNotificationInfo.findViewById(R.id.automatic_summary).getVisibility()); } @Test public void testBindNotification_automaticIsSelected() throws Exception { + when(mAssistantFeedbackController.isFeedbackEnabled()).thenReturn(true); mNotificationChannel.unlockFields(USER_LOCKED_IMPORTANCE); mNotificationInfo.bindNotification( mMockPackageManager, @@ -687,7 +695,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, true, - true); + mAssistantFeedbackController); assertTrue(mNotificationInfo.findViewById(R.id.automatic).isSelected()); } @@ -708,7 +716,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, true, - false); + mAssistantFeedbackController); assertTrue(mNotificationInfo.findViewById(R.id.alert).isSelected()); } @@ -729,7 +737,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, false, - false); + mAssistantFeedbackController); assertTrue(mNotificationInfo.findViewById(R.id.silence).isSelected()); } @@ -750,7 +758,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, true, - false); + mAssistantFeedbackController); mTestableLooper.processAllMessages(); verify(mMockINotificationManager, never()).updateNotificationChannelForPackage( anyString(), eq(TEST_UID), any()); @@ -773,7 +781,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, true, - false); + mAssistantFeedbackController); assertEquals(1, mUiEventLogger.numLogs()); assertEquals(NotificationControlsEvent.NOTIFICATION_CONTROLS_OPEN.getId(), mUiEventLogger.eventId(0)); @@ -797,7 +805,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, false, - false); + mAssistantFeedbackController); mNotificationInfo.findViewById(R.id.alert).performClick(); mTestableLooper.processAllMessages(); @@ -824,7 +832,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, true, - false); + mAssistantFeedbackController); mNotificationInfo.findViewById(R.id.silence).performClick(); mTestableLooper.processAllMessages(); @@ -851,7 +859,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, true, - false); + mAssistantFeedbackController); mNotificationInfo.findViewById(R.id.automatic).performClick(); mTestableLooper.processAllMessages(); @@ -862,6 +870,7 @@ public class NotificationInfoTest extends SysuiTestCase { @Test public void testHandleCloseControls_persistAutomatic() throws Exception { + when(mAssistantFeedbackController.isFeedbackEnabled()).thenReturn(true); mNotificationChannel.unlockFields(USER_LOCKED_IMPORTANCE); mNotificationInfo.bindNotification( mMockPackageManager, @@ -878,7 +887,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, true, - true); + mAssistantFeedbackController); mNotificationInfo.handleCloseControls(true, false); mTestableLooper.processAllMessages(); @@ -905,7 +914,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, true, - false); + mAssistantFeedbackController); mNotificationInfo.handleCloseControls(true, false); mTestableLooper.processAllMessages(); @@ -940,7 +949,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, true, - false); + mAssistantFeedbackController); mNotificationInfo.handleCloseControls(true, false); @@ -968,7 +977,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, true, - false); + mAssistantFeedbackController); mNotificationInfo.findViewById(R.id.silence).performClick(); mNotificationInfo.findViewById(R.id.done).performClick(); @@ -1008,7 +1017,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, false, - false); + mAssistantFeedbackController); mNotificationInfo.findViewById(R.id.alert).performClick(); mNotificationInfo.findViewById(R.id.done).performClick(); @@ -1026,6 +1035,7 @@ public class NotificationInfoTest extends SysuiTestCase { @Test public void testAutomaticUnlocksUserImportance() throws Exception { + when(mAssistantFeedbackController.isFeedbackEnabled()).thenReturn(true); mNotificationChannel.setImportance(IMPORTANCE_DEFAULT); mNotificationChannel.lockFields(USER_LOCKED_IMPORTANCE); mNotificationInfo.bindNotification( @@ -1043,7 +1053,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, true, - true); + mAssistantFeedbackController); mNotificationInfo.findViewById(R.id.automatic).performClick(); mNotificationInfo.findViewById(R.id.done).performClick(); @@ -1074,7 +1084,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, true, - false); + mAssistantFeedbackController); mNotificationInfo.findViewById(R.id.silence).performClick(); mNotificationInfo.findViewById(R.id.done).performClick(); @@ -1109,7 +1119,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, false, - false); + mAssistantFeedbackController); assertEquals(mContext.getString(R.string.inline_done_button), ((TextView) mNotificationInfo.findViewById(R.id.done)).getText()); @@ -1147,7 +1157,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, false, - false); + mAssistantFeedbackController); assertEquals(mContext.getString(R.string.inline_done_button), ((TextView) mNotificationInfo.findViewById(R.id.done)).getText()); @@ -1184,7 +1194,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, true, - false); + mAssistantFeedbackController); mNotificationInfo.findViewById(R.id.silence).performClick(); mNotificationInfo.findViewById(R.id.done).performClick(); @@ -1212,7 +1222,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, false, - false); + mAssistantFeedbackController); assertEquals(mContext.getString(R.string.inline_done_button), ((TextView) mNotificationInfo.findViewById(R.id.done)).getText()); @@ -1243,7 +1253,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, false, - false); + mAssistantFeedbackController); mNotificationInfo.findViewById(R.id.alert).performClick(); mNotificationInfo.findViewById(R.id.done).performClick(); @@ -1277,7 +1287,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, false, - false); + mAssistantFeedbackController); mNotificationInfo.findViewById(R.id.alert).performClick(); mNotificationInfo.findViewById(R.id.done).performClick(); @@ -1310,7 +1320,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, false, - false); + mAssistantFeedbackController); mNotificationInfo.findViewById(R.id.alert).performClick(); mNotificationInfo.findViewById(R.id.done).performClick(); @@ -1343,7 +1353,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, false, - false); + mAssistantFeedbackController); mNotificationInfo.findViewById(R.id.alert).performClick(); @@ -1369,7 +1379,7 @@ public class NotificationInfoTest extends SysuiTestCase { true, false, false, - false); + mAssistantFeedbackController); assertFalse(mNotificationInfo.willBeRemoved()); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java index 43ba844bdef3..6fcc7fa9376c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java @@ -455,10 +455,8 @@ public class NotificationTestHelper { private BubbleMetadata makeBubbleMetadata(PendingIntent deleteIntent) { Intent target = new Intent(mContext, BubblesTestActivity.class); - // TODO(b/175014468) Please replace FLAG_MUTABLE_UNAUDITED below - // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0, target, - PendingIntent.FLAG_MUTABLE_UNAUDITED); + PendingIntent.FLAG_MUTABLE); return new BubbleMetadata.Builder(bubbleIntent, Icon.createWithResource(mContext, R.drawable.android)) 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 aca34242e5fa..1ac793730f02 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 @@ -30,6 +30,7 @@ import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import com.android.internal.widget.LockPatternUtils; +import com.android.keyguard.KeyguardSecurityModel; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.SysuiTestCase; import com.android.systemui.dock.DockManager; @@ -80,6 +81,8 @@ public class LockscreenIconControllerTest extends SysuiTestCase { private Resources mResources; @Mock private HeadsUpManagerPhone mHeadsUpManagerPhone; + @Mock + private KeyguardSecurityModel mKeyguardSecurityModel; private LockscreenLockIconController mLockIconController; private OnAttachStateChangeListener mOnAttachStateChangeListener; @@ -94,7 +97,7 @@ public class LockscreenIconControllerTest extends SysuiTestCase { mShadeController, mAccessibilityController, mKeyguardIndicationController, mStatusBarStateController, mConfigurationController, mNotificationWakeUpCoordinator, mKeyguardBypassController, mDockManager, mKeyguardStateController, mResources, - mHeadsUpManagerPhone); + mHeadsUpManagerPhone, mKeyguardSecurityModel); ArgumentCaptor<OnAttachStateChangeListener> onAttachStateChangeListenerArgumentCaptor = ArgumentCaptor.forClass(OnAttachStateChangeListener.class); @@ -139,6 +142,15 @@ public class LockscreenIconControllerTest extends SysuiTestCase { sBStateListenerCaptor.getValue().onDozingChanged(true); verify(mLockIcon).updateIconVisibility(false); + } + + @Test + public void testVisibility_noBouncer() { + // no security (ie: no lock screen OR swipe to unlock) + when(mKeyguardSecurityModel.getSecurityMode(anyInt())).thenReturn( + KeyguardSecurityModel.SecurityMode.None); + mOnAttachStateChangeListener.onViewAttachedToWindow(mLockIcon); + verify(mLockIcon).updateIconVisibility(false); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java index 5416f75dffff..8e84f1a4e843 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java @@ -148,9 +148,10 @@ import com.android.systemui.util.time.FakeSystemClock; import com.android.systemui.volume.VolumeComponent; import com.android.systemui.wmshell.BubblesManager; import com.android.wm.shell.bubbles.Bubbles; -import com.android.wm.shell.splitscreen.SplitScreen; +import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; @@ -244,7 +245,7 @@ public class StatusBarTest extends SysuiTestCase { @Mock private StatusBarComponent.Builder mStatusBarComponentBuilder; @Mock private StatusBarComponent mStatusBarComponent; @Mock private PluginManager mPluginManager; - @Mock private SplitScreen mSplitScreen; + @Mock private LegacySplitScreen mLegacySplitScreen; @Mock private SuperStatusBarViewFactory mSuperStatusBarViewFactory; @Mock private LightsOutNotifController mLightsOutNotifController; @Mock private ViewMediatorCallback mViewMediatorCallback; @@ -404,7 +405,7 @@ public class StatusBarTest extends SysuiTestCase { mCommandQueue, mStatusBarComponentBuilderProvider, mPluginManager, - Optional.of(mSplitScreen), + Optional.of(mLegacySplitScreen), mLightsOutNotifController, mStatusBarNotificationActivityStarterBuilder, mShadeController, @@ -886,6 +887,7 @@ public class StatusBarTest extends SysuiTestCase { verify(mDozeServiceHost).setDozeSuppressed(false); } + @Ignore // TODO (b/175240607) - Figure out if the device will actually dial 911. @Test public void onEmergencyActionLaunchGesture_launchesEmergencyIntent() { ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); @@ -896,7 +898,6 @@ public class StatusBarTest extends SysuiTestCase { verify(statusBarSpy).startActivity(intentCaptor.capture(), eq(true)); Intent sentIntent = intentCaptor.getValue(); assertEquals(sentIntent.getAction(), EmergencyGesture.ACTION_LAUNCH_EMERGENCY); - } public static class TestableNotificationInterruptStateProviderImpl extends diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java index 23fa6fd5e4ca..2577dbdbb593 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java @@ -16,7 +16,11 @@ package com.android.systemui.statusbar.policy; +import static android.os.BatteryManager.EXTRA_PRESENT; + +import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.Intent; @@ -31,6 +35,7 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.demomode.DemoModeController; import com.android.systemui.power.EnhancedEstimates; +import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback; import org.junit.Assert; import org.junit.Before; @@ -98,4 +103,36 @@ public class BatteryControllerTest extends SysuiTestCase { Assert.assertFalse(mBatteryController.isAodPowerSave()); } + @Test + public void testBatteryPresentState_notPresent() { + // GIVEN a battery state callback listening for changes + BatteryStateChangeCallback cb = mock(BatteryStateChangeCallback.class); + mBatteryController.addCallback(cb); + + // WHEN the state of the battery becomes unknown + Intent i = new Intent(Intent.ACTION_BATTERY_CHANGED); + i.putExtra(EXTRA_PRESENT, false); + mBatteryController.onReceive(getContext(), i); + + // THEN the callback is notified + verify(cb, atLeastOnce()).onBatteryUnknownStateChanged(true); + } + + @Test + public void testBatteryPresentState_callbackAddedAfterStateChange() { + // GIVEN a battery state callback + BatteryController.BatteryStateChangeCallback cb = + mock(BatteryController.BatteryStateChangeCallback.class); + + // GIVEN the state has changed before adding a new callback + Intent i = new Intent(Intent.ACTION_BATTERY_CHANGED); + i.putExtra(EXTRA_PRESENT, false); + mBatteryController.onReceive(getContext(), i); + + // WHEN a callback is added + mBatteryController.addCallback(cb); + + // THEN it is informed about the battery state + verify(cb, atLeastOnce()).onBatteryUnknownStateChanged(true); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java index 18e7840f1201..ebc45f41ce61 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java @@ -26,7 +26,8 @@ import android.test.suitebuilder.annotation.SmallTest; import androidx.test.runner.AndroidJUnit4; -import com.android.systemui.R; +import com.android.settingslib.R; +import com.android.settingslib.mobile.TelephonyIcons; import com.android.systemui.SysuiTestCase; import com.android.systemui.statusbar.policy.NetworkController.EmergencyListener; import com.android.systemui.statusbar.policy.NetworkController.IconState; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java index 138236af70ce..6adf94e180a5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java @@ -60,17 +60,18 @@ import android.util.Log; import androidx.test.InstrumentationRegistry; +import com.android.settingslib.R; import com.android.settingslib.graph.SignalDrawable; +import com.android.settingslib.mobile.MobileMappings.Config; +import com.android.settingslib.mobile.MobileStatusTracker.SubscriptionDefaults; +import com.android.settingslib.mobile.TelephonyIcons; import com.android.settingslib.net.DataUsageController; -import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.demomode.DemoModeController; import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener; import com.android.systemui.statusbar.policy.NetworkController.IconState; import com.android.systemui.statusbar.policy.NetworkController.SignalCallback; -import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config; -import com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults; import org.junit.Before; import org.junit.Rule; @@ -225,7 +226,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase { setDefaultSubId(mSubId); setSubscriptions(mSubId); mMobileSignalController = mNetworkController.mMobileSignalControllers.get(mSubId); - mPhoneStateListener = mMobileSignalController.mPhoneStateListener; + mPhoneStateListener = mMobileSignalController.mMobileStatusTracker.getPhoneStateListener(); ArgumentCaptor<ConnectivityManager.NetworkCallback> callbackArg = ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java index 68992179de59..d11aee8a5194 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java @@ -19,6 +19,7 @@ import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; +import com.android.settingslib.mobile.TelephonyIcons; import com.android.settingslib.net.DataUsageController; import org.junit.Test; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java index 61f71b758d80..da35de926e70 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java @@ -38,6 +38,7 @@ import android.testing.AndroidTestingRunner; import android.testing.TestableLooper.RunWithLooper; import com.android.settingslib.graph.SignalDrawable; +import com.android.settingslib.mobile.TelephonyIcons; import com.android.settingslib.net.DataUsageController; import com.android.systemui.R; diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java index ef25b73fd748..73d87b0d4596 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java @@ -40,7 +40,7 @@ import com.android.wm.shell.onehanded.OneHandedGestureHandler; import com.android.wm.shell.onehanded.OneHandedTransitionCallback; import com.android.wm.shell.pip.Pip; import com.android.wm.shell.pip.phone.PipTouchHandler; -import com.android.wm.shell.splitscreen.SplitScreen; +import com.android.wm.shell.legacysplitscreen.LegacySplitScreen; import org.junit.Before; import org.junit.Test; @@ -63,7 +63,8 @@ public class WMShellTest extends SysuiTestCase { @Mock SysUiState mSysUiState; @Mock Pip mPip; @Mock PipTouchHandler mPipTouchHandler; - @Mock SplitScreen mSplitScreen; + @Mock + LegacySplitScreen mLegacySplitScreen; @Mock OneHanded mOneHanded; @Mock HideDisplayCutout mHideDisplayCutout; @Mock ProtoTracer mProtoTracer; @@ -75,7 +76,7 @@ public class WMShellTest extends SysuiTestCase { mWMShell = new WMShell(mContext, mCommandQueue, mConfigurationController, mKeyguardUpdateMonitor, mNavigationModeController, - mScreenLifecycle, mSysUiState, Optional.of(mPip), Optional.of(mSplitScreen), + mScreenLifecycle, mSysUiState, Optional.of(mPip), Optional.of(mLegacySplitScreen), Optional.of(mOneHanded), Optional.of(mHideDisplayCutout), mProtoTracer, Optional.of(mShellCommandHandler)); @@ -91,7 +92,7 @@ public class WMShellTest extends SysuiTestCase { @Test public void initSplitScreen_registersCallbacks() { - mWMShell.initSplitScreen(mSplitScreen); + mWMShell.initSplitScreen(mLegacySplitScreen); verify(mKeyguardUpdateMonitor).registerCallback(any(KeyguardUpdateMonitorCallback.class)); } diff --git a/proto/src/metrics_constants/OWNERS b/proto/src/metrics_constants/OWNERS index ab4d808f5ff0..7009282b66e1 100644 --- a/proto/src/metrics_constants/OWNERS +++ b/proto/src/metrics_constants/OWNERS @@ -1,4 +1,4 @@ -cwren@google.com +cwren@android.com yanglu@google.com yaochen@google.com yro@google.com diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java index b3977829d1c3..e1af2c48789f 100644 --- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java +++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java @@ -349,7 +349,7 @@ public class TouchExplorer extends BaseEventStreamTransformation AccessibilityService.GESTURE_DOUBLE_TAP_AND_HOLD, event.getDisplayId(), mGestureDetector.getMotionEvents()); - mAms.onGesture(gestureEvent); + dispatchGesture(gestureEvent); } mState.startDelegating(); } @@ -367,7 +367,7 @@ public class TouchExplorer extends BaseEventStreamTransformation AccessibilityService.GESTURE_DOUBLE_TAP, event.getDisplayId(), mGestureDetector.getMotionEvents()); - mAms.onGesture(gestureEvent); + dispatchGesture(gestureEvent); } if (mSendTouchExplorationEndDelayed.isPending()) { mSendTouchExplorationEndDelayed.forceSendAndRemove(); @@ -402,13 +402,9 @@ public class TouchExplorer extends BaseEventStreamTransformation @Override public boolean onGestureCompleted(AccessibilityGestureEvent gestureEvent) { - if (DEBUG) { - Slog.d(LOG_TAG, "Dispatching gesture event:" + gestureEvent.toString()); - } endGestureDetection(true); mSendTouchInteractionEndDelayed.cancel(); - mAms.onGesture(gestureEvent); - + dispatchGesture(gestureEvent); return true; } @@ -444,10 +440,7 @@ public class TouchExplorer extends BaseEventStreamTransformation AccessibilityService.GESTURE_UNKNOWN, event.getDisplayId(), mGestureDetector.getMotionEvents()); - if (DEBUG) { - Slog.d(LOG_TAG, "Dispatching gesture event:" + gestureEvent.toString()); - } - mAms.onGesture(gestureEvent); + dispatchGesture(gestureEvent); } return false; } @@ -658,7 +651,7 @@ public class TouchExplorer extends BaseEventStreamTransformation AccessibilityService.GESTURE_PASSTHROUGH, event.getDisplayId(), mGestureDetector.getMotionEvents()); - mAms.onGesture(gestureEvent); + dispatchGesture(gestureEvent); } computeDraggingPointerIdIfNeeded(event); pointerIdBits = 1 << mDraggingPointerId; @@ -682,7 +675,7 @@ public class TouchExplorer extends BaseEventStreamTransformation AccessibilityService.GESTURE_PASSTHROUGH, event.getDisplayId(), mGestureDetector.getMotionEvents()); - mAms.onGesture(gestureEvent); + dispatchGesture(gestureEvent); } mState.startDelegating(); mDispatcher.sendDownForAllNotInjectedPointers(event, policyFlags); @@ -704,7 +697,7 @@ public class TouchExplorer extends BaseEventStreamTransformation AccessibilityService.GESTURE_PASSTHROUGH, event.getDisplayId(), mGestureDetector.getMotionEvents()); - mAms.onGesture(gestureEvent); + dispatchGesture(gestureEvent); } mState.startDelegating(); if (mState.isTouchExploring()) { @@ -725,7 +718,7 @@ public class TouchExplorer extends BaseEventStreamTransformation AccessibilityService.GESTURE_PASSTHROUGH, event.getDisplayId(), mGestureDetector.getMotionEvents()); - mAms.onGesture(gestureEvent); + dispatchGesture(gestureEvent); } mState.startDelegating(); event = MotionEvent.obtainNoHistory(event); @@ -1304,7 +1297,7 @@ public class TouchExplorer extends BaseEventStreamTransformation AccessibilityService.GESTURE_TOUCH_EXPLORATION, mState.getLastReceivedEvent().getDisplayId(), mGestureDetector.getMotionEvents()); - mAms.onGesture(gestureEvent); + dispatchGesture(gestureEvent); } if (!mEvents.isEmpty() && !mRawEvents.isEmpty()) { // Deliver a down event. @@ -1439,6 +1432,13 @@ public class TouchExplorer extends BaseEventStreamTransformation } } + private void dispatchGesture(AccessibilityGestureEvent gestureEvent) { + if (DEBUG) { + Slog.d(LOG_TAG, "Dispatching gesture event:" + gestureEvent.toString()); + } + mAms.onGesture(gestureEvent); + } + @Override public String toString() { return "TouchExplorer { " diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java index 33d13de8be4b..bc59602d3378 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java @@ -29,8 +29,6 @@ import static com.android.server.autofill.Helper.sVerbose; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManagerInternal; -import android.app.ActivityTaskManager; -import android.app.IActivityTaskManager; import android.content.ComponentName; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; @@ -86,6 +84,7 @@ import com.android.server.autofill.ui.AutoFillUI; import com.android.server.contentcapture.ContentCaptureManagerInternal; import com.android.server.infra.AbstractPerUserSystemService; import com.android.server.inputmethod.InputMethodManagerInternal; +import com.android.server.wm.ActivityTaskManagerInternal; import java.io.PrintWriter; import java.util.ArrayList; @@ -1638,19 +1637,16 @@ final class AutofillManagerServiceImpl } } - final IActivityTaskManager atm = ActivityTaskManager.getService(); + final ActivityTaskManagerInternal atmInternal = LocalServices.getService( + ActivityTaskManagerInternal.class); // Only remove sessions which's activities are not known to the activity manager anymore for (int i = 0; i < numSessionsToRemove; i++) { - try { - // The activity manager cannot resolve activities that have been removed - if (atm.getActivityClassForToken(sessionsToRemove.valueAt(i)) != null) { - sessionsToRemove.removeAt(i); - i--; - numSessionsToRemove--; - } - } catch (RemoteException e) { - Slog.w(TAG, "Cannot figure out if activity is finished", e); + // The activity task manager cannot resolve activities that have been removed. + if (atmInternal.getActivityName(sessionsToRemove.valueAt(i)) != null) { + sessionsToRemove.removeAt(i); + i--; + numSessionsToRemove--; } } diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index 9d8901adbc9c..c7fd20944c27 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -422,12 +422,15 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState @GuardedBy("mLock") private FillRequest mPendingFillRequest; - @Nullable Consumer<InlineSuggestionsRequest> newAutofillRequestLocked(ViewState viewState, - boolean isInlineRequest) { + void newAutofillRequestLocked(boolean isInlineRequest) { mPendingFillRequest = null; mWaitForInlineRequest = isInlineRequest; mPendingInlineSuggestionsRequest = null; - return isInlineRequest ? (inlineSuggestionsRequest) -> { + } + + @NonNull Consumer<InlineSuggestionsRequest> newInlineRequestConsumerLocked( + ViewState viewState) { + return (inlineSuggestionsRequest) -> { synchronized (mLock) { if (!mWaitForInlineRequest || mPendingInlineSuggestionsRequest != null) { return; @@ -436,7 +439,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState maybeRequestFillLocked(); viewState.resetState(ViewState.STATE_PENDING_CREATE_INLINE_REQUEST); } - } : null; + }; } void maybeRequestFillLocked() { @@ -808,32 +811,12 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // structure is taken. This causes only one fill request per burst of focus changes. cancelCurrentRequestLocked(); - // Only ask IME to create inline suggestions request if Autofill provider supports it and - // the render service is available except the autofill is triggered manually and the view - // is also not focused. - final RemoteInlineSuggestionRenderService remoteRenderService = - mService.getRemoteInlineSuggestionRenderServiceLocked(); - if (mSessionFlags.mInlineSupportedByService - && remoteRenderService != null - && isViewFocusedLocked(flags)) { - Consumer<InlineSuggestionsRequest> inlineSuggestionsRequestConsumer = - mAssistReceiver.newAutofillRequestLocked(viewState, - /* isInlineRequest= */ true); - if (inlineSuggestionsRequestConsumer != null) { - final AutofillId focusedId = mCurrentViewId; - remoteRenderService.getInlineSuggestionsRendererInfo( - new RemoteCallback((extras) -> { - synchronized (mLock) { - mInlineSessionController.onCreateInlineSuggestionsRequestLocked( - focusedId, inlineSuggestionsRequestConsumer, extras); - } - }, mHandler) - ); - viewState.setState(ViewState.STATE_PENDING_CREATE_INLINE_REQUEST); - } - } else { - mAssistReceiver.newAutofillRequestLocked(viewState, /* isInlineRequest= */ false); - } + final Consumer<InlineSuggestionsRequest> inlineSuggestionsRequestConsumer = + mAssistReceiver.newInlineRequestConsumerLocked(viewState); + final boolean isInlineRequest = maybeRequestCreateInlineSuggestionsRequestLocked( + /* isAugmented= */ false, inlineSuggestionsRequestConsumer, viewState, + mCurrentViewId, flags); + mAssistReceiver.newAutofillRequestLocked(isInlineRequest); // Now request the assist structure data. try { @@ -853,6 +836,60 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } } + @GuardedBy("mLock") + private boolean maybeRequestCreateInlineSuggestionsRequestLocked(boolean isAugmented, + @NonNull Consumer<InlineSuggestionsRequest> requestConsumer, + @NonNull ViewState viewState, @NonNull AutofillId focusedId, int flags) { + final RemoteInlineSuggestionRenderService remoteRenderService = + mService.getRemoteInlineSuggestionRenderServiceLocked(); + if (remoteRenderService == null || !isViewFocusedLocked(flags)) { + return false; + } + + // Standard: + // Only ask IME to create inline suggestions request if Autofill provider supports it + // and the render service is available except the autofill is triggered manually and the + // view is also not focused. + // + // Augmented: + // When the inline suggestion render service is available and the view is focused, there + // are 3 cases when augmented autofill should ask IME for inline suggestion request, + // because standard autofill flow didn't: + // 1. the field is augmented autofill only (when standard autofill provider is None or + // when it returns null response) + // 2. standard autofill provider doesn't support inline suggestion + // 3. we re-entered the autofill session and standard autofill was not re-triggered, + // this is recognized by seeing mExpiredResponse == true + if ((!isAugmented && mSessionFlags.mInlineSupportedByService) + || (isAugmented && (mSessionFlags.mAugmentedAutofillOnly + || !mSessionFlags.mInlineSupportedByService + || mSessionFlags.mExpiredResponse))) { + if (sDebug) { + Slog.d(TAG, "Create inline request for " + + (isAugmented ? "augmented" : "standard") + " autofill"); + } + requestCreateInlineSuggestionsRequestLocked(remoteRenderService, focusedId, + requestConsumer); + viewState.setState(ViewState.STATE_PENDING_CREATE_INLINE_REQUEST); + return true; + } + + return false; + } + + private void requestCreateInlineSuggestionsRequestLocked( + @NonNull RemoteInlineSuggestionRenderService remoteRenderService, + @NonNull AutofillId focusedId, + @NonNull Consumer<InlineSuggestionsRequest> requestConsumer) { + remoteRenderService.getInlineSuggestionsRendererInfo( + new RemoteCallback((extras) -> { + synchronized (mLock) { + mInlineSessionController.onCreateInlineSuggestionsRequestLocked( + focusedId, requestConsumer, extras); + } + }, mHandler)); + } + Session(@NonNull AutofillManagerServiceImpl service, @NonNull AutoFillUI ui, @NonNull Context context, @NonNull Handler handler, int userId, @NonNull Object lock, int sessionId, int taskId, int uid, @NonNull IBinder activityToken, @@ -2570,23 +2607,27 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } /** - * Starts (if necessary) a new fill request upon entering a view. + * Invokes either regular or augmented autofill process upon entering a view. * - * <p>A new request will be started in 2 scenarios: + * <p> A new standard autofill request will be started in 2 scenarios: * <ol> - * <li>If the user manually requested autofill. - * <li>If the view is part of a new partition. + * <li> If the user manually requested autofill. + * <li> If the view is part of a new partition. * </ol> + * </p> + * + * <p> A new augmented autofill request will be started if the autofill id was marked as + * uninterested/unfillable by the standard service. * * @param id The id of the view that is entered. * @param viewState The view that is entered. * @param flags The flag that was passed by the AutofillManager. * - * @return {@code true} if a new fill response is requested. + * @return {@code true} if either regular or augmented autofill is invoked. */ @GuardedBy("mLock") - private boolean requestNewFillResponseOnViewEnteredIfNecessaryLocked(@NonNull AutofillId id, - @NonNull ViewState viewState, int flags) { + private boolean maybeRequestFillOnViewEnteredLocked(@NonNull AutofillId id, + @NonNull ViewState viewState, boolean isSameViewEntered, int flags) { if ((flags & FLAG_MANUAL_REQUEST) != 0) { mSessionFlags.mAugmentedAutofillOnly = false; if (sDebug) Slog.d(TAG, "Re-starting session on view " + id + " and flags " + flags); @@ -2594,7 +2635,24 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState return true; } - // If it's not, then check if it it should start a partition. + if (mAugmentedAutofillableIds != null && mAugmentedAutofillableIds.contains(id)) { + // Regular autofill handled the view and returned null response, but it can trigger + // augmented autofill. + if (!isSameViewEntered) { + if (sDebug) Slog.d(TAG, "trigger augmented autofill."); + triggerAugmentedAutofillLocked(flags); + } else { + if (sDebug) Slog.d(TAG, "skip augmented autofill for same view."); + } + return true; + } else if (mSessionFlags.mAugmentedAutofillOnly && isSameViewEntered) { + // Regular autofill is disabled. + if (sDebug) Slog.d(TAG, "skip augmented autofill for same view."); + return true; + } + + // If it's not for augmented, then check if it should start a partition for + // regular autofill. if (shouldStartNewPartitionLocked(id)) { if (sDebug) { Slog.d(TAG, "Starting partition or augmented request for view id " + id + ": " @@ -2789,27 +2847,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState return; } - if ((flags & FLAG_MANUAL_REQUEST) == 0) { - // Not a manual request - if (mAugmentedAutofillableIds != null && mAugmentedAutofillableIds.contains( - id)) { - // Regular autofill handled the view and returned null response, but it - // triggered augmented autofill - if (!isSameViewEntered) { - if (sDebug) Slog.d(TAG, "trigger augmented autofill."); - triggerAugmentedAutofillLocked(flags); - } else { - if (sDebug) Slog.d(TAG, "skip augmented autofill for same view."); - } - return; - } else if (mSessionFlags.mAugmentedAutofillOnly && isSameViewEntered) { - // Regular autofill is disabled. - if (sDebug) Slog.d(TAG, "skip augmented autofill for same view."); - return; - } - } - - if (requestNewFillResponseOnViewEnteredIfNecessaryLocked(id, viewState, flags)) { + if (maybeRequestFillOnViewEnteredLocked(id, viewState, isSameViewEntered, flags)) { return; } @@ -3407,34 +3445,12 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } }; - // When the inline suggestion render service is available and the view is focused, there - // are 3 cases when augmented autofill should ask IME for inline suggestion request, - // because standard autofill flow didn't: - // 1. the field is augmented autofill only (when standard autofill provider is None or - // when it returns null response) - // 2. standard autofill provider doesn't support inline suggestion - // 3. we re-entered the autofill session and standard autofill was not re-triggered, this is - // recognized by seeing mExpiredResponse == true - final RemoteInlineSuggestionRenderService remoteRenderService = - mService.getRemoteInlineSuggestionRenderServiceLocked(); - if (remoteRenderService != null - && (mSessionFlags.mAugmentedAutofillOnly - || !mSessionFlags.mInlineSupportedByService - || mSessionFlags.mExpiredResponse) - && isViewFocusedLocked(flags)) { - if (sDebug) Slog.d(TAG, "Create inline request for augmented autofill"); - remoteRenderService.getInlineSuggestionsRendererInfo(new RemoteCallback( - (extras) -> { - synchronized (mLock) { - mInlineSessionController.onCreateInlineSuggestionsRequestLocked( - focusedId, /*requestConsumer=*/ requestAugmentedAutofill, - extras); - } - }, mHandler)); - } else { + if (!maybeRequestCreateInlineSuggestionsRequestLocked(/* isAugmented= */ true, + requestAugmentedAutofill, viewState, focusedId, flags)) { requestAugmentedAutofill.accept( mInlineSessionController.getInlineSuggestionsRequestLocked().orElse(null)); } + if (mAugmentedAutofillDestroyer == null) { mAugmentedAutofillDestroyer = remoteService::onDestroyAutofillWindowsRequest; } diff --git a/services/autofill/java/com/android/server/autofill/TEST_MAPPING b/services/autofill/java/com/android/server/autofill/TEST_MAPPING index cf058add0262..d8a69177387d 100644 --- a/services/autofill/java/com/android/server/autofill/TEST_MAPPING +++ b/services/autofill/java/com/android/server/autofill/TEST_MAPPING @@ -1,5 +1,5 @@ { - "presubmit": [ + "presubmit-large": [ { "name": "CtsAutoFillServiceTestCases", "options": [ diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java index ac6ed440093d..6c30999f63a4 100644 --- a/services/backup/java/com/android/server/backup/BackupManagerService.java +++ b/services/backup/java/com/android/server/backup/BackupManagerService.java @@ -512,7 +512,7 @@ public class BackupManagerService extends IBackupManager.Stub { int callingUid = Binder.getCallingUid(); if (CompatChanges.isChangeEnabled( BackupManager.IS_BACKUP_SERVICE_ACTIVE_ENFORCE_PERMISSION_IN_SERVICE, callingUid)) { - mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, "isBackupServiceActive"); } synchronized (mStateLock) { diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java index 0a80b02a964c..e6e52de0440f 100644 --- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java @@ -40,6 +40,7 @@ import android.bluetooth.BluetoothDevice; import android.companion.Association; import android.companion.AssociationRequest; import android.companion.CompanionDeviceManager; +import android.companion.DeviceNotAssociatedException; import android.companion.ICompanionDeviceDiscoveryService; import android.companion.ICompanionDeviceManager; import android.companion.IFindDeviceCallback; @@ -486,6 +487,43 @@ public class CompanionDeviceManagerService extends SystemService implements Bind a -> Objects.equals(a.getDeviceMacAddress(), macAddress)); } + @Override + public void registerDevicePresenceListenerService( + String packageName, String deviceAddress) + throws RemoteException { + checkCanRegisterObserverService(packageName, deviceAddress); + + //TODO(eugenesusla) implement + } + + @Override + public void unregisterDevicePresenceListenerService( + String packageName, String deviceAddress) + throws RemoteException { + checkCanRegisterObserverService(packageName, deviceAddress); + + //TODO(eugenesusla) implement + } + + private void checkCanRegisterObserverService(String packageName, String deviceAddress) + throws RemoteException { + getContext().enforceCallingOrSelfPermission( + android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE, + "[un]registerDevicePresenceListenerService"); + checkCallerIsSystemOr(packageName); + + int userId = getCallingUserId(); + Set<Association> deviceAssociations = CollectionUtils.filter( + getAllAssociations(userId, packageName), + association -> deviceAddress.equals(association.getDeviceMacAddress())); + + if (deviceAssociations.isEmpty()) { + throw new RemoteException(new DeviceNotAssociatedException("App " + packageName + + " is not associated with device " + deviceAddress + + " for user " + userId)); + } + } + private void checkCanCallNotificationApi(String callingPackage) throws RemoteException { checkCallerIsSystemOr(callingPackage); int userId = getCallingUserId(); diff --git a/services/core/Android.bp b/services/core/Android.bp index 17e3456e565b..252fd63ae83c 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -110,6 +110,7 @@ java_library_static { ], required: [ + "cec_config.xml", "gps_debug.conf", "protolog.conf.json.gz", ], @@ -172,6 +173,11 @@ java_library_host { } prebuilt_etc { + name: "cec_config.xml", + src: "java/com/android/server/hdmi/cec_config.xml", +} + +prebuilt_etc { name: "gps_debug.conf", src: "java/com/android/server/location/gnss/gps_debug.conf", } diff --git a/services/core/java/com/android/server/BluetoothAirplaneModeListener.java b/services/core/java/com/android/server/BluetoothAirplaneModeListener.java index 4d9680c785bc..aa56da5773e9 100644 --- a/services/core/java/com/android/server/BluetoothAirplaneModeListener.java +++ b/services/core/java/com/android/server/BluetoothAirplaneModeListener.java @@ -119,7 +119,9 @@ class BluetoothAirplaneModeListener { } return; } - mAirplaneHelper.onAirplaneModeChanged(mBluetoothManager); + if (mAirplaneHelper != null) { + mAirplaneHelper.onAirplaneModeChanged(mBluetoothManager); + } } @VisibleForTesting diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index 0a684287849a..dc24ffdb936d 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -1275,7 +1275,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { @Override public boolean bindBluetoothProfileService(int bluetoothProfile, IBluetoothProfileServiceConnection proxy) { - if (!mEnable) { + if (mState != BluetoothAdapter.STATE_ON) { if (DBG) { Slog.d(TAG, "Trying to bind to profile: " + bluetoothProfile + ", while Bluetooth was disabled"); @@ -1441,7 +1441,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mBluetoothLock.readLock().unlock(); } - if (!mEnable || state != BluetoothAdapter.STATE_ON) { + if (state != BluetoothAdapter.STATE_ON) { if (DBG) { Slog.d(TAG, "Unable to bindService while Bluetooth is disabled"); } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 854f9258e2b1..a6559f9521e0 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -129,6 +129,7 @@ import android.net.RouteInfoParcel; import android.net.SocketKeepalive; import android.net.TetheringManager; import android.net.UidRange; +import android.net.UidRangeParcel; import android.net.Uri; import android.net.VpnManager; import android.net.VpnService; @@ -184,7 +185,6 @@ import com.android.internal.net.VpnInfo; import com.android.internal.net.VpnProfile; import com.android.internal.util.ArrayUtils; import com.android.internal.util.AsyncChannel; -import com.android.internal.util.DumpUtils; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.LocationPermissionChecker; import com.android.internal.util.MessageUtils; @@ -2525,9 +2525,21 @@ public class ConnectivityService extends IConnectivityManager.Stub PriorityDump.dump(mPriorityDumper, fd, writer, args); } + private boolean checkDumpPermission(Context context, String tag, PrintWriter pw) { + 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() + + " due to missing android.permission.DUMP permission"); + return false; + } else { + return true; + } + } + private void doDump(FileDescriptor fd, PrintWriter writer, String[] args, boolean asProto) { final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); - if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; + if (!checkDumpPermission(mContext, TAG, pw)) return; if (asProto) return; if (ArrayUtils.contains(args, DIAG_ARG)) { @@ -2811,6 +2823,7 @@ public class ConnectivityService extends IConnectivityManager.Stub break; } case NetworkAgent.EVENT_UNDERLYING_NETWORKS_CHANGED: { + // TODO: prevent loops, e.g., if a network declares itself as underlying. if (!nai.supportsUnderlyingNetworks()) { Log.wtf(TAG, "Non-virtual networks cannot have underlying networks"); break; @@ -3410,6 +3423,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } } nai.clearLingerState(); + propagateUnderlyingNetworkCapabilities(nai.network); if (nai.isSatisfyingRequest(mDefaultRequest.requestId)) { mDefaultNetworkNai = null; updateDataActivityTracking(null /* newNetwork */, nai); @@ -3417,9 +3431,6 @@ public class ConnectivityService extends IConnectivityManager.Stub ensureNetworkTransitionWakelock(nai.toShortString()); } mLegacyTypeTracker.remove(nai, wasDefault); - if (!nai.networkCapabilities.hasTransport(TRANSPORT_VPN)) { - propagateUnderlyingNetworkCapabilities(); - } rematchAllNetworksAndRequests(); mLingerMonitor.noteDisconnect(nai); if (nai.created) { @@ -4808,17 +4819,35 @@ public class ConnectivityService extends IConnectivityManager.Stub } } + private Network[] underlyingNetworksOrDefault(Network[] underlyingNetworks) { + final Network defaultNetwork = getNetwork(getDefaultNetwork()); + if (underlyingNetworks == null && defaultNetwork != null) { + // null underlying networks means to track the default. + underlyingNetworks = new Network[] { defaultNetwork }; + } + return underlyingNetworks; + } + + // Returns true iff |network| is an underlying network of |nai|. + private boolean hasUnderlyingNetwork(NetworkAgentInfo nai, Network network) { + // TODO: support more than one level of underlying networks, either via a fixed-depth search + // (e.g., 2 levels of underlying networks), or via loop detection, or.... + if (!nai.supportsUnderlyingNetworks()) return false; + final Network[] underlying = underlyingNetworksOrDefault(nai.declaredUnderlyingNetworks); + return ArrayUtils.contains(underlying, network); + } + /** - * Ask all networks with underlying networks to recompute and update their capabilities. + * Recompute the capabilities for any networks that had a specific network as underlying. * * When underlying networks change, such networks may have to update capabilities to reflect * things like the metered bit, their transports, and so on. The capabilities are calculated * immediately. This method runs on the ConnectivityService thread. */ - private void propagateUnderlyingNetworkCapabilities() { + private void propagateUnderlyingNetworkCapabilities(Network updatedNetwork) { ensureRunningOnConnectivityServiceThread(); for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) { - if (nai.supportsUnderlyingNetworks()) { + if (updatedNetwork == null || hasUnderlyingNetwork(nai, updatedNetwork)) { updateCapabilitiesForNetwork(nai); } } @@ -5141,7 +5170,7 @@ public class ConnectivityService extends IConnectivityManager.Stub loge("Starting user already has a VPN"); return; } - userVpn = new Vpn(mHandler.getLooper(), mContext, mNMS, userId, mKeyStore); + userVpn = new Vpn(mHandler.getLooper(), mContext, mNMS, mNetd, userId, mKeyStore); mVpns.put(userId, userVpn); if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) { updateLockdownVpn(); @@ -5568,11 +5597,12 @@ public class ConnectivityService extends IConnectivityManager.Stub } private boolean checkUnsupportedStartingFrom(int version, String callingPackageName) { - final PackageManager pm = mContext.getPackageManager(); - final int userId = UserHandle.getCallingUserId(); + final UserHandle user = UserHandle.getUserHandleForUid(Binder.getCallingUid()); + final PackageManager pm = + mContext.createContextAsUser(user, 0 /* flags */).getPackageManager(); try { - final int callingVersion = pm.getApplicationInfoAsUser( - callingPackageName, 0 /* flags */, userId).targetSdkVersion; + final int callingVersion = pm.getApplicationInfo( + callingPackageName, 0 /* flags */).targetSdkVersion; if (callingVersion < version) return false; } catch (PackageManager.NameNotFoundException e) { } return true; @@ -6356,27 +6386,28 @@ public class ConnectivityService extends IConnectivityManager.Stub * This method should never alter the agent's NetworkCapabilities, only store data in |nai|. */ private void processCapabilitiesFromAgent(NetworkAgentInfo nai, NetworkCapabilities nc) { - nai.declaredMetered = !nc.hasCapability(NET_CAPABILITY_NOT_METERED); + // Note: resetting the owner UID before storing the agent capabilities in NAI means that if + // the agent attempts to change the owner UID, then nai.declaredCapabilities will not + // actually be the same as the capabilities sent by the agent. Still, it is safer to reset + // the owner UID here and behave as if the agent had never tried to change it. if (nai.networkCapabilities.getOwnerUid() != nc.getOwnerUid()) { Log.e(TAG, nai.toShortString() + ": ignoring attempt to change owner from " + nai.networkCapabilities.getOwnerUid() + " to " + nc.getOwnerUid()); nc.setOwnerUid(nai.networkCapabilities.getOwnerUid()); } + nai.declaredCapabilities = new NetworkCapabilities(nc); } - /** Modifies |caps| based on the capabilities of the specified underlying networks. */ + /** Modifies |newNc| based on the capabilities of |underlyingNetworks| and |agentCaps|. */ @VisibleForTesting void applyUnderlyingCapabilities(@Nullable Network[] underlyingNetworks, - @NonNull NetworkCapabilities caps, boolean declaredMetered) { - final Network defaultNetwork = getNetwork(getDefaultNetwork()); - if (underlyingNetworks == null && defaultNetwork != null) { - // null underlying networks means to track the default. - underlyingNetworks = new Network[] { defaultNetwork }; - } - int[] transportTypes = new int[] { NetworkCapabilities.TRANSPORT_VPN }; + @NonNull NetworkCapabilities agentCaps, @NonNull NetworkCapabilities newNc) { + underlyingNetworks = underlyingNetworksOrDefault(underlyingNetworks); + int[] transportTypes = agentCaps.getTransportTypes(); int downKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED; int upKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED; - boolean metered = declaredMetered; // metered if any underlying is metered, or agentMetered + // metered if any underlying is metered, or originally declared metered by the agent. + boolean metered = !agentCaps.hasCapability(NET_CAPABILITY_NOT_METERED); boolean roaming = false; // roaming if any underlying is roaming boolean congested = false; // congested if any underlying is congested boolean suspended = true; // suspended if all underlying are suspended @@ -6422,13 +6453,13 @@ public class ConnectivityService extends IConnectivityManager.Stub suspended = false; } - caps.setTransportTypes(transportTypes); - caps.setLinkDownstreamBandwidthKbps(downKbps); - caps.setLinkUpstreamBandwidthKbps(upKbps); - caps.setCapability(NET_CAPABILITY_NOT_METERED, !metered); - caps.setCapability(NET_CAPABILITY_NOT_ROAMING, !roaming); - caps.setCapability(NET_CAPABILITY_NOT_CONGESTED, !congested); - caps.setCapability(NET_CAPABILITY_NOT_SUSPENDED, !suspended); + newNc.setTransportTypes(transportTypes); + newNc.setLinkDownstreamBandwidthKbps(downKbps); + newNc.setLinkUpstreamBandwidthKbps(upKbps); + newNc.setCapability(NET_CAPABILITY_NOT_METERED, !metered); + newNc.setCapability(NET_CAPABILITY_NOT_ROAMING, !roaming); + newNc.setCapability(NET_CAPABILITY_NOT_CONGESTED, !congested); + newNc.setCapability(NET_CAPABILITY_NOT_SUSPENDED, !suspended); } /** @@ -6485,7 +6516,8 @@ public class ConnectivityService extends IConnectivityManager.Stub } if (nai.supportsUnderlyingNetworks()) { - applyUnderlyingCapabilities(nai.declaredUnderlyingNetworks, newNc, nai.declaredMetered); + applyUnderlyingCapabilities(nai.declaredUnderlyingNetworks, nai.declaredCapabilities, + newNc); } return newNc; @@ -6564,11 +6596,8 @@ public class ConnectivityService extends IConnectivityManager.Stub } } - if (!newNc.hasTransport(TRANSPORT_VPN)) { - // Tell VPNs about updated capabilities, since they may need to - // bubble those changes through. - propagateUnderlyingNetworkCapabilities(); - } + // This network might have been underlying another network. Propagate its capabilities. + propagateUnderlyingNetworkCapabilities(nai.network); if (!newNc.equalsTransportTypes(prevNc)) { mDnsManager.updateTransportsForNetwork( @@ -6610,6 +6639,16 @@ public class ConnectivityService extends IConnectivityManager.Stub && (lp.hasIpv6DefaultRoute() || lp.hasIpv6UnreachableDefaultRoute()); } + private static UidRangeParcel[] toUidRangeStableParcels(final @NonNull Set<UidRange> ranges) { + final UidRangeParcel[] stableRanges = new UidRangeParcel[ranges.size()]; + int index = 0; + for (UidRange range : ranges) { + stableRanges[index] = new UidRangeParcel(range.start, range.stop); + index++; + } + return stableRanges; + } + private void updateUids(NetworkAgentInfo nai, NetworkCapabilities prevNc, NetworkCapabilities newNc) { Set<UidRange> prevRanges = null == prevNc ? null : prevNc.getUids(); @@ -6629,14 +6668,11 @@ public class ConnectivityService extends IConnectivityManager.Stub // removing old range works because, unlike the filtering rules below, it's possible to // add duplicate UID routing rules. if (!newRanges.isEmpty()) { - final UidRange[] addedRangesArray = new UidRange[newRanges.size()]; - newRanges.toArray(addedRangesArray); - mNMS.addVpnUidRanges(nai.network.getNetId(), addedRangesArray); + mNetd.networkAddUidRanges(nai.network.netId, toUidRangeStableParcels(newRanges)); } if (!prevRanges.isEmpty()) { - final UidRange[] removedRangesArray = new UidRange[prevRanges.size()]; - prevRanges.toArray(removedRangesArray); - mNMS.removeVpnUidRanges(nai.network.getNetId(), removedRangesArray); + mNetd.networkRemoveUidRanges( + nai.network.netId, toUidRangeStableParcels(prevRanges)); } final boolean wasFiltering = requiresVpnIsolation(nai, prevNc, nai.linkProperties); final boolean shouldFilter = requiresVpnIsolation(nai, newNc, nai.linkProperties); @@ -6891,8 +6927,10 @@ public class ConnectivityService extends IConnectivityManager.Stub updateTcpBufferSizes(null != newNetwork ? newNetwork.linkProperties.getTcpBufferSizes() : null); notifyIfacesChangedForNetworkStats(); - // Fix up the NetworkCapabilities of any VPNs that don't specify underlying networks. - propagateUnderlyingNetworkCapabilities(); + // Fix up the NetworkCapabilities of any networks that have this network as underlying. + if (newNetwork != null) { + propagateUnderlyingNetworkCapabilities(newNetwork.network); + } } private void processListenRequests(@NonNull final NetworkAgentInfo nai) { @@ -7348,13 +7386,11 @@ public class ConnectivityService extends IConnectivityManager.Stub networkAgent.networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND); if (!createNativeNetwork(networkAgent)) return; - if (networkAgent.isVPN()) { - // Initialize the VPN capabilities to their starting values according to the - // underlying networks. This will avoid a spurious callback to - // onCapabilitiesUpdated being sent in updateAllVpnCapabilities below as - // the VPN would switch from its default, blank capabilities to those - // that reflect the capabilities of its underlying networks. - propagateUnderlyingNetworkCapabilities(); + if (networkAgent.supportsUnderlyingNetworks()) { + // Initialize the network's capabilities to their starting values according to the + // underlying networks. This ensures that the capabilities are correct before + // anything happens to the network. + updateCapabilitiesForNetwork(networkAgent); } networkAgent.created = true; } @@ -7396,10 +7432,6 @@ public class ConnectivityService extends IConnectivityManager.Stub // doing. updateSignalStrengthThresholds(networkAgent, "CONNECT", null); - if (networkAgent.supportsUnderlyingNetworks()) { - propagateUnderlyingNetworkCapabilities(); - } - // Consider network even though it is not yet validated. rematchAllNetworksAndRequests(); diff --git a/services/core/java/com/android/server/DropBoxManagerService.java b/services/core/java/com/android/server/DropBoxManagerService.java index 886bfb8f4736..30fc3364f6b7 100644 --- a/services/core/java/com/android/server/DropBoxManagerService.java +++ b/services/core/java/com/android/server/DropBoxManagerService.java @@ -268,7 +268,7 @@ public final class DropBoxManagerService extends SystemService { if (!DropBoxManagerService.this.mBooted) { intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); } - getContext().sendBroadcastAsUser(intent, UserHandle.SYSTEM, + getContext().sendBroadcastAsUser(intent, UserHandle.ALL, android.Manifest.permission.READ_LOGS); } diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java index 8ed23f900d73..c34285e9c062 100644 --- a/services/core/java/com/android/server/GestureLauncherService.java +++ b/services/core/java/com/android/server/GestureLauncherService.java @@ -257,7 +257,7 @@ public class GestureLauncherService extends SystemService { @VisibleForTesting void updateEmergencyGestureEnabled() { - boolean enabled = isEmergencyGestureEnabled(mContext, mUserId); + boolean enabled = isEmergencyGestureSettingEnabled(mContext, mUserId); synchronized (this) { mEmergencyGestureEnabled = enabled; } @@ -390,38 +390,50 @@ public class GestureLauncherService extends SystemService { /** * Whether to enable emergency gesture. */ - public static boolean isEmergencyGestureEnabled(Context context, int userId) { - return Settings.Secure.getIntForUser(context.getContentResolver(), + @VisibleForTesting + static boolean isEmergencyGestureSettingEnabled(Context context, int userId) { + return isEmergencyGestureEnabled(context.getResources()) + && Settings.Secure.getIntForUser(context.getContentResolver(), Settings.Secure.EMERGENCY_GESTURE_ENABLED, 0, userId) != 0; } /** * Whether to enable the camera launch gesture. */ - public static boolean isCameraLaunchEnabled(Resources resources) { + private static boolean isCameraLaunchEnabled(Resources resources) { boolean configSet = resources.getInteger( com.android.internal.R.integer.config_cameraLaunchGestureSensorType) != -1; return configSet && !SystemProperties.getBoolean("gesture.disable_camera_launch", false); } - public static boolean isCameraDoubleTapPowerEnabled(Resources resources) { + @VisibleForTesting + static boolean isCameraDoubleTapPowerEnabled(Resources resources) { return resources.getBoolean( com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled); } - public static boolean isCameraLiftTriggerEnabled(Resources resources) { + private static boolean isCameraLiftTriggerEnabled(Resources resources) { boolean configSet = resources.getInteger( com.android.internal.R.integer.config_cameraLiftTriggerSensorType) != -1; return configSet; } /** + * Whether or not the emergency gesture feature is enabled by platform + */ + private static boolean isEmergencyGestureEnabled(Resources resources) { + return resources.getBoolean(com.android.internal.R.bool.config_emergencyGestureEnabled); + } + + /** * Whether GestureLauncherService should be enabled according to system properties. */ public static boolean isGestureLauncherEnabled(Resources resources) { - return isCameraLaunchEnabled(resources) || isCameraDoubleTapPowerEnabled(resources) || - isCameraLiftTriggerEnabled(resources); + return isCameraLaunchEnabled(resources) + || isCameraDoubleTapPowerEnabled(resources) + || isCameraLiftTriggerEnabled(resources) + || isEmergencyGestureEnabled(resources); } /** diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index 5e86f855c1e7..086cc1ca32ed 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -60,7 +60,6 @@ import android.net.NetworkStack; import android.net.NetworkStats; import android.net.RouteInfo; import android.net.TetherStatsParcel; -import android.net.UidRange; import android.net.UidRangeParcel; import android.net.shared.NetdUtils; import android.net.shared.RouteUtils; @@ -1393,38 +1392,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub { } } - private static UidRangeParcel makeUidRangeParcel(int start, int stop) { - UidRangeParcel range = new UidRangeParcel(); - range.start = start; - range.stop = stop; - return range; - } - - private static UidRangeParcel[] toStableParcels(UidRange[] ranges) { - UidRangeParcel[] stableRanges = new UidRangeParcel[ranges.length]; - for (int i = 0; i < ranges.length; i++) { - stableRanges[i] = makeUidRangeParcel(ranges[i].start, ranges[i].stop); - } - return stableRanges; - } - - @Override - public void setAllowOnlyVpnForUids(boolean add, UidRange[] uidRanges) - throws ServiceSpecificException { - NetworkStack.checkNetworkStackPermission(mContext); - try { - mNetdService.networkRejectNonSecureVpn(add, toStableParcels(uidRanges)); - } catch (ServiceSpecificException e) { - Log.w(TAG, "setAllowOnlyVpnForUids(" + add + ", " + Arrays.toString(uidRanges) + ")" - + ": netd command failed", e); - throw e; - } catch (RemoteException e) { - Log.w(TAG, "setAllowOnlyVpnForUids(" + add + ", " + Arrays.toString(uidRanges) + ")" - + ": netd command failed", e); - throw e.rethrowAsRuntimeException(); - } - } - private void applyUidCleartextNetworkPolicy(int uid, int policy) { final int policyValue; switch (policy) { @@ -1553,27 +1520,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub { } @Override - public void addVpnUidRanges(int netId, UidRange[] ranges) { - NetworkStack.checkNetworkStackPermission(mContext); - - try { - mNetdService.networkAddUidRanges(netId, toStableParcels(ranges)); - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException(e); - } - } - - @Override - public void removeVpnUidRanges(int netId, UidRange[] ranges) { - NetworkStack.checkNetworkStackPermission(mContext); - try { - mNetdService.networkRemoveUidRanges(netId, toStableParcels(ranges)); - } catch (RemoteException | ServiceSpecificException e) { - throw new IllegalStateException(e); - } - } - - @Override public void setFirewallEnabled(boolean enabled) { enforceSystemUid(); try { @@ -1616,7 +1562,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub { ranges = new UidRangeParcel[] { // TODO: is there a better way of finding all existing users? If so, we could // specify their ranges here. - makeUidRangeParcel(Process.FIRST_APPLICATION_UID, Integer.MAX_VALUE), + new UidRangeParcel(Process.FIRST_APPLICATION_UID, Integer.MAX_VALUE), }; // ... except for the UIDs that have allow rules. synchronized (mRulesLock) { @@ -1647,7 +1593,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub { for (int i = 0; i < ranges.length; i++) { if (rules.valueAt(i) == FIREWALL_RULE_DENY) { int uid = rules.keyAt(i); - ranges[numUids] = makeUidRangeParcel(uid, uid); + ranges[numUids] = new UidRangeParcel(uid, uid); numUids++; } } diff --git a/services/core/java/com/android/server/OWNERS b/services/core/java/com/android/server/OWNERS index 733590c4f6c6..a10764b9956c 100644 --- a/services/core/java/com/android/server/OWNERS +++ b/services/core/java/com/android/server/OWNERS @@ -10,8 +10,11 @@ per-file ZramWriteback.java = minchan@google.com, rajekumar@google.com, srnvs@go # Userspace reboot per-file UserspaceRebootLogger.java = ioffe@google.com, tomcherry@google.com +# Sensor Privacy +per-file SensorPrivacyService.java = file:platform/frameworks/native:/libs/sensorprivacy/OWNERS + per-file *Alarm* = file:/apex/jobscheduler/OWNERS -per-file *AppOps* = file:/core/java/android/permission/OWNERS +per-file *AppOp* = file:/core/java/android/permission/OWNERS per-file *Bluetooth* = file:/core/java/android/bluetooth/OWNERS per-file *Gnss* = file:/services/core/java/com/android/server/location/OWNERS per-file *Location* = file:/services/core/java/com/android/server/location/OWNERS diff --git a/services/core/java/com/android/server/SensorPrivacyService.java b/services/core/java/com/android/server/SensorPrivacyService.java index 51e2b12bcee4..010213453940 100644 --- a/services/core/java/com/android/server/SensorPrivacyService.java +++ b/services/core/java/com/android/server/SensorPrivacyService.java @@ -16,39 +16,68 @@ package com.android.server; +import static android.app.AppOpsManager.MODE_ALLOWED; +import static android.app.AppOpsManager.OP_CAMERA; +import static android.app.AppOpsManager.OP_RECORD_AUDIO; import static android.content.pm.PackageManager.PERMISSION_GRANTED; - +import static android.service.SensorPrivacyIndividualEnabledSensorProto.CAMERA; +import static android.service.SensorPrivacyIndividualEnabledSensorProto.MICROPHONE; +import static android.service.SensorPrivacyIndividualEnabledSensorProto.UNKNOWN; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.app.AppOpsManager; +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.graphics.drawable.Icon; import android.hardware.ISensorPrivacyListener; import android.hardware.ISensorPrivacyManager; +import android.hardware.SensorPrivacyManager; +import android.os.Binder; import android.os.Environment; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.RemoteCallbackList; import android.os.RemoteException; +import android.os.ResultReceiver; +import android.os.ShellCallback; +import android.os.ShellCommand; +import android.service.SensorPrivacyIndividualEnabledSensorProto; +import android.service.SensorPrivacyServiceDumpProto; import android.util.ArrayMap; import android.util.AtomicFile; +import android.util.IndentingPrintWriter; import android.util.Log; +import android.util.SparseBooleanArray; import android.util.TypedXmlPullParser; import android.util.TypedXmlSerializer; import android.util.Xml; +import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; -import com.android.internal.util.FastXmlSerializer; +import com.android.internal.util.DumpUtils; import com.android.internal.util.XmlUtils; +import com.android.internal.util.dump.DualDumpOutputStream; import com.android.internal.util.function.pooled.PooledLambda; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; import java.io.File; +import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; -import java.nio.charset.StandardCharsets; +import java.io.PrintWriter; import java.util.NoSuchElementException; +import java.util.Objects; /** @hide */ public final class SensorPrivacyService extends SystemService { @@ -57,7 +86,15 @@ public final class SensorPrivacyService extends SystemService { private static final String SENSOR_PRIVACY_XML_FILE = "sensor_privacy.xml"; private static final String XML_TAG_SENSOR_PRIVACY = "sensor-privacy"; + private static final String XML_TAG_INDIVIDUAL_SENSOR_PRIVACY = "individual-sensor-privacy"; private static final String XML_ATTRIBUTE_ENABLED = "enabled"; + private static final String XML_ATTRIBUTE_SENSOR = "sensor"; + + private static final String SENSOR_PRIVACY_CHANNEL_ID = Context.SENSOR_PRIVACY_SERVICE; + private static final String ACTION_DISABLE_INDIVIDUAL_SENSOR_PRIVACY = + SensorPrivacyService.class.getName() + ".action.disable_sensor_privacy"; + private static final String EXTRA_SENSOR = SensorPrivacyService.class.getName() + + ".extra.sensor"; private final SensorPrivacyServiceImpl mSensorPrivacyServiceImpl; @@ -71,7 +108,8 @@ public final class SensorPrivacyService extends SystemService { publishBinderService(Context.SENSOR_PRIVACY_SERVICE, mSensorPrivacyServiceImpl); } - class SensorPrivacyServiceImpl extends ISensorPrivacyManager.Stub { + class SensorPrivacyServiceImpl extends ISensorPrivacyManager.Stub implements + AppOpsManager.OnOpNotedListener, AppOpsManager.OnOpStartedListener { private final SensorPrivacyHandler mHandler; private final Context mContext; @@ -80,6 +118,7 @@ public final class SensorPrivacyService extends SystemService { private final AtomicFile mAtomicFile; @GuardedBy("mLock") private boolean mEnabled; + private SparseBooleanArray mIndividualEnabled = new SparseBooleanArray(); SensorPrivacyServiceImpl(Context context) { mContext = context; @@ -88,8 +127,100 @@ public final class SensorPrivacyService extends SystemService { SENSOR_PRIVACY_XML_FILE); mAtomicFile = new AtomicFile(sensorPrivacyFile); synchronized (mLock) { - mEnabled = readPersistedSensorPrivacyEnabledLocked(); + readPersistedSensorPrivacyStateLocked(); } + + int[] micAndCameraOps = new int[]{OP_RECORD_AUDIO, OP_CAMERA}; + AppOpsManager appOpsManager = mContext.getSystemService(AppOpsManager.class); + appOpsManager.startWatchingNoted(micAndCameraOps, this); + appOpsManager.startWatchingStarted(micAndCameraOps, this); + + mContext.registerReceiver(new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + setIndividualSensorPrivacy(intent.getIntExtra(EXTRA_SENSOR, UNKNOWN), false); + } + }, new IntentFilter(ACTION_DISABLE_INDIVIDUAL_SENSOR_PRIVACY)); + } + + @Override + public void onOpStarted(int code, int uid, String packageName, + @AppOpsManager.OpFlags int flags, @AppOpsManager.Mode int result) { + onOpNoted(code, uid, packageName, flags, result); + } + + @Override + public void onOpNoted(int code, int uid, String packageName, + @AppOpsManager.OpFlags int flags, @AppOpsManager.Mode int result) { + if (result != MODE_ALLOWED || (flags & AppOpsManager.OP_FLAGS_ALL_TRUSTED) == 0) { + return; + } + + int sensor; + if (code == OP_RECORD_AUDIO) { + sensor = MICROPHONE; + } else { + sensor = CAMERA; + } + + onSensorUseStarted(uid, packageName, sensor); + } + + /** + * Called when a sensor protected by individual sensor privacy is attempting to get used. + * + * @param uid The uid of the app using the sensor + * @param packageName The package name of the app using the sensor + * @param sensor The sensor that is attempting to be used + */ + private void onSensorUseStarted(int uid, String packageName, int sensor) { + if (!isIndividualSensorPrivacyEnabled(sensor)) { + return; + } + + // TODO moltmann: Use dialog instead of notification if we can determine the activity + // which triggered this usage + + // TODO evanseverson: - Implement final UX for notification + // - Finalize strings and icons and add as resources + + int icon; + CharSequence notificationMessage; + if (sensor == MICROPHONE) { + icon = com.android.internal.R.drawable.ic_mic; + notificationMessage = "Microphone is muted because of sensor privacy"; + } else { + icon = com.android.internal.R.drawable.ic_camera; + notificationMessage = "Camera is blocked because of sensor privacy"; + } + + NotificationManager notificationManager = + mContext.getSystemService(NotificationManager.class); + NotificationChannel channel = new NotificationChannel( + SENSOR_PRIVACY_CHANNEL_ID, "Sensor privacy", + NotificationManager.IMPORTANCE_HIGH); + channel.setSound(null, null); + channel.setBypassDnd(true); + channel.enableVibration(false); + channel.setBlockable(false); + + notificationManager.createNotificationChannel(channel); + + notificationManager.notify(sensor, + new Notification.Builder(mContext, SENSOR_PRIVACY_CHANNEL_ID) + .setContentTitle(notificationMessage) + .setSmallIcon(icon) + .addAction(new Notification.Action.Builder( + Icon.createWithResource(mContext, icon), + "Disable sensor privacy", + PendingIntent.getBroadcast(mContext, sensor, + new Intent(ACTION_DISABLE_INDIVIDUAL_SENSOR_PRIVACY) + .setPackage(mContext.getPackageName()) + .putExtra(EXTRA_SENSOR, sensor), + PendingIntent.FLAG_IMMUTABLE + | PendingIntent.FLAG_UPDATE_CURRENT)) + .build()) + .build()); } /** @@ -101,24 +232,28 @@ public final class SensorPrivacyService extends SystemService { enforceSensorPrivacyPermission(); synchronized (mLock) { mEnabled = enable; - FileOutputStream outputStream = null; - try { - outputStream = mAtomicFile.startWrite(); - TypedXmlSerializer serializer = Xml.resolveSerializer(outputStream); - serializer.startDocument(null, true); - serializer.startTag(null, XML_TAG_SENSOR_PRIVACY); - serializer.attributeBoolean(null, XML_ATTRIBUTE_ENABLED, enable); - serializer.endTag(null, XML_TAG_SENSOR_PRIVACY); - serializer.endDocument(); - mAtomicFile.finishWrite(outputStream); - } catch (IOException e) { - Log.e(TAG, "Caught an exception persisting the sensor privacy state: ", e); - mAtomicFile.failWrite(outputStream); - } + persistSensorPrivacyStateLocked(); } mHandler.onSensorPrivacyChanged(enable); } + public void setIndividualSensorPrivacy(int sensor, boolean enable) { + enforceSensorPrivacyPermission(); + synchronized (mLock) { + mIndividualEnabled.put(sensor, enable); + + if (!enable) { + // Remove any notifications prompting the user to disable sensory privacy + NotificationManager notificationManager = + mContext.getSystemService(NotificationManager.class); + + notificationManager.cancel(sensor); + } + + persistSensorPrivacyState(); + } + } + /** * Enforces the caller contains the necessary permission to change the state of sensor * privacy. @@ -143,30 +278,48 @@ public final class SensorPrivacyService extends SystemService { } } + @Override + public boolean isIndividualSensorPrivacyEnabled(int sensor) { + synchronized (mLock) { + return mIndividualEnabled.get(sensor, false); + } + } + /** * Returns the state of sensor privacy from persistent storage. */ - private boolean readPersistedSensorPrivacyEnabledLocked() { + private void readPersistedSensorPrivacyStateLocked() { // if the file does not exist then sensor privacy has not yet been enabled on // the device. if (!mAtomicFile.exists()) { - return false; + return; } - boolean enabled; try (FileInputStream inputStream = mAtomicFile.openRead()) { TypedXmlPullParser parser = Xml.resolvePullParser(inputStream); XmlUtils.beginDocument(parser, XML_TAG_SENSOR_PRIVACY); parser.next(); - String tagName = parser.getName(); - enabled = parser.getAttributeBoolean(null, XML_ATTRIBUTE_ENABLED, false); + mEnabled = parser.getAttributeBoolean(null, XML_ATTRIBUTE_ENABLED, false); + + XmlUtils.nextElement(parser); + while (parser.getEventType() != XmlPullParser.END_DOCUMENT) { + String tagName = parser.getName(); + if (XML_TAG_INDIVIDUAL_SENSOR_PRIVACY.equals(tagName)) { + int sensor = XmlUtils.readIntAttribute(parser, XML_ATTRIBUTE_SENSOR); + boolean enabled = XmlUtils.readBooleanAttribute(parser, + XML_ATTRIBUTE_ENABLED); + mIndividualEnabled.put(sensor, enabled); + XmlUtils.skipCurrentTag(parser); + } else { + XmlUtils.nextElement(parser); + } + } + } catch (IOException | XmlPullParserException e) { Log.e(TAG, "Caught an exception reading the state from storage: ", e); // Delete the file to prevent the same error on subsequent calls and assume sensor // privacy is not enabled. mAtomicFile.delete(); - enabled = false; } - return enabled; } /** @@ -174,20 +327,33 @@ public final class SensorPrivacyService extends SystemService { */ private void persistSensorPrivacyState() { synchronized (mLock) { - FileOutputStream outputStream = null; - try { - outputStream = mAtomicFile.startWrite(); - TypedXmlSerializer serializer = Xml.resolveSerializer(outputStream); - serializer.startDocument(null, true); - serializer.startTag(null, XML_TAG_SENSOR_PRIVACY); - serializer.attributeBoolean(null, XML_ATTRIBUTE_ENABLED, mEnabled); - serializer.endTag(null, XML_TAG_SENSOR_PRIVACY); - serializer.endDocument(); - mAtomicFile.finishWrite(outputStream); - } catch (IOException e) { - Log.e(TAG, "Caught an exception persisting the sensor privacy state: ", e); - mAtomicFile.failWrite(outputStream); + persistSensorPrivacyStateLocked(); + } + } + + private void persistSensorPrivacyStateLocked() { + FileOutputStream outputStream = null; + try { + outputStream = mAtomicFile.startWrite(); + TypedXmlSerializer serializer = Xml.resolveSerializer(outputStream); + serializer.startDocument(null, true); + serializer.startTag(null, XML_TAG_SENSOR_PRIVACY); + serializer.attributeBoolean(null, XML_ATTRIBUTE_ENABLED, mEnabled); + int numIndividual = mIndividualEnabled.size(); + for (int i = 0; i < numIndividual; i++) { + serializer.startTag(null, XML_TAG_INDIVIDUAL_SENSOR_PRIVACY); + int sensor = mIndividualEnabled.keyAt(i); + boolean enabled = mIndividualEnabled.valueAt(i); + serializer.attributeInt(null, XML_ATTRIBUTE_SENSOR, sensor); + serializer.attributeBoolean(null, XML_ATTRIBUTE_ENABLED, enabled); + serializer.endTag(null, XML_TAG_INDIVIDUAL_SENSOR_PRIVACY); } + serializer.endTag(null, XML_TAG_SENSOR_PRIVACY); + serializer.endDocument(); + mAtomicFile.finishWrite(outputStream); + } catch (IOException e) { + Log.e(TAG, "Caught an exception persisting the sensor privacy state: ", e); + mAtomicFile.failWrite(outputStream); } } @@ -212,6 +378,170 @@ public final class SensorPrivacyService extends SystemService { } mHandler.removeListener(listener); } + + @Override + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + Objects.requireNonNull(fd); + + if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; + + int opti = 0; + boolean dumpAsProto = false; + while (opti < args.length) { + String opt = args[opti]; + if (opt == null || opt.length() <= 0 || opt.charAt(0) != '-') { + break; + } + opti++; + if ("--proto".equals(opt)) { + dumpAsProto = true; + } else { + pw.println("Unknown argument: " + opt + "; use -h for help"); + } + } + + final long identity = Binder.clearCallingIdentity(); + try { + if (dumpAsProto) { + dump(new DualDumpOutputStream(new ProtoOutputStream(fd))); + } else { + pw.println("SENSOR PRIVACY MANAGER STATE (dumpsys " + + Context.SENSOR_PRIVACY_SERVICE + ")"); + + dump(new DualDumpOutputStream(new IndentingPrintWriter(pw, " "))); + } + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + /** + * Dump state to {@link DualDumpOutputStream}. + * + * @param dumpStream The destination to dump to + */ + private void dump(@NonNull DualDumpOutputStream dumpStream) { + synchronized (mLock) { + dumpStream.write("is_enabled", SensorPrivacyServiceDumpProto.IS_ENABLED, mEnabled); + + int numIndividualEnabled = mIndividualEnabled.size(); + for (int i = 0; i < numIndividualEnabled; i++) { + long token = dumpStream.start("individual_enabled_sensor", + SensorPrivacyServiceDumpProto.INDIVIDUAL_ENABLED_SENSOR); + + dumpStream.write("sensor", + SensorPrivacyIndividualEnabledSensorProto.SENSOR, + mIndividualEnabled.keyAt(i)); + dumpStream.write("is_enabled", + SensorPrivacyIndividualEnabledSensorProto.IS_ENABLED, + mIndividualEnabled.valueAt(i)); + + dumpStream.end(token); + } + } + + dumpStream.flush(); + } + + /** + * Convert a string into a {@link SensorPrivacyManager.IndividualSensor id}. + * + * @param sensor The name to convert + * + * @return The id corresponding to the name + */ + private @SensorPrivacyManager.IndividualSensor int sensorStrToId(@Nullable String sensor) { + if (sensor == null) { + return UNKNOWN; + } + + switch (sensor) { + case "microphone": + return MICROPHONE; + case "camera": + return CAMERA; + default: { + return UNKNOWN; + } + } + } + + @Override + public void onShellCommand(FileDescriptor in, FileDescriptor out, + FileDescriptor err, String[] args, ShellCallback callback, + ResultReceiver resultReceiver) { + (new ShellCommand() { + @Override + public int onCommand(String cmd) { + if (cmd == null) { + return handleDefaultCommands(cmd); + } + + final PrintWriter pw = getOutPrintWriter(); + switch (cmd) { + case "enable" : { + int sensor = sensorStrToId(getNextArg()); + if (sensor == UNKNOWN) { + pw.println("Invalid sensor"); + return -1; + } + + setIndividualSensorPrivacy(sensor, true); + } + break; + case "disable" : { + int sensor = sensorStrToId(getNextArg()); + if (sensor == UNKNOWN) { + pw.println("Invalid sensor"); + return -1; + } + + setIndividualSensorPrivacy(sensor, false); + } + break; + case "reset": { + int sensor = sensorStrToId(getNextArg()); + if (sensor == UNKNOWN) { + pw.println("Invalid sensor"); + return -1; + } + + enforceSensorPrivacyPermission(); + + synchronized (mLock) { + mIndividualEnabled.delete(sensor); + persistSensorPrivacyState(); + } + } + break; + default: + return handleDefaultCommands(cmd); + } + + return 0; + } + + @Override + public void onHelp() { + final PrintWriter pw = getOutPrintWriter(); + + pw.println("Sensor privacy manager (" + Context.SENSOR_PRIVACY_SERVICE + + ") commands:"); + pw.println(" help"); + pw.println(" Print this help text."); + pw.println(""); + pw.println(" enable SENSOR"); + pw.println(" Enable privacy for a certain sensor."); + pw.println(""); + pw.println(" disable SENSOR"); + pw.println(" Disable privacy for a certain sensor."); + pw.println(""); + pw.println(" reset SENSOR"); + pw.println(" Reset privacy state for a certain sensor."); + pw.println(""); + } + }).exec(this, in, out, err, args, callback, resultReceiver); + } } /** diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index c95bfd031af4..d9ddebdccea6 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -108,6 +108,7 @@ import android.os.storage.StorageManagerInternal; import android.os.storage.StorageVolume; import android.os.storage.VolumeInfo; import android.os.storage.VolumeRecord; +import android.provider.DeviceConfig; import android.provider.DocumentsContract; import android.provider.Downloads; import android.provider.MediaStore; @@ -879,6 +880,8 @@ class StorageManagerService extends IStorageManager.Stub com.android.internal.R.bool.config_zramWriteback)) { ZramWriteback.scheduleZramWriteback(mContext); } + + updateTranscodeEnabled(); } /** @@ -910,6 +913,21 @@ class StorageManagerService extends IStorageManager.Stub } } + private void updateTranscodeEnabled() { + // See MediaProvider TranscodeHelper#getBooleanProperty for more information + boolean transcodeEnabled = false; + boolean defaultValue = true; + + if (SystemProperties.getBoolean("persist.sys.fuse.transcode_user_control", false)) { + transcodeEnabled = SystemProperties.getBoolean("persist.sys.fuse.transcode_enabled", + defaultValue); + } else { + transcodeEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT, + "transcode_enabled", defaultValue); + } + SystemProperties.set("sys.fuse.transcode_enabled", String.valueOf(transcodeEnabled)); + } + /** * MediaProvider has a ton of code that makes assumptions about storage * paths never changing, so we outright kill them to pick up new state. @@ -4375,14 +4393,7 @@ class StorageManagerService extends IStorageManager.Stub // Create package obb and data dir if it doesn't exist. int appUid = UserHandle.getUid(userId, mPmInternal.getPackage(pkg).getUid()); - File file = new File(packageObbDir); - if (!file.exists()) { - vold.setupAppDir(packageObbDir, appUid); - } - file = new File(packageDataDir); - if (!file.exists()) { - vold.setupAppDir(packageDataDir, appUid); - } + vold.ensureAppDirsCreated(new String[] {packageObbDir, packageDataDir}, appUid); } } catch (ServiceManager.ServiceNotFoundException | RemoteException e) { Slog.e(TAG, "Unable to create obb and data directories for " + processName,e); @@ -4488,10 +4499,13 @@ class StorageManagerService extends IStorageManager.Stub // When using FUSE, we may need to kill the app if the op changes switch(code) { case OP_REQUEST_INSTALL_PACKAGES: - if (previousMode == MODE_ALLOWED || mode == MODE_ALLOWED) { - // If we transition to/from MODE_ALLOWED, kill the app to make - // sure it has the correct view of /storage. Changing between - // MODE_DEFAULT / MODE_ERRORED is a no-op + // In R, we used to kill the app here if it transitioned to/from + // MODE_ALLOWED, to make sure the app had the correct (writable) OBB + // view. But the majority of apps don't handle OBBs anyway, and for those + // that do, they can restart themselves. Therefore, starting from S, + // only kill the app when it transitions away from MODE_ALLOWED (eg, + // when the permission is taken away). + if (previousMode == MODE_ALLOWED && mode != MODE_ALLOWED) { killAppForOpChange(code, uid); } return; diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java index 75ebe70591df..655d8abf3e84 100644 --- a/services/core/java/com/android/server/TestNetworkService.java +++ b/services/core/java/com/android/server/TestNetworkService.java @@ -61,9 +61,8 @@ import java.util.concurrent.atomic.AtomicInteger; /** @hide */ class TestNetworkService extends ITestNetworkManager.Stub { - @NonNull private static final String TAG = TestNetworkService.class.getSimpleName(); @NonNull private static final String TEST_NETWORK_LOGTAG = "TestNetworkAgent"; - @NonNull private static final String TEST_NETWORK_PROVIDER_NAME = TAG; + @NonNull private static final String TEST_NETWORK_PROVIDER_NAME = "TestNetworkProvider"; @NonNull private static final AtomicInteger sTestTunIndex = new AtomicInteger(); @NonNull private final Context mContext; @@ -168,17 +167,15 @@ class TestNetworkService extends ITestNetworkManager.Stub { private TestNetworkAgent( @NonNull Context context, @NonNull Looper looper, - @NonNull NetworkAgentConfig config, @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, + @NonNull NetworkAgentConfig config, int uid, @NonNull IBinder binder, @NonNull NetworkProvider np) throws RemoteException { super(context, looper, TEST_NETWORK_LOGTAG, nc, lp, NETWORK_SCORE, config, np); - mUid = uid; - synchronized (mBinderLock) { mBinder = binder; // Binder null-checks in create() @@ -286,8 +283,8 @@ class TestNetworkService extends ITestNetworkManager.Stub { lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null, iface)); } - final TestNetworkAgent agent = new TestNetworkAgent(context, looper, - new NetworkAgentConfig.Builder().build(), nc, lp, callingUid, binder, + final TestNetworkAgent agent = new TestNetworkAgent(context, looper, nc, lp, + new NetworkAgentConfig.Builder().build(), callingUid, binder, mNetworkProvider); agent.register(); agent.markConnected(); diff --git a/services/core/java/com/android/server/VibratorManagerService.java b/services/core/java/com/android/server/VibratorManagerService.java index f1f2815be8fa..eca1dfaed810 100644 --- a/services/core/java/com/android/server/VibratorManagerService.java +++ b/services/core/java/com/android/server/VibratorManagerService.java @@ -16,32 +16,85 @@ package com.android.server; +import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.AppOpsManager; import android.content.Context; +import android.content.pm.PackageManager; +import android.hardware.vibrator.IVibrator; import android.os.CombinedVibrationEffect; +import android.os.Handler; import android.os.IBinder; import android.os.IVibratorManagerService; +import android.os.Looper; import android.os.ResultReceiver; import android.os.ShellCallback; import android.os.ShellCommand; +import android.os.Trace; import android.os.VibrationAttributes; +import android.os.VibrationEffect; +import android.os.Vibrator; +import android.os.VibratorInfo; +import android.util.Slog; +import android.util.SparseArray; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.server.vibrator.Vibration; +import com.android.server.vibrator.VibrationScaler; +import com.android.server.vibrator.VibrationSettings; +import com.android.server.vibrator.VibratorController; import libcore.util.NativeAllocationRegistry; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.lang.ref.WeakReference; import java.util.Arrays; +import java.util.function.Consumer; +import java.util.function.Function; /** System implementation of {@link IVibratorManagerService}. */ public class VibratorManagerService extends IVibratorManagerService.Stub { private static final String TAG = "VibratorManagerService"; private static final boolean DEBUG = false; + private static final VibrationAttributes DEFAULT_ATTRIBUTES = + new VibrationAttributes.Builder().build(); + /** Lifecycle responsible for initializing this class at the right system server phases. */ + public static class Lifecycle extends SystemService { + private VibratorManagerService mService; + + public Lifecycle(Context context) { + super(context); + } + + @Override + public void onStart() { + mService = new VibratorManagerService(getContext(), new Injector()); + publishBinderService("vibrator_manager", mService); + } + + @Override + public void onBootPhase(int phase) { + if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { + mService.systemReady(); + } + } + } + + private final Object mLock = new Object(); private final Context mContext; + private final Handler mHandler; + private final AppOpsManager mAppOps; private final NativeWrapper mNativeWrapper; private final int[] mVibratorIds; + private final SparseArray<VibratorController> mVibrators; + @GuardedBy("mLock") + private final SparseArray<AlwaysOnVibration> mAlwaysOnEffects = new SparseArray<>(); + + private VibrationSettings mVibrationSettings; + private VibrationScaler mVibrationScaler; static native long nativeInit(); @@ -49,19 +102,53 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { static native int[] nativeGetVibratorIds(long nativeServicePtr); - VibratorManagerService(Context context) { - this(context, new Injector()); - } - @VisibleForTesting VibratorManagerService(Context context, Injector injector) { mContext = context; + mHandler = injector.createHandler(Looper.myLooper()); mNativeWrapper = injector.getNativeWrapper(); - mNativeWrapper.init(); + mAppOps = mContext.getSystemService(AppOpsManager.class); + int[] vibratorIds = mNativeWrapper.getVibratorIds(); - mVibratorIds = vibratorIds == null ? new int[0] : vibratorIds; + if (vibratorIds == null) { + mVibratorIds = new int[0]; + mVibrators = new SparseArray<>(0); + } else { + // Keep original vibrator id order, which might be meaningful. + mVibratorIds = vibratorIds; + mVibrators = new SparseArray<>(mVibratorIds.length); + VibrationCompleteListener listener = new VibrationCompleteListener(this); + for (int vibratorId : vibratorIds) { + mVibrators.put(vibratorId, injector.createVibratorController(vibratorId, listener)); + } + } + } + + /** Finish initialization at boot phase {@link SystemService#PHASE_SYSTEM_SERVICES_READY}. */ + @VisibleForTesting + void systemReady() { + Slog.v(TAG, "Initializing VibratorManager service..."); + Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "systemReady"); + try { + mVibrationSettings = new VibrationSettings(mContext, mHandler); + mVibrationScaler = new VibrationScaler(mContext, mVibrationSettings); + + mVibrationSettings.addListener(this::updateServiceState); + + updateServiceState(); + } finally { + Slog.v(TAG, "VibratorManager service initialized"); + Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); + } + } + + @Override // Binder call + @Nullable + public VibratorInfo getVibratorInfo(int vibratorId) { + VibratorController controller = mVibrators.get(vibratorId); + return controller == null ? null : controller.getVibratorInfo(); } @Override // Binder call @@ -70,7 +157,48 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } @Override // Binder call - public void vibrate(int uid, String opPkg, CombinedVibrationEffect effect, + public boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, + @Nullable CombinedVibrationEffect effect, @Nullable VibrationAttributes attrs) { + Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "setAlwaysOnEffect"); + try { + if (!hasPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON)) { + throw new SecurityException("Requires VIBRATE_ALWAYS_ON permission"); + } + if (effect == null) { + synchronized (mLock) { + mAlwaysOnEffects.delete(alwaysOnId); + onAllVibratorsLocked(v -> { + if (v.hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) { + v.updateAlwaysOn(alwaysOnId, /* effect= */ null); + } + }); + } + return true; + } + if (!isEffectValid(effect)) { + return false; + } + attrs = fixupVibrationAttributes(attrs); + synchronized (mLock) { + SparseArray<VibrationEffect.Prebaked> effects = fixupAlwaysOnEffectsLocked(effect); + if (effects == null) { + // Invalid effects set in CombinedVibrationEffect, or always-on capability is + // missing on individual vibrators. + return false; + } + AlwaysOnVibration alwaysOnVibration = new AlwaysOnVibration( + alwaysOnId, uid, opPkg, attrs, effects); + mAlwaysOnEffects.put(alwaysOnId, alwaysOnVibration); + updateAlwaysOnLocked(alwaysOnVibration); + } + return true; + } finally { + Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); + } + } + + @Override // Binder call + public void vibrate(int uid, String opPkg, @NonNull CombinedVibrationEffect effect, @Nullable VibrationAttributes attrs, String reason, IBinder token) { throw new UnsupportedOperationException("Not implemented"); } @@ -86,6 +214,201 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { new VibratorManagerShellCommand(this).exec(this, in, out, err, args, cb, resultReceiver); } + private void updateServiceState() { + synchronized (mLock) { + for (int i = 0; i < mAlwaysOnEffects.size(); i++) { + updateAlwaysOnLocked(mAlwaysOnEffects.valueAt(i)); + } + } + } + + @GuardedBy("mLock") + private void updateAlwaysOnLocked(AlwaysOnVibration vib) { + for (int i = 0; i < vib.effects.size(); i++) { + VibratorController vibrator = mVibrators.get(vib.effects.keyAt(i)); + VibrationEffect.Prebaked effect = vib.effects.valueAt(i); + if (vibrator == null) { + continue; + } + Vibration.Status ignoredStatus = shouldIgnoreVibrationLocked( + vib.uid, vib.opPkg, vib.attrs); + if (ignoredStatus == null) { + effect = mVibrationScaler.scale(effect, vib.attrs.getUsage()); + } else { + // Vibration should not run, use null effect to remove registered effect. + effect = null; + } + vibrator.updateAlwaysOn(vib.alwaysOnId, effect); + } + } + + /** + * Check if a vibration with given {@code uid}, {@code opPkg} and {@code attrs} should be + * ignored by this service. + * + * @param uid The user id of this vibration + * @param opPkg The package name of this vibration + * @param attrs The attributes of this vibration + * @return One of Vibration.Status.IGNORED_* values if the vibration should be ignored. + */ + @GuardedBy("mLock") + @Nullable + private Vibration.Status shouldIgnoreVibrationLocked(int uid, String opPkg, + VibrationAttributes attrs) { + if (!mVibrationSettings.shouldVibrateForPowerMode(attrs.getUsage())) { + return Vibration.Status.IGNORED_FOR_POWER; + } + + int intensity = mVibrationSettings.getCurrentIntensity(attrs.getUsage()); + if (intensity == Vibrator.VIBRATION_INTENSITY_OFF) { + return Vibration.Status.IGNORED_FOR_SETTINGS; + } + + if (!mVibrationSettings.shouldVibrateForRingerMode(attrs.getUsage())) { + if (DEBUG) { + Slog.e(TAG, "Vibrate ignored, not vibrating for ringtones"); + } + return Vibration.Status.IGNORED_RINGTONE; + } + + int mode = getAppOpMode(uid, opPkg, attrs); + if (mode != AppOpsManager.MODE_ALLOWED) { + if (mode == AppOpsManager.MODE_ERRORED) { + // We might be getting calls from within system_server, so we don't actually + // want to throw a SecurityException here. + Slog.w(TAG, "Would be an error: vibrate from uid " + uid); + return Vibration.Status.IGNORED_ERROR_APP_OPS; + } else { + return Vibration.Status.IGNORED_APP_OPS; + } + } + + return null; + } + + /** + * Check which mode should be set for a vibration with given {@code uid}, {@code opPkg} and + * {@code attrs}. This will return one of the AppOpsManager.MODE_*. + */ + private int getAppOpMode(int uid, String opPkg, VibrationAttributes attrs) { + int mode = mAppOps.checkAudioOpNoThrow(AppOpsManager.OP_VIBRATE, + attrs.getAudioUsage(), uid, opPkg); + if (mode == AppOpsManager.MODE_ALLOWED) { + mode = mAppOps.startOpNoThrow(AppOpsManager.OP_VIBRATE, uid, opPkg); + } + if (mode == AppOpsManager.MODE_IGNORED + && attrs.isFlagSet(VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY)) { + // If we're just ignoring the vibration op then this is set by DND and we should ignore + // if we're asked to bypass. AppOps won't be able to record this operation, so make + // sure we at least note it in the logs for debugging. + Slog.d(TAG, "Bypassing DND for vibrate from uid " + uid); + mode = AppOpsManager.MODE_ALLOWED; + } + return mode; + } + + /** + * Validate the incoming {@link CombinedVibrationEffect}. + * + * We can't throw exceptions here since we might be called from some system_server component, + * which would bring the whole system down. + * + * @return whether the CombinedVibrationEffect is non-null and valid + */ + private static boolean isEffectValid(@Nullable CombinedVibrationEffect effect) { + if (effect == null) { + Slog.wtf(TAG, "effect must not be null"); + return false; + } + try { + effect.validate(); + } catch (Exception e) { + Slog.wtf(TAG, "Encountered issue when verifying CombinedVibrationEffect.", e); + return false; + } + return true; + } + + /** + * Return new {@link VibrationAttributes} that only applies flags that this user has permissions + * to use. + */ + private VibrationAttributes fixupVibrationAttributes(@Nullable VibrationAttributes attrs) { + if (attrs == null) { + attrs = DEFAULT_ATTRIBUTES; + } + if (attrs.isFlagSet(VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY)) { + if (!(hasPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) + || hasPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + || hasPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING))) { + final int flags = attrs.getFlags() + & ~VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY; + attrs = new VibrationAttributes.Builder(attrs) + .setFlags(flags, attrs.getFlags()).build(); + } + } + return attrs; + } + + @GuardedBy("mLock") + @Nullable + private SparseArray<VibrationEffect.Prebaked> fixupAlwaysOnEffectsLocked( + CombinedVibrationEffect effect) { + Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "fixupAlwaysOnEffectsLocked"); + try { + SparseArray<VibrationEffect> effects; + if (effect instanceof CombinedVibrationEffect.Mono) { + VibrationEffect syncedEffect = ((CombinedVibrationEffect.Mono) effect).getEffect(); + effects = transformAllVibratorsLocked(unused -> syncedEffect); + } else if (effect instanceof CombinedVibrationEffect.Stereo) { + effects = ((CombinedVibrationEffect.Stereo) effect).getEffects(); + } else { + // Only synced combinations can be used for always-on effects. + return null; + } + SparseArray<VibrationEffect.Prebaked> result = new SparseArray<>(); + for (int i = 0; i < effects.size(); i++) { + VibrationEffect prebaked = effects.valueAt(i); + if (!(prebaked instanceof VibrationEffect.Prebaked)) { + Slog.e(TAG, "Only prebaked effects supported for always-on."); + return null; + } + int vibratorId = effects.keyAt(i); + VibratorController vibrator = mVibrators.get(vibratorId); + if (vibrator != null && vibrator.hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) { + result.put(vibratorId, (VibrationEffect.Prebaked) prebaked); + } + } + if (result.size() == 0) { + return null; + } + return result; + } finally { + Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); + } + } + + private boolean hasPermission(String permission) { + return mContext.checkCallingOrSelfPermission(permission) + == PackageManager.PERMISSION_GRANTED; + } + + @GuardedBy("mLock") + private void onAllVibratorsLocked(Consumer<VibratorController> consumer) { + for (int i = 0; i < mVibrators.size(); i++) { + consumer.accept(mVibrators.valueAt(i)); + } + } + + @GuardedBy("mLock") + private <T> SparseArray<T> transformAllVibratorsLocked(Function<VibratorController, T> fn) { + SparseArray<T> ret = new SparseArray<>(mVibrators.size()); + for (int i = 0; i < mVibrators.size(); i++) { + ret.put(mVibrators.keyAt(i), fn.apply(mVibrators.valueAt(i))); + } + return ret; + } + /** Point of injection for test dependencies */ @VisibleForTesting static class Injector { @@ -93,6 +416,57 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { NativeWrapper getNativeWrapper() { return new NativeWrapper(); } + + Handler createHandler(Looper looper) { + return new Handler(looper); + } + + VibratorController createVibratorController(int vibratorId, + VibratorController.OnVibrationCompleteListener listener) { + return new VibratorController(vibratorId, listener); + } + } + + /** + * Implementation of {@link VibratorController.OnVibrationCompleteListener} with a weak + * reference to this service. + */ + private static final class VibrationCompleteListener implements + VibratorController.OnVibrationCompleteListener { + private WeakReference<VibratorManagerService> mServiceRef; + + VibrationCompleteListener(VibratorManagerService service) { + mServiceRef = new WeakReference<>(service); + } + + @Override + public void onComplete(int vibratorId, long vibrationId) { + VibratorManagerService service = mServiceRef.get(); + if (service != null) { + // TODO(b/159207608): finish vibration if all vibrators finished for this vibration + } + } + } + + /** + * Combination of prekabed vibrations on multiple vibrators, with the same {@link + * VibrationAttributes}, that can be set for always-on effects. + */ + private static final class AlwaysOnVibration { + public final int alwaysOnId; + public final int uid; + public final String opPkg; + public final VibrationAttributes attrs; + public final SparseArray<VibrationEffect.Prebaked> effects; + + AlwaysOnVibration(int alwaysOnId, int uid, String opPkg, VibrationAttributes attrs, + SparseArray<VibrationEffect.Prebaked> effects) { + this.alwaysOnId = alwaysOnId; + this.uid = uid; + this.opPkg = opPkg; + this.attrs = attrs; + this.effects = effects; + } } /** Wrapper around the static-native methods of {@link VibratorManagerService} for tests. */ @@ -120,7 +494,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } } - /** Provides limited functionality from {@link VibratorManagerService} as shell commands. */ + /** Provide limited functionality from {@link VibratorManagerService} as shell commands. */ private final class VibratorManagerShellCommand extends ShellCommand { private final IBinder mToken; diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java index db2b4e4edd2b..6a9715e49b99 100644 --- a/services/core/java/com/android/server/VibratorService.java +++ b/services/core/java/com/android/server/VibratorService.java @@ -19,7 +19,6 @@ package com.android.server; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.AppOpsManager; -import android.app.IUidObserver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -37,9 +36,6 @@ import android.os.IVibratorService; import android.os.IVibratorStateListener; import android.os.Looper; import android.os.PowerManager; -import android.os.PowerManager.ServiceType; -import android.os.PowerManagerInternal; -import android.os.PowerSaveState; import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; @@ -51,9 +47,9 @@ import android.os.Trace; import android.os.VibrationAttributes; import android.os.VibrationEffect; import android.os.Vibrator; +import android.os.VibratorInfo; import android.os.WorkSource; import android.util.Slog; -import android.util.SparseArray; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; @@ -73,7 +69,6 @@ import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.LinkedList; -import java.util.List; import java.util.concurrent.atomic.AtomicInteger; /** System implementation of {@link IVibratorService}. */ @@ -95,7 +90,6 @@ public class VibratorService extends IVibratorService.Stub { private final LinkedList<Vibration.DebugInfo> mPreviousExternalVibrations; private final LinkedList<Vibration.DebugInfo> mPreviousVibrations; private final int mPreviousVibrationsLimit; - private final SparseArray<Integer> mProcStatesCache = new SparseArray<>(); private final WorkSource mTmpWorkSource = new WorkSource(); private final Handler mH; private final Object mLock = new Object(); @@ -106,7 +100,6 @@ public class VibratorService extends IVibratorService.Stub { private final AppOpsManager mAppOps; private final IBatteryStats mBatteryStatsService; private final String mSystemUiPackage; - private PowerManagerInternal mPowerManagerInternal; private VibrationSettings mVibrationSettings; private VibrationScaler mVibrationScaler; private InputDeviceDelegate mInputDeviceDelegate; @@ -119,31 +112,6 @@ public class VibratorService extends IVibratorService.Stub { private VibrationDeathRecipient mCurrentVibrationDeathRecipient; private int mCurVibUid = -1; private ExternalVibrationHolder mCurrentExternalVibration; - private boolean mLowPowerMode; - private SparseArray<Vibration> mAlwaysOnEffects = new SparseArray<>(); - - private final IUidObserver mUidObserver = new IUidObserver.Stub() { - @Override public void onUidStateChanged(int uid, int procState, long procStateSeq, - int capability) { - mProcStatesCache.put(uid, procState); - } - - @Override public void onUidGone(int uid, boolean disabled) { - mProcStatesCache.delete(uid); - } - - @Override - public void onUidActive(int uid) { - } - - @Override - public void onUidIdle(int uid, boolean disabled) { - } - - @Override - public void onUidCachedChanged(int uid, boolean cached) { - } - }; /** * Implementation of {@link OnVibrationCompleteListener} with a weak reference to this service. @@ -277,37 +245,15 @@ public class VibratorService extends IVibratorService.Stub { mVibrationScaler = new VibrationScaler(mContext, mVibrationSettings); mInputDeviceDelegate = new InputDeviceDelegate(mContext, mH); - mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); - mPowerManagerInternal.registerLowPowerModeObserver( - new PowerManagerInternal.LowPowerModeListener() { - @Override - public int getServiceType() { - return ServiceType.VIBRATION; - } - - @Override - public void onLowPowerModeChanged(PowerSaveState result) { - updateVibrators(); - } - }); - mVibrationSettings.addListener(this::updateVibrators); mContext.registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { - updateVibrators(); + mVibrationSettings.updateSettings(); } }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mH); - try { - ActivityManager.getService().registerUidObserver(mUidObserver, - ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_GONE, - ActivityManager.PROCESS_STATE_UNKNOWN, null); - } catch (RemoteException e) { - // ignored; both services live in system_server - } - updateVibrators(); } finally { Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); @@ -346,6 +292,11 @@ public class VibratorService extends IVibratorService.Stub { } @Override // Binder call + public VibratorInfo getVibratorInfo() { + return mVibratorController.getVibratorInfo(); + } + + @Override // Binder call public boolean registerVibratorStateListener(IVibratorStateListener listener) { if (!hasPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)) { throw new SecurityException("Requires ACCESS_VIBRATOR_STATE permission"); @@ -369,61 +320,6 @@ public class VibratorService extends IVibratorService.Stub { || mVibratorController.hasCapability(IVibrator.CAP_AMPLITUDE_CONTROL); } - @Override // Binder call - public int[] areEffectsSupported(int[] effectIds) { - return mVibratorController.areEffectsSupported(effectIds); - } - - @Override // Binder call - public boolean[] arePrimitivesSupported(int[] primitiveIds) { - return mVibratorController.arePrimitivesSupported(primitiveIds); - } - - private static List<Integer> asList(int... vals) { - if (vals == null) { - return null; - } - List<Integer> l = new ArrayList<>(vals.length); - for (int val : vals) { - l.add(val); - } - return l; - } - - @Override // Binder call - public boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, VibrationEffect effect, - VibrationAttributes attrs) { - if (!hasPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON)) { - throw new SecurityException("Requires VIBRATE_ALWAYS_ON permission"); - } - if (!mVibratorController.hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) { - Slog.e(TAG, "Always-on effects not supported."); - return false; - } - if (effect == null) { - synchronized (mLock) { - mAlwaysOnEffects.delete(alwaysOnId); - mVibratorController.updateAlwaysOn(alwaysOnId, /* effect= */ null); - } - } else { - if (!verifyVibrationEffect(effect)) { - return false; - } - if (!(effect instanceof VibrationEffect.Prebaked)) { - Slog.e(TAG, "Only prebaked effects supported for always-on."); - return false; - } - attrs = fixupVibrationAttributes(attrs); - synchronized (mLock) { - Vibration vib = new Vibration(null, mNextVibrationId.getAndIncrement(), effect, - attrs, uid, opPkg, null); - mAlwaysOnEffects.put(alwaysOnId, vib); - updateAlwaysOnLocked(alwaysOnId, vib); - } - } - return true; - } - private void verifyIncomingUid(int uid) { if (uid == Binder.getCallingUid()) { return; @@ -543,9 +439,7 @@ public class VibratorService extends IVibratorService.Stub { return; } - if (mProcStatesCache.get(uid, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) - > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND - && !isNotification(vib) && !isRingtone(vib) && !isAlarm(vib)) { + if (!mVibrationSettings.shouldVibrateForUid(uid, vib.attrs.getUsage())) { Slog.e(TAG, "Ignoring incoming vibration as process with" + " uid= " + uid + " is background," + " attrs= " + vib.attrs); @@ -582,16 +476,19 @@ public class VibratorService extends IVibratorService.Stub { private void endVibrationLocked(Vibration vib, Vibration.Status status) { final LinkedList<Vibration.DebugInfo> previousVibrations; - if (isRingtone(vib)) { - previousVibrations = mPreviousRingVibrations; - } else if (isNotification(vib)) { - previousVibrations = mPreviousNotificationVibrations; - } else if (isAlarm(vib)) { - previousVibrations = mPreviousAlarmVibrations; - } else { - previousVibrations = mPreviousVibrations; + switch (vib.attrs.getUsage()) { + case VibrationAttributes.USAGE_NOTIFICATION: + previousVibrations = mPreviousNotificationVibrations; + break; + case VibrationAttributes.USAGE_RINGTONE: + previousVibrations = mPreviousRingVibrations; + break; + case VibrationAttributes.USAGE_ALARM: + previousVibrations = mPreviousAlarmVibrations; + break; + default: + previousVibrations = mPreviousVibrations; } - if (previousVibrations.size() > mPreviousVibrationsLimit) { previousVibrations.removeFirst(); } @@ -706,17 +603,6 @@ public class VibratorService extends IVibratorService.Stub { } } - private boolean shouldVibrateForPowerModeLocked(Vibration vib) { - if (!mLowPowerMode) { - return true; - } - - int usage = vib.attrs.getUsage(); - return usage == VibrationAttributes.USAGE_RINGTONE - || usage == VibrationAttributes.USAGE_ALARM - || usage == VibrationAttributes.USAGE_COMMUNICATION_REQUEST; - } - /** Scale the vibration effect by the intensity as appropriate based its intent. */ private void applyVibrationIntensityScalingLocked(Vibration vib) { vib.updateEffect(mVibrationScaler.scale(vib.getEffect(), vib.attrs.getUsage())); @@ -744,7 +630,7 @@ public class VibratorService extends IVibratorService.Stub { } private boolean shouldVibrate(Vibration vib) { - if (!shouldVibrateForPowerModeLocked(vib)) { + if (!mVibrationSettings.shouldVibrateForPowerMode(vib.attrs.getUsage())) { endVibrationLocked(vib, Vibration.Status.IGNORED_FOR_POWER); return false; } @@ -755,7 +641,7 @@ public class VibratorService extends IVibratorService.Stub { return false; } - if (isRingtone(vib) && !mVibrationSettings.shouldVibrateForRingtone()) { + if (!mVibrationSettings.shouldVibrateForRingerMode(vib.attrs.getUsage())) { if (DEBUG) { Slog.e(TAG, "Vibrate ignored, not vibrating for ringtones"); } @@ -769,7 +655,7 @@ public class VibratorService extends IVibratorService.Stub { // We might be getting calls from within system_server, so we don't actually // want to throw a SecurityException here. Slog.w(TAG, "Would be an error: vibrate from uid " + vib.uid); - endVibrationLocked(vib, Vibration.Status.ERROR_APP_OPS); + endVibrationLocked(vib, Vibration.Status.IGNORED_ERROR_APP_OPS); } else { endVibrationLocked(vib, Vibration.Status.IGNORED_APP_OPS); } @@ -821,44 +707,11 @@ public class VibratorService extends IVibratorService.Stub { private void updateVibrators() { synchronized (mLock) { - boolean devicesUpdated = mInputDeviceDelegate.updateInputDeviceVibrators( + mInputDeviceDelegate.updateInputDeviceVibrators( mVibrationSettings.shouldVibrateInputDevices()); - boolean lowPowerModeUpdated = updateLowPowerModeLocked(); - - if (devicesUpdated || lowPowerModeUpdated) { - // If the state changes out from under us then just reset. - doCancelVibrateLocked(Vibration.Status.CANCELLED); - } - updateAlwaysOnLocked(); - } - } - - private boolean updateLowPowerModeLocked() { - boolean lowPowerMode = mPowerManagerInternal - .getLowPowerState(ServiceType.VIBRATION).batterySaverEnabled; - if (lowPowerMode != mLowPowerMode) { - mLowPowerMode = lowPowerMode; - return true; - } - return false; - } - - private void updateAlwaysOnLocked(int id, Vibration vib) { - VibrationEffect.Prebaked effect; - if (!shouldVibrate(vib)) { - effect = null; - } else { - effect = mVibrationScaler.scale(vib.getEffect(), vib.attrs.getUsage()); - } - mVibratorController.updateAlwaysOn(id, effect); - } - - private void updateAlwaysOnLocked() { - for (int i = 0; i < mAlwaysOnEffects.size(); i++) { - int id = mAlwaysOnEffects.keyAt(i); - Vibration vib = mAlwaysOnEffects.valueAt(i); - updateAlwaysOnLocked(id, vib); + // If the state changes out from under us then just reset. + doCancelVibrateLocked(Vibration.Status.CANCELLED); } } @@ -994,23 +847,10 @@ public class VibratorService extends IVibratorService.Stub { } - private static boolean isNotification(Vibration vib) { - return vib.attrs.getUsage() == VibrationAttributes.USAGE_NOTIFICATION; - } - - private static boolean isRingtone(Vibration vib) { - return vib.attrs.getUsage() == VibrationAttributes.USAGE_RINGTONE; - } - - private static boolean isHapticFeedback(Vibration vib) { - return vib.attrs.getUsage() == VibrationAttributes.USAGE_TOUCH; - } - - private static boolean isAlarm(Vibration vib) { - return vib.attrs.getUsage() == VibrationAttributes.USAGE_ALARM; - } - - private boolean isFromSystem(Vibration vib) { + private boolean isSystemHapticFeedback(Vibration vib) { + if (vib.attrs.getUsage() != VibrationAttributes.USAGE_TOUCH) { + return false; + } return vib.uid == Process.SYSTEM_UID || vib.uid == 0 || mSystemUiPackage.equals(vib.opPkg); } @@ -1050,7 +890,6 @@ public class VibratorService extends IVibratorService.Stub { } else { pw.println("null"); } - pw.println(" mLowPowerMode=" + mLowPowerMode); pw.println(" mVibratorController=" + mVibratorController); pw.println(" mVibrationSettings=" + mVibrationSettings); pw.println(); @@ -1097,7 +936,6 @@ public class VibratorService extends IVibratorService.Stub { proto.write(VibratorServiceDumpProto.IS_VIBRATING, mVibratorController.isVibrating()); proto.write(VibratorServiceDumpProto.VIBRATOR_UNDER_EXTERNAL_CONTROL, mVibratorController.isUnderExternalControl()); - proto.write(VibratorServiceDumpProto.LOW_POWER_MODE, mLowPowerMode); proto.write(VibratorServiceDumpProto.HAPTIC_FEEDBACK_INTENSITY, mVibrationSettings.getCurrentIntensity(VibrationAttributes.USAGE_TOUCH)); proto.write(VibratorServiceDumpProto.HAPTIC_FEEDBACK_DEFAULT_INTENSITY, @@ -1289,7 +1127,7 @@ public class VibratorService extends IVibratorService.Stub { static class Injector { VibratorController createVibratorController(OnVibrationCompleteListener listener) { - return new VibratorController(/* vibratorId= */ 0, listener); + return new VibratorController(/* vibratorId= */ -1, listener); } Handler createHandler(Looper looper) { @@ -1311,9 +1149,7 @@ public class VibratorService extends IVibratorService.Stub { // them. However it may happen that the system is currently playing // haptic feedback as part of the transition. So we don't cancel // system vibrations. - if (mCurrentVibration != null - && !(isHapticFeedback(mCurrentVibration) - && isFromSystem(mCurrentVibration))) { + if (mCurrentVibration != null && !isSystemHapticFeedback(mCurrentVibration)) { doCancelVibrateLocked(Vibration.Status.CANCELLED); } } @@ -1373,7 +1209,7 @@ public class VibratorService extends IVibratorService.Stub { vibHolder.scale = SCALE_MUTE; if (mode == AppOpsManager.MODE_ERRORED) { Slog.w(TAG, "Would be an error: external vibrate from uid " + vib.getUid()); - endVibrationLocked(vibHolder, Vibration.Status.ERROR_APP_OPS); + endVibrationLocked(vibHolder, Vibration.Status.IGNORED_ERROR_APP_OPS); } else { endVibrationLocked(vibHolder, Vibration.Status.IGNORED_APP_OPS); } diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index 9a94e4efdfe3..15e31ba0f140 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -3085,7 +3085,8 @@ public class AccountManagerService .setContentTitle(title) .setContentText(subtitle) .setContentIntent(PendingIntent.getActivityAsUser(mContext, 0, intent, - PendingIntent.FLAG_CANCEL_CURRENT, null, user)) + PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE, + null, user)) .build(); installNotification(getCredentialPermissionNotificationId( account, authTokenType, uid), n, packageName, user.getIdentifier()); @@ -5307,7 +5308,8 @@ public class AccountManagerService .setContentTitle(String.format(notificationTitleFormat, account.name)) .setContentText(message) .setContentIntent(PendingIntent.getActivityAsUser( - mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT, + mContext, 0, intent, + PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE, null, new UserHandle(userId))) .build(); installNotification(id, n, packageName, userId); diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index dffe0ba7ac78..7d6e54243d89 100644 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -19,7 +19,6 @@ package com.android.server.am; import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND; import static android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND; import static android.Manifest.permission.SYSTEM_ALERT_WINDOW; -import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST; import static android.os.Process.NFC_UID; @@ -168,6 +167,7 @@ public final class ActiveServices { public static final int FGS_FEATURE_ALLOWED_BY_SYSTEM_ALERT_WINDOW_PERMISSION = 16; 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; @IntDef(flag = true, prefix = { "FGS_FEATURE_" }, value = { FGS_FEATURE_DENIED, @@ -187,7 +187,8 @@ public final class ActiveServices { FGS_FEATURE_ALLOWED_BY_DEVICE_IDLE_ALLOW_LIST, 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_DEVICE_DEMO_MODE, + FGS_FEATURE_ALLOWED_BY_PROCESS_RECORD }) @Retention(RetentionPolicy.SOURCE) public @interface FgsFeatureRetCode {} @@ -1859,7 +1860,7 @@ public final class ActiveServices { private final AppOpsManager.OnOpNotedListener mOpNotedCallback = new AppOpsManager.OnOpNotedListener() { @Override - public void onOpNoted(int op, int uid, String pkgName, int result) { + public void onOpNoted(int op, int uid, String pkgName, int flags, int result) { incrementOpCountIfNeeded(op, uid, result); } }; @@ -1867,7 +1868,8 @@ public final class ActiveServices { private final AppOpsManager.OnOpStartedListener mOpStartedCallback = new AppOpsManager.OnOpStartedListener() { @Override - public void onOpStarted(int op, int uid, String pkgName, int result) { + public void onOpStarted(int op, int uid, String pkgName, int flags, + int result) { incrementOpCountIfNeeded(op, uid, result); } }; @@ -5243,10 +5245,14 @@ public final class ActiveServices { if (ret == FGS_FEATURE_DENIED) { for (int i = mAm.mProcessList.mLruProcesses.size() - 1; i >= 0; i--) { final ProcessRecord pr = mAm.mProcessList.mLruProcesses.get(i); - if (pr.uid == callingUid - && pr.mAllowStartFgsState <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE) { - ret = FGS_FEATURE_ALLOWED_BY_PROC_STATE; - break; + if (pr.uid == callingUid) { + if (pr.mAllowStartFgs) { + ret = FGS_FEATURE_ALLOWED_BY_PROCESS_RECORD; + break; + } else if (pr.isAllowedStartFgsState()) { + ret = FGS_FEATURE_ALLOWED_BY_PROC_STATE; + break; + } } } } @@ -5285,8 +5291,7 @@ public final class ActiveServices { } if (ret == FGS_FEATURE_DENIED) { - if (mAm.mConstants.mFlagFgsStartTempAllowListEnabled - && mAm.isWhitelistedForFgsStartLocked(r.appInfo.uid)) { + if (mAm.isWhitelistedForFgsStartLocked(callingUid)) { // uid is on DeviceIdleController's user/system allowlist // or AMS's FgsStartTempAllowList. ret = FGS_FEATURE_ALLOWED_BY_DEVICE_IDLE_ALLOW_LIST; @@ -5354,6 +5359,8 @@ public final class ActiveServices { return "ALLOWED_BY_FGS_BINDING"; case FGS_FEATURE_ALLOWED_BY_DEVICE_DEMO_MODE: return "ALLOWED_BY_DEVICE_DEMO_MODE"; + case FGS_FEATURE_ALLOWED_BY_PROCESS_RECORD: + return "ALLOWED_BY_PROCESS_RECORD"; 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 b4e856bb0706..b0f296f68a47 100644 --- a/services/core/java/com/android/server/am/ActivityManagerConstants.java +++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java @@ -167,13 +167,6 @@ final class ActivityManagerConstants extends ContentObserver { "default_fgs_starts_restriction_enabled"; /** - * Default value for mFlagFgsStartTempAllowListEnabled if not explicitly set in - * Settings.Global. - */ - private static final String KEY_DEFAULT_FGS_STARTS_TEMP_ALLOWLIST_ENABLED = - "default_fgs_starts_temp_allowlist_enabled"; - - /** * Whether FGS notification display is deferred following the transition into * the foreground state. Default behavior is {@code true} unless overridden. */ @@ -372,10 +365,6 @@ final class ActivityManagerConstants extends ContentObserver { // at all. volatile boolean mFlagFgsStartRestrictionEnabled = false; - // When the foreground service background start restriction is enabled, if the app in - // DeviceIdleController's Temp AllowList is allowed to bypass the restriction. - volatile boolean mFlagFgsStartTempAllowListEnabled = false; - // Whether we defer FGS notifications a few seconds following their transition to // the foreground state. Applies only to S+ apps; enabled by default. volatile boolean mFlagFgsNotificationDeferralEnabled = true; @@ -540,9 +529,6 @@ final class ActivityManagerConstants extends ContentObserver { case KEY_DEFAULT_FGS_STARTS_RESTRICTION_ENABLED: updateFgsStartsRestriction(); break; - case KEY_DEFAULT_FGS_STARTS_TEMP_ALLOWLIST_ENABLED: - updateFgsStartsTempAllowList(); - break; case KEY_DEFERRED_FGS_NOTIFICATIONS_ENABLED: updateFgsNotificationDeferralEnable(); break; @@ -809,13 +795,6 @@ final class ActivityManagerConstants extends ContentObserver { /*defaultValue*/ false); } - private void updateFgsStartsTempAllowList() { - mFlagFgsStartTempAllowListEnabled = DeviceConfig.getBoolean( - DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, - KEY_DEFAULT_FGS_STARTS_TEMP_ALLOWLIST_ENABLED, - /*defaultValue*/ false); - } - private void updateFgsNotificationDeferralEnable() { mFlagFgsNotificationDeferralEnabled = DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 18cc9a04efe9..10102cd12346 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -174,6 +174,7 @@ import android.app.ProfilerInfo; import android.app.WaitResult; import android.app.backup.BackupManager.OperationType; import android.app.backup.IBackupManager; +import android.app.compat.CompatChanges; import android.app.usage.UsageEvents; import android.app.usage.UsageEvents.Event; import android.app.usage.UsageStatsManager; @@ -13713,6 +13714,37 @@ public class ActivityManagerService extends IActivityManager.Stub forceStopPackageLocked(packageName, -1, false, true, true, false, false, userId, "package unstartable"); break; + case Intent.ACTION_CLOSE_SYSTEM_DIALOGS: + if (!canCloseSystemDialogs(callingPid, callingUid, callerApp)) { + // The app can't close system dialogs, throw only if it targets S+ + if (CompatChanges.isChangeEnabled( + ActivityManager.LOCK_DOWN_CLOSE_SYSTEM_DIALOGS, callingUid)) { + throw new SecurityException( + "Permission Denial: " + Intent.ACTION_CLOSE_SYSTEM_DIALOGS + + " broadcast from " + callerPackage + " (pid=" + + callingPid + ", uid=" + callingUid + ")" + + " requires " + + permission.BROADCAST_CLOSE_SYSTEM_DIALOGS + "."); + } else if (CompatChanges.isChangeEnabled( + ActivityManager.DROP_CLOSE_SYSTEM_DIALOGS, callingUid)) { + Slog.w(TAG, "Permission Denial: " + intent.getAction() + + " broadcast from " + callerPackage + " (pid=" + callingPid + + ", uid=" + callingUid + ")" + + " requires " + + permission.BROADCAST_CLOSE_SYSTEM_DIALOGS + + ", dropping broadcast."); + // Returning success seems to be the pattern here + return ActivityManager.BROADCAST_SUCCESS; + } else { + Slog.w(TAG, intent.getAction() + + " broadcast from " + callerPackage + " (pid=" + callingPid + + ", uid=" + callingUid + ")" + + " will require " + + permission.BROADCAST_CLOSE_SYSTEM_DIALOGS + + " in future builds."); + } + } + break; } if (Intent.ACTION_PACKAGE_ADDED.equals(action) || @@ -14005,6 +14037,32 @@ public class ActivityManagerService extends IActivityManager.Stub return ActivityManager.BROADCAST_SUCCESS; } + private boolean canCloseSystemDialogs(int pid, int uid, @Nullable ProcessRecord callerApp) { + if (checkPermission(permission.BROADCAST_CLOSE_SYSTEM_DIALOGS, pid, uid) + == PERMISSION_GRANTED) { + return true; + } + if (callerApp == null) { + synchronized (mPidsSelfLocked) { + callerApp = mPidsSelfLocked.get(pid); + } + } + // Check if the instrumentation of the process has the permission. This covers the usual + // test started from the shell (which has the permission) case. This is needed for apps + // targeting SDK level < S but we are also allowing for targetSdk S+ as a convenience to + // avoid breaking a bunch of existing tests and asking them to adopt shell permissions to do + // this. + if (callerApp != null) { + ActiveInstrumentation instrumentation = callerApp.getActiveInstrumentation(); + if (instrumentation != null && checkPermission( + permission.BROADCAST_CLOSE_SYSTEM_DIALOGS, -1, instrumentation.mSourceUid) + == PERMISSION_GRANTED) { + return true; + } + } + return false; + } + /** * @return uid from the extra field {@link Intent#EXTRA_UID} if present, Otherwise -1 */ @@ -14610,11 +14668,11 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public int getLaunchedFromUid(IBinder activityToken) { - return mActivityTaskManager.getLaunchedFromUid(activityToken); + return ActivityClient.getInstance().getLaunchedFromUid(activityToken); } public String getLaunchedFromPackage(IBinder activityToken) { - return mActivityTaskManager.getLaunchedFromPackage(activityToken); + return ActivityClient.getInstance().getLaunchedFromPackage(activityToken); } // ========================================================= @@ -15704,6 +15762,11 @@ public class ActivityManagerService extends IActivityManager.Stub return mUserController.getCurrentUser(); } + @Override + public @UserIdInt int getCurrentUserId() { + return mUserController.getCurrentUserIdChecked(); + } + String getStartedUserState(int userId) { final UserState userState = mUserController.getStartedUserState(userId); return UserState.stateToString(userState.state); @@ -16322,7 +16385,7 @@ public class ActivityManagerService extends IActivityManager.Stub final ActivityClient ac = ActivityClient.getInstance(); return new ActivityPresentationInfo(ac.getTaskForActivity(token, /*onlyRoot=*/ false), ac.getDisplayId(token), - mActivityTaskManager.getActivityClassForToken(token)); + mAtmInternal.getActivityName(token)); } @Override diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java index e3c071fe10e2..12fe3eda78a4 100644 --- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java +++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java @@ -118,7 +118,6 @@ import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Locale; -import java.util.Objects; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -1842,9 +1841,11 @@ final class ActivityManagerShellCommand extends ShellCommand { } int runGetCurrentUser(PrintWriter pw) throws RemoteException { - UserInfo currentUser = Objects.requireNonNull(mInterface.getCurrentUser(), - "Current user not set"); - pw.println(currentUser.id); + int userId = mInterface.getCurrentUserId(); + if (userId == UserHandle.USER_NULL) { + throw new IllegalStateException("Current user not set"); + } + pw.println(userId); return 0; } diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java index 0b4d27f4990b..f2c1e90e2476 100644 --- a/services/core/java/com/android/server/am/AppErrors.java +++ b/services/core/java/com/android/server/am/AppErrors.java @@ -756,8 +756,9 @@ class AppErrors { boolean handleAppCrashLocked(ProcessRecord app, String reason, String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) { final long now = SystemClock.uptimeMillis(); - final boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0; + final boolean showBackground = Settings.Secure.getIntForUser(mContext.getContentResolver(), + Settings.Secure.ANR_SHOW_BACKGROUND, 0, + mService.mUserController.getCurrentUserId()) != 0; final boolean procIsBoundForeground = (app.getCurProcState() == ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE); @@ -889,8 +890,9 @@ class AppErrors { void handleShowAppErrorUi(Message msg) { AppErrorDialog.Data data = (AppErrorDialog.Data) msg.obj; - boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0; + boolean showBackground = Settings.Secure.getIntForUser(mContext.getContentResolver(), + Settings.Secure.ANR_SHOW_BACKGROUND, 0, + mService.mUserController.getCurrentUserId()) != 0; final int userId; synchronized (mService) { @@ -982,8 +984,9 @@ class AppErrors { return; } - boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0; + boolean showBackground = Settings.Secure.getIntForUser(mContext.getContentResolver(), + Settings.Secure.ANR_SHOW_BACKGROUND, 0, + mService.mUserController.getCurrentUserId()) != 0; if (mService.mAtmInternal.canShowErrorDialogs() || showBackground) { proc.getDialogController().showAnrDialogs(data); } else { diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS index 60530c4eb920..9e79b02f8c96 100644 --- a/services/core/java/com/android/server/am/OWNERS +++ b/services/core/java/com/android/server/am/OWNERS @@ -23,6 +23,8 @@ toddke@google.com # Battery Stats joeo@google.com +per-file BatteryStats* = file:/BATTERY_STATS_OWNERS +per-file BatteryExternalStats* = file:/BATTERY_STATS_OWNERS # Londoners michaelwr@google.com diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index 771f273781fa..5b3e6514c6a6 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -1329,7 +1329,7 @@ public final class OomAdjuster { app.setCached(false); app.shouldNotFreeze = false; - app.mAllowStartFgsState = PROCESS_STATE_NONEXISTENT; + app.resetAllowStartFgs(); final int appUid = app.info.uid; final int logUid = mService.mCurOomAdjUid; @@ -1351,7 +1351,6 @@ public final class OomAdjuster { app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_DEFAULT); app.curCapability = PROCESS_CAPABILITY_ALL; app.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT); - app.bumpAllowStartFgsState(PROCESS_STATE_PERSISTENT); // System processes can do UI, and when they do we want to have // them trim their memory after the user leaves the UI. To // facilitate this, here we need to determine whether or not it @@ -1382,6 +1381,8 @@ public final class OomAdjuster { app.setCurRawProcState(app.getCurProcState()); app.curAdj = app.maxAdj; app.completedAdjSeq = app.adjSeq; + app.bumpAllowStartFgsState(app.getCurProcState()); + app.setAllowStartFgs(); // if curAdj is less than prevAppAdj, then this process was promoted return app.curAdj < prevAppAdj || app.getCurProcState() < prevProcState; } @@ -1773,6 +1774,11 @@ public final class OomAdjuster { int clientAdj = client.getCurRawAdj(); int clientProcState = client.getCurRawProcState(); + // pass client's mAllowStartFgs to the app if client is not persistent process. + if (client.mAllowStartFgs && client.maxAdj >= ProcessList.FOREGROUND_APP_ADJ) { + app.mAllowStartFgs = true; + } + if ((cr.flags & Context.BIND_WAIVE_PRIORITY) == 0) { if (shouldSkipDueToCycle(app, client, procState, adj, cycleReEval)) { continue; @@ -2236,7 +2242,7 @@ public final class OomAdjuster { app.setCurRawProcState(procState); app.setHasForegroundActivities(foregroundActivities); app.completedAdjSeq = mAdjSeq; - + app.setAllowStartFgs(); // if curAdj or curProcState improved, then this process was promoted return app.curAdj < prevAppAdj || app.getCurProcState() < prevProcState || app.curCapability != prevCapability ; diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index cf4adc65a7fc..255badd3239f 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -16,7 +16,16 @@ package com.android.server.am; +import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND; +import static android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND; +import static android.Manifest.permission.SYSTEM_ALERT_WINDOW; +import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE; import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import static android.os.Process.NFC_UID; +import static android.os.Process.ROOT_UID; +import static android.os.Process.SHELL_UID; +import static android.os.Process.SYSTEM_UID; import static com.android.server.Watchdog.NATIVE_STACKS_OF_INTEREST; import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ANR; @@ -361,6 +370,17 @@ class ProcessRecord implements WindowProcessListener { private final ArraySet<Binder> mBackgroundFgsStartTokens = new ArraySet<>(); + // The list of permissions that can start FGS from background. + private static String[] ALLOW_BG_START_FGS_PERMISSIONS = + {START_ACTIVITIES_FROM_BACKGROUND, START_FOREGROUND_SERVICES_FROM_BACKGROUND, + SYSTEM_ALERT_WINDOW}; + // Does the process has permission to start FGS from background. + boolean mAllowStartFgsByPermission; + // Can this process start FGS from background? + // If this process has the ability to start FGS from background, this ability can be passed to + // another process through service binding. + boolean mAllowStartFgs; + void setStartParams(int startUid, HostingRecord hostingRecord, String seInfo, long startTime) { this.startUid = startUid; @@ -476,6 +496,9 @@ class ProcessRecord implements WindowProcessListener { pw.println(); pw.print(prefix); pw.print("allowStartFgsState="); pw.println(mAllowStartFgsState); + if (mAllowStartFgs) { + pw.print(prefix); pw.print("allowStartFgs="); pw.println(mAllowStartFgs); + } if (hasShownUi || mPendingUiClean || hasAboveClient || treatLikeActivity) { pw.print(prefix); pw.print("hasShownUi="); pw.print(hasShownUi); pw.print(" pendingUiClean="); pw.print(mPendingUiClean); @@ -672,6 +695,7 @@ class ProcessRecord implements WindowProcessListener { mWindowProcessController = new WindowProcessController( mService.mActivityTaskManager, info, processName, uid, userId, this, this); pkgList.put(_info.packageName, new ProcessStats.ProcessStateHolder(_info.longVersionCode)); + setAllowStartFgsByPermission(); } public void setPid(int _pid) { @@ -1983,12 +2007,78 @@ class ProcessRecord implements WindowProcessListener { return mDialogController; } + void resetAllowStartFgs() { + mAllowStartFgsState = PROCESS_STATE_NONEXISTENT; + mAllowStartFgs = mAllowStartFgsByPermission; + } + void bumpAllowStartFgsState(int newProcState) { if (newProcState < mAllowStartFgsState) { mAllowStartFgsState = newProcState; } } + void setAllowStartFgsByPermission() { + boolean ret = false; + if (!ret) { + boolean isSystem = false; + final int uid = UserHandle.getAppId(info.uid); + switch (uid) { + case ROOT_UID: + case SYSTEM_UID: + case NFC_UID: + case SHELL_UID: + isSystem = true; + break; + default: + isSystem = false; + break; + } + + if (isSystem) { + ret = true; + } + } + + if (!ret) { + for (int i = 0; i < ALLOW_BG_START_FGS_PERMISSIONS.length; ++i) { + if (ActivityManager.checkComponentPermission(ALLOW_BG_START_FGS_PERMISSIONS[i], + info.uid, -1, true) + == PERMISSION_GRANTED) { + ret = true; + break; + } + } + } + mAllowStartFgs = mAllowStartFgsByPermission = ret; + } + + boolean isAllowedStartFgsState() { + return mAllowStartFgsState <= PROCESS_STATE_BOUND_FOREGROUND_SERVICE; + } + + void setAllowStartFgs() { + if (mAllowStartFgs) { + return; + } + if (!mAllowStartFgs) { + mAllowStartFgs = isAllowedStartFgsState(); + } + + if (!mAllowStartFgs) { + // Is the calling UID a device owner app? + if (mService.mInternal != null) { + mAllowStartFgs = mService.mInternal.isDeviceOwner(info.uid); + } + } + + if (!mAllowStartFgs) { + // uid is on DeviceIdleController's user/system allowlist + // or AMS's FgsStartTempAllowList. + mAllowStartFgs = mService.isWhitelistedForFgsStartLocked(info.uid); + } + } + /** A controller to generate error dialogs in {@link ProcessRecord} */ class ErrorDialogController { /** dialogs being displayed due to crash */ diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index 12fcc9cc26bf..c04f6ff37229 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -2173,7 +2173,7 @@ class UserController implements Handler.Callback { } } - UserInfo getCurrentUser() { + private void checkGetCurrentUserPermissions() { if ((mInjector.checkCallingPermission(INTERACT_ACROSS_USERS) != PackageManager.PERMISSION_GRANTED) && ( mInjector.checkCallingPermission(INTERACT_ACROSS_USERS_FULL) @@ -2185,8 +2185,12 @@ class UserController implements Handler.Callback { Slog.w(TAG, msg); throw new SecurityException(msg); } + } - // Optimization - if there is no pending user switch, return current id + UserInfo getCurrentUser() { + checkGetCurrentUserPermissions(); + + // Optimization - if there is no pending user switch, return user for current id // (no need to acquire lock because mTargetUserId and mCurrentUserId are volatile) if (mTargetUserId == UserHandle.USER_NULL) { return getUserInfo(mCurrentUserId); @@ -2196,9 +2200,23 @@ class UserController implements Handler.Callback { } } + /** + * Gets the current user id, but checking that caller has the proper permissions. + */ + int getCurrentUserIdChecked() { + checkGetCurrentUserPermissions(); + + // Optimization - if there is no pending user switch, return current id + // (no need to acquire lock because mTargetUserId and mCurrentUserId are volatile) + if (mTargetUserId == UserHandle.USER_NULL) { + return mCurrentUserId; + } + return getCurrentOrTargetUserId(); + } + @GuardedBy("mLock") UserInfo getCurrentUserLU() { - int userId = mTargetUserId != UserHandle.USER_NULL ? mTargetUserId : mCurrentUserId; + int userId = getCurrentOrTargetUserIdLU(); return getUserInfo(userId); } @@ -2213,7 +2231,6 @@ class UserController implements Handler.Callback { return mTargetUserId != UserHandle.USER_NULL ? mTargetUserId : mCurrentUserId; } - @GuardedBy("mLock") int getCurrentUserIdLU() { return mCurrentUserId; diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java index d4e2d27ca7a1..4da78252bccb 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -3090,7 +3090,7 @@ public class AppOpsService extends IAppOpsService.Stub { final Ops ops = getOpsLocked(uid, packageName, attributionTag, bypass, true /* edit */); if (ops == null) { - scheduleOpNotedIfNeededLocked(code, uid, packageName, + scheduleOpNotedIfNeededLocked(code, uid, packageName, flags, AppOpsManager.MODE_IGNORED); if (DEBUG) Slog.d(TAG, "noteOperation: no op for code " + code + " uid " + uid + " package " + packageName); @@ -3098,7 +3098,7 @@ public class AppOpsService extends IAppOpsService.Stub { } final Op op = getOpLocked(ops, code, uid, true); if (isOpRestrictedLocked(uid, code, packageName, bypass)) { - scheduleOpNotedIfNeededLocked(code, uid, packageName, + scheduleOpNotedIfNeededLocked(code, uid, packageName, flags, AppOpsManager.MODE_IGNORED); return AppOpsManager.MODE_IGNORED; } @@ -3120,7 +3120,7 @@ public class AppOpsService extends IAppOpsService.Stub { + switchCode + " (" + code + ") uid " + uid + " package " + packageName); attributedOp.rejected(uidState.state, flags); - scheduleOpNotedIfNeededLocked(code, uid, packageName, uidMode); + scheduleOpNotedIfNeededLocked(code, uid, packageName, flags, uidMode); return uidMode; } } else { @@ -3132,7 +3132,7 @@ public class AppOpsService extends IAppOpsService.Stub { + switchCode + " (" + code + ") uid " + uid + " package " + packageName); attributedOp.rejected(uidState.state, flags); - scheduleOpNotedIfNeededLocked(code, uid, packageName, mode); + scheduleOpNotedIfNeededLocked(code, uid, packageName, flags, mode); return mode; } } @@ -3142,7 +3142,8 @@ public class AppOpsService extends IAppOpsService.Stub { + packageName + (attributionTag == null ? "" : "." + attributionTag)); } - scheduleOpNotedIfNeededLocked(code, uid, packageName, AppOpsManager.MODE_ALLOWED); + scheduleOpNotedIfNeededLocked(code, uid, packageName, flags, + AppOpsManager.MODE_ALLOWED); attributedOp.accessed(proxyUid, proxyPackageName, proxyAttributionTag, uidState.state, flags); @@ -3545,7 +3546,7 @@ public class AppOpsService extends IAppOpsService.Stub { if (ops == null) { if (!dryRun) { scheduleOpStartedIfNeededLocked(code, uid, packageName, - AppOpsManager.MODE_IGNORED); + flags, AppOpsManager.MODE_IGNORED); } if (DEBUG) Slog.d(TAG, "startOperation: no op for code " + code + " uid " + uid + " package " + packageName); @@ -3555,7 +3556,7 @@ public class AppOpsService extends IAppOpsService.Stub { if (isOpRestrictedLocked(uid, code, packageName, bypass)) { if (!dryRun) { scheduleOpStartedIfNeededLocked(code, uid, packageName, - AppOpsManager.MODE_IGNORED); + flags, AppOpsManager.MODE_IGNORED); } return AppOpsManager.MODE_IGNORED; } @@ -3575,7 +3576,7 @@ public class AppOpsService extends IAppOpsService.Stub { } if (!dryRun) { attributedOp.rejected(uidState.state, flags); - scheduleOpStartedIfNeededLocked(code, uid, packageName, uidMode); + scheduleOpStartedIfNeededLocked(code, uid, packageName, flags, uidMode); } return uidMode; } @@ -3590,7 +3591,7 @@ public class AppOpsService extends IAppOpsService.Stub { + packageName); if (!dryRun) { attributedOp.rejected(uidState.state, flags); - scheduleOpStartedIfNeededLocked(code, uid, packageName, mode); + scheduleOpStartedIfNeededLocked(code, uid, packageName, flags, mode); } return mode; } @@ -3598,7 +3599,8 @@ public class AppOpsService extends IAppOpsService.Stub { if (DEBUG) Slog.d(TAG, "startOperation: allowing code " + code + " uid " + uid + " package " + packageName); if (!dryRun) { - scheduleOpStartedIfNeededLocked(code, uid, packageName, AppOpsManager.MODE_ALLOWED); + scheduleOpStartedIfNeededLocked(code, uid, packageName, flags, + AppOpsManager.MODE_ALLOWED); try { attributedOp.started(clientId, proxyUid, proxyPackageName, proxyAttributionTag, uidState.state, flags); @@ -3736,7 +3738,8 @@ public class AppOpsService extends IAppOpsService.Stub { } } - private void scheduleOpStartedIfNeededLocked(int code, int uid, String pkgName, int result) { + private void scheduleOpStartedIfNeededLocked(int code, int uid, String pkgName, + @OpFlags int flags, @Mode int result) { ArraySet<StartedCallback> dispatchedCallbacks = null; final int callbackListCount = mStartedWatchers.size(); for (int i = 0; i < callbackListCount; i++) { @@ -3761,18 +3764,18 @@ public class AppOpsService extends IAppOpsService.Stub { mHandler.sendMessage(PooledLambda.obtainMessage( AppOpsService::notifyOpStarted, - this, dispatchedCallbacks, code, uid, pkgName, result)); + this, dispatchedCallbacks, code, uid, pkgName, flags, result)); } private void notifyOpStarted(ArraySet<StartedCallback> callbacks, - int code, int uid, String packageName, int result) { + int code, int uid, String packageName, @OpFlags int flags, @Mode int result) { final long identity = Binder.clearCallingIdentity(); try { final int callbackCount = callbacks.size(); for (int i = 0; i < callbackCount; i++) { final StartedCallback callback = callbacks.valueAt(i); try { - callback.mCallback.opStarted(code, uid, packageName, result); + callback.mCallback.opStarted(code, uid, packageName, flags, result); } catch (RemoteException e) { /* do nothing */ } @@ -3783,7 +3786,7 @@ public class AppOpsService extends IAppOpsService.Stub { } private void scheduleOpNotedIfNeededLocked(int code, int uid, String packageName, - int result) { + @OpFlags int flags, @Mode int result) { ArraySet<NotedCallback> dispatchedCallbacks = null; final int callbackListCount = mNotedWatchers.size(); for (int i = 0; i < callbackListCount; i++) { @@ -3804,11 +3807,11 @@ public class AppOpsService extends IAppOpsService.Stub { } mHandler.sendMessage(PooledLambda.obtainMessage( AppOpsService::notifyOpChecked, - this, dispatchedCallbacks, code, uid, packageName, result)); + this, dispatchedCallbacks, code, uid, packageName, flags, result)); } private void notifyOpChecked(ArraySet<NotedCallback> callbacks, - int code, int uid, String packageName, int result) { + int code, int uid, String packageName, @OpFlags int flags, @Mode int result) { // There are features watching for checks in our process. The callbacks in // these features may require permissions our remote caller does not have. final long identity = Binder.clearCallingIdentity(); @@ -3817,7 +3820,7 @@ public class AppOpsService extends IAppOpsService.Stub { for (int i = 0; i < callbackCount; i++) { final NotedCallback callback = callbacks.valueAt(i); try { - callback.mCallback.opNoted(code, uid, packageName, result); + callback.mCallback.opNoted(code, uid, packageName, flags, result); } catch (RemoteException e) { /* do nothing */ } diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java index ccd1f3bb16f6..52b9f5c15c50 100644 --- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java @@ -138,9 +138,10 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { // not guaranteed to be current or correct, or even to exist. public @Nullable Network[] declaredUnderlyingNetworks; - // Whether this network is always metered even if its underlying networks are unmetered. - // Only relevant if #supportsUnderlyingNetworks is true. - public boolean declaredMetered; + // The capabilities originally announced by the NetworkAgent, regardless of any capabilities + // that were added or removed due to this network's underlying networks. + // Only set if #supportsUnderlyingNetworks is true. + public @Nullable NetworkCapabilities declaredCapabilities; // Indicates if netd has been told to create this Network. From this point on the appropriate // routing rules are setup and routes are added so packets can begin flowing over the Network. diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java index 4c63eb488118..d507b5f82bd0 100644 --- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java +++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java @@ -35,7 +35,6 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManagerInternal; -import android.content.pm.UserInfo; import android.net.INetd; import android.net.UidRange; import android.os.Build; @@ -174,11 +173,9 @@ public class PermissionMonitor implements PackageManagerInternal.PackageListObse netdPermsUids.put(uid, netdPermsUids.get(uid) | otherNetdPerms); } - List<UserInfo> users = mUserManager.getAliveUsers(); - if (users != null) { - for (UserInfo user : users) { - mUsers.add(user.id); - } + final List<UserHandle> users = mUserManager.getUserHandles(true /* excludeDying */); + for (UserHandle user : users) { + mUsers.add(user.getIdentifier()); } final SparseArray<ArraySet<String>> systemPermission = diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index 5cb0994c5cb2..cabfbc02491c 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -48,6 +48,7 @@ import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; import android.net.ConnectivityManager; import android.net.DnsResolver; +import android.net.INetd; import android.net.INetworkManagementEventObserver; import android.net.Ikev2VpnProfile; import android.net.IpPrefix; @@ -68,6 +69,7 @@ import android.net.NetworkProvider; import android.net.NetworkRequest; import android.net.RouteInfo; import android.net.UidRange; +import android.net.UidRangeParcel; import android.net.VpnManager; import android.net.VpnService; import android.net.ipsec.ike.ChildSessionCallback; @@ -188,7 +190,8 @@ public class Vpn { private PendingIntent mStatusIntent; private volatile boolean mEnableTeardown = true; - private final INetworkManagementService mNetd; + private final INetworkManagementService mNms; + private final INetd mNetd; @VisibleForTesting protected VpnConfig mConfig; private final NetworkProvider mNetworkProvider; @@ -234,7 +237,7 @@ public class Vpn { * @see mLockdown */ @GuardedBy("this") - private final Set<UidRange> mBlockedUidsAsToldToNetd = new ArraySet<>(); + private final Set<UidRangeParcel> mBlockedUidsAsToldToNetd = new ArraySet<>(); // The user id of initiating VPN. private final int mUserId; @@ -363,22 +366,23 @@ public class Vpn { } } - public Vpn(Looper looper, Context context, INetworkManagementService netService, + public Vpn(Looper looper, Context context, INetworkManagementService netService, INetd netd, @UserIdInt int userId, @NonNull KeyStore keyStore) { - this(looper, context, new Dependencies(), netService, userId, keyStore, + this(looper, context, new Dependencies(), netService, netd, userId, keyStore, new SystemServices(context), new Ikev2SessionCreator()); } @VisibleForTesting protected Vpn(Looper looper, Context context, Dependencies deps, - INetworkManagementService netService, + INetworkManagementService netService, INetd netd, int userId, @NonNull KeyStore keyStore, SystemServices systemServices, Ikev2SessionCreator ikev2SessionCreator) { mContext = context; mConnectivityManager = mContext.getSystemService(ConnectivityManager.class); mUserIdContext = context.createContextAsUser(UserHandle.of(userId), 0 /* flags */); mDeps = deps; - mNetd = netService; + mNms = netService; + mNetd = netd; mUserId = userId; mLooper = looper; mSystemServices = systemServices; @@ -912,7 +916,7 @@ public class Vpn { } try { - mNetd.denyProtect(mOwnerUID); + mNms.denyProtect(mOwnerUID); } catch (Exception e) { Log.wtf(TAG, "Failed to disallow UID " + mOwnerUID + " to call protect() " + e); } @@ -922,7 +926,7 @@ public class Vpn { mOwnerUID = getAppUid(newPackage, mUserId); mIsPackageTargetingAtLeastQ = doesPackageTargetAtLeastQ(newPackage); try { - mNetd.allowProtect(mOwnerUID); + mNms.allowProtect(mOwnerUID); } catch (Exception e) { Log.wtf(TAG, "Failed to allow UID " + mOwnerUID + " to call protect() " + e); } @@ -1253,7 +1257,7 @@ public class Vpn { final PackageManager packageManager = mUserIdContext.getPackageManager(); if (packageManager == null) { - throw new UnsupportedOperationException("Cannot get PackageManager."); + throw new IllegalStateException("Cannot get PackageManager."); } final ResolveInfo info = packageManager.resolveService(intent, 0 /* flags */); if (info == null) { @@ -1579,24 +1583,25 @@ public class Vpn { exemptedPackages = new ArrayList<>(mLockdownAllowlist); exemptedPackages.add(mPackage); } - final Set<UidRange> rangesToTellNetdToRemove = new ArraySet<>(mBlockedUidsAsToldToNetd); + final Set<UidRangeParcel> rangesToTellNetdToRemove = + new ArraySet<>(mBlockedUidsAsToldToNetd); - final Set<UidRange> rangesToTellNetdToAdd; + final Set<UidRangeParcel> rangesToTellNetdToAdd; if (enforce) { - final Set<UidRange> rangesThatShouldBeBlocked = + final Set<UidRange> restrictedProfilesRanges = createUserAndRestrictedProfilesRanges(mUserId, - /* allowedApplications */ null, - /* disallowedApplications */ exemptedPackages); + /* allowedApplications */ null, + /* disallowedApplications */ exemptedPackages); + final Set<UidRangeParcel> rangesThatShouldBeBlocked = new ArraySet<>(); // The UID range of the first user (0-99999) would block the IPSec traffic, which comes // directly from the kernel and is marked as uid=0. So we adjust the range to allow // it through (b/69873852). - for (UidRange range : rangesThatShouldBeBlocked) { - if (range.start == 0) { - rangesThatShouldBeBlocked.remove(range); - if (range.stop != 0) { - rangesThatShouldBeBlocked.add(new UidRange(1, range.stop)); - } + for (UidRange range : restrictedProfilesRanges) { + if (range.start == 0 && range.stop != 0) { + rangesThatShouldBeBlocked.add(new UidRangeParcel(1, range.stop)); + } else if (range.start != 0) { + rangesThatShouldBeBlocked.add(new UidRangeParcel(range.start, range.stop)); } } @@ -1628,13 +1633,13 @@ public class Vpn { * including added ranges that already existed or removed ones that didn't. */ @GuardedBy("this") - private boolean setAllowOnlyVpnForUids(boolean enforce, Collection<UidRange> ranges) { + private boolean setAllowOnlyVpnForUids(boolean enforce, Collection<UidRangeParcel> ranges) { if (ranges.size() == 0) { return true; } - final UidRange[] rangesArray = ranges.toArray(new UidRange[ranges.size()]); + final UidRangeParcel[] stableRanges = ranges.toArray(new UidRangeParcel[ranges.size()]); try { - mNetd.setAllowOnlyVpnForUids(enforce, rangesArray); + mNetd.networkRejectNonSecureVpn(enforce, stableRanges); } catch (RemoteException | RuntimeException e) { Log.e(TAG, "Updating blocked=" + enforce + " for UIDs " + Arrays.toString(ranges.toArray()) + " failed", e); @@ -1849,10 +1854,20 @@ public class Vpn { if (mNetworkInfo.isConnected()) { return !appliesToUid(uid); } else { - return UidRange.containsUid(mBlockedUidsAsToldToNetd, uid); + return containsUid(mBlockedUidsAsToldToNetd, uid); } } + private boolean containsUid(Collection<UidRangeParcel> ranges, int uid) { + if (ranges == null) return false; + for (UidRangeParcel range : ranges) { + if (range.start <= uid && uid <= range.stop) { + return true; + } + } + return false; + } + private void updateAlwaysOnNotification(DetailedState networkState) { final boolean visible = (mAlwaysOn && networkState != DetailedState.CONNECTED); @@ -2495,7 +2510,7 @@ public class Vpn { address /* unused */, address /* unused */, network); - mNetd.setInterfaceUp(mTunnelIface.getInterfaceName()); + mNms.setInterfaceUp(mTunnelIface.getInterfaceName()); mSession = mIkev2SessionCreator.createIkeSession( mContext, diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index d4a19d6bc366..2c7cd5bce514 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -403,7 +403,7 @@ public final class DisplayManagerService extends SystemService { mUiHandler = UiThread.getHandler(); mDisplayDeviceRepo = new DisplayDeviceRepository(mSyncRoot, mPersistentDataStore); mLogicalDisplayMapper = new LogicalDisplayMapper(context, mDisplayDeviceRepo, - new LogicalDisplayListener(), mPersistentDataStore); + new LogicalDisplayListener()); mDisplayModeDirector = new DisplayModeDirector(context, mHandler); Resources resources = mContext.getResources(); mDefaultDisplayDefaultColorMode = mContext.getResources().getInteger( diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java index 74ea2d7114fc..155b246a1408 100644 --- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java +++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java @@ -177,10 +177,10 @@ final class LocalDisplayAdapter extends DisplayAdapter { private final class LocalDisplayDevice extends DisplayDevice { private final long mPhysicalDisplayId; - private final LogicalLight mBacklight; private final SparseArray<DisplayModeRecord> mSupportedModes = new SparseArray<>(); private final ArrayList<Integer> mSupportedColorModes = new ArrayList<>(); private final boolean mIsDefaultDisplay; + private final BacklightAdapter mBacklightAdapter; private DisplayDeviceInfo mInfo; private boolean mHavePendingChanges; @@ -205,7 +205,6 @@ final class LocalDisplayAdapter extends DisplayAdapter { private SurfaceControl.DisplayConfig[] mDisplayConfigs; private Spline mSystemBrightnessToNits; private Spline mNitsToHalBrightness; - private DisplayDeviceConfig mDisplayDeviceConfig; private DisplayEventReceiver.FrameRateOverride[] mFrameRateOverrides = @@ -222,12 +221,7 @@ final class LocalDisplayAdapter extends DisplayAdapter { updateDisplayPropertiesLocked(info, configs, activeConfigId, configSpecs, colorModes, activeColorMode, hdrCapabilities); mSidekickInternal = LocalServices.getService(SidekickInternal.class); - if (mIsDefaultDisplay) { - LightsManager lights = LocalServices.getService(LightsManager.class); - mBacklight = lights.getLight(LightsManager.LIGHT_ID_BACKLIGHT); - } else { - mBacklight = null; - } + mBacklightAdapter = new BacklightAdapter(displayToken, isDefaultDisplay); mAllmSupported = SurfaceControl.getAutoLowLatencyModeSupport(displayToken); mGameContentTypeSupported = SurfaceControl.getGameContentTypeSupport(displayToken); mDisplayDeviceConfig = null; @@ -643,8 +637,7 @@ final class LocalDisplayAdapter extends DisplayAdapter { brightnessState, PowerManager.BRIGHTNESS_OFF_FLOAT); final boolean stateChanged = (mState != state); final boolean brightnessChanged = (!BrightnessSynchronizer.floatEquals( - mBrightnessState, brightnessState)) - && mBacklight != null; + mBrightnessState, brightnessState)); if (stateChanged || brightnessChanged) { final long physicalDisplayId = mPhysicalDisplayId; final IBinder token = getDisplayTokenLocked(); @@ -712,9 +705,7 @@ final class LocalDisplayAdapter extends DisplayAdapter { + "id=" + physicalDisplayId + ", state=" + Display.stateToString(state) + ")"); } - if (mBacklight != null) { - mBacklight.setVrMode(isVrEnabled); - } + mBacklightAdapter.setVrMode(isVrEnabled); } private void setDisplayState(int state) { @@ -770,13 +761,8 @@ final class LocalDisplayAdapter extends DisplayAdapter { Trace.traceBegin(Trace.TRACE_TAG_POWER, "setDisplayBrightness(" + "id=" + physicalDisplayId + ", brightness=" + brightness + ")"); try { - if (isHalBrightnessRangeSpecified()) { - brightness = displayBrightnessToHalBrightness( - BrightnessSynchronizer.brightnessFloatToIntRange(brightness)); - } - if (mBacklight != null) { - mBacklight.setBrightness(brightness); - } + brightness = displayBrightnessToHalBrightness(brightness); + mBacklightAdapter.setBrightness(brightness); Trace.traceCounter(Trace.TRACE_TAG_POWER, "ScreenBrightness", BrightnessSynchronizer.brightnessFloatToInt(brightness)); @@ -785,26 +771,33 @@ final class LocalDisplayAdapter extends DisplayAdapter { } } - private boolean isHalBrightnessRangeSpecified() { - return !(mSystemBrightnessToNits == null || mNitsToHalBrightness == null); - } - /** * Converts brightness range from the framework's brightness space to the * Hal brightness space if the HAL brightness space has been provided via * a display device configuration file. */ private float displayBrightnessToHalBrightness(float brightness) { - if (!isHalBrightnessRangeSpecified()) { - return PowerManager.BRIGHTNESS_INVALID_FLOAT; + // TODO: b/171380847 - This needs to be deprecated. The nits-to-brightness + // relationship should be specified in display-config OR config.xml, but not + // both, and no nits-space conversion should be necessary. + // + // Only do a conversion if there exists a unique system brightness and a + // unique HAL brightness-to-nits range defined. + if (mSystemBrightnessToNits == null || mNitsToHalBrightness == null) { + return brightness; } + // Sys brightness in this conversion is always specified in the old 1-255 + // range, so convert that here before the translation. + final float brightnessInt = + BrightnessSynchronizer.brightnessFloatToIntRange(brightness); + if (BrightnessSynchronizer.floatEquals( - brightness, PowerManager.BRIGHTNESS_OFF)) { + brightnessInt, PowerManager.BRIGHTNESS_OFF)) { return PowerManager.BRIGHTNESS_OFF_FLOAT; } - final float nits = mSystemBrightnessToNits.interpolate(brightness); + final float nits = mSystemBrightnessToNits.interpolate(brightnessInt); final float halBrightness = mNitsToHalBrightness.interpolate(nits); return halBrightness; } @@ -988,7 +981,7 @@ final class LocalDisplayAdapter extends DisplayAdapter { pw.println("mDefaultModeId=" + mDefaultModeId); pw.println("mState=" + Display.stateToString(mState)); pw.println("mBrightnessState=" + mBrightnessState); - pw.println("mBacklight=" + mBacklight); + pw.println("mBacklightAdapter=" + mBacklightAdapter); pw.println("mAllmSupported=" + mAllmSupported); pw.println("mAllmRequested=" + mAllmRequested); pw.println("mGameContentTypeSupported=" + mGameContentTypeSupported); @@ -1209,4 +1202,44 @@ final class LocalDisplayAdapter extends DisplayAdapter { } } } + + static class BacklightAdapter { + private final IBinder mDisplayToken; + private final LogicalLight mBacklight; + private final boolean mUseSurfaceControlBrightness; + + BacklightAdapter(IBinder displayToken, boolean isDefaultDisplay) { + mDisplayToken = displayToken; + + mUseSurfaceControlBrightness = + SurfaceControl.getDisplayBrightnessSupport(mDisplayToken); + + if (!mUseSurfaceControlBrightness && isDefaultDisplay) { + LightsManager lights = LocalServices.getService(LightsManager.class); + mBacklight = lights.getLight(LightsManager.LIGHT_ID_BACKLIGHT); + } else { + mBacklight = null; + } + } + + public void setBrightness(float brightness) { + if (mUseSurfaceControlBrightness) { + SurfaceControl.setDisplayBrightness(mDisplayToken, brightness); + } else if (mBacklight != null) { + mBacklight.setBrightness(brightness); + } + } + + public void setVrMode(boolean isVrModeEnabled) { + if (mBacklight != null) { + mBacklight.setVrMode(isVrModeEnabled); + } + } + + @Override + public String toString() { + return "BacklightAdapter [useSurfaceControl=" + mUseSurfaceControlBrightness + + ", backlight=" + mBacklight + "]"; + } + } } diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java index cdcbb4f123a1..a12785889bd3 100644 --- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java +++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java @@ -20,13 +20,13 @@ import android.content.Context; import android.os.Process; import android.os.SystemProperties; import android.text.TextUtils; +import android.util.IndentingPrintWriter; import android.util.Slog; import android.util.SparseArray; import android.view.Display; import android.view.DisplayEventReceiver; import android.view.DisplayInfo; -import com.android.internal.util.IndentingPrintWriter; import java.io.PrintWriter; import java.util.Arrays; @@ -102,13 +102,10 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { private final SparseArray<DisplayGroup> mDisplayGroups = new SparseArray<>(); private final DisplayDeviceRepository mDisplayDeviceRepo; - private final PersistentDataStore mPersistentDataStore; private final Listener mListener; - LogicalDisplayMapper(Context context, DisplayDeviceRepository repo, Listener listener, - PersistentDataStore persistentDataStore) { + LogicalDisplayMapper(Context context, DisplayDeviceRepository repo, Listener listener) { mDisplayDeviceRepo = repo; - mPersistentDataStore = persistentDataStore; mListener = listener; mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false); mDisplayDeviceRepo.addListener(this); @@ -238,7 +235,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener { // Find the associated LogicalDisplays for the configured "folding" DeviceDisplays. final LogicalDisplay displayFolded = getLocked(deviceFolded); final LogicalDisplay displayUnfolded = getLocked(deviceUnfolded); - if (displayFolded == null || displayFolded == null) { + if (displayFolded == null || displayUnfolded == null) { // If the expected displays are not present, return early. return; } diff --git a/services/core/java/com/android/server/dreams/OWNERS b/services/core/java/com/android/server/dreams/OWNERS index 3c9bbf8797ea..426f002ad236 100644 --- a/services/core/java/com/android/server/dreams/OWNERS +++ b/services/core/java/com/android/server/dreams/OWNERS @@ -1,3 +1,3 @@ -dsandler@google.com +dsandler@android.com michaelwr@google.com roosa@google.com diff --git a/services/core/java/com/android/server/hdmi/HdmiCecConfig.java b/services/core/java/com/android/server/hdmi/HdmiCecConfig.java index 98d130f1ef69..371fd3d33090 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecConfig.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecConfig.java @@ -85,7 +85,7 @@ public class HdmiCecConfig { @NonNull private final Context mContext; @NonNull private final StorageAdapter mStorageAdapter; - @Nullable private final CecSettings mProductConfig; + @Nullable private final CecSettings mSystemConfig; @Nullable private final CecSettings mVendorOverride; /** @@ -162,14 +162,14 @@ public class HdmiCecConfig { @VisibleForTesting HdmiCecConfig(@NonNull Context context, @NonNull StorageAdapter storageAdapter, - @Nullable CecSettings productConfig, + @Nullable CecSettings systemConfig, @Nullable CecSettings vendorOverride) { mContext = context; mStorageAdapter = storageAdapter; - mProductConfig = productConfig; + mSystemConfig = systemConfig; mVendorOverride = vendorOverride; - if (mProductConfig == null) { - Slog.i(TAG, "CEC master configuration XML missing."); + if (mSystemConfig == null) { + Slog.i(TAG, "CEC system configuration XML missing."); } if (mVendorOverride == null) { Slog.i(TAG, "CEC OEM configuration override XML missing."); @@ -178,7 +178,7 @@ public class HdmiCecConfig { HdmiCecConfig(@NonNull Context context) { this(context, new StorageAdapter(context), - readSettingsFromFile(Environment.buildPath(Environment.getProductDirectory(), + readSettingsFromFile(Environment.buildPath(Environment.getRootDirectory(), ETC_DIR, CONFIG_FILE)), readSettingsFromFile(Environment.buildPath(Environment.getVendorDirectory(), ETC_DIR, CONFIG_FILE))); @@ -226,7 +226,7 @@ public class HdmiCecConfig { @Nullable private Setting getSetting(@NonNull String name) { - if (mProductConfig == null) { + if (mSystemConfig == null) { return null; } if (mVendorOverride != null) { @@ -237,8 +237,8 @@ public class HdmiCecConfig { } } } - // If not found, try the product config. - for (Setting setting : mProductConfig.getSetting()) { + // If not found, try the system config. + for (Setting setting : mSystemConfig.getSetting()) { if (setting.getName().equals(name)) { return setting; } @@ -322,11 +322,11 @@ public class HdmiCecConfig { * Returns a list of all settings based on the XML metadata. */ public @CecSettingName List<String> getAllSettings() { - if (mProductConfig == null) { + if (mSystemConfig == null) { return new ArrayList<String>(); } List<String> allSettings = new ArrayList<String>(); - for (Setting setting : mProductConfig.getSetting()) { + for (Setting setting : mSystemConfig.getSetting()) { allSettings.add(setting.getName()); } return allSettings; @@ -336,12 +336,12 @@ public class HdmiCecConfig { * Returns a list of user-modifiable settings based on the XML metadata. */ public @CecSettingName List<String> getUserSettings() { - if (mProductConfig == null) { + if (mSystemConfig == null) { return new ArrayList<String>(); } Set<String> userSettings = new HashSet<String>(); - // First read from the product config. - for (Setting setting : mProductConfig.getSetting()) { + // First read from the system config. + for (Setting setting : mSystemConfig.getSetting()) { if (setting.getUserConfigurable()) { userSettings.add(setting.getName()); } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java index 9b3f788d7457..52121f352783 100755 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java @@ -282,6 +282,8 @@ abstract class HdmiCecLocalDevice { return handleGiveOsdName(message); case Constants.MESSAGE_GIVE_DEVICE_VENDOR_ID: return handleGiveDeviceVendorId(null); + case Constants.MESSAGE_CEC_VERSION: + return handleCecVersion(); case Constants.MESSAGE_GET_CEC_VERSION: return handleGetCecVersion(message); case Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS: @@ -406,6 +408,14 @@ abstract class HdmiCecLocalDevice { } @ServiceThreadOnly + private boolean handleCecVersion() { + assertRunOnServiceThread(); + + // Return true to avoid <Feature Abort> responses. Cec Version is tracked in HdmiCecNetwork. + return true; + } + + @ServiceThreadOnly protected boolean handleActiveSource(HdmiCecMessage message) { return false; } @@ -613,6 +623,14 @@ abstract class HdmiCecLocalDevice { return false; } + if (isPowerOffOrToggleCommand(message) || isPowerOnOrToggleCommand(message)) { + // Power commands should already be handled above. Don't continue and convert the CEC + // keycode to Android keycode. + // Do not <Feature Abort> as the local device should already be in the correct power + // state. + return true; + } + final long downTime = SystemClock.uptimeMillis(); final byte[] params = message.getParams(); final int keycode = HdmiCecKeycode.cecKeycodeAndParamsToAndroidKey(params); diff --git a/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java b/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java index fc21724714c5..b748ae026cfc 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecNetwork.java @@ -166,7 +166,6 @@ public class HdmiCecNetwork { } return false; } - /** * Clear all logical addresses registered in the device. * @@ -523,11 +522,32 @@ public class HdmiCecNetwork { case Constants.MESSAGE_DEVICE_VENDOR_ID: handleDeviceVendorId(message); break; - + case Constants.MESSAGE_CEC_VERSION: + handleCecVersion(message); + break; + case Constants.MESSAGE_REPORT_FEATURES: + handleReportFeatures(message); + break; } } @ServiceThreadOnly + private void handleReportFeatures(HdmiCecMessage message) { + assertRunOnServiceThread(); + + int version = Byte.toUnsignedInt(message.getParams()[0]); + updateDeviceCecVersion(message.getSource(), version); + } + + @ServiceThreadOnly + private void handleCecVersion(HdmiCecMessage message) { + assertRunOnServiceThread(); + + int version = Byte.toUnsignedInt(message.getParams()[0]); + updateDeviceCecVersion(message.getSource(), version); + } + + @ServiceThreadOnly private void handleReportPhysicalAddress(HdmiCecMessage message) { assertRunOnServiceThread(); int logicalAddress = message.getSource(); @@ -543,7 +563,8 @@ public class HdmiCecNetwork { HdmiDeviceInfo updatedDeviceInfo = new HdmiDeviceInfo(deviceInfo.getLogicalAddress(), physicalAddress, physicalAddressToPortId(physicalAddress), type, deviceInfo.getVendorId(), - deviceInfo.getDisplayName(), deviceInfo.getDevicePowerStatus()); + deviceInfo.getDisplayName(), deviceInfo.getDevicePowerStatus(), + deviceInfo.getCecVersion()); updateCecDevice(updatedDeviceInfo); } } @@ -554,6 +575,31 @@ public class HdmiCecNetwork { // Update power status of device int newStatus = message.getParams()[0] & 0xFF; updateDevicePowerStatus(message.getSource(), newStatus); + + if (message.getDestination() == Constants.ADDR_BROADCAST) { + updateDeviceCecVersion(message.getSource(), HdmiControlManager.HDMI_CEC_VERSION_2_0); + } + } + + @ServiceThreadOnly + private void updateDeviceCecVersion(int logicalAddress, int hdmiCecVersion) { + assertRunOnServiceThread(); + HdmiDeviceInfo deviceInfo = getCecDeviceInfo(logicalAddress); + if (deviceInfo == null) { + Slog.w(TAG, "Can not update CEC version of non-existing device:" + logicalAddress); + return; + } + + if (deviceInfo.getCecVersion() == hdmiCecVersion) { + return; + } + + HdmiDeviceInfo updatedDeviceInfo = new HdmiDeviceInfo(deviceInfo.getLogicalAddress(), + deviceInfo.getPhysicalAddress(), deviceInfo.getPortId(), deviceInfo.getDeviceType(), + deviceInfo.getVendorId(), + deviceInfo.getDisplayName(), deviceInfo.getDevicePowerStatus(), + hdmiCecVersion); + updateCecDevice(updatedDeviceInfo); } @ServiceThreadOnly @@ -586,7 +632,7 @@ public class HdmiCecNetwork { updateCecDevice(new HdmiDeviceInfo(deviceInfo.getLogicalAddress(), deviceInfo.getPhysicalAddress(), deviceInfo.getPortId(), deviceInfo.getDeviceType(), deviceInfo.getVendorId(), osdName, - deviceInfo.getDevicePowerStatus())); + deviceInfo.getDevicePowerStatus(), deviceInfo.getCecVersion())); } @ServiceThreadOnly @@ -602,7 +648,8 @@ public class HdmiCecNetwork { HdmiDeviceInfo updatedDeviceInfo = new HdmiDeviceInfo(deviceInfo.getLogicalAddress(), deviceInfo.getPhysicalAddress(), deviceInfo.getPortId(), deviceInfo.getDeviceType(), vendorId, - deviceInfo.getDisplayName(), deviceInfo.getDevicePowerStatus()); + deviceInfo.getDisplayName(), deviceInfo.getDevicePowerStatus(), + deviceInfo.getCecVersion()); updateCecDevice(updatedDeviceInfo); } } diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index a1d13e974019..c943fbcdee2e 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -813,7 +813,7 @@ public class HdmiControlService extends SystemService { // with system. HdmiDeviceInfo deviceInfo = createDeviceInfo(logicalAddress, deviceType, - HdmiControlManager.POWER_STATUS_ON); + HdmiControlManager.POWER_STATUS_ON, getCecVersion()); localDevice.setDeviceInfo(deviceInfo); mHdmiCecNetwork.addLocalDevice(deviceType, localDevice); mCecController.addLogicalAddress(logicalAddress); @@ -1222,11 +1222,12 @@ public class HdmiControlService extends SystemService { } } - private HdmiDeviceInfo createDeviceInfo(int logicalAddress, int deviceType, int powerStatus) { + private HdmiDeviceInfo createDeviceInfo(int logicalAddress, int deviceType, int powerStatus, + int cecVersion) { String displayName = readStringSetting(Global.DEVICE_NAME, Build.MODEL); return new HdmiDeviceInfo(logicalAddress, getPhysicalAddress(), pathToPortId(getPhysicalAddress()), deviceType, - getVendorId(), displayName, powerStatus); + getVendorId(), displayName, powerStatus, cecVersion); } // Set the display name in HdmiDeviceInfo of the current devices to content provided by @@ -1240,7 +1241,7 @@ public class HdmiControlService extends SystemService { device.setDeviceInfo(new HdmiDeviceInfo( deviceInfo.getLogicalAddress(), deviceInfo.getPhysicalAddress(), deviceInfo.getPortId(), deviceInfo.getDeviceType(), deviceInfo.getVendorId(), - newDisplayName, deviceInfo.getDevicePowerStatus())); + newDisplayName, deviceInfo.getDevicePowerStatus(), deviceInfo.getCecVersion())); sendCecCommand(HdmiCecMessageBuilder.buildSetOsdNameCommand( device.mAddress, Constants.ADDR_TV, newDisplayName)); } diff --git a/services/core/java/com/android/server/hdmi/HdmiUtils.java b/services/core/java/com/android/server/hdmi/HdmiUtils.java index 52a804a36750..03e5de8ac8bd 100644 --- a/services/core/java/com/android/server/hdmi/HdmiUtils.java +++ b/services/core/java/com/android/server/hdmi/HdmiUtils.java @@ -396,7 +396,7 @@ final class HdmiUtils { static HdmiDeviceInfo cloneHdmiDeviceInfo(HdmiDeviceInfo info, int newPowerStatus) { return new HdmiDeviceInfo(info.getLogicalAddress(), info.getPhysicalAddress(), info.getPortId(), info.getDeviceType(), - info.getVendorId(), info.getDisplayName(), newPowerStatus); + info.getVendorId(), info.getDisplayName(), newPowerStatus, info.getCecVersion()); } /** diff --git a/services/core/java/com/android/server/hdmi/cec_config.xml b/services/core/java/com/android/server/hdmi/cec_config.xml new file mode 100644 index 000000000000..480e0ec040a8 --- /dev/null +++ b/services/core/java/com/android/server/hdmi/cec_config.xml @@ -0,0 +1,49 @@ +<?xml version='1.0' encoding='utf-8' standalone='yes' ?> +<cec-settings> + <setting name="hdmi_cec_enabled" + value-type="int" + user-configurable="true"> + <allowed-values> + <value int-value="0" /> + <value int-value="1" /> + </allowed-values> + <default-value int-value="1" /> + </setting> + <setting name="hdmi_cec_version" + value-type="int" + user-configurable="true"> + <allowed-values> + <value int-value="0x05" /> + <value int-value="0x06" /> + </allowed-values> + <default-value int-value="0x05" /> + </setting> + <setting name="send_standby_on_sleep" + value-type="string" + user-configurable="true"> + <allowed-values> + <value string-value="to_tv" /> + <value string-value="broadcast" /> + <value string-value="none" /> + </allowed-values> + <default-value string-value="to_tv" /> + </setting> + <setting name="power_state_change_on_active_source_lost" + value-type="string" + user-configurable="true"> + <allowed-values> + <value string-value="none" /> + <value string-value="standby_now" /> + </allowed-values> + <default-value string-value="none" /> + </setting> + <setting name="system_audio_mode_muting" + value-type="int" + user-configurable="true"> + <allowed-values> + <value int-value="0" /> + <value int-value="1" /> + </allowed-values> + <default-value int-value="1" /> + </setting> +</cec-settings> diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java index a0121bba4a05..46ccf1e18802 100644 --- a/services/core/java/com/android/server/input/InputManagerService.java +++ b/services/core/java/com/android/server/input/InputManagerService.java @@ -204,7 +204,12 @@ public class InputManagerService extends IInputManager.Stub private int mNextVibratorTokenValue; // State for lid switch + // Lock for the lid switch state. Held when triggering callbacks to guarantee lid switch events + // are delivered in order. For ex, when a new lid switch callback is registered the lock is held + // while the callback is processing the initial lid switch event which guarantees that any + // events that occur at the same time are delivered after the callback has returned. private final Object mLidSwitchLock = new Object(); + @GuardedBy("mLidSwitchLock") private List<LidSwitchCallback> mLidSwitchCallbacks = new ArrayList<>(); // State for the currently installed input filter. @@ -348,9 +353,6 @@ public class InputManagerService extends IInputManager.Stub public static final int SW_CAMERA_LENS_COVER_BIT = 1 << SW_CAMERA_LENS_COVER; public static final int SW_MUTE_DEVICE_BIT = 1 << SW_MUTE_DEVICE; - /** Indicates an open state for the lid switch. */ - public static final int SW_STATE_LID_OPEN = 0; - /** Whether to use the dev/input/event or uevent subsystem for the audio jack. */ final boolean mUseDevInputEventForAudioJack; @@ -386,13 +388,18 @@ public class InputManagerService extends IInputManager.Stub } void registerLidSwitchCallbackInternal(@NonNull LidSwitchCallback callback) { - boolean lidOpen; synchronized (mLidSwitchLock) { mLidSwitchCallbacks.add(callback); - lidOpen = getSwitchState(-1 /* deviceId */, InputDevice.SOURCE_ANY, SW_LID) - == SW_STATE_LID_OPEN; + + // Skip triggering the initial callback if the system is not yet ready as the switch + // state will be reported as KEY_STATE_UNKNOWN. The callback will be triggered in + // systemRunning(). + if (mSystemReady) { + boolean lidOpen = getSwitchState(-1 /* deviceId */, InputDevice.SOURCE_ANY, SW_LID) + == KEY_STATE_UP; + callback.notifyLidSwitchChanged(0 /* whenNanos */, lidOpen); + } } - callback.notifyLidSwitchChanged(0 /* whenNanos */, lidOpen); } void unregisterLidSwitchCallbackInternal(@NonNull LidSwitchCallback callback) { @@ -440,7 +447,18 @@ public class InputManagerService extends IInputManager.Stub } mNotificationManager = (NotificationManager)mContext.getSystemService( Context.NOTIFICATION_SERVICE); - mSystemReady = true; + + synchronized (mLidSwitchLock) { + mSystemReady = true; + + // Send the initial lid switch state to any callback registered before the system was + // ready. + int switchState = getSwitchState(-1 /* deviceId */, InputDevice.SOURCE_ANY, SW_LID); + for (int i = 0; i < mLidSwitchCallbacks.size(); i++) { + LidSwitchCallback callback = mLidSwitchCallbacks.get(i); + callback.notifyLidSwitchChanged(0 /* whenNanos */, switchState == KEY_STATE_UP); + } + } IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED); filter.addAction(Intent.ACTION_PACKAGE_REMOVED); @@ -2125,14 +2143,13 @@ public class InputManagerService extends IInputManager.Stub if ((switchMask & SW_LID_BIT) != 0) { final boolean lidOpen = ((switchValues & SW_LID_BIT) == 0); - - ArrayList<LidSwitchCallback> callbacksCopy; synchronized (mLidSwitchLock) { - callbacksCopy = new ArrayList<>(mLidSwitchCallbacks); - } - for (int i = 0; i < callbacksCopy.size(); i++) { - LidSwitchCallback callbacks = callbacksCopy.get(i); - callbacks.notifyLidSwitchChanged(whenNanos, lidOpen); + if (mSystemReady) { + for (int i = 0; i < mLidSwitchCallbacks.size(); i++) { + LidSwitchCallback callbacks = mLidSwitchCallbacks.get(i); + callbacks.notifyLidSwitchChanged(whenNanos, lidOpen); + } + } } } diff --git a/services/core/java/com/android/server/lights/LightsService.java b/services/core/java/com/android/server/lights/LightsService.java index d624019bfec8..43c965dde27b 100644 --- a/services/core/java/com/android/server/lights/LightsService.java +++ b/services/core/java/com/android/server/lights/LightsService.java @@ -29,14 +29,12 @@ import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.os.Looper; -import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceManager; import android.os.Trace; import android.provider.Settings; import android.util.Slog; import android.util.SparseArray; -import android.view.SurfaceControl; import com.android.internal.BrightnessSynchronizer; import com.android.internal.annotations.GuardedBy; @@ -262,25 +260,9 @@ public class LightsService extends SystemService { } private final class LightImpl extends LogicalLight { - private final IBinder mDisplayToken; - private final int mSurfaceControlMaximumBrightness; private LightImpl(Context context, HwLight hwLight) { mHwLight = hwLight; - mDisplayToken = SurfaceControl.getInternalDisplayToken(); - final boolean brightnessSupport = SurfaceControl.getDisplayBrightnessSupport( - mDisplayToken); - if (DEBUG) { - Slog.d(TAG, "Display brightness support: " + brightnessSupport); - } - int maximumBrightness = 0; - if (brightnessSupport) { - PowerManager pm = context.getSystemService(PowerManager.class); - if (pm != null) { - maximumBrightness = pm.getMaximumScreenBrightnessSetting(); - } - } - mSurfaceControlMaximumBrightness = maximumBrightness; } @Override @@ -301,28 +283,10 @@ public class LightsService extends SystemService { + ": brightness=" + brightness); return; } - // Ideally, we'd like to set the brightness mode through the SF/HWC as well, but - // right now we just fall back to the old path through Lights brightessMode is - // anything but USER or the device shouldBeInLowPersistenceMode(). - if (brightnessMode == BRIGHTNESS_MODE_USER && !shouldBeInLowPersistenceMode() - && mSurfaceControlMaximumBrightness == 255) { - // New system - // TODO: the last check should be mSurfaceControlMaximumBrightness != 0; the - // reason we enforce 255 right now is to stay consistent with the old path. In - // the future, the framework should be refactored so that brightness is a float - // between 0.0f and 1.0f, and the actual number of supported brightness levels - // is determined in the device-specific implementation. - if (DEBUG) { - Slog.d(TAG, "Using new setBrightness path!"); - } - SurfaceControl.setDisplayBrightness(mDisplayToken, brightness); - } else { - // Old system - int brightnessInt = BrightnessSynchronizer.brightnessFloatToInt(brightness); - int color = brightnessInt & 0x000000ff; - color = 0xff000000 | (color << 16) | (color << 8) | color; - setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode); - } + int brightnessInt = BrightnessSynchronizer.brightnessFloatToInt(brightness); + int color = brightnessInt & 0x000000ff; + color = 0xff000000 | (color << 16) | (color << 8) | color; + setLightLocked(color, LIGHT_FLASH_NONE, 0, 0, brightnessMode); } } diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java index 3854f8c8ff76..324332f1e134 100644 --- a/services/core/java/com/android/server/location/LocationManagerService.java +++ b/services/core/java/com/android/server/location/LocationManagerService.java @@ -519,9 +519,6 @@ public class LocationManagerService extends ILocationManager.Stub { public List<String> getAllProviders() { ArrayList<String> providers = new ArrayList<>(mProviderManagers.size()); for (LocationProviderManager manager : mProviderManagers) { - if (FUSED_PROVIDER.equals(manager.getName())) { - continue; - } providers.add(manager.getName()); } return providers; @@ -538,9 +535,6 @@ public class LocationManagerService extends ILocationManager.Stub { ArrayList<String> providers = new ArrayList<>(mProviderManagers.size()); for (LocationProviderManager manager : mProviderManagers) { String name = manager.getName(); - if (FUSED_PROVIDER.equals(name)) { - continue; - } if (enabledOnly && !manager.isEnabled(UserHandle.getCallingUserId())) { continue; } @@ -565,7 +559,9 @@ public class LocationManagerService extends ILocationManager.Stub { } if (!providers.isEmpty()) { - if (providers.contains(GPS_PROVIDER)) { + if (providers.contains(FUSED_PROVIDER)) { + return FUSED_PROVIDER; + } else if (providers.contains(GPS_PROVIDER)) { return GPS_PROVIDER; } else if (providers.contains(NETWORK_PROVIDER)) { return NETWORK_PROVIDER; @@ -1046,10 +1042,6 @@ public class LocationManagerService extends ILocationManager.Stub { @Override public boolean isProviderEnabledForUser(String provider, int userId) { - // fused provider is accessed indirectly via criteria rather than the provider-based APIs, - // so we discourage its use - if (FUSED_PROVIDER.equals(provider)) return false; - return mLocalService.isProviderEnabledForUser(provider, userId); } diff --git a/services/core/java/com/android/server/location/OWNERS b/services/core/java/com/android/server/location/OWNERS index c2c95e6042de..696a0c22c605 100644 --- a/services/core/java/com/android/server/location/OWNERS +++ b/services/core/java/com/android/server/location/OWNERS @@ -1,8 +1 @@ -aadmal@google.com -arthuri@google.com -bduddie@google.com -gomo@google.com -sooniln@google.com -weiwa@google.com -wyattriley@google.com -yuhany@google.com +file:/location/java/android/location/OWNERS diff --git a/services/core/java/com/android/server/location/contexthub/OWNERS b/services/core/java/com/android/server/location/contexthub/OWNERS new file mode 100644 index 000000000000..d4393d6a83d2 --- /dev/null +++ b/services/core/java/com/android/server/location/contexthub/OWNERS @@ -0,0 +1,2 @@ +arthuri@google.com +bduddie@google.com diff --git a/services/core/java/com/android/server/locksettings/OWNERS b/services/core/java/com/android/server/locksettings/OWNERS index dad6e39be47f..08b8a8c106b7 100644 --- a/services/core/java/com/android/server/locksettings/OWNERS +++ b/services/core/java/com/android/server/locksettings/OWNERS @@ -1,2 +1,3 @@ jaggies@google.com kchyn@google.com +rubinxu@google.com diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java index 5787f7c48138..8d5f553dba5c 100644 --- a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java +++ b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java @@ -15,20 +15,15 @@ */ package com.android.server.locksettings; - import static android.os.UserHandle.USER_SYSTEM; import android.annotation.NonNull; -import android.annotation.Nullable; import android.annotation.UserIdInt; import android.content.Context; import android.content.pm.UserInfo; -import android.hardware.rebootescrow.IRebootEscrow; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.os.ServiceSpecificException; import android.os.SystemClock; import android.os.UserManager; +import android.provider.DeviceConfig; import android.provider.Settings; import android.util.Slog; @@ -44,7 +39,6 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Locale; -import java.util.NoSuchElementException; class RebootEscrowManager { private static final String TAG = "RebootEscrowManager"; @@ -116,8 +110,24 @@ class RebootEscrowManager { static class Injector { protected Context mContext; + private final RebootEscrowProviderInterface mRebootEscrowProvider; + Injector(Context context) { mContext = context; + RebootEscrowProviderInterface rebootEscrowProvider = null; + // TODO(xunchang) add implementation for server based ror. + if (DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_OTA, + "server_based_ror_enabled", false)) { + Slog.e(TAG, "Server based ror isn't implemented yet."); + } else { + rebootEscrowProvider = new RebootEscrowProviderHalImpl(); + } + + if (rebootEscrowProvider != null && rebootEscrowProvider.hasRebootEscrowSupport()) { + mRebootEscrowProvider = rebootEscrowProvider; + } else { + mRebootEscrowProvider = null; + } } public Context getContext() { @@ -128,15 +138,8 @@ class RebootEscrowManager { return (UserManager) mContext.getSystemService(Context.USER_SERVICE); } - @Nullable - public IRebootEscrow getRebootEscrow() { - try { - return IRebootEscrow.Stub.asInterface(ServiceManager.getService( - "android.hardware.rebootescrow.IRebootEscrow/default")); - } catch (NoSuchElementException e) { - Slog.i(TAG, "Device doesn't implement RebootEscrow HAL"); - } - return null; + public RebootEscrowProviderInterface getRebootEscrowProvider() { + return mRebootEscrowProvider; } public int getBootCount() { @@ -210,45 +213,18 @@ class RebootEscrowManager { } private RebootEscrowKey getAndClearRebootEscrowKey() { - IRebootEscrow rebootEscrow = mInjector.getRebootEscrow(); - if (rebootEscrow == null) { - Slog.w(TAG, "Had reboot escrow data for users, but RebootEscrow HAL is unavailable"); + RebootEscrowProviderInterface rebootEscrowProvider = mInjector.getRebootEscrowProvider(); + if (rebootEscrowProvider == null) { + Slog.w(TAG, + "Had reboot escrow data for users, but RebootEscrowProvider is unavailable"); return null; } - try { - byte[] escrowKeyBytes = rebootEscrow.retrieveKey(); - if (escrowKeyBytes == null) { - Slog.w(TAG, "Had reboot escrow data for users, but could not retrieve key"); - return null; - } else if (escrowKeyBytes.length != 32) { - Slog.e(TAG, "IRebootEscrow returned key of incorrect size " - + escrowKeyBytes.length); - return null; - } - - // Make sure we didn't get the null key. - int zero = 0; - for (int i = 0; i < escrowKeyBytes.length; i++) { - zero |= escrowKeyBytes[i]; - } - if (zero == 0) { - Slog.w(TAG, "IRebootEscrow returned an all-zeroes key"); - return null; - } - - // Overwrite the existing key with the null key - rebootEscrow.storeKey(new byte[32]); - + RebootEscrowKey key = rebootEscrowProvider.getAndClearRebootEscrowKey(null); + if (key != null) { mEventLog.addEntry(RebootEscrowEvent.RETRIEVED_STORED_KEK); - return RebootEscrowKey.fromKeyBytes(escrowKeyBytes); - } catch (RemoteException e) { - Slog.w(TAG, "Could not retrieve escrow data"); - return null; - } catch (ServiceSpecificException e) { - Slog.w(TAG, "Got service-specific exception: " + e.errorCode); - return null; } + return key; } private boolean restoreRebootEscrowForUser(@UserIdInt int userId, RebootEscrowKey key) { @@ -279,9 +255,9 @@ class RebootEscrowManager { return; } - IRebootEscrow rebootEscrow = mInjector.getRebootEscrow(); - if (rebootEscrow == null) { - Slog.w(TAG, "Reboot escrow requested, but RebootEscrow HAL is unavailable"); + if (mInjector.getRebootEscrowProvider() == null) { + Slog.w(TAG, + "Had reboot escrow data for users, but RebootEscrowProvider is unavailable"); return; } @@ -293,6 +269,7 @@ class RebootEscrowManager { final RebootEscrowData escrowData; try { + // TODO(xunchang) further wrap the escrowData with a key from keystore. escrowData = RebootEscrowData.fromSyntheticPassword(escrowKey, spVersion, syntheticPassword); } catch (IOException e) { @@ -330,18 +307,16 @@ class RebootEscrowManager { mRebootEscrowWanted = false; setRebootEscrowReady(false); - IRebootEscrow rebootEscrow = mInjector.getRebootEscrow(); - if (rebootEscrow == null) { + + RebootEscrowProviderInterface rebootEscrowProvider = mInjector.getRebootEscrowProvider(); + if (rebootEscrowProvider == null) { + Slog.w(TAG, + "Had reboot escrow data for users, but RebootEscrowProvider is unavailable"); return; } mStorage.removeKey(REBOOT_ESCROW_ARMED_KEY, USER_SYSTEM); - - try { - rebootEscrow.storeKey(new byte[32]); - } catch (RemoteException | ServiceSpecificException e) { - Slog.w(TAG, "Could not call RebootEscrow HAL to shred key"); - } + rebootEscrowProvider.clearRebootEscrowKey(); List<UserInfo> users = mUserManager.getUsers(); for (UserInfo user : users) { @@ -356,9 +331,10 @@ class RebootEscrowManager { return false; } - IRebootEscrow rebootEscrow = mInjector.getRebootEscrow(); - if (rebootEscrow == null) { - Slog.w(TAG, "Escrow marked as ready, but RebootEscrow HAL is unavailable"); + RebootEscrowProviderInterface rebootEscrowProvider = mInjector.getRebootEscrowProvider(); + if (rebootEscrowProvider == null) { + Slog.w(TAG, + "Had reboot escrow data for users, but RebootEscrowProvider is unavailable"); return false; } @@ -372,15 +348,7 @@ class RebootEscrowManager { return false; } - boolean armedRebootEscrow = false; - try { - rebootEscrow.storeKey(escrowKey.getKeyBytes()); - armedRebootEscrow = true; - Slog.i(TAG, "Reboot escrow key stored with RebootEscrow HAL"); - } catch (RemoteException | ServiceSpecificException e) { - Slog.e(TAG, "Failed escrow secret to RebootEscrow HAL", e); - } - + boolean armedRebootEscrow = rebootEscrowProvider.storeRebootEscrowKey(escrowKey, null); if (armedRebootEscrow) { mStorage.setInt(REBOOT_ESCROW_ARMED_KEY, mInjector.getBootCount(), USER_SYSTEM); mEventLog.addEntry(RebootEscrowEvent.SET_ARMED_STATUS); @@ -397,7 +365,7 @@ class RebootEscrowManager { } boolean prepareRebootEscrow() { - if (mInjector.getRebootEscrow() == null) { + if (mInjector.getRebootEscrowProvider() == null) { return false; } @@ -408,7 +376,7 @@ class RebootEscrowManager { } boolean clearRebootEscrow() { - if (mInjector.getRebootEscrow() == null) { + if (mInjector.getRebootEscrowProvider() == null) { return false; } diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowProviderHalImpl.java b/services/core/java/com/android/server/locksettings/RebootEscrowProviderHalImpl.java new file mode 100644 index 000000000000..6c1040b596c8 --- /dev/null +++ b/services/core/java/com/android/server/locksettings/RebootEscrowProviderHalImpl.java @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.locksettings; + +import android.annotation.Nullable; +import android.hardware.rebootescrow.IRebootEscrow; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.ServiceSpecificException; +import android.util.Slog; + +import com.android.internal.annotations.VisibleForTesting; + +import java.util.NoSuchElementException; + +import javax.crypto.SecretKey; + +/** + * An implementation of the {@link RebootEscrowProviderInterface} by calling the RebootEscrow HAL. + */ +class RebootEscrowProviderHalImpl implements RebootEscrowProviderInterface { + private static final String TAG = "RebootEscrowProvider"; + + private final Injector mInjector; + + static class Injector { + @Nullable + public IRebootEscrow getRebootEscrow() { + try { + return IRebootEscrow.Stub.asInterface(ServiceManager.getService( + "android.hardware.rebootescrow.IRebootEscrow/default")); + } catch (NoSuchElementException e) { + Slog.i(TAG, "Device doesn't implement RebootEscrow HAL"); + } + return null; + } + } + + RebootEscrowProviderHalImpl() { + mInjector = new Injector(); + } + + @VisibleForTesting + RebootEscrowProviderHalImpl(Injector injector) { + mInjector = injector; + } + + @Override + public boolean hasRebootEscrowSupport() { + return mInjector.getRebootEscrow() != null; + } + + @Override + public RebootEscrowKey getAndClearRebootEscrowKey(SecretKey decryptionKey) { + IRebootEscrow rebootEscrow = mInjector.getRebootEscrow(); + if (rebootEscrow == null) { + Slog.w(TAG, "Had reboot escrow data for users, but RebootEscrow HAL is unavailable"); + return null; + } + + try { + byte[] escrowKeyBytes = rebootEscrow.retrieveKey(); + if (escrowKeyBytes == null) { + Slog.w(TAG, "Had reboot escrow data for users, but could not retrieve key"); + return null; + } else if (escrowKeyBytes.length != 32) { + Slog.e(TAG, "IRebootEscrow returned key of incorrect size " + + escrowKeyBytes.length); + return null; + } + + // Make sure we didn't get the null key. + int zero = 0; + for (int i = 0; i < escrowKeyBytes.length; i++) { + zero |= escrowKeyBytes[i]; + } + if (zero == 0) { + Slog.w(TAG, "IRebootEscrow returned an all-zeroes key"); + return null; + } + + // Overwrite the existing key with the null key + rebootEscrow.storeKey(new byte[32]); + + return RebootEscrowKey.fromKeyBytes(escrowKeyBytes); + } catch (RemoteException e) { + Slog.w(TAG, "Could not retrieve escrow data"); + return null; + } catch (ServiceSpecificException e) { + Slog.w(TAG, "Got service-specific exception: " + e.errorCode); + return null; + } + } + + @Override + public void clearRebootEscrowKey() { + IRebootEscrow rebootEscrow = mInjector.getRebootEscrow(); + if (rebootEscrow == null) { + return; + } + + try { + rebootEscrow.storeKey(new byte[32]); + } catch (RemoteException | ServiceSpecificException e) { + Slog.w(TAG, "Could not call RebootEscrow HAL to shred key"); + } + + } + + @Override + public boolean storeRebootEscrowKey(RebootEscrowKey escrowKey, SecretKey encryptionKey) { + IRebootEscrow rebootEscrow = mInjector.getRebootEscrow(); + if (rebootEscrow == null) { + Slog.w(TAG, "Escrow marked as ready, but RebootEscrow HAL is unavailable"); + return false; + } + + try { + // The HAL interface only accept 32 bytes data. And the encrypted bytes for the escrow + // key may exceed that limit. So we just store the raw key bytes here. + rebootEscrow.storeKey(escrowKey.getKeyBytes()); + Slog.i(TAG, "Reboot escrow key stored with RebootEscrow HAL"); + return true; + } catch (RemoteException | ServiceSpecificException e) { + Slog.e(TAG, "Failed escrow secret to RebootEscrow HAL", e); + } + return false; + } +} diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowProviderInterface.java b/services/core/java/com/android/server/locksettings/RebootEscrowProviderInterface.java new file mode 100644 index 000000000000..857ad5fc312a --- /dev/null +++ b/services/core/java/com/android/server/locksettings/RebootEscrowProviderInterface.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.locksettings; + +import javax.crypto.SecretKey; + +/** + * Provides APIs for {@link RebootEscrowManager} to access and manage the reboot escrow key. + * Implementations need to find a way to persist the key across a reboot, and securely discards the + * persisted copy. + * + * @hide + */ +public interface RebootEscrowProviderInterface { + /** + * Returns true if the secure store/discard of reboot escrow key is supported. + */ + boolean hasRebootEscrowSupport(); + + /** + * Returns the stored RebootEscrowKey, and clears the storage. If the stored key is encrypted, + * use the input key to decrypt the RebootEscrowKey. Returns null on failure. + */ + RebootEscrowKey getAndClearRebootEscrowKey(SecretKey decryptionKey); + + /** + * Clears the stored RebootEscrowKey. + */ + void clearRebootEscrowKey(); + + /** + * Saves the given RebootEscrowKey, optionally encrypt the storage with the encryptionKey. + */ + boolean storeRebootEscrowKey(RebootEscrowKey escrowKey, SecretKey encryptionKey); +} diff --git a/services/core/java/com/android/server/media/BluetoothRouteProvider.java b/services/core/java/com/android/server/media/BluetoothRouteProvider.java index 0b3cdae9231e..7afa81aa047d 100644 --- a/services/core/java/com/android/server/media/BluetoothRouteProvider.java +++ b/services/core/java/com/android/server/media/BluetoothRouteProvider.java @@ -165,11 +165,13 @@ class BluetoothRouteProvider { private void buildBluetoothRoutes() { mBluetoothRoutes.clear(); - for (BluetoothDevice device : mBluetoothAdapter.getBondedDevices()) { - if (device.isConnected()) { - BluetoothRouteInfo newBtRoute = createBluetoothRoute(device); - if (newBtRoute.connectedProfiles.size() > 0) { - mBluetoothRoutes.put(device.getAddress(), newBtRoute); + if (mBluetoothAdapter.getBondedDevices() != null) { + for (BluetoothDevice device : mBluetoothAdapter.getBondedDevices()) { + if (device.isConnected()) { + BluetoothRouteInfo newBtRoute = createBluetoothRoute(device); + if (newBtRoute.connectedProfiles.size() > 0) { + mBluetoothRoutes.put(device.getAddress(), newBtRoute); + } } } } diff --git a/services/core/java/com/android/server/media/MediaRoute2Provider.java b/services/core/java/com/android/server/media/MediaRoute2Provider.java index f882c57e49ba..edc9d7c64146 100644 --- a/services/core/java/com/android/server/media/MediaRoute2Provider.java +++ b/services/core/java/com/android/server/media/MediaRoute2Provider.java @@ -77,7 +77,7 @@ abstract class MediaRoute2Provider { @NonNull public List<RoutingSessionInfo> getSessionInfos() { synchronized (mLock) { - return mSessionInfos; + return new ArrayList<>(mSessionInfos); } } diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java index 85af346aa88a..ab38dca2387d 100644 --- a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java +++ b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java @@ -108,8 +108,8 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider mLastDiscoveryPreference = discoveryPreference; if (mConnectionReady) { mActiveConnection.updateDiscoveryPreference(discoveryPreference); - updateBinding(); } + updateBinding(); } @Override @@ -205,9 +205,11 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider } private boolean shouldBind() { - //TODO: Binding could be delayed until it's necessary. if (mRunning) { - return true; + // Bind when there is a discovery preference or an active route session. + return (mLastDiscoveryPreference != null + && !mLastDiscoveryPreference.getPreferredFeatures().isEmpty()) + || !getSessionInfos().isEmpty(); } return false; } diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java index 1114fe0d9bf8..31edf43679e9 100644 --- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java +++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java @@ -16,6 +16,7 @@ package com.android.server.media; +import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND; import static android.media.MediaRoute2ProviderService.REASON_UNKNOWN_ERROR; import static android.media.MediaRouter2Utils.getOriginalId; import static android.media.MediaRouter2Utils.getProviderId; @@ -73,10 +74,12 @@ class MediaRouter2ServiceImpl { // TODO: (In Android S or later) if we add callback methods for generic failures // in MediaRouter2, remove this constant and replace the usages with the real request IDs. private static final long DUMMY_REQUEST_ID = -1; + private static final int PACKAGE_IMPORTANCE_FOR_DISCOVERY = IMPORTANCE_FOREGROUND; private final Context mContext; private final Object mLock = new Object(); final AtomicInteger mNextRouterOrManagerId = new AtomicInteger(1); + final ActivityManager mActivityManager; @GuardedBy("mLock") private final SparseArray<UserRecord> mUserRecords = new SparseArray<>(); @@ -87,8 +90,21 @@ class MediaRouter2ServiceImpl { @GuardedBy("mLock") private int mCurrentUserId = -1; + private final ActivityManager.OnUidImportanceListener mOnUidImportanceListener = + (uid, importance) -> { + synchronized (mLock) { + final int count = mUserRecords.size(); + for (int i = 0; i < count; i++) { + mUserRecords.valueAt(i).mHandler.maybeUpdateDiscoveryPreferenceForUid(uid); + } + } + }; + MediaRouter2ServiceImpl(Context context) { mContext = context; + mActivityManager = mContext.getSystemService(ActivityManager.class); + mActivityManager.addOnUidImportanceListener(mOnUidImportanceListener, + PACKAGE_IMPORTANCE_FOR_DISCOVERY); } //////////////////////////////////////////////////////////////// @@ -388,6 +404,30 @@ class MediaRouter2ServiceImpl { } } + public void startScan(IMediaRouter2Manager manager) { + Objects.requireNonNull(manager, "manager must not be null"); + final long token = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + startScanLocked(manager); + } + } finally { + Binder.restoreCallingIdentity(token); + } + } + + public void stopScan(IMediaRouter2Manager manager) { + Objects.requireNonNull(manager, "manager must not be null"); + final long token = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + stopScanLocked(manager); + } + } finally { + Binder.restoreCallingIdentity(token); + } + } + public void setRouteVolumeWithManager(IMediaRouter2Manager manager, int requestId, MediaRoute2Info route, int volume) { Objects.requireNonNull(manager, "manager must not be null"); @@ -839,6 +879,24 @@ class MediaRouter2ServiceImpl { disposeUserIfNeededLocked(userRecord); // since manager removed from user } + private void startScanLocked(@NonNull IMediaRouter2Manager manager) { + final IBinder binder = manager.asBinder(); + ManagerRecord managerRecord = mAllManagerRecords.get(binder); + if (managerRecord == null) { + return; + } + managerRecord.startScan(); + } + + private void stopScanLocked(@NonNull IMediaRouter2Manager manager) { + final IBinder binder = manager.asBinder(); + ManagerRecord managerRecord = mAllManagerRecords.get(binder); + if (managerRecord == null) { + return; + } + managerRecord.stopScan(); + } + private void setRouteVolumeWithManagerLocked(int requestId, @NonNull IMediaRouter2Manager manager, @NonNull MediaRoute2Info route, int volume) { @@ -1122,6 +1180,7 @@ class MediaRouter2ServiceImpl { public final String mPackageName; public final int mManagerId; public SessionCreationRequest mLastSessionCreationRequest; + public boolean mIsScanning; ManagerRecord(UserRecord userRecord, IMediaRouter2Manager manager, int uid, int pid, String packageName) { @@ -1146,6 +1205,24 @@ class MediaRouter2ServiceImpl { pw.println(prefix + this); } + public void startScan() { + if (mIsScanning) { + return; + } + mIsScanning = true; + mUserRecord.mHandler.sendMessage(PooledLambda.obtainMessage( + UserHandler::updateDiscoveryPreferenceOnHandler, mUserRecord.mHandler)); + } + + public void stopScan() { + if (!mIsScanning) { + return; + } + mIsScanning = false; + mUserRecord.mHandler.sendMessage(PooledLambda.obtainMessage( + UserHandler::updateDiscoveryPreferenceOnHandler, mUserRecord.mHandler)); + } + @Override public String toString() { return "Manager " + mPackageName + " (pid " + mPid + ")"; @@ -1262,6 +1339,24 @@ class MediaRouter2ServiceImpl { return null; } + public void maybeUpdateDiscoveryPreferenceForUid(int uid) { + MediaRouter2ServiceImpl service = mServiceRef.get(); + if (service == null) { + return; + } + boolean isUidRelevant; + synchronized (service.mLock) { + isUidRelevant = mUserRecord.mRouterRecords.stream().anyMatch( + router -> router.mUid == uid) + | mUserRecord.mManagerRecords.stream().anyMatch( + manager -> manager.mUid == uid); + } + if (isUidRelevant) { + sendMessage(PooledLambda.obtainMessage( + UserHandler::updateDiscoveryPreferenceOnHandler, this)); + } + } + private void onProviderStateChangedOnHandler(@NonNull MediaRoute2Provider provider) { int providerInfoIndex = getLastProviderInfoIndex(provider.getUniqueId()); MediaRoute2ProviderInfo currentInfo = provider.getProviderInfo(); @@ -1767,6 +1862,16 @@ class MediaRouter2ServiceImpl { return managers; } + private List<RouterRecord> getRouterRecords() { + MediaRouter2ServiceImpl service = mServiceRef.get(); + if (service == null) { + return Collections.emptyList(); + } + synchronized (service.mLock) { + return new ArrayList<>(mUserRecord.mRouterRecords); + } + } + private List<ManagerRecord> getManagerRecords() { MediaRouter2ServiceImpl service = mServiceRef.get(); if (service == null) { @@ -2001,13 +2106,28 @@ class MediaRouter2ServiceImpl { return; } List<RouteDiscoveryPreference> discoveryPreferences = new ArrayList<>(); - synchronized (service.mLock) { - for (RouterRecord routerRecord : mUserRecord.mRouterRecords) { + List<RouterRecord> routerRecords = getRouterRecords(); + List<ManagerRecord> managerRecords = getManagerRecords(); + boolean isAnyManagerScanning = + managerRecords.stream().anyMatch(manager -> manager.mIsScanning + && service.mActivityManager.getPackageImportance(manager.mPackageName) + <= PACKAGE_IMPORTANCE_FOR_DISCOVERY); + + for (RouterRecord routerRecord : routerRecords) { + if (isAnyManagerScanning + || service.mActivityManager.getPackageImportance(routerRecord.mPackageName) + <= PACKAGE_IMPORTANCE_FOR_DISCOVERY) { discoveryPreferences.add(routerRecord.mDiscoveryPreference); } - mUserRecord.mCompositeDiscoveryPreference = - new RouteDiscoveryPreference.Builder(discoveryPreferences) - .build(); + } + + synchronized (service.mLock) { + RouteDiscoveryPreference newPreference = + new RouteDiscoveryPreference.Builder(discoveryPreferences).build(); + if (newPreference.equals(mUserRecord.mCompositeDiscoveryPreference)) { + return; + } + mUserRecord.mCompositeDiscoveryPreference = newPreference; } for (MediaRoute2Provider provider : mRouteProviders) { provider.updateDiscoveryPreference(mUserRecord.mCompositeDiscoveryPreference); diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java index 0e52a67c8d39..b6d6cc48d0cd 100644 --- a/services/core/java/com/android/server/media/MediaRouterService.java +++ b/services/core/java/com/android/server/media/MediaRouterService.java @@ -544,6 +544,18 @@ public final class MediaRouterService extends IMediaRouterService.Stub // Binder call @Override + public void startScan(IMediaRouter2Manager manager) { + mService2.startScan(manager); + } + + // Binder call + @Override + public void stopScan(IMediaRouter2Manager manager) { + mService2.stopScan(manager); + } + + // Binder call + @Override public void setRouteVolumeWithManager(IMediaRouter2Manager manager, int requestId, MediaRoute2Info route, int volume) { mService2.setRouteVolumeWithManager(manager, requestId, route, volume); diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index a44ddcb03c16..5f8b31abb23d 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -230,7 +230,6 @@ import com.android.internal.util.ArrayUtils; import com.android.internal.util.CollectionUtils; import com.android.internal.util.ConcurrentUtils; import com.android.internal.util.DumpUtils; -import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.IndentingPrintWriter; import com.android.internal.util.StatLogger; import com.android.internal.util.XmlUtils; @@ -243,9 +242,7 @@ import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener; import libcore.io.IoUtils; -import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; import java.io.File; import java.io.FileDescriptor; @@ -256,7 +253,6 @@ import java.io.IOException; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import java.nio.charset.StandardCharsets; import java.time.Clock; import java.time.Instant; import java.time.ZoneId; @@ -271,6 +267,7 @@ import java.util.Objects; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import java.util.function.IntConsumer; /** * Service that maintains low-level network policy rules, using @@ -4034,7 +4031,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { try { updateRulesForDeviceIdleUL(); updateRulesForPowerSaveUL(); - updateRulesForAllAppsUL(TYPE_RESTRICT_POWER); + forEachUid("updateRulesForRestrictPower", + uid -> updateRulesForPowerRestrictionsUL(uid)); } finally { Trace.traceEnd(Trace.TRACE_TAG_NETWORK); } @@ -4044,31 +4042,19 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private void updateRulesForRestrictBackgroundUL() { Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForRestrictBackgroundUL"); try { - updateRulesForAllAppsUL(TYPE_RESTRICT_BACKGROUND); + forEachUid("updateRulesForRestrictBackground", + uid -> updateRulesForDataUsageRestrictionsUL(uid)); } finally { Trace.traceEnd(Trace.TRACE_TAG_NETWORK); } } - private static final int TYPE_RESTRICT_BACKGROUND = 1; - private static final int TYPE_RESTRICT_POWER = 2; - @Retention(RetentionPolicy.SOURCE) - @IntDef(flag = false, value = { - TYPE_RESTRICT_BACKGROUND, - TYPE_RESTRICT_POWER, - }) - public @interface RestrictType { - } - - // TODO: refactor / consolidate all those updateXyz methods, there are way too many of them... - @GuardedBy("mUidRulesFirstLock") - private void updateRulesForAllAppsUL(@RestrictType int type) { + private void forEachUid(String tag, IntConsumer consumer) { if (Trace.isTagEnabled(Trace.TRACE_TAG_NETWORK)) { - Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "updateRulesForRestrictPowerUL-" + type); + Trace.traceBegin(Trace.TRACE_TAG_NETWORK, "forEachUid-" + tag); } try { // update rules for all installed applications - final PackageManager pm = mContext.getPackageManager(); final List<UserInfo> users; final List<ApplicationInfo> apps; @@ -4096,16 +4082,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { for (int j = 0; j < appsSize; j++) { final ApplicationInfo app = apps.get(j); final int uid = UserHandle.getUid(user.id, app.uid); - switch (type) { - case TYPE_RESTRICT_BACKGROUND: - updateRulesForDataUsageRestrictionsUL(uid); - break; - case TYPE_RESTRICT_POWER: - updateRulesForPowerRestrictionsUL(uid); - break; - default: - Slog.w(TAG, "Invalid type for updateRulesForAllApps: " + type); - } + consumer.accept(uid); } } } finally { diff --git a/services/core/java/com/android/server/net/OWNERS b/services/core/java/com/android/server/net/OWNERS index d5c7618199fe..28ae6a417bd3 100644 --- a/services/core/java/com/android/server/net/OWNERS +++ b/services/core/java/com/android/server/net/OWNERS @@ -2,7 +2,7 @@ set noparent codewiz@google.com jchalard@google.com -jsharkey@google.com +jsharkey@android.com junyulai@google.com lorenzo@google.com reminv@google.com diff --git a/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java b/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java index c1deb965b054..b9984a5c24ee 100644 --- a/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java +++ b/services/core/java/com/android/server/notification/NotificationHistoryDatabase.java @@ -293,9 +293,7 @@ public class NotificationHistoryDatabase { .appendPath(file.getAbsolutePath()).build()) .addFlags(Intent.FLAG_RECEIVER_FOREGROUND) .putExtra(EXTRA_KEY, file.getAbsolutePath()), - // TODO(b/174161800) Please replace FLAG_MUTABLE_UNAUDITED below - // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. - PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED); + PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, deletionTime, pi); } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 692e97a4ad16..d3d998acd39c 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -242,7 +242,6 @@ import android.widget.Toast; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.compat.IPlatformCompat; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; import com.android.internal.logging.InstanceId; import com.android.internal.logging.InstanceIdSequence; @@ -468,7 +467,6 @@ public class NotificationManagerService extends SystemService { private UriGrantsManagerInternal mUgmInternal; private RoleObserver mRoleObserver; private UserManager mUm; - private IPlatformCompat mPlatformCompat; private ShortcutHelper mShortcutHelper; final IBinder mForegroundToken = new Binder(); @@ -1987,8 +1985,6 @@ public class NotificationManagerService extends SystemService { mDeviceIdleManager = getContext().getSystemService(DeviceIdleManager.class); mDpm = dpm; mUm = userManager; - mPlatformCompat = IPlatformCompat.Stub.asInterface( - ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE)); mUiHandler = new Handler(UiThread.get().getLooper()); String[] extractorNames; @@ -2278,10 +2274,24 @@ public class NotificationManagerService extends SystemService { if (!DeviceConfig.NAMESPACE_SYSTEMUI.equals(properties.getNamespace())) { return; } - if (properties.getKeyset() - .contains(SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE)) { - mAssistants.allowAdjustmentType(Adjustment.KEY_IMPORTANCE); - mAssistants.resetDefaultAssistantsIfNecessary(); + for (String name : properties.getKeyset()) { + if (SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE.equals(name)) { + mAssistants.resetDefaultAssistantsIfNecessary(); + } else if (SystemUiDeviceConfigFlags.ENABLE_NAS_PRIORITIZER.equals(name)) { + String value = properties.getString(name, null); + if ("true".equals(value)) { + mAssistants.allowAdjustmentType(Adjustment.KEY_IMPORTANCE); + } else if ("false".equals(value)) { + mAssistants.disallowAdjustmentType(Adjustment.KEY_IMPORTANCE); + } + } else if (SystemUiDeviceConfigFlags.ENABLE_NAS_RANKING.equals(name)) { + String value = properties.getString(name, null); + if ("true".equals(value)) { + mAssistants.allowAdjustmentType(Adjustment.KEY_RANKING_SCORE); + } else if ("false".equals(value)) { + mAssistants.disallowAdjustmentType(Adjustment.KEY_RANKING_SCORE); + } + } } }; DeviceConfig.addOnPropertiesChangedListener( @@ -2886,16 +2896,16 @@ public class NotificationManagerService extends SystemService { return userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM : userId; } - private ToastRecord getToastRecord(int uid, int pid, String packageName, IBinder token, - @Nullable CharSequence text, @Nullable ITransientNotification callback, int duration, - Binder windowToken, int displayId, + private ToastRecord getToastRecord(int uid, int pid, String packageName, boolean isSystemToast, + IBinder token, @Nullable CharSequence text, @Nullable ITransientNotification callback, + int duration, Binder windowToken, int displayId, @Nullable ITransientNotificationCallback textCallback) { if (callback == null) { - return new TextToastRecord(this, mStatusBar, uid, pid, packageName, token, text, - duration, windowToken, displayId, textCallback); + return new TextToastRecord(this, mStatusBar, uid, pid, packageName, + isSystemToast, token, text, duration, windowToken, displayId, textCallback); } else { - return new CustomToastRecord(this, uid, pid, packageName, token, callback, duration, - windowToken, displayId); + return new CustomToastRecord(this, uid, pid, packageName, + isSystemToast, token, callback, duration, windowToken, displayId); } } @@ -2966,31 +2976,10 @@ public class NotificationManagerService extends SystemService { } boolean isAppRenderedToast = (callback != null); - if (isAppRenderedToast && !isSystemToast && !isPackageInForegroundForToast(pkg, - callingUid)) { - boolean block; - final long id = Binder.clearCallingIdentity(); - try { - // CHANGE_BACKGROUND_CUSTOM_TOAST_BLOCK is gated on targetSdk, so block will be - // false for apps with targetSdk < R. For apps with targetSdk R+, text toasts - // are not app-rendered, so isAppRenderedToast == true means it's a custom - // toast. - block = mPlatformCompat.isChangeEnabledByPackageName( - CHANGE_BACKGROUND_CUSTOM_TOAST_BLOCK, pkg, - callingUser.getIdentifier()); - } catch (RemoteException e) { - // Shouldn't happen have since it's a local local - Slog.e(TAG, "Unexpected exception while checking block background custom toasts" - + " change", e); - block = false; - } finally { - Binder.restoreCallingIdentity(id); - } - if (block) { - Slog.w(TAG, "Blocking custom toast from package " + pkg - + " due to package not in the foreground"); - return; - } + if (blockToast(callingUid, isSystemToast, isAppRenderedToast)) { + Slog.w(TAG, "Blocking custom toast from package " + pkg + + " due to package not in the foreground at time the toast was posted"); + return; } synchronized (mToastQueue) { @@ -3023,8 +3012,8 @@ public class NotificationManagerService extends SystemService { Binder windowToken = new Binder(); mWindowManagerInternal.addWindowToken(windowToken, TYPE_TOAST, displayId); - record = getToastRecord(callingUid, callingPid, pkg, token, text, callback, - duration, windowToken, displayId, textCallback); + record = getToastRecord(callingUid, callingPid, pkg, isSystemToast, token, + text, callback, duration, windowToken, displayId, textCallback); mToastQueue.add(record); index = mToastQueue.size() - 1; keepProcessAliveForToastIfNeededLocked(callingPid); @@ -3042,28 +3031,6 @@ public class NotificationManagerService extends SystemService { } } - /** - * Implementation note: Our definition of foreground for toasts is an implementation matter - * and should strike a balance between functionality and anti-abuse effectiveness. We - * currently worry about the following cases: - * <ol> - * <li>App with fullscreen activity: Allow toasts - * <li>App behind translucent activity from other app: Block toasts - * <li>App in multi-window: Allow toasts - * <li>App with expanded bubble: Allow toasts - * <li>App posting toasts on onCreate(), onStart(), onResume(): Allow toasts - * <li>App posting toasts on onPause(), onStop(), onDestroy(): Block toasts - * </ol> - * Checking if the UID has any resumed activities satisfy use-cases above. - * - * <p>Checking if {@code mActivityManager.getUidImportance(callingUid) == - * IMPORTANCE_FOREGROUND} does not work because it considers the app in foreground if it has - * any visible activities, failing case 2 in list above. - */ - private boolean isPackageInForegroundForToast(String pkg, int callingUid) { - return mAtm.hasResumedActivity(callingUid); - } - @Override public void cancelToast(String pkg, IBinder token) { Slog.i(TAG, "cancelToast pkg=" + pkg + " token=" + token); @@ -6396,7 +6363,6 @@ public class NotificationManagerService extends SystemService { 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, @@ -6416,7 +6382,6 @@ public class NotificationManagerService extends SystemService { this.mRank = rank; this.mCount = count; this.mListener = listener; - this.mWhen = System.currentTimeMillis(); } @Override @@ -6428,33 +6393,8 @@ public class NotificationManagerService extends SystemService { } synchronized (mNotificationLock) { - // Check to see if there is a notification in the enqueued list that hasn't had a - // chance to post yet. - List<NotificationRecord> enqueued = findEnqueuedNotificationsForCriteria( - mPkg, mTag, mId, mUserId); - boolean repost = false; - if (enqueued.size() > 0) { - // Found something, let's see what it was - repost = true; - // If all enqueues happened before this cancel then wait for them to happen, - // otherwise we should let this cancel through so the next enqueue happens - for (NotificationRecord r : enqueued) { - if (r.mUpdateTimeMs > mWhen) { - // At least one enqueue was posted after the cancel, so we're invalid - Slog.i(TAG, "notification cancel ignored due to newer enqueued entry" - + "key=" + r.getSbn().getKey()); - return; - } - } - } - if (repost) { - mHandler.post(this); - return; - } - - // Look for the notification in the posted list, since we already checked enqueued. - NotificationRecord r = - findNotificationByListLocked(mNotificationList, mPkg, mTag, mId, mUserId); + // Look for the notification, searching both the posted and enqueued lists. + NotificationRecord r = findNotificationLocked(mPkg, mTag, mId, mUserId); if (r != null) { // The notification was found, check if it should be removed. @@ -6477,10 +6417,6 @@ public class NotificationManagerService extends SystemService { 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. @@ -7388,17 +7324,16 @@ public class NotificationManagerService extends SystemService { CompatChanges.isChangeEnabled(RATE_LIMIT_TOASTS, record.uid); boolean isWithinQuota = mToastRateLimiter.isWithinQuota(userId, record.pkg, TOAST_QUOTA_TAG); - if ((!rateLimitingEnabled || isWithinQuota) && record.show()) { + + if (tryShowToast(record, rateLimitingEnabled, isWithinQuota)) { scheduleDurationReachedLocked(record); mIsCurrentToastShown = true; if (rateLimitingEnabled) { mToastRateLimiter.noteEvent(userId, record.pkg, TOAST_QUOTA_TAG); } return; - } else if (rateLimitingEnabled && !isWithinQuota) { - Slog.w(TAG, "Package " + record.pkg + " is above allowed toast quota, the " - + "following toast was blocked and discarded: " + record); } + int index = mToastQueue.indexOf(record); if (index >= 0) { mToastQueue.remove(index); @@ -7407,6 +7342,22 @@ public class NotificationManagerService extends SystemService { } } + /** Returns true if it successfully showed the toast. */ + private boolean tryShowToast(ToastRecord record, boolean rateLimitingEnabled, + boolean isWithinQuota) { + if (rateLimitingEnabled && !isWithinQuota) { + Slog.w(TAG, "Package " + record.pkg + " is above allowed toast quota, the " + + "following toast was blocked and discarded: " + record); + return false; + } + if (blockToast(record.uid, record.isSystemToast, record.isAppRendered())) { + Slog.w(TAG, "Blocking custom toast from package " + record.pkg + + " due to package not in the foreground at the time of showing the toast"); + return false; + } + return record.show(); + } + @GuardedBy("mToastQueue") void cancelToastLocked(int index) { ToastRecord record = mToastQueue.get(index); @@ -7526,6 +7477,44 @@ public class NotificationManagerService extends SystemService { } } + /** + * Implementation note: Our definition of foreground for toasts is an implementation matter + * and should strike a balance between functionality and anti-abuse effectiveness. We + * currently worry about the following cases: + * <ol> + * <li>App with fullscreen activity: Allow toasts + * <li>App behind translucent activity from other app: Block toasts + * <li>App in multi-window: Allow toasts + * <li>App with expanded bubble: Allow toasts + * <li>App posting toasts on onCreate(), onStart(), onResume(): Allow toasts + * <li>App posting toasts on onPause(), onStop(), onDestroy(): Block toasts + * </ol> + * Checking if the UID has any resumed activities satisfy use-cases above. + * + * <p>Checking if {@code mActivityManager.getUidImportance(callingUid) == + * IMPORTANCE_FOREGROUND} does not work because it considers the app in foreground if it has + * any visible activities, failing case 2 in list above. + */ + private boolean isPackageInForegroundForToast(int callingUid) { + return mAtm.hasResumedActivity(callingUid); + } + + /** + * True if the toast should be blocked. It will return true if all of the following conditions + * apply: it's a custom toast, it's not a system toast, the package that sent the toast is in + * the background and CHANGE_BACKGROUND_CUSTOM_TOAST_BLOCK is enabled. + * + * CHANGE_BACKGROUND_CUSTOM_TOAST_BLOCK is gated on targetSdk, so it will return false for apps + * with targetSdk < R. For apps with targetSdk R+, text toasts are not app-rendered, so + * isAppRenderedToast == true means it's a custom toast. + */ + private boolean blockToast(int uid, boolean isSystemToast, boolean isAppRenderedToast) { + return isAppRenderedToast + && !isSystemToast + && !isPackageInForegroundForToast(uid) + && CompatChanges.isChangeEnabled(CHANGE_BACKGROUND_CUSTOM_TOAST_BLOCK, uid); + } + private void handleRankingReconsideration(Message message) { if (!(message.obj instanceof RankingReconsideration)) return; RankingReconsideration recon = (RankingReconsideration) message.obj; @@ -9180,7 +9169,16 @@ public class NotificationManagerService extends SystemService { @Override protected void readExtraAttributes(String tag, TypedXmlPullParser parser, int userId) throws IOException { - boolean userSet = parser.getAttributeBoolean(null, ATT_USER_SET, false); + // TODO: this logic looks broken, since it's trying to convert a + // list into a boolean; for now we preserve the old parsing behavior + // to avoid a performance regression, but someone should investigate + final String value = parser.getAttributeValue(null, ATT_USER_SET); + final boolean userSet; + if (TextUtils.isEmpty(value)) { + userSet = false; + } else { + userSet = Boolean.parseBoolean(value); + } setUserSet(userId, userSet); } diff --git a/services/core/java/com/android/server/notification/OWNERS b/services/core/java/com/android/server/notification/OWNERS index 4dcb7995d8ae..5a19656b36a6 100644 --- a/services/core/java/com/android/server/notification/OWNERS +++ b/services/core/java/com/android/server/notification/OWNERS @@ -1,4 +1,4 @@ -dsandler@google.com +dsandler@android.com juliacr@google.com beverlyt@google.com pixel@google.com diff --git a/services/core/java/com/android/server/notification/SnoozeHelper.java b/services/core/java/com/android/server/notification/SnoozeHelper.java index 3e197fb78346..f078242a659f 100644 --- a/services/core/java/com/android/server/notification/SnoozeHelper.java +++ b/services/core/java/com/android/server/notification/SnoozeHelper.java @@ -462,8 +462,6 @@ public class SnoozeHelper { } private PendingIntent createPendingIntent(String pkg, String key, int userId) { - // TODO(b/174969959) Please replace FLAG_MUTABLE_UNAUDITED below - // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. return PendingIntent.getBroadcast(mContext, REQUEST_CODE_REPOST, new Intent(REPOST_ACTION) @@ -471,7 +469,7 @@ public class SnoozeHelper { .addFlags(Intent.FLAG_RECEIVER_FOREGROUND) .putExtra(EXTRA_KEY, key) .putExtra(EXTRA_USER_ID, userId), - PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED); + PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); } public void scheduleRepostsForPersistedNotifications(long currentTime) { diff --git a/services/core/java/com/android/server/notification/toast/CustomToastRecord.java b/services/core/java/com/android/server/notification/toast/CustomToastRecord.java index 17e0b39ea890..30378ac058c6 100644 --- a/services/core/java/com/android/server/notification/toast/CustomToastRecord.java +++ b/services/core/java/com/android/server/notification/toast/CustomToastRecord.java @@ -37,9 +37,10 @@ public class CustomToastRecord extends ToastRecord { public final ITransientNotification callback; public CustomToastRecord(NotificationManagerService notificationManager, int uid, int pid, - String packageName, IBinder token, ITransientNotification callback, int duration, - Binder windowToken, int displayId) { - super(notificationManager, uid, pid, packageName, token, duration, windowToken, displayId); + String packageName, boolean isSystemToast, IBinder token, + ITransientNotification callback, int duration, Binder windowToken, int displayId) { + super(notificationManager, uid, pid, packageName, isSystemToast, token, duration, + windowToken, displayId); this.callback = checkNotNull(callback); } @@ -78,10 +79,16 @@ public class CustomToastRecord extends ToastRecord { } @Override + public boolean isAppRendered() { + return true; + } + + @Override public String toString() { return "CustomToastRecord{" + Integer.toHexString(System.identityHashCode(this)) + " " + pid + ":" + pkg + "/" + UserHandle.formatUid(uid) + + " isSystemToast=" + isSystemToast + " token=" + token + " callback=" + callback + " duration=" + getDuration() diff --git a/services/core/java/com/android/server/notification/toast/TextToastRecord.java b/services/core/java/com/android/server/notification/toast/TextToastRecord.java index 544520edc7fc..7b36db2fe38c 100644 --- a/services/core/java/com/android/server/notification/toast/TextToastRecord.java +++ b/services/core/java/com/android/server/notification/toast/TextToastRecord.java @@ -43,9 +43,11 @@ public class TextToastRecord extends ToastRecord { public TextToastRecord(NotificationManagerService notificationManager, @Nullable StatusBarManagerInternal statusBarManager, int uid, int pid, - String packageName, IBinder token, CharSequence text, int duration, Binder windowToken, - int displayId, @Nullable ITransientNotificationCallback callback) { - super(notificationManager, uid, pid, packageName, token, duration, windowToken, displayId); + String packageName, boolean isSystemToast, IBinder token, CharSequence text, + int duration, Binder windowToken, int displayId, + @Nullable ITransientNotificationCallback callback) { + super(notificationManager, uid, pid, packageName, isSystemToast, token, duration, + windowToken, displayId); mStatusBar = statusBarManager; mCallback = callback; this.text = checkNotNull(text); @@ -73,10 +75,16 @@ public class TextToastRecord extends ToastRecord { } @Override + public boolean isAppRendered() { + return false; + } + + @Override public String toString() { return "TextToastRecord{" + Integer.toHexString(System.identityHashCode(this)) + " " + pid + ":" + pkg + "/" + UserHandle.formatUid(uid) + + " isSystemToast=" + isSystemToast + " token=" + token + " text=" + text + " duration=" + getDuration() diff --git a/services/core/java/com/android/server/notification/toast/ToastRecord.java b/services/core/java/com/android/server/notification/toast/ToastRecord.java index 33906ccd3cd1..1d5fc27c52c2 100644 --- a/services/core/java/com/android/server/notification/toast/ToastRecord.java +++ b/services/core/java/com/android/server/notification/toast/ToastRecord.java @@ -31,6 +31,7 @@ public abstract class ToastRecord { public final int uid; public final int pid; public final String pkg; + public final boolean isSystemToast; public final IBinder token; public final int displayId; public final Binder windowToken; @@ -38,11 +39,13 @@ public abstract class ToastRecord { private int mDuration; protected ToastRecord(NotificationManagerService notificationManager, int uid, int pid, - String pkg, IBinder token, int duration, Binder windowToken, int displayId) { + String pkg, boolean isSystemToast, IBinder token, int duration, Binder windowToken, + int displayId) { this.mNotificationManager = notificationManager; this.uid = uid; this.pid = pid; this.pkg = pkg; + this.isSystemToast = isSystemToast; this.token = token; this.windowToken = windowToken; this.displayId = displayId; @@ -95,4 +98,10 @@ public abstract class ToastRecord { // should override this method. return false; } + + /** + * Returns true if the app is responsible for rendering the toast, false otherwise (for example, + * if it's rendered by the system). + */ + public abstract boolean isAppRendered(); } diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java index dac2e4ff4c62..b131aff24cee 100644 --- a/services/core/java/com/android/server/pm/AppsFilter.java +++ b/services/core/java/com/android/server/pm/AppsFilter.java @@ -347,7 +347,7 @@ public class AppsFilter { } final StateProvider stateProvider = command -> { synchronized (injector.getLock()) { - command.currentState(injector.getSettings().mPackages, + command.currentState(injector.getSettings().getPackagesLocked(), injector.getUserManagerInternal().getUserInfos()); } }; diff --git a/services/core/java/com/android/server/pm/OWNERS b/services/core/java/com/android/server/pm/OWNERS index 7a2b7a62b7dd..004259b7478c 100644 --- a/services/core/java/com/android/server/pm/OWNERS +++ b/services/core/java/com/android/server/pm/OWNERS @@ -1,12 +1,12 @@ +hackbod@android.com hackbod@google.com -hackbod@google.com -jsharkey@google.com +jsharkey@android.com jsharkey@google.com narayan@google.com patb@google.com +svetoslavganov@android.com svetoslavganov@google.com -svetoslavganov@google.com -toddke@google.com +toddke@android.com toddke@google.com # apex support diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java index 7db2319b5164..d6400f3c879e 100644 --- a/services/core/java/com/android/server/pm/OtaDexoptService.java +++ b/services/core/java/com/android/server/pm/OtaDexoptService.java @@ -128,12 +128,12 @@ public class OtaDexoptService extends IOtaDexopt.Stub { synchronized (mPackageManagerService.mLock) { // Important: the packages we need to run with ab-ota compiler-reason. important = PackageManagerServiceUtils.getPackagesForDexopt( - mPackageManagerService.mSettings.mPackages.values(), mPackageManagerService, - DEBUG_DEXOPT); + mPackageManagerService.mSettings.getPackagesLocked().values(), + mPackageManagerService, DEBUG_DEXOPT); // Remove Platform Package from A/B OTA b/160735835. important.removeIf(isPlatformPackage); // Others: we should optimize this with the (first-)boot compiler-reason. - others = new ArrayList<>(mPackageManagerService.mSettings.mPackages.values()); + others = new ArrayList<>(mPackageManagerService.mSettings.getPackagesLocked().values()); others.removeAll(important); others.removeIf(PackageManagerServiceUtils.REMOVE_IF_NULL_PKG); others.removeIf(isPlatformPackage); diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index 34bee9572753..9e48ddd63c01 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -532,6 +532,20 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements + "to use a data loader"); } + // INSTALL_REASON_ROLLBACK allows an app to be rolled back without requiring the ROLLBACK + // capability; ensure if this is set as the install reason the app has one of the necessary + // signature permissions to perform the rollback. + if (params.installReason == PackageManager.INSTALL_REASON_ROLLBACK) { + if (mContext.checkCallingOrSelfPermission(Manifest.permission.MANAGE_ROLLBACKS) + != PackageManager.PERMISSION_GRANTED && + mContext.checkCallingOrSelfPermission(Manifest.permission.TEST_MANAGE_ROLLBACKS) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException( + "INSTALL_REASON_ROLLBACK requires the MANAGE_ROLLBACKS permission or the " + + "TEST_MANAGE_ROLLBACKS permission"); + } + } + // App package name and label length is restricted so that really long strings aren't // written to disk. if (params.appPackageName != null @@ -733,8 +747,8 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements installerAttributionTag); session = new PackageInstallerSession(mInternalCallback, mContext, mPm, this, mInstallThread.getLooper(), mStagingManager, sessionId, userId, callingUid, - installSource, params, createdMillis, stageDir, stageCid, null, null, false, false, - false, false, null, SessionInfo.INVALID_ID, false, false, false, + installSource, params, createdMillis, 0L, stageDir, stageCid, null, null, false, + false, false, false, null, SessionInfo.INVALID_ID, false, false, false, SessionInfo.STAGED_SESSION_NO_ERROR, ""); synchronized (mSessions) { diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 4ab12823dfb7..b8daa832cd2d 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -35,6 +35,7 @@ import static android.system.OsConstants.O_CREAT; import static android.system.OsConstants.O_RDONLY; import static android.system.OsConstants.O_WRONLY; +import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE; import static com.android.internal.util.XmlUtils.readBitmapAttribute; import static com.android.internal.util.XmlUtils.readByteArrayAttribute; import static com.android.internal.util.XmlUtils.readStringAttribute; @@ -132,6 +133,7 @@ import android.util.apk.ApkSignatureVerifier; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.content.NativeLibraryHelper; import com.android.internal.content.PackageHelper; import com.android.internal.messages.nano.SystemMessageProto; @@ -201,6 +203,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { "installOriginatingPackageName"; private static final String ATTR_CREATED_MILLIS = "createdMillis"; private static final String ATTR_UPDATED_MILLIS = "updatedMillis"; + private static final String ATTR_COMMITTED_MILLIS = "committedMillis"; private static final String ATTR_SESSION_STAGE_DIR = "sessionStageDir"; private static final String ATTR_SESSION_STAGE_CID = "sessionStageCid"; private static final String ATTR_PREPARED = "prepared"; @@ -291,6 +294,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { @GuardedBy("mLock") private long updatedMillis; + /** Timestamp of the time this session is committed */ + @GuardedBy("mLock") + private long committedMillis; + /** Uid of the creator of this session. */ private final int mOriginalInstallerUid; @@ -625,7 +632,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { Context context, PackageManagerService pm, PackageSessionProvider sessionProvider, Looper looper, StagingManager stagingManager, int sessionId, int userId, int installerUid, @NonNull InstallSource installSource, - SessionParams params, long createdMillis, + SessionParams params, long createdMillis, long committedMillis, File stageDir, String stageCid, InstallationFile[] files, ArrayMap<String, List<CertifiedChecksum>> checksums, boolean prepared, boolean committed, boolean destroyed, boolean sealed, @@ -648,6 +655,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { this.params = params; this.createdMillis = createdMillis; this.updatedMillis = createdMillis; + this.committedMillis = committedMillis; this.stageDir = stageDir; this.stageCid = stageCid; this.mShouldBeSealed = sealed; @@ -1641,6 +1649,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { mActiveCount.incrementAndGet(); mCommitted = true; + committedMillis = System.currentTimeMillis(); } return true; } catch (PackageManagerException e) { @@ -2963,7 +2972,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { /** * @return the package name of this session */ - String getPackageName() { + @VisibleForTesting(visibility = PACKAGE) + public String getPackageName() { synchronized (mLock) { return mPackageName; } @@ -2978,6 +2988,12 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } } + long getCommittedMillis() { + synchronized (mLock) { + return committedMillis; + } + } + String getInstallerPackageName() { return getInstallSource().installerPackageName; } @@ -3923,6 +3939,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { pw.printPair("mInstallerUid", mInstallerUid); pw.printPair("createdMillis", createdMillis); pw.printPair("updatedMillis", updatedMillis); + pw.printPair("committedMillis", committedMillis); pw.printPair("stageDir", stageDir); pw.printPair("stageCid", stageCid); pw.println(); @@ -4099,6 +4116,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { mInstallSource.originatingPackageName); out.attributeLong(null, ATTR_CREATED_MILLIS, createdMillis); out.attributeLong(null, ATTR_UPDATED_MILLIS, updatedMillis); + out.attributeLong(null, ATTR_COMMITTED_MILLIS, committedMillis); if (stageDir != null) { writeStringAttribute(out, ATTR_SESSION_STAGE_DIR, stageDir.getAbsolutePath()); @@ -4252,6 +4270,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { readStringAttribute(in, ATTR_ORIGINATING_PACKAGE_NAME); final long createdMillis = in.getAttributeLong(null, ATTR_CREATED_MILLIS); long updatedMillis = in.getAttributeLong(null, ATTR_UPDATED_MILLIS); + final long committedMillis = in.getAttributeLong(null, ATTR_COMMITTED_MILLIS, 0L); final String stageDirRaw = readStringAttribute(in, ATTR_SESSION_STAGE_DIR); final File stageDir = (stageDirRaw != null) ? new File(stageDirRaw) : null; final String stageCid = readStringAttribute(in, ATTR_SESSION_STAGE_CID); @@ -4395,8 +4414,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { installOriginatingPackageName, installerPackageName, installerAttributionTag); return new PackageInstallerSession(callback, context, pm, sessionProvider, installerThread, stagingManager, sessionId, userId, installerUid, - installSource, params, createdMillis, stageDir, stageCid, fileArray, checksums, - prepared, committed, destroyed, sealed, childSessionIdsArray, parentSessionId, - isReady, isFailed, isApplied, stagedSessionErrorCode, stagedSessionErrorMessage); + installSource, params, createdMillis, committedMillis, stageDir, stageCid, + fileArray, checksums, prepared, committed, destroyed, sealed, childSessionIdsArray, + parentSessionId, isReady, isFailed, isApplied, stagedSessionErrorCode, + stagedSessionErrorMessage); } } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 72dad6128e02..cd9d11dbe35f 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -24,6 +24,7 @@ import static android.Manifest.permission.SET_HARMFUL_APP_WARNINGS; import static android.app.AppOpsManager.MODE_DEFAULT; import static android.app.AppOpsManager.MODE_IGNORED; import static android.content.Intent.ACTION_MAIN; +import static android.content.Intent.CATEGORY_BROWSABLE; import static android.content.Intent.CATEGORY_DEFAULT; import static android.content.Intent.CATEGORY_HOME; import static android.content.Intent.EXTRA_LONG_VERSION_CODE; @@ -238,6 +239,7 @@ import android.content.pm.VersionedPackage; import android.content.pm.dex.ArtManager; import android.content.pm.dex.DexMetadataHelper; import android.content.pm.dex.IArtManager; +import android.content.pm.parsing.ApkLiteParseUtils; import android.content.pm.parsing.ParsingPackageUtils; import android.content.pm.parsing.component.ParsedActivity; import android.content.pm.parsing.component.ParsedInstrumentation; @@ -248,6 +250,8 @@ import android.content.pm.parsing.component.ParsedPermissionGroup; import android.content.pm.parsing.component.ParsedProcess; import android.content.pm.parsing.component.ParsedProvider; import android.content.pm.parsing.component.ParsedService; +import android.content.pm.parsing.result.ParseResult; +import android.content.pm.parsing.result.ParseTypeImpl; import android.content.res.Resources; import android.database.ContentObserver; import android.graphics.Bitmap; @@ -8003,6 +8007,13 @@ public class PackageManagerService extends IPackageManager.Stub Slog.i(TAG, " + always: " + info.activityInfo.packageName + " : linkgen=" + linkGeneration); } + + if (!intent.hasCategory(CATEGORY_BROWSABLE) + || !intent.hasCategory(CATEGORY_DEFAULT)) { + undefinedList.add(info); + continue; + } + // Use link-enabled generation as preferredOrder, i.e. // prefer newly-enabled over earlier-enabled. info.preferredOrder = linkGeneration; @@ -15322,7 +15333,7 @@ public class PackageManagerService extends IPackageManager.Stub InstallParams(OriginInfo origin, MoveInfo move, IPackageInstallObserver2 observer, int installFlags, InstallSource installSource, String volumeUuid, - UserHandle user, String packageAbiOverride) { + UserHandle user, String packageAbiOverride, PackageLite packageLite) { super(user); this.origin = origin; this.move = move; @@ -15341,7 +15352,7 @@ public class PackageManagerService extends IPackageManager.Stub this.forceQueryableOverride = false; this.mDataLoaderType = DataLoaderType.NONE; this.requiredInstalledVersionCode = PackageManager.VERSION_CODE_HIGHEST; - this.mPackageLite = null; + this.mPackageLite = packageLite; } InstallParams(File stagedDir, IPackageInstallObserver2 observer, @@ -17681,12 +17692,12 @@ public class PackageManagerService extends IPackageManager.Stub final SparseArray<int[]> newBroadcastAllowList; final String codePath; synchronized (mLock) { - final PackageSetting ps = mSettings.mPackages.get(mPackageName); + final PackageSetting ps = mSettings.getPackageLPr(mPackageName); if (ps == null) { return; } newBroadcastAllowList = mAppsFilter.getVisibilityAllowList( - ps, mInstalledUserIds, mSettings.mPackages); + ps, mInstalledUserIds, mSettings.getPackagesLocked()); codePath = ps.getPathString(); } Bundle extras = new Bundle(); @@ -17704,12 +17715,12 @@ public class PackageManagerService extends IPackageManager.Stub public void onPackageUnstartable(int reason) { final SparseArray<int[]> newBroadcastAllowList; synchronized (mLock) { - final PackageSetting ps = mSettings.mPackages.get(mPackageName); + final PackageSetting ps = mSettings.getPackageLPr(mPackageName); if (ps == null) { return; } newBroadcastAllowList = mAppsFilter.getVisibilityAllowList( - ps, mInstalledUserIds, mSettings.mPackages); + ps, mInstalledUserIds, mSettings.getPackagesLocked()); } Bundle extras = new Bundle(); extras.putInt(Intent.EXTRA_UID, mUid); @@ -17726,12 +17737,12 @@ public class PackageManagerService extends IPackageManager.Stub public void onPackageStartable() { final SparseArray<int[]> newBroadcastAllowList; synchronized (mLock) { - final PackageSetting ps = mSettings.mPackages.get(mPackageName); + final PackageSetting ps = mSettings.getPackageLPr(mPackageName); if (ps == null) { return; } newBroadcastAllowList = mAppsFilter.getVisibilityAllowList( - ps, mInstalledUserIds, mSettings.mPackages); + ps, mInstalledUserIds, mSettings.getPackagesLocked()); } Bundle extras = new Bundle(); extras.putInt(Intent.EXTRA_UID, mUid); @@ -17757,7 +17768,7 @@ public class PackageManagerService extends IPackageManager.Stub public void onPackageLoadingProgressChanged(float progress) { final PackageSetting ps; synchronized (mLock) { - ps = mSettings.mPackages.get(mPackageName); + ps = mSettings.getPackageLPr(mPackageName); } if (ps == null) { return; @@ -17780,7 +17791,7 @@ public class PackageManagerService extends IPackageManager.Stub public void onHealthStatus(int storageId, int status) throws RemoteException { final PackageSetting ps; synchronized (mLock) { - ps = mSettings.mPackages.get(mPackageName); + ps = mSettings.getPackageLPr(mPackageName); } if (ps == null) { return; @@ -17793,7 +17804,7 @@ public class PackageManagerService extends IPackageManager.Stub int userId) { final PackageSetting ps; synchronized (mLock) { - ps = mSettings.mPackages.get(packageName); + ps = mSettings.getPackageLPr(packageName); if (ps == null) { Slog.w(TAG, "Failed to get package setting. Package " + packageName + " is not installed"); @@ -24182,8 +24193,12 @@ public class PackageManagerService extends IPackageManager.Stub final Message msg = mHandler.obtainMessage(INIT_COPY); final OriginInfo origin = OriginInfo.fromExistingFile(codeFile); + final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing(); + final ParseResult<PackageLite> ret = ApkLiteParseUtils.parsePackageLite(input, + new File(origin.resolvedPath), /* flags */ 0); + final PackageLite lite = ret.isSuccess() ? ret.getResult() : null; final InstallParams params = new InstallParams(origin, move, installObserver, installFlags, - installSource, volumeUuid, user, packageAbiOverride); + installSource, volumeUuid, user, packageAbiOverride, lite); params.setTraceMethod("movePackage").setTraceCookie(System.identityHashCode(params)); msg.obj = params; @@ -24597,7 +24612,7 @@ public class PackageManagerService extends IPackageManager.Stub // which was uninstalled while keeping its data. AndroidPackage dataOwnerPkg = mPackages.get(packageName); if (dataOwnerPkg == null) { - PackageSetting ps = mSettings.mPackages.get(packageName); + PackageSetting ps = mSettings.getPackageLPr(packageName); if (ps != null) { dataOwnerPkg = ps.pkg; } @@ -26044,7 +26059,7 @@ public class PackageManagerService extends IPackageManager.Stub public void notifyPackageCrashOrAnr(@NonNull String packageName) { final PackageSetting ps; synchronized (mLock) { - ps = mSettings.mPackages.get(packageName); + ps = mSettings.getPackageLPr(packageName); if (ps == null) { Slog.w(TAG, "Failed notifyPackageCrash. Package " + packageName + " is not installed"); diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java index c77eda161c67..d3d7c6055fce 100644 --- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java +++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java @@ -822,7 +822,7 @@ public class PackageManagerServiceUtils { public static PackageInfoLite getMinimalPackageInfo(Context context, PackageParser.PackageLite pkg, String packagePath, int flags, String abiOverride) { final PackageInfoLite ret = new PackageInfoLite(); - if (packagePath == null) { + if (packagePath == null || pkg == null) { Slog.i(TAG, "Invalid package file " + packagePath); ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_APK; return ret; diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 2d5034e624cd..7482ef4598f1 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -295,6 +295,7 @@ public final class Settings { private final File mKernelMappingFilename; /** Map from package name to settings */ + @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) final ArrayMap<String, PackageSetting> mPackages = new ArrayMap<>(); /** diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java index 0ac0c8d95423..9f07695fcecf 100644 --- a/services/core/java/com/android/server/pm/ShortcutPackage.java +++ b/services/core/java/com/android/server/pm/ShortcutPackage.java @@ -737,7 +737,7 @@ class ShortcutPackage extends ShortcutPackageItem { || ((pinnedByCallerSet != null) && pinnedByCallerSet.contains(si.getId())); if (!getPinnedByAnyLauncher) { - if (si.isFloating()) { + if (si.isFloating() && !si.isCached()) { if (!isPinnedByCaller) { continue; } diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java index c68fe81d0565..56fb5e8fd449 100644 --- a/services/core/java/com/android/server/pm/ShortcutService.java +++ b/services/core/java/com/android/server/pm/ShortcutService.java @@ -537,7 +537,9 @@ public class ShortcutService extends IShortcutService.Stub { synchronized (mLock) { // Clear the launcher cache for this user. It will be set again next time the default // launcher is read from RoleManager. - getUserShortcutsLocked(userId).setCachedLauncher(null); + if (isUserLoadedLocked(userId)) { + getUserShortcutsLocked(userId).setCachedLauncher(null); + } } } diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java index 85c4ab2c8a10..222874d3eb82 100644 --- a/services/core/java/com/android/server/pm/StagingManager.java +++ b/services/core/java/com/android/server/pm/StagingManager.java @@ -59,6 +59,7 @@ import android.util.SparseArray; import android.util.apk.ApkSignatureVerifier; import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.content.PackageHelper; import com.android.internal.os.BackgroundThread; import com.android.server.LocalServices; @@ -720,7 +721,8 @@ public class StagingManager { * </ul> * @throws PackageManagerException if session fails the check */ - private void checkNonOverlappingWithStagedSessions(@NonNull PackageInstallerSession session) + @VisibleForTesting + void checkNonOverlappingWithStagedSessions(@NonNull PackageInstallerSession session) throws PackageManagerException { if (session.isMultiPackage()) { // We cannot say a parent session overlaps until we process its children @@ -747,6 +749,13 @@ public class StagingManager { continue; } + if (stagedSession.getCommittedMillis() > session.getCommittedMillis()) { + // Ignore sessions that are committed after the provided session. When there are + // overlaps between sessions, we will fail the one committed later instead of + // the earlier one. + continue; + } + // From here on, stagedSession is a parent active staged session // Check if session is one of the active sessions @@ -793,7 +802,8 @@ public class StagingManager { } } - private void createSession(@NonNull PackageInstallerSession sessionInfo) { + @VisibleForTesting + void createSession(@NonNull PackageInstallerSession sessionInfo) { synchronized (mStagedSessions) { mStagedSessions.append(sessionInfo.sessionId, sessionInfo); } diff --git a/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerInternal.java b/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerInternal.java index a098484b803b..7ca9f0536de1 100644 --- a/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerInternal.java +++ b/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerInternal.java @@ -99,52 +99,6 @@ public interface LegacyPermissionManagerInternal { */ void scheduleReadDefaultPermissionExceptions(); - // TODO(zhanghai): The following methods should be moved to a new AIDL to support - // the legacy PermissionManager directly in a later CL. - - /** - * Grant default permissions to currently active LUI app - * @param packageName The package name for the LUI app - * @param userId The user ID - */ - void grantDefaultPermissionsToActiveLuiApp(String packageName, int userId); - - /** - * Revoke default permissions to currently active LUI app - * @param packageNames The package names for the LUI apps - * @param userId The user ID - */ - void revokeDefaultPermissionsFromLuiApps(String[] packageNames, int userId); - - /** - * Grant default permissions to currently active Ims services - * @param packageNames The package names for the Ims services - * @param userId The user ID - */ - void grantDefaultPermissionsToEnabledImsServices(String[] packageNames, int userId); - - /** - * Grant default permissions to currently enabled telephony data services - * @param packageNames The package name for the services - * @param userId The user ID - */ - void grantDefaultPermissionsToEnabledTelephonyDataServices(String[] packageNames, int userId); - - /** - * Revoke default permissions to currently active telephony data services - * @param packageNames The package name for the services - * @param userId The IDhandle - */ - void revokeDefaultPermissionsFromDisabledTelephonyDataServices(String[] packageNames, - int userId); - - /** - * Grant default permissions to currently enabled carrier apps - * @param packageNames Package names of the apps to be granted permissions - * @param userId The user ID - */ - void grantDefaultPermissionsToEnabledCarrierApps(String[] packageNames, int userId); - /** * Provider for package names. */ diff --git a/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java b/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java index 0c0a8dfeaaec..f453d7460d9d 100644 --- a/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java @@ -17,16 +17,31 @@ package com.android.server.pm.permission; import android.annotation.NonNull; +import android.annotation.Nullable; +import android.app.AppOpsManager; +import android.app.admin.DevicePolicyManager; import android.content.Context; +import android.content.pm.PackageManager; import android.os.Binder; +import android.os.Process; +import android.os.ServiceManager; +import android.os.UserHandle; +import android.permission.ILegacyPermissionManager; +import android.util.Log; +import com.android.internal.annotations.VisibleForTesting; import com.android.server.LocalServices; import com.android.server.pm.PackageManagerServiceUtils; /** * Legacy permission manager service. */ -public class LegacyPermissionManagerService { +public class LegacyPermissionManagerService extends ILegacyPermissionManager.Stub { + private static final String TAG = "PackageManager"; + + /** Injector that can be used to facilitate testing. */ + private final Injector mInjector; + @NonNull private final DefaultPermissionGrantPolicy mDefaultPermissionGrantPolicy; @@ -51,8 +66,126 @@ public class LegacyPermissionManagerService { } private LegacyPermissionManagerService(@NonNull Context context) { - mDefaultPermissionGrantPolicy = new DefaultPermissionGrantPolicy(context); + this(context, new Injector(context)); + LocalServices.addService(LegacyPermissionManagerInternal.class, new Internal()); + ServiceManager.addService("legacy_permission", this); + } + + @VisibleForTesting + LegacyPermissionManagerService(@NonNull Context context, @NonNull Injector injector) { + mInjector = injector; + mDefaultPermissionGrantPolicy = new DefaultPermissionGrantPolicy(context); + } + + @Override + public int checkDeviceIdentifierAccess(@Nullable String packageName, @Nullable String message, + @Nullable String callingFeatureId, int pid, int uid) { + // If the check is being requested by an app then only allow the app to query its own + // access status. + int callingUid = mInjector.getCallingUid(); + int callingPid = mInjector.getCallingPid(); + if (UserHandle.getAppId(callingUid) >= Process.FIRST_APPLICATION_UID && (callingUid != uid + || callingPid != pid)) { + String response = String.format( + "Calling uid %d, pid %d cannot check device identifier access for package %s " + + "(uid=%d, pid=%d)", + callingUid, callingPid, packageName, uid, pid); + Log.w(TAG, response); + throw new SecurityException(response); + } + // Allow system and root access to the device identifiers. + final int appId = UserHandle.getAppId(uid); + if (appId == Process.SYSTEM_UID || appId == Process.ROOT_UID) { + return PackageManager.PERMISSION_GRANTED; + } + // Allow access to packages that have the READ_PRIVILEGED_PHONE_STATE permission. + if (mInjector.checkPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, pid, + uid) == PackageManager.PERMISSION_GRANTED) { + return PackageManager.PERMISSION_GRANTED; + } + // If the calling package is not null then perform the appop and device / profile owner + // check. + if (packageName != null) { + // Allow access to a package that has been granted the READ_DEVICE_IDENTIFIERS appop. + final long token = mInjector.clearCallingIdentity(); + AppOpsManager appOpsManager = (AppOpsManager) mInjector.getSystemService( + Context.APP_OPS_SERVICE); + try { + if (appOpsManager.noteOpNoThrow(AppOpsManager.OPSTR_READ_DEVICE_IDENTIFIERS, uid, + packageName, callingFeatureId, message) == AppOpsManager.MODE_ALLOWED) { + return PackageManager.PERMISSION_GRANTED; + } + } finally { + mInjector.restoreCallingIdentity(token); + } + // Check if the calling packages meets the device / profile owner requirements for + // identifier access. + DevicePolicyManager devicePolicyManager = + (DevicePolicyManager) mInjector.getSystemService(Context.DEVICE_POLICY_SERVICE); + if (devicePolicyManager != null && devicePolicyManager.hasDeviceIdentifierAccess( + packageName, pid, uid)) { + return PackageManager.PERMISSION_GRANTED; + } + } + return PackageManager.PERMISSION_DENIED; + } + + @Override + public void grantDefaultPermissionsToActiveLuiApp(String packageName, int userId) { + final int callingUid = Binder.getCallingUid(); + PackageManagerServiceUtils.enforceSystemOrPhoneCaller( + "grantDefaultPermissionsToActiveLuiApp", callingUid); + Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy + .grantDefaultPermissionsToActiveLuiApp(packageName, userId)); + } + + @Override + public void revokeDefaultPermissionsFromLuiApps(String[] packageNames, int userId) { + final int callingUid = Binder.getCallingUid(); + PackageManagerServiceUtils.enforceSystemOrPhoneCaller( + "revokeDefaultPermissionsFromLuiApps", callingUid); + Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy + .revokeDefaultPermissionsFromLuiApps(packageNames, userId)); + } + + @Override + public void grantDefaultPermissionsToEnabledImsServices(String[] packageNames, int userId) { + final int callingUid = Binder.getCallingUid(); + PackageManagerServiceUtils.enforceSystemOrPhoneCaller( + "grantDefaultPermissionsToEnabledImsServices", callingUid); + Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy + .grantDefaultPermissionsToEnabledImsServices(packageNames, userId)); + } + + @Override + public void grantDefaultPermissionsToEnabledTelephonyDataServices( + String[] packageNames, int userId) { + final int callingUid = Binder.getCallingUid(); + PackageManagerServiceUtils.enforceSystemOrPhoneCaller( + "grantDefaultPermissionsToEnabledTelephonyDataServices", callingUid); + Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy + .grantDefaultPermissionsToEnabledTelephonyDataServices(packageNames, userId)); + } + + @Override + public void revokeDefaultPermissionsFromDisabledTelephonyDataServices( + String[] packageNames, int userId) { + final int callingUid = Binder.getCallingUid(); + PackageManagerServiceUtils.enforceSystemOrPhoneCaller( + "revokeDefaultPermissionsFromDisabledTelephonyDataServices", callingUid); + Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy + .revokeDefaultPermissionsFromDisabledTelephonyDataServices(packageNames, + userId)); + } + + @Override + public void grantDefaultPermissionsToEnabledCarrierApps(String[] packageNames, int userId) { + final int callingUid = Binder.getCallingUid(); + PackageManagerServiceUtils.enforceSystemOrPhoneCaller( + "grantPermissionsToEnabledCarrierApps", callingUid); + Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy + .grantDefaultPermissionsToEnabledCarrierApps(packageNames, userId)); } private class Internal implements LegacyPermissionManagerInternal { @@ -117,65 +250,74 @@ public class LegacyPermissionManagerService { public void scheduleReadDefaultPermissionExceptions() { mDefaultPermissionGrantPolicy.scheduleReadDefaultPermissionExceptions(); } + } + + /** + * Allows injection of services and method responses to facilitate testing. + * + * <p>Test classes can create a mock of this class and pass it to the PermissionManagerService + * constructor to control behavior of services and external methods during execution. + * @hide + */ + @VisibleForTesting + public static class Injector { + private final Context mContext; - // TODO(zhanghai): The following methods should be moved to a new AIDL to support - // the legacy PermissionManager directly in a later CL. + /** + * Public constructor that accepts a {@code context} within which to operate. + */ + public Injector(@NonNull Context context) { + mContext = context; + } - @Override - public void grantDefaultPermissionsToActiveLuiApp(String packageName, int userId) { - final int callingUid = Binder.getCallingUid(); - PackageManagerServiceUtils.enforceSystemOrPhoneCaller( - "grantDefaultPermissionsToActiveLuiApp", callingUid); - Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy - .grantDefaultPermissionsToActiveLuiApp(packageName, userId)); + /** + * Returns the UID of the calling package. + */ + public int getCallingUid() { + return Binder.getCallingUid(); } - @Override - public void revokeDefaultPermissionsFromLuiApps(String[] packageNames, int userId) { - final int callingUid = Binder.getCallingUid(); - PackageManagerServiceUtils.enforceSystemOrPhoneCaller( - "revokeDefaultPermissionsFromLuiApps", callingUid); - Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy - .revokeDefaultPermissionsFromLuiApps(packageNames, userId)); + /** + * Returns the process ID of the calling package. + */ + public int getCallingPid() { + return Binder.getCallingPid(); } - @Override - public void grantDefaultPermissionsToEnabledImsServices(String[] packageNames, int userId) { - final int callingUid = Binder.getCallingUid(); - PackageManagerServiceUtils.enforceSystemOrPhoneCaller( - "grantDefaultPermissionsToEnabledImsServices", callingUid); - Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy - .grantDefaultPermissionsToEnabledImsServices(packageNames, userId)); + /** + * Checks if the package running under the specified {@code pid} and {@code uid} has been + * granted the provided {@code permission}. + * + * @return {@link PackageManager#PERMISSION_GRANTED} if the package has been granted the + * permission, {@link PackageManager#PERMISSION_DENIED} otherwise + */ + public int checkPermission(@NonNull String permission, int pid, int uid) { + return mContext.checkPermission(permission, pid, uid); } - @Override - public void grantDefaultPermissionsToEnabledTelephonyDataServices( - String[] packageNames, int userId) { - final int callingUid = Binder.getCallingUid(); - PackageManagerServiceUtils.enforceSystemOrPhoneCaller( - "grantDefaultPermissionsToEnabledTelephonyDataServices", callingUid); - Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy - .grantDefaultPermissionsToEnabledTelephonyDataServices(packageNames, userId)); + /** + * Clears the calling identity to allow subsequent calls to be treated as coming from this + * package. + * + * @return a token that can be used to restore the calling identity + */ + public long clearCallingIdentity() { + return Binder.clearCallingIdentity(); } - @Override - public void revokeDefaultPermissionsFromDisabledTelephonyDataServices( - String[] packageNames, int userId) { - final int callingUid = Binder.getCallingUid(); - PackageManagerServiceUtils.enforceSystemOrPhoneCaller( - "revokeDefaultPermissionsFromDisabledTelephonyDataServices", callingUid); - Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy - .revokeDefaultPermissionsFromDisabledTelephonyDataServices(packageNames, - userId)); + /** + * Restores the calling identity to that of the calling package based on the provided + * {@code token}. + */ + public void restoreCallingIdentity(long token) { + Binder.restoreCallingIdentity(token); } - @Override - public void grantDefaultPermissionsToEnabledCarrierApps(String[] packageNames, int userId) { - final int callingUid = Binder.getCallingUid(); - PackageManagerServiceUtils.enforceSystemOrPhoneCaller( - "grantPermissionsToEnabledCarrierApps", callingUid); - Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy - .grantDefaultPermissionsToEnabledCarrierApps(packageNames, userId)); + /** + * Returns the system service with the provided {@code name}. + */ + public Object getSystemService(@NonNull String name) { + return mContext.getSystemService(name); } } } diff --git a/services/core/java/com/android/server/pm/permission/OWNERS b/services/core/java/com/android/server/pm/permission/OWNERS index 6e678305b860..0e88862e01b1 100644 --- a/services/core/java/com/android/server/pm/permission/OWNERS +++ b/services/core/java/com/android/server/pm/permission/OWNERS @@ -1,7 +1,7 @@ moltmann@google.com zhanghai@google.com -per-file DefaultPermissionGrantPolicy.java = hackbod@google.com -per-file DefaultPermissionGrantPolicy.java = jsharkey@google.com +per-file DefaultPermissionGrantPolicy.java = hackbod@android.com +per-file DefaultPermissionGrantPolicy.java = jsharkey@android.com per-file DefaultPermissionGrantPolicy.java = svetoslavganov@google.com per-file DefaultPermissionGrantPolicy.java = toddke@google.com per-file DefaultPermissionGrantPolicy.java = yamasani@google.com 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 1df51772f823..1dbf8396bcfb 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -66,9 +66,7 @@ import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.AppOpsManager; -import android.app.ApplicationPackageManager; import android.app.IActivityManager; -import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManagerInternal; import android.app.role.RoleManager; import android.compat.annotation.ChangeId; @@ -126,7 +124,6 @@ import android.util.SparseArray; import android.util.SparseBooleanArray; import com.android.internal.annotations.GuardedBy; -import com.android.internal.annotations.VisibleForTesting; import com.android.internal.compat.IPlatformCompat; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; @@ -264,9 +261,6 @@ public class PermissionManagerService extends IPermissionManager.Stub { @NonNull private final PermissionRegistry mRegistry = new PermissionRegistry(); - /** Injector that can be used to facilitate testing. */ - private final Injector mInjector; - @GuardedBy("mLock") @Nullable private ArraySet<String> mPrivappPermissionsViolations; @@ -364,17 +358,11 @@ public class PermissionManagerService extends IPermissionManager.Stub { }; PermissionManagerService(@NonNull Context context) { - this(context, new Injector(context)); - } - - @VisibleForTesting - PermissionManagerService(@NonNull Context context, @NonNull Injector injector) { - mInjector = injector; // The package info cache is the cache for package and permission information. // Disable the package info and package permission caches locally but leave the // checkPermission cache active. - mInjector.invalidatePackageInfoCache(); - mInjector.disablePackageNamePermissionCache(); + PackageManager.invalidatePackageInfoCache(); + PermissionManager.disablePackageNamePermissionCache(); mContext = context; mPackageManagerInt = LocalServices.getService(PackageManagerInternal.class); @@ -806,8 +794,8 @@ public class PermissionManagerService extends IPermissionManager.Stub { private void updatePermissionFlagsInternal(String permName, String packageName, int flagMask, int flagValues, int callingUid, int userId, boolean overridePolicy, PermissionCallback callback) { - if (ApplicationPackageManager.DEBUG_TRACE_PERMISSION_UPDATES - && ApplicationPackageManager.shouldTraceGrant(packageName, permName, userId)) { + if (PermissionManager.DEBUG_TRACE_PERMISSION_UPDATES + && PermissionManager.shouldTraceGrant(packageName, permName, userId)) { Log.i(TAG, "System is updating flags for " + packageName + " " + permName + " for user " + userId + " " + DebugUtils.flagsToString( @@ -1113,59 +1101,6 @@ public class PermissionManagerService extends IPermissionManager.Stub { } @Override - public int checkDeviceIdentifierAccess(@Nullable String packageName, @Nullable String message, - @Nullable String callingFeatureId, int pid, int uid) { - // If the check is being requested by an app then only allow the app to query its own - // access status. - int callingUid = mInjector.getCallingUid(); - int callingPid = mInjector.getCallingPid(); - if (UserHandle.getAppId(callingUid) >= Process.FIRST_APPLICATION_UID && (callingUid != uid - || callingPid != pid)) { - String response = String.format( - "Calling uid %d, pid %d cannot check device identifier access for package %s " - + "(uid=%d, pid=%d)", - callingUid, callingPid, packageName, uid, pid); - Log.w(TAG, response); - throw new SecurityException(response); - } - // Allow system and root access to the device identifiers. - final int appId = UserHandle.getAppId(uid); - if (appId == Process.SYSTEM_UID || appId == Process.ROOT_UID) { - return PackageManager.PERMISSION_GRANTED; - } - // Allow access to packages that have the READ_PRIVILEGED_PHONE_STATE permission. - if (mInjector.checkPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, pid, - uid) == PackageManager.PERMISSION_GRANTED) { - return PackageManager.PERMISSION_GRANTED; - } - // If the calling package is not null then perform the appop and device / profile owner - // check. - if (packageName != null) { - // Allow access to a package that has been granted the READ_DEVICE_IDENTIFIERS appop. - final long token = mInjector.clearCallingIdentity(); - AppOpsManager appOpsManager = (AppOpsManager) mInjector.getSystemService( - Context.APP_OPS_SERVICE); - try { - if (appOpsManager.noteOpNoThrow(AppOpsManager.OPSTR_READ_DEVICE_IDENTIFIERS, uid, - packageName, callingFeatureId, message) == AppOpsManager.MODE_ALLOWED) { - return PackageManager.PERMISSION_GRANTED; - } - } finally { - mInjector.restoreCallingIdentity(token); - } - // Check if the calling packages meets the device / profile owner requirements for - // identifier access. - DevicePolicyManager devicePolicyManager = - (DevicePolicyManager) mInjector.getSystemService(Context.DEVICE_POLICY_SERVICE); - if (devicePolicyManager != null && devicePolicyManager.hasDeviceIdentifierAccess( - packageName, pid, uid)) { - return PackageManager.PERMISSION_GRANTED; - } - } - return PackageManager.PERMISSION_DENIED; - } - - @Override public void addOnPermissionsChangeListener(IOnPermissionsChangeListener listener) { mContext.enforceCallingOrSelfPermission( Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS, @@ -1520,8 +1455,8 @@ public class PermissionManagerService extends IPermissionManager.Stub { // TODO swap permission name and package name private void grantRuntimePermissionInternal(String permName, String packageName, boolean overridePolicy, int callingUid, final int userId, PermissionCallback callback) { - if (ApplicationPackageManager.DEBUG_TRACE_GRANTS - && ApplicationPackageManager.shouldTraceGrant(packageName, permName, userId)) { + if (PermissionManager.DEBUG_TRACE_GRANTS + && PermissionManager.shouldTraceGrant(packageName, permName, userId)) { Log.i(TAG, "System is granting " + packageName + " " + permName + " for user " + userId + " on behalf of uid " + callingUid + " " + mPackageManagerInt.getNameForUid(callingUid), @@ -1697,8 +1632,8 @@ public class PermissionManagerService extends IPermissionManager.Stub { private void revokeRuntimePermissionInternal(String permName, String packageName, boolean overridePolicy, int callingUid, final int userId, String reason, PermissionCallback callback) { - if (ApplicationPackageManager.DEBUG_TRACE_PERMISSION_UPDATES - && ApplicationPackageManager.shouldTraceGrant(packageName, permName, userId)) { + if (PermissionManager.DEBUG_TRACE_PERMISSION_UPDATES + && PermissionManager.shouldTraceGrant(packageName, permName, userId)) { Log.i(TAG, "System is revoking " + packageName + " " + permName + " for user " + userId + " on behalf of uid " + callingUid + " " + mPackageManagerInt.getNameForUid(callingUid), @@ -2037,44 +1972,6 @@ public class PermissionManagerService extends IPermissionManager.Stub { mPackageManagerInt.writePermissionSettings(asyncUpdatedUsers.toArray(), true); } - @Override - public void grantDefaultPermissionsToEnabledCarrierApps(String[] packageNames, int userId) { - LocalServices.getService(LegacyPermissionManagerInternal.class) - .grantDefaultPermissionsToEnabledCarrierApps(packageNames, userId); - } - - @Override - public void grantDefaultPermissionsToEnabledImsServices(String[] packageNames, int userId) { - LocalServices.getService(LegacyPermissionManagerInternal.class) - .grantDefaultPermissionsToEnabledImsServices(packageNames, userId); - } - - @Override - public void grantDefaultPermissionsToEnabledTelephonyDataServices( - String[] packageNames, int userId) { - LocalServices.getService(LegacyPermissionManagerInternal.class) - .grantDefaultPermissionsToEnabledTelephonyDataServices(packageNames, userId); - } - - @Override - public void revokeDefaultPermissionsFromDisabledTelephonyDataServices( - String[] packageNames, int userId) { - LocalServices.getService(LegacyPermissionManagerInternal.class) - .revokeDefaultPermissionsFromDisabledTelephonyDataServices(packageNames, userId); - } - - @Override - public void grantDefaultPermissionsToActiveLuiApp(String packageName, int userId) { - LocalServices.getService(LegacyPermissionManagerInternal.class) - .grantDefaultPermissionsToActiveLuiApp(packageName, userId); - } - - @Override - public void revokeDefaultPermissionsFromLuiApps(String[] packageNames, int userId) { - LocalServices.getService(LegacyPermissionManagerInternal.class) - .revokeDefaultPermissionsFromLuiApps(packageNames, userId); - } - /** * This change makes it so that apps are told to show rationale for asking for background * location access every time they request. @@ -2885,12 +2782,13 @@ public class PermissionManagerService extends IPermissionManager.Stub { // TODO(zhanghai): This calls into SystemConfig, which generally // shouldn't cause deadlock, but maybe we should keep a cache of the // split permission list and just eliminate the possibility. - final List<SplitPermissionInfoParcelable> permissionList = - getSplitPermissions(); + final List<PermissionManager.SplitPermissionInfo> permissionList = + getSplitPermissionInfos(); int numSplitPerms = permissionList.size(); for (int splitPermNum = 0; splitPermNum < numSplitPerms; splitPermNum++) { - SplitPermissionInfoParcelable sp = permissionList.get(splitPermNum); + PermissionManager.SplitPermissionInfo sp = permissionList.get( + splitPermNum); String splitPermName = sp.getSplitPermission(); if (sp.getNewPermissions().contains(permName) && origState.isPermissionGranted(splitPermName)) { @@ -3287,10 +3185,11 @@ public class PermissionManagerService extends IPermissionManager.Stub { String pkgName = pkg.getPackageName(); ArrayMap<String, ArraySet<String>> newToSplitPerms = new ArrayMap<>(); - final List<SplitPermissionInfoParcelable> permissionList = getSplitPermissions(); + final List<PermissionManager.SplitPermissionInfo> permissionList = + getSplitPermissionInfos(); int numSplitPerms = permissionList.size(); for (int splitPermNum = 0; splitPermNum < numSplitPerms; splitPermNum++) { - SplitPermissionInfoParcelable spi = permissionList.get(splitPermNum); + PermissionManager.SplitPermissionInfo spi = permissionList.get(splitPermNum); List<String> newPerms = spi.getNewPermissions(); int numNewPerms = newPerms.size(); @@ -3356,10 +3255,15 @@ public class PermissionManagerService extends IPermissionManager.Stub { return updatedUserIds; } + @NonNull @Override public List<SplitPermissionInfoParcelable> getSplitPermissions() { - return PermissionManager.splitPermissionInfoListToParcelableList( - SystemConfig.getInstance().getSplitPermissions()); + return PermissionManager.splitPermissionInfoListToParcelableList(getSplitPermissionInfos()); + } + + @NonNull + private List<PermissionManager.SplitPermissionInfo> getSplitPermissionInfos() { + return SystemConfig.getInstance().getSplitPermissions(); } @NonNull @@ -5456,94 +5360,4 @@ public class PermissionManagerService extends IPermissionManager.Stub { || mDelegatedPermissionNames.contains(permissionName); } } - - /** - * Allows injection of services and method responses to facilitate testing. - * - * <p>Test classes can create a mock of this class and pass it to the PermissionManagerService - * constructor to control behavior of services and external methods during execution. - * @hide - */ - @VisibleForTesting - public static class Injector { - private final Context mContext; - - /** - * Public constructor that accepts a {@code context} within which to operate. - */ - public Injector(@NonNull Context context) { - mContext = context; - } - - /** - * Returns the UID of the calling package. - */ - public int getCallingUid() { - return Binder.getCallingUid(); - } - - /** - * Returns the process ID of the calling package. - */ - public int getCallingPid() { - return Binder.getCallingPid(); - } - - /** - * Invalidates the package info cache. - */ - public void invalidatePackageInfoCache() { - PackageManager.invalidatePackageInfoCache(); - } - - /** - * Disables the permission cache. - */ - public void disablePermissionCache() { - PermissionManager.disablePermissionCache(); - } - - /** - * Disables the package name permission cache. - */ - public void disablePackageNamePermissionCache() { - PermissionManager.disablePackageNamePermissionCache(); - } - - /** - * Checks if the package running under the specified {@code pid} and {@code uid} has been - * granted the provided {@code permission}. - * - * @return {@link PackageManager#PERMISSION_GRANTED} if the package has been granted the - * permission, {@link PackageManager#PERMISSION_DENIED} otherwise - */ - public int checkPermission(@NonNull String permission, int pid, int uid) { - return mContext.checkPermission(permission, pid, uid); - } - - /** - * Clears the calling identity to allow subsequent calls to be treated as coming from this - * package. - * - * @return a token that can be used to restore the calling identity - */ - public long clearCallingIdentity() { - return Binder.clearCallingIdentity(); - } - - /** - * Restores the calling identity to that of the calling package based on the provided - * {@code token}. - */ - public void restoreCallingIdentity(long token) { - Binder.restoreCallingIdentity(token); - } - - /** - * Returns the system service with the provided {@code name}. - */ - public Object getSystemService(@NonNull String name) { - return mContext.getSystemService(name); - } - } } diff --git a/services/core/java/com/android/server/policy/DisplayFoldController.java b/services/core/java/com/android/server/policy/DisplayFoldController.java index b007a75c1ca5..ff51237a900a 100644 --- a/services/core/java/com/android/server/policy/DisplayFoldController.java +++ b/services/core/java/com/android/server/policy/DisplayFoldController.java @@ -20,12 +20,10 @@ import android.annotation.Nullable; import android.content.Context; import android.graphics.Rect; import android.hardware.ICameraService; -import android.hardware.Sensor; -import android.hardware.SensorEvent; -import android.hardware.SensorEventListener; -import android.hardware.SensorManager; +import android.hardware.devicestate.DeviceStateManager; import android.hardware.display.DisplayManagerInternal; import android.os.Handler; +import android.os.HandlerExecutor; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.util.Slog; @@ -63,7 +61,8 @@ class DisplayFoldController { private String mFocusedApp; private final DisplayFoldDurationLogger mDurationLogger = new DisplayFoldDurationLogger(); - DisplayFoldController(WindowManagerInternal windowManagerInternal, + DisplayFoldController( + Context context, WindowManagerInternal windowManagerInternal, DisplayManagerInternal displayManagerInternal, @Nullable CameraServiceProxy cameraServiceProxy, int displayId, Rect foldedArea, Handler handler) { @@ -73,6 +72,10 @@ class DisplayFoldController { mDisplayId = displayId; mFoldedArea = new Rect(foldedArea); mHandler = handler; + + DeviceStateManager deviceStateManager = context.getSystemService(DeviceStateManager.class); + deviceStateManager.registerDeviceStateListener(new DeviceStateListener(context), + new HandlerExecutor(handler)); } void finishedGoingToSleep() { @@ -83,11 +86,7 @@ class DisplayFoldController { mDurationLogger.onFinishedWakingUp(mFolded); } - void requestDeviceFolded(boolean folded) { - mHandler.post(() -> setDeviceFolded(folded)); - } - - void setDeviceFolded(boolean folded) { + private void setDeviceFolded(boolean folded) { if (mFolded != null && mFolded == folded) { return; } @@ -179,33 +178,6 @@ class DisplayFoldController { } } - /** - * Only used for the case that persist.debug.force_foldable is set. - * This is using proximity sensor to simulate the fold state switch. - */ - static DisplayFoldController createWithProxSensor(Context context, int displayId) { - final SensorManager sensorManager = context.getSystemService(SensorManager.class); - final Sensor proxSensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); - if (proxSensor == null) { - return null; - } - - final DisplayFoldController result = create(context, displayId); - sensorManager.registerListener(new SensorEventListener() { - @Override - public void onSensorChanged(SensorEvent event) { - result.requestDeviceFolded(event.values[0] < 1f); - } - - @Override - public void onAccuracyChanged(Sensor sensor, int accuracy) { - // Ignore. - } - }, proxSensor, SensorManager.SENSOR_DELAY_NORMAL); - - return result; - } - void onDefaultDisplayFocusChanged(String pkg) { mFocusedApp = pkg; } @@ -227,7 +199,26 @@ class DisplayFoldController { foldedArea = Rect.unflattenFromString(configFoldedArea); } - return new DisplayFoldController(windowManagerService, displayService, cameraServiceProxy, - displayId, foldedArea, DisplayThread.getHandler()); + return new DisplayFoldController(context, windowManagerService, displayService, + cameraServiceProxy, displayId, foldedArea, DisplayThread.getHandler()); + } + + /** + * Listens to changes in device state and reports the state as folded if the device state + * matches the value in the {@link com.android.internal.R.integer.config_foldedDeviceState} + * resource. + */ + private class DeviceStateListener implements DeviceStateManager.DeviceStateListener { + private final int mFoldedDeviceState; + + DeviceStateListener(Context context) { + mFoldedDeviceState = context.getResources().getInteger( + com.android.internal.R.integer.config_foldedDeviceState); + } + + @Override + public void onDeviceStateChanged(int deviceState) { + setDeviceFolded(deviceState == mFoldedDeviceState); + } } } diff --git a/services/core/java/com/android/server/policy/OWNERS b/services/core/java/com/android/server/policy/OWNERS index 0862c05e0ee4..d25ec4a560a3 100644 --- a/services/core/java/com/android/server/policy/OWNERS +++ b/services/core/java/com/android/server/policy/OWNERS @@ -1 +1,2 @@ include /services/core/java/com/android/server/wm/OWNERS +include /services/core/java/com/android/server/input/OWNERS diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index ea985df1c6b8..6919ceaa5a9f 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -472,7 +472,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { int mLidKeyboardAccessibility; int mLidNavigationAccessibility; - private boolean mLidControlsDisplayFold; int mShortPressOnPowerBehavior; int mLongPressOnPowerBehavior; int mVeryLongPressOnPowerBehavior; @@ -648,8 +647,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { break; case MSG_LAUNCH_ASSIST: final int deviceId = msg.arg1; - final String hint = (String) msg.obj; - launchAssistAction(hint, deviceId); + final Long eventTime = (Long) msg.obj; + launchAssistAction(null /* hint */, deviceId, eventTime); break; case MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK: launchVoiceAssistWithWakeLock(); @@ -659,7 +658,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { finishPowerKeyPress(); break; case MSG_POWER_LONG_PRESS: - powerLongPress(); + powerLongPress((Long) msg.obj /* eventTime */); break; case MSG_POWER_VERY_LONG_PRESS: powerVeryLongPress(); @@ -934,9 +933,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Wait for a long press or for the button to be released to decide what to do. if (hasLongPressOnPowerBehavior()) { if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) { - powerLongPress(); + powerLongPress(event.getEventTime()); } else { - Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS); + Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS, + event.getEventTime()); msg.setAsynchronous(true); mHandler.sendMessageDelayed(msg, ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); @@ -953,9 +953,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) { if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) { - powerLongPress(); + powerLongPress(event.getEventTime()); } else { - Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS); + Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS, + event.getEventTime()); msg.setAsynchronous(true); mHandler.sendMessageDelayed(msg, ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); @@ -1188,7 +1189,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { return 1; } - private void powerLongPress() { + private void powerLongPress(long eventTime) { final int behavior = getResolvedLongPressOnPowerBehavior(); switch (behavior) { case LONG_PRESS_POWER_NOTHING: @@ -1221,7 +1222,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false, "Power - Long Press - Go To Assistant"); final int powerKeyDeviceId = Integer.MIN_VALUE; - launchAssistAction(null, powerKeyDeviceId); + launchAssistAction(null, powerKeyDeviceId, eventTime); break; } } @@ -1624,7 +1625,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) { if (!keyguardOn) { // Post to main thread to avoid blocking input pipeline. - mHandler.post(() -> handleLongPressOnHome(event.getDeviceId())); + mHandler.post(() -> handleLongPressOnHome(event.getDeviceId(), + event.getEventTime())); } } return -1; @@ -1637,7 +1639,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } - private void handleLongPressOnHome(int deviceId) { + private void handleLongPressOnHome(int deviceId, long eventTime) { if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_NOTHING) { return; } @@ -1649,7 +1651,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { launchAllAppsAction(); break; case LONG_PRESS_HOME_ASSIST: - launchAssistAction(null, deviceId); + launchAssistAction(null, deviceId, eventTime); break; case LONG_PRESS_HOME_NOTIFICATION_PANEL: toggleNotificationPanel(); @@ -1789,8 +1791,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { com.android.internal.R.integer.config_lidKeyboardAccessibility); mLidNavigationAccessibility = mContext.getResources().getInteger( com.android.internal.R.integer.config_lidNavigationAccessibility); - mLidControlsDisplayFold = mContext.getResources().getBoolean( - com.android.internal.R.bool.config_lidControlsDisplayFold); mAllowTheaterModeWakeFromKey = mContext.getResources().getBoolean( com.android.internal.R.bool.config_allowTheaterModeWakeFromKey); @@ -1847,12 +1847,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { readConfigurationDependentBehaviors(); - if (mLidControlsDisplayFold) { - mDisplayFoldController = DisplayFoldController.create(context, DEFAULT_DISPLAY); - } else if (SystemProperties.getBoolean("persist.debug.force_foldable", false)) { - mDisplayFoldController = DisplayFoldController.createWithProxSensor(context, - DEFAULT_DISPLAY); - } + mDisplayFoldController = DisplayFoldController.create(context, DEFAULT_DISPLAY); mAccessibilityManager = (AccessibilityManager) context.getSystemService( Context.ACCESSIBILITY_SERVICE); @@ -2791,7 +2786,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (down) { mPendingMetaAction = true; } else if (mPendingMetaAction) { - launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD, event.getDeviceId()); + launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD, event.getDeviceId(), + event.getEventTime()); } return -1; } @@ -3134,7 +3130,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } - private int handleStartTransitionForKeyguardLw(boolean keyguardGoingAway, long duration) { + @Override + public int applyKeyguardOcclusionChange() { if (mKeyguardOccludedChanged) { if (DEBUG_KEYGUARD) Slog.d(TAG, "transition/occluded changed occluded=" + mPendingKeyguardOccluded); @@ -3143,6 +3140,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { return FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_WALLPAPER; } } + return 0; + } + + private int handleStartTransitionForKeyguardLw(boolean keyguardGoingAway, long duration) { + final int res = applyKeyguardOcclusionChange(); + if (res != 0) return res; if (keyguardGoingAway) { if (DEBUG_KEYGUARD) Slog.d(TAG, "Starting keyguard exit animation"); startKeyguardExitAnimation(SystemClock.uptimeMillis(), duration); @@ -3154,22 +3157,24 @@ public class PhoneWindowManager implements WindowManagerPolicy { // various parts of the UI. /** Asks the status bar to startAssist(), usually a full "assistant" interface */ - private void launchAssistAction(String hint, int deviceId) { + private void launchAssistAction(String hint, int deviceId, long eventTime) { sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST); if (!isUserSetupComplete()) { // Disable opening assist window during setup return; } + + // Add Intent Extra data. Bundle args = null; - if (deviceId > Integer.MIN_VALUE || hint != null) { - args = new Bundle(); - if (deviceId > Integer.MIN_VALUE) { - args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, deviceId); - } - if (hint != null) { - args.putBoolean(hint, true); - } + args = new Bundle(); + if (deviceId > Integer.MIN_VALUE) { + args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, deviceId); + } + if (hint != null) { + args.putBoolean(hint, true); } + args.putLong(Intent.EXTRA_TIME, eventTime); + ((SearchManager) mContext.createContextAsUser(UserHandle.of(mCurrentUserId), 0) .getSystemService(Context.SEARCH_SERVICE)).launchAssist(args); } @@ -3791,7 +3796,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { final boolean longPressed = event.getRepeatCount() > 0; if (down && !longPressed) { Message msg = mHandler.obtainMessage(MSG_LAUNCH_ASSIST, event.getDeviceId(), - 0 /* unused */, null /* hint */); + 0 /* unused */, event.getEventTime() /* eventTime */); msg.setAsynchronous(true); msg.sendToTarget(); } @@ -4012,9 +4017,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { return true; } - // Watches handle BACK specially + // Watches handle BACK and hardware buttons specially if (mHasFeatureWatch && (keyCode == KeyEvent.KEYCODE_BACK - || keyCode == KeyEvent.KEYCODE_STEM_PRIMARY)) { + || keyCode == KeyEvent.KEYCODE_STEM_PRIMARY + || keyCode == KeyEvent.KEYCODE_STEM_1 + || keyCode == KeyEvent.KEYCODE_STEM_2 + || keyCode == KeyEvent.KEYCODE_STEM_3)) { return false; } @@ -4853,9 +4861,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { private void applyLidSwitchState() { final int lidState = mDefaultDisplayPolicy.getLidState(); - if (mLidControlsDisplayFold && mDisplayFoldController != null) { - mDisplayFoldController.requestDeviceFolded(lidState == LID_CLOSED); - } else if (lidState == LID_CLOSED) { + if (lidState == LID_CLOSED) { int lidBehavior = getLidBehavior(); switch (lidBehavior) { case LID_BEHAVIOR_LOCK: diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java index 6934e5c3bcc1..977b31e6d683 100644 --- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java +++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java @@ -172,6 +172,9 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { */ void onKeyguardOccludedChangedLw(boolean occluded); + /** Applies a keyguard occlusion change if one happened. */ + int applyKeyguardOcclusionChange(); + /** * Interface to the Window Manager state associated with a particular * window. You can hold on to an instance of this interface from the call diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java index 8eb66cdee5cd..eea79f6eca95 100644 --- a/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java +++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java @@ -1138,6 +1138,7 @@ public class BatterySaverPolicy extends ContentObserver implements ipw.println(mLastDeviceConfigProperties.getString(key, null)); } } + ipw.decreaseIndent(); ipw.println("mAccessibilityEnabled=" + mAccessibilityEnabled.get()); ipw.println("mAutomotiveProjectionActive=" + mAutomotiveProjectionActive.get()); @@ -1191,7 +1192,7 @@ public class BatterySaverPolicy extends ContentObserver implements } private void dumpMap(PrintWriter pw, ArrayMap<String, String> map) { - if (map == null) { + if (map == null || map.size() == 0) { pw.println("N/A"); return; } diff --git a/services/core/java/com/android/server/powerstats/OWNERS b/services/core/java/com/android/server/powerstats/OWNERS index d68066bb8c40..c22f6a4bbbf6 100644 --- a/services/core/java/com/android/server/powerstats/OWNERS +++ b/services/core/java/com/android/server/powerstats/OWNERS @@ -1 +1,2 @@ +include /BATTERY_STATS_OWNERS include /services/core/java/com/android/server/power/OWNERS diff --git a/services/core/java/com/android/server/recoverysystem/OWNERS b/services/core/java/com/android/server/recoverysystem/OWNERS new file mode 100644 index 000000000000..79ded0dfba77 --- /dev/null +++ b/services/core/java/com/android/server/recoverysystem/OWNERS @@ -0,0 +1,2 @@ +rvrolyk@google.com +zhaojiac@google.com diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java index 192a00303a30..bd66aa39b8d2 100644 --- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java +++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java @@ -1316,7 +1316,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub implements Rollba private SparseIntArray getExtensionVersions() { // This list must be updated whenever the current API level is increased, or should be // replaced when we have another way of determining the relevant SDK versions. - final int[] relevantSdkVersions = { Build.VERSION_CODES.R }; + final int[] relevantSdkVersions = { Build.VERSION_CODES.R, Build.VERSION_CODES.S }; SparseIntArray result = new SparseIntArray(relevantSdkVersions.length); for (int i = 0; i < relevantSdkVersions.length; i++) { diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java index cf20cf4c0c9f..ac3816e7ea2d 100644 --- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java +++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java @@ -31,6 +31,7 @@ import static android.net.NetworkTemplate.buildTemplateMobileWithRatType; import static android.net.NetworkTemplate.buildTemplateWifiWildcard; import static android.net.NetworkTemplate.getAllCollapsedRatTypes; import static android.os.Debug.getIonHeapsSizeKb; +import static android.os.Process.LAST_SHARED_APPLICATION_GID; import static android.os.Process.getUidForPid; import static android.os.storage.VolumeInfo.TYPE_PRIVATE; import static android.os.storage.VolumeInfo.TYPE_PUBLIC; @@ -168,7 +169,6 @@ import com.android.server.stats.pull.netstats.SubInfo; import com.android.server.storage.DiskStatsFileLogger; import com.android.server.storage.DiskStatsLoggingService; -import java.util.concurrent.ExecutionException; import libcore.io.IoUtils; import org.json.JSONArray; @@ -191,6 +191,7 @@ import java.util.Random; import java.util.Set; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; @@ -1517,14 +1518,53 @@ public class StatsPullAtomService extends SystemService { } int pullCpuTimePerUidFreqLocked(int atomTag, List<StatsEvent> pulledData) { + // Aggregate times for the same uids. + SparseArray<long[]> aggregated = new SparseArray<>(); mCpuUidFreqTimeReader.readAbsolute((uid, cpuFreqTimeMs) -> { - for (int freqIndex = 0; freqIndex < cpuFreqTimeMs.length; ++freqIndex) { - if (cpuFreqTimeMs[freqIndex] >= MIN_CPU_TIME_PER_UID_FREQ) { - pulledData.add(FrameworkStatsLog.buildStatsEvent( - atomTag, uid, freqIndex, cpuFreqTimeMs[freqIndex])); + // For uids known to be aggregated from many entries allow mutating in place to avoid + // many copies. Otherwise, copy before aggregating. + boolean mutateInPlace = false; + if (UserHandle.isIsolated(uid)) { + // Skip individual isolated uids because they are recycled and quickly removed from + // the underlying data source. + return; + } else if (UserHandle.isSharedAppGid(uid)) { + // All shared app gids are accounted together. + uid = LAST_SHARED_APPLICATION_GID; + mutateInPlace = true; + } else { + // Everything else is accounted under their base uid. + uid = UserHandle.getAppId(uid); + } + + long[] aggCpuFreqTimeMs = aggregated.get(uid); + if (aggCpuFreqTimeMs != null) { + if (!mutateInPlace) { + aggCpuFreqTimeMs = Arrays.copyOf(aggCpuFreqTimeMs, cpuFreqTimeMs.length); + aggregated.put(uid, aggCpuFreqTimeMs); } + for (int freqIndex = 0; freqIndex < cpuFreqTimeMs.length; ++freqIndex) { + aggCpuFreqTimeMs[freqIndex] += cpuFreqTimeMs[freqIndex]; + } + } else { + if (mutateInPlace) { + cpuFreqTimeMs = Arrays.copyOf(cpuFreqTimeMs, cpuFreqTimeMs.length); + } + aggregated.put(uid, cpuFreqTimeMs); } }); + + int size = aggregated.size(); + for (int i = 0; i < size; ++i) { + int uid = aggregated.keyAt(i); + long[] aggCpuFreqTimeMs = aggregated.valueAt(i); + for (int freqIndex = 0; freqIndex < aggCpuFreqTimeMs.length; ++freqIndex) { + if (aggCpuFreqTimeMs[freqIndex] >= MIN_CPU_TIME_PER_UID_FREQ) { + pulledData.add(FrameworkStatsLog.buildStatsEvent( + atomTag, uid, freqIndex, aggCpuFreqTimeMs[freqIndex])); + } + } + } return StatsManager.PULL_SUCCESS; } diff --git a/services/core/java/com/android/server/timedetector/OWNERS b/services/core/java/com/android/server/timedetector/OWNERS index 09447a971bdd..8f8089717e3b 100644 --- a/services/core/java/com/android/server/timedetector/OWNERS +++ b/services/core/java/com/android/server/timedetector/OWNERS @@ -1 +1,3 @@ -include /core/java/android/app/timezone/OWNERS +# Bug component: 847766 +mingaleev@google.com +include /core/java/android/app/timedetector/OWNERS diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorService.java b/services/core/java/com/android/server/timedetector/TimeDetectorService.java index 7de0e87f91c3..c7fe20415511 100644 --- a/services/core/java/com/android/server/timedetector/TimeDetectorService.java +++ b/services/core/java/com/android/server/timedetector/TimeDetectorService.java @@ -18,6 +18,7 @@ package com.android.server.timedetector; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.timedetector.GnssTimeSuggestion; import android.app.timedetector.ITimeDetectorService; import android.app.timedetector.ManualTimeSuggestion; import android.app.timedetector.NetworkTimeSuggestion; @@ -129,6 +130,14 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub { mHandler.post(() -> mTimeDetectorStrategy.suggestNetworkTime(timeSignal)); } + @Override + public void suggestGnssTime(@NonNull GnssTimeSuggestion timeSignal) { + enforceSuggestGnssTimePermission(); + Objects.requireNonNull(timeSignal); + + mHandler.post(() -> mTimeDetectorStrategy.suggestGnssTime(timeSignal)); + } + /** Internal method for handling the auto time setting being changed. */ @VisibleForTesting public void handleAutoTimeDetectionChanged() { @@ -162,4 +171,10 @@ public final class TimeDetectorService extends ITimeDetectorService.Stub { android.Manifest.permission.SET_TIME, "set time"); } + + private void enforceSuggestGnssTimePermission() { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.SET_TIME, + "suggest gnss time"); + } } diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java index f278ef68c536..b539f013d6d3 100644 --- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java +++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategy.java @@ -18,6 +18,7 @@ package com.android.server.timedetector; import android.annotation.IntDef; import android.annotation.NonNull; +import android.app.timedetector.GnssTimeSuggestion; import android.app.timedetector.ManualTimeSuggestion; import android.app.timedetector.NetworkTimeSuggestion; import android.app.timedetector.TelephonyTimeSuggestion; @@ -41,7 +42,7 @@ import java.lang.annotation.RetentionPolicy; */ public interface TimeDetectorStrategy extends Dumpable { - @IntDef({ ORIGIN_TELEPHONY, ORIGIN_MANUAL, ORIGIN_NETWORK }) + @IntDef({ ORIGIN_TELEPHONY, ORIGIN_MANUAL, ORIGIN_NETWORK, ORIGIN_GNSS }) @Retention(RetentionPolicy.SOURCE) @interface Origin {} @@ -57,6 +58,10 @@ public interface TimeDetectorStrategy extends Dumpable { @Origin int ORIGIN_NETWORK = 3; + /** Used when a time value originated from a gnss signal. */ + @Origin + int ORIGIN_GNSS = 4; + /** Processes the suggested time from telephony sources. */ void suggestTelephonyTime(@NonNull TelephonyTimeSuggestion timeSuggestion); @@ -71,6 +76,9 @@ public interface TimeDetectorStrategy extends Dumpable { /** Processes the suggested time from network sources. */ void suggestNetworkTime(@NonNull NetworkTimeSuggestion timeSuggestion); + /** Processes the suggested time from gnss sources. */ + void suggestGnssTime(@NonNull GnssTimeSuggestion timeSuggestion); + /** * Handles the auto-time configuration changing For example, when the auto-time setting is * toggled on or off. @@ -100,6 +108,8 @@ public interface TimeDetectorStrategy extends Dumpable { return "network"; case ORIGIN_TELEPHONY: return "telephony"; + case ORIGIN_GNSS: + return "gnss"; default: throw new IllegalArgumentException("origin=" + origin); } @@ -117,6 +127,8 @@ public interface TimeDetectorStrategy extends Dumpable { return ORIGIN_NETWORK; case "telephony": return ORIGIN_TELEPHONY; + case "gnss": + return ORIGIN_GNSS; default: throw new IllegalArgumentException("originString=" + originString); } diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java index b5d49cfbe9c8..48af81e5c59c 100644 --- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java +++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java @@ -23,6 +23,7 @@ import static java.util.stream.Collectors.joining; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.AlarmManager; +import android.app.timedetector.GnssTimeSuggestion; import android.app.timedetector.ManualTimeSuggestion; import android.app.timedetector.NetworkTimeSuggestion; import android.app.timedetector.TelephonyTimeSuggestion; @@ -108,6 +109,10 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy { private final ReferenceWithHistory<NetworkTimeSuggestion> mLastNetworkSuggestion = new ReferenceWithHistory<>(KEEP_SUGGESTION_HISTORY_SIZE); + @GuardedBy("this") + private final ReferenceWithHistory<GnssTimeSuggestion> mLastGnssSuggestion = + new ReferenceWithHistory<>(KEEP_SUGGESTION_HISTORY_SIZE); + /** * The interface used by the strategy to interact with the surrounding service. * @@ -165,6 +170,20 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy { } @Override + public synchronized void suggestGnssTime(@NonNull GnssTimeSuggestion timeSuggestion) { + final TimestampedValue<Long> newUtcTime = timeSuggestion.getUtcTime(); + + if (!validateAutoSuggestionTime(newUtcTime, timeSuggestion)) { + return; + } + + mLastGnssSuggestion.set(timeSuggestion); + + String reason = "GNSS time suggestion received: suggestion=" + timeSuggestion; + doAutoTimeDetection(reason); + } + + @Override public synchronized boolean suggestManualTime(@NonNull ManualTimeSuggestion suggestion) { final TimestampedValue<Long> newUtcTime = suggestion.getUtcTime(); @@ -278,6 +297,11 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy { mLastNetworkSuggestion.dump(ipw); ipw.decreaseIndent(); // level 2 + ipw.println("Gnss suggestion history:"); + ipw.increaseIndent(); // level 2 + mLastGnssSuggestion.dump(ipw); + ipw.decreaseIndent(); // level 2 + ipw.decreaseIndent(); // level 1 } @@ -383,6 +407,14 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy { + ", networkSuggestion=" + networkSuggestion + ", detectionReason=" + detectionReason; } + } else if (origin == ORIGIN_GNSS) { + GnssTimeSuggestion gnssTimeSuggestion = findLatestValidGnssSuggestion(); + if (gnssTimeSuggestion != null) { + newUtcTime = gnssTimeSuggestion.getUtcTime(); + cause = "Found good gnss suggestion." + + ", gnssTimeSuggestion=" + gnssTimeSuggestion + + ", detectionReason=" + detectionReason; + } } else { Slog.w(LOG_TAG, "Unknown or unsupported origin=" + origin + " in " + Arrays.toString(originPriorities) @@ -524,6 +556,26 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy { return networkSuggestion; } + /** Returns the latest, valid, gnss suggestion. Returns {@code null} if there isn't one. */ + @GuardedBy("this") + @Nullable + private GnssTimeSuggestion findLatestValidGnssSuggestion() { + GnssTimeSuggestion gnssTimeSuggestion = mLastGnssSuggestion.get(); + if (gnssTimeSuggestion == null) { + // No gnss suggestions received. This is normal if there's no gnss signal. + return null; + } + + TimestampedValue<Long> utcTime = gnssTimeSuggestion.getUtcTime(); + long elapsedRealTimeMillis = mCallback.elapsedRealtimeMillis(); + if (!validateSuggestionUtcTime(elapsedRealTimeMillis, utcTime)) { + // The latest suggestion is not valid, usually due to its age. + return null; + } + + return gnssTimeSuggestion; + } + @GuardedBy("this") private boolean setSystemClockIfRequired( @Origin int origin, @NonNull TimestampedValue<Long> time, @NonNull String cause) { @@ -652,6 +704,16 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy { } /** + * Returns the latest valid gnss suggestion. Not intended for general use: it is used during + * tests to check strategy behavior. + */ + @VisibleForTesting + @Nullable + public synchronized GnssTimeSuggestion findLatestValidGnssSuggestionForTests() { + return findLatestValidGnssSuggestion(); + } + + /** * A method used to inspect state during tests. Not intended for general use. */ @VisibleForTesting @@ -669,6 +731,15 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy { return mLastNetworkSuggestion.get(); } + /** + * A method used to inspect state during tests. Not intended for general use. + */ + @VisibleForTesting + @Nullable + public synchronized GnssTimeSuggestion getLatestGnssSuggestion() { + return mLastGnssSuggestion.get(); + } + private static boolean validateSuggestionUtcTime( long elapsedRealtimeMillis, TimestampedValue<Long> utcTime) { long referenceTimeMillis = utcTime.getReferenceTimeMillis(); diff --git a/services/core/java/com/android/server/timezone/OWNERS b/services/core/java/com/android/server/timezone/OWNERS index 09447a971bdd..8f8089717e3b 100644 --- a/services/core/java/com/android/server/timezone/OWNERS +++ b/services/core/java/com/android/server/timezone/OWNERS @@ -1 +1,3 @@ -include /core/java/android/app/timezone/OWNERS +# Bug component: 847766 +mingaleev@google.com +include /core/java/android/app/timedetector/OWNERS diff --git a/services/core/java/com/android/server/timezonedetector/OWNERS b/services/core/java/com/android/server/timezonedetector/OWNERS index 09447a971bdd..8f8089717e3b 100644 --- a/services/core/java/com/android/server/timezonedetector/OWNERS +++ b/services/core/java/com/android/server/timezonedetector/OWNERS @@ -1 +1,3 @@ -include /core/java/android/app/timezone/OWNERS +# Bug component: 847766 +mingaleev@google.com +include /core/java/android/app/timedetector/OWNERS diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java index 1754e593914d..ff5b65b61807 100755 --- a/services/core/java/com/android/server/tv/TvInputManagerService.java +++ b/services/core/java/com/android/server/tv/TvInputManagerService.java @@ -77,6 +77,7 @@ import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.UserHandle; import android.text.TextUtils; +import android.util.ArrayMap; import android.util.Pair; import android.util.Slog; import android.util.SparseArray; @@ -100,6 +101,7 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -329,18 +331,27 @@ public final class TvInputManagerService extends SystemService { userState.packageSet.add(si.packageName); } + // sort the input list by input id so that TvInputState.inputNumber is stable. + Collections.sort(inputList, Comparator.comparing(TvInputInfo::getId)); Map<String, TvInputState> inputMap = new HashMap<>(); + ArrayMap<String, Integer> tisInputCount = new ArrayMap<>(inputMap.size()); for (TvInputInfo info : inputList) { + String inputId = info.getId(); if (DEBUG) { - Slog.d(TAG, "add " + info.getId()); + Slog.d(TAG, "add " + inputId); } - TvInputState inputState = userState.inputMap.get(info.getId()); + // Running count of input for each input service + Integer count = tisInputCount.get(inputId); + count = count == null ? Integer.valueOf(1) : count + 1; + tisInputCount.put(inputId, count); + TvInputState inputState = userState.inputMap.get(inputId); if (inputState == null) { inputState = new TvInputState(); } inputState.info = info; inputState.uid = getInputUid(info); - inputMap.put(info.getId(), inputState); + inputMap.put(inputId, inputState); + inputState.inputNumber = count; } for (String inputId : inputMap.keySet()) { @@ -2452,11 +2463,31 @@ public final class TvInputManagerService extends SystemService { */ private void logTuneStateChanged(int state, SessionState sessionState, @Nullable TvInputState inputState) { - // TODO(b/173536904): log input type and id + int tisUid = Process.INVALID_UID; + int inputType = FrameworkStatsLog.TIF_TUNE_STATE_CHANGED__TYPE__TIF_INPUT_TYPE_UNKNOWN; + int inputId = 0; + int hdmiPort = 0; + if (inputState != null) { + tisUid = inputState.uid; + inputType = inputState.info.getType(); + if (inputType == TvInputInfo.TYPE_TUNER) { + inputType = FrameworkStatsLog.TIF_TUNE_STATE_CHANGED__TYPE__TUNER; + } + inputId = inputState.inputNumber; + HdmiDeviceInfo hdmiDeviceInfo = inputState.info.getHdmiDeviceInfo(); + if (hdmiDeviceInfo != null) { + hdmiPort = hdmiDeviceInfo.getPortId(); + } + } FrameworkStatsLog.write(FrameworkStatsLog.TIF_TUNE_CHANGED, new int[]{sessionState.callingUid, - inputState == null ? Process.INVALID_UID : inputState.uid}, - new String[]{"tif_player", "tv_input_service"}, state, sessionState.sessionId); + tisUid}, + new String[]{"tif_player", "tv_input_service"}, + state, + sessionState.sessionId, + inputType, + inputId, + hdmiPort); } private static final class UserState { @@ -2569,6 +2600,11 @@ public final class TvInputManagerService extends SystemService { private TvInputInfo info; /** + * ID unique to a specific TvInputService. + */ + private int inputNumber; + + /** * The kernel user-ID that has been assigned to the application the TvInput is a part of. * * <p> diff --git a/services/core/java/com/android/server/vibrator/Vibration.java b/services/core/java/com/android/server/vibrator/Vibration.java index e2cdd02deab9..b0266d025c08 100644 --- a/services/core/java/com/android/server/vibrator/Vibration.java +++ b/services/core/java/com/android/server/vibrator/Vibration.java @@ -47,7 +47,7 @@ public class Vibration { FINISHED, FORWARDED_TO_INPUT_DEVICES, CANCELLED, - ERROR_APP_OPS, + IGNORED_ERROR_APP_OPS, IGNORED, IGNORED_APP_OPS, IGNORED_BACKGROUND, diff --git a/services/core/java/com/android/server/vibrator/VibrationSettings.java b/services/core/java/com/android/server/vibrator/VibrationSettings.java index 6a5d1c4173c9..a34a50737ec5 100644 --- a/services/core/java/com/android/server/vibrator/VibrationSettings.java +++ b/services/core/java/com/android/server/vibrator/VibrationSettings.java @@ -16,12 +16,18 @@ package com.android.server.vibrator; +import android.app.ActivityManager; +import android.app.IUidObserver; import android.content.Context; import android.content.res.Resources; import android.database.ContentObserver; import android.media.AudioManager; import android.net.Uri; import android.os.Handler; +import android.os.PowerManager; +import android.os.PowerManagerInternal; +import android.os.PowerSaveState; +import android.os.RemoteException; import android.os.UserHandle; import android.os.VibrationAttributes; import android.os.VibrationEffect; @@ -30,7 +36,7 @@ import android.provider.Settings; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; -import com.android.internal.annotations.VisibleForTesting; +import com.android.server.LocalServices; import java.util.ArrayList; import java.util.List; @@ -53,6 +59,7 @@ public final class VibrationSettings { private final Vibrator mVibrator; private final AudioManager mAudioManager; private final SettingsObserver mSettingObserver; + private final UidObserver mUidObserver; @GuardedBy("mLock") private final List<OnVibratorSettingsChanged> mListeners = new ArrayList<>(); @@ -72,12 +79,15 @@ public final class VibrationSettings { private int mNotificationIntensity; @GuardedBy("mLock") private int mRingIntensity; + @GuardedBy("mLock") + private boolean mLowPowerMode; public VibrationSettings(Context context, Handler handler) { mContext = context; mVibrator = context.getSystemService(Vibrator.class); mAudioManager = context.getSystemService(AudioManager.class); mSettingObserver = new SettingsObserver(handler); + mUidObserver = new UidObserver(); registerSettingsObserver(Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES)); registerSettingsObserver(Settings.System.getUriFor(Settings.System.VIBRATE_WHEN_RINGING)); @@ -107,6 +117,35 @@ public final class VibrationSettings { mFallbackEffects.put(VibrationEffect.EFFECT_TEXTURE_TICK, VibrationEffect.get(VibrationEffect.EFFECT_TICK, false)); + try { + ActivityManager.getService().registerUidObserver(mUidObserver, + ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_GONE, + ActivityManager.PROCESS_STATE_UNKNOWN, null); + } catch (RemoteException e) { + // ignored; both services live in system_server + } + + PowerManagerInternal pm = LocalServices.getService(PowerManagerInternal.class); + pm.registerLowPowerModeObserver( + new PowerManagerInternal.LowPowerModeListener() { + @Override + public int getServiceType() { + return PowerManager.ServiceType.VIBRATION; + } + + @Override + public void onLowPowerModeChanged(PowerSaveState result) { + boolean shouldNotifyListeners; + synchronized (mLock) { + shouldNotifyListeners = result.batterySaverEnabled != mLowPowerMode; + mLowPowerMode = result.batterySaverEnabled; + } + if (shouldNotifyListeners) { + notifyListeners(); + } + } + }); + // Update with current values from settings. updateSettings(); } @@ -184,12 +223,15 @@ public final class VibrationSettings { } /** - * Return {@code true} if the device should vibrate for ringtones. + * Return {@code true} if the device should vibrate for current ringer mode. * * <p>This checks the current {@link AudioManager#getRingerModeInternal()} against user settings - * for vibrations while ringing. + * for ringtone usage only. All other usages are allowed independently of ringer mode. */ - public boolean shouldVibrateForRingtone() { + public boolean shouldVibrateForRingerMode(int usageHint) { + if (!isRingtone(usageHint)) { + return true; + } int ringerMode = mAudioManager.getRingerModeInternal(); synchronized (mLock) { if (mVibrateWhenRinging) { @@ -202,6 +244,28 @@ public final class VibrationSettings { } } + /** + * Returns {@code true} if this vibration is allowed for given {@code uid}. + * + * <p>This checks if the user is aware of this foreground process, or if the vibration usage is + * allowed to play in the background (i.e. it's a notification, ringtone or alarm vibration). + */ + public boolean shouldVibrateForUid(int uid, int usageHint) { + return mUidObserver.isUidForeground(uid) || isNotification(usageHint) + || isRingtone(usageHint) || isAlarm(usageHint); + } + + /** + * Returns {@code true} if this vibration is allowed for current power mode state. + * + * <p>This checks if the device is in battery saver mode, in which case only alarm, ringtone and + * {@link VibrationAttributes#USAGE_COMMUNICATION_REQUEST} usages are allowed to vibrate. + */ + public boolean shouldVibrateForPowerMode(int usageHint) { + return !mLowPowerMode || isRingtone(usageHint) || isAlarm(usageHint) + || usageHint == VibrationAttributes.USAGE_COMMUNICATION_REQUEST; + } + /** Return {@code true} if input devices should vibrate instead of this device. */ public boolean shouldVibrateInputDevices() { return mVibrateInputDevices; @@ -229,9 +293,7 @@ public final class VibrationSettings { } /** Updates all vibration settings and triggers registered listeners. */ - @VisibleForTesting public void updateSettings() { - List<OnVibratorSettingsChanged> currentListeners; synchronized (mLock) { mVibrateWhenRinging = getSystemSetting(Settings.System.VIBRATE_WHEN_RINGING, 0) != 0; mApplyRampingRinger = getGlobalSetting(Settings.Global.APPLY_RAMPING_RINGER, 0) != 0; @@ -244,12 +306,8 @@ public final class VibrationSettings { mVibrator.getDefaultRingVibrationIntensity()); mVibrateInputDevices = getSystemSetting(Settings.System.VIBRATE_INPUT_DEVICES, 0) > 0; mZenMode = getGlobalSetting(Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF); - currentListeners = new ArrayList<>(mListeners); - } - - for (OnVibratorSettingsChanged listener : currentListeners) { - listener.onChange(); } + notifyListeners(); } @Override @@ -258,9 +316,11 @@ public final class VibrationSettings { + "mVibrateInputDevices=" + mVibrateInputDevices + ", mVibrateWhenRinging=" + mVibrateWhenRinging + ", mApplyRampingRinger=" + mApplyRampingRinger + + ", mLowPowerMode=" + mLowPowerMode + ", mZenMode=" + Settings.Global.zenModeToString(mZenMode) + + ", mProcStatesCache=" + mUidObserver.mProcStatesCache + ", mHapticFeedbackIntensity=" - + intensityToString(getCurrentIntensity(VibrationAttributes.USAGE_TOUCH)) + + intensityToString(getCurrentIntensity(VibrationAttributes.USAGE_TOUCH)) + ", mHapticFeedbackDefaultIntensity=" + intensityToString(getDefaultIntensity(VibrationAttributes.USAGE_TOUCH)) + ", mNotificationIntensity=" @@ -274,6 +334,16 @@ public final class VibrationSettings { + '}'; } + private void notifyListeners() { + List<OnVibratorSettingsChanged> currentListeners; + synchronized (mLock) { + currentListeners = new ArrayList<>(mListeners); + } + for (OnVibratorSettingsChanged listener : currentListeners) { + listener.onChange(); + } + } + private static String intensityToString(int intensity) { switch (intensity) { case Vibrator.VIBRATION_INTENSITY_OFF: @@ -342,4 +412,36 @@ public final class VibrationSettings { updateSettings(); } } + + /** Implementation of {@link ContentObserver} to be registered to a setting {@link Uri}. */ + private final class UidObserver extends IUidObserver.Stub { + private final SparseArray<Integer> mProcStatesCache = new SparseArray<>(); + + public boolean isUidForeground(int uid) { + return mProcStatesCache.get(uid, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) + <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; + } + + @Override + public void onUidGone(int uid, boolean disabled) { + mProcStatesCache.delete(uid); + } + + @Override + public void onUidActive(int uid) { + } + + @Override + public void onUidIdle(int uid, boolean disabled) { + } + + @Override + public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) { + mProcStatesCache.put(uid, procState); + } + + @Override + public void onUidCachedChanged(int uid, boolean cached) { + } + } } diff --git a/services/core/java/com/android/server/vibrator/VibratorController.java b/services/core/java/com/android/server/vibrator/VibratorController.java index f76c1a1b2b9d..311c73bcb19f 100644 --- a/services/core/java/com/android/server/vibrator/VibratorController.java +++ b/services/core/java/com/android/server/vibrator/VibratorController.java @@ -23,7 +23,7 @@ import android.os.IVibratorStateListener; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.VibrationEffect; -import android.os.Vibrator; +import android.os.VibratorInfo; import android.util.Slog; import com.android.internal.annotations.GuardedBy; @@ -31,10 +31,6 @@ import com.android.internal.annotations.VisibleForTesting; import libcore.util.NativeAllocationRegistry; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; - /** Controls a single vibrator. */ // TODO(b/159207608): Make this package-private once vibrator services are moved to this package public final class VibratorController { @@ -42,12 +38,7 @@ public final class VibratorController { private final Object mLock = new Object(); private final NativeWrapper mNativeWrapper; - private final int mVibratorId; - private final long mCapabilities; - @Nullable - private final Set<Integer> mSupportedEffects; - @Nullable - private final Set<Integer> mSupportedPrimitives; + private final VibratorInfo mVibratorInfo; @GuardedBy("mLock") private final RemoteCallbackList<IVibratorStateListener> mVibratorStateListeners = @@ -115,13 +106,11 @@ public final class VibratorController { @VisibleForTesting public VibratorController(int vibratorId, OnVibrationCompleteListener listener, NativeWrapper nativeWrapper) { - mVibratorId = vibratorId; mNativeWrapper = nativeWrapper; + mNativeWrapper.init(vibratorId, listener); - nativeWrapper.init(vibratorId, listener); - mCapabilities = nativeWrapper.getCapabilities(); - mSupportedEffects = asSet(nativeWrapper.getSupportedEffects()); - mSupportedPrimitives = asSet(nativeWrapper.getSupportedPrimitives()); + mVibratorInfo = new VibratorInfo(vibratorId, nativeWrapper.getCapabilities(), + nativeWrapper.getSupportedEffects(), nativeWrapper.getSupportedPrimitives()); } /** Register state listener for this vibrator. */ @@ -153,9 +142,9 @@ public final class VibratorController { } } - /** Return the id of the vibrator controlled by this instance. */ - public int getVibratorId() { - return mVibratorId; + /** Return the {@link VibratorInfo} representing the vibrator controlled by this instance. */ + public VibratorInfo getVibratorInfo() { + return mVibratorInfo; } /** @@ -184,43 +173,7 @@ public final class VibratorController { * @return true if this vibrator has this capability, false otherwise */ public boolean hasCapability(long capability) { - return (mCapabilities & capability) == capability; - } - - /** - * Check against this vibrator supported effects. - * - * @param effectIds list of effects, one of VibrationEffect.EFFECT_* - * @return one entry per requested effectId, with one of Vibrator.VIBRATION_EFFECT_SUPPORT_* - */ - public int[] areEffectsSupported(int[] effectIds) { - int[] supported = new int[effectIds.length]; - if (mSupportedEffects == null) { - Arrays.fill(supported, Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN); - } else { - for (int i = 0; i < effectIds.length; i++) { - supported[i] = mSupportedEffects.contains(effectIds[i]) - ? Vibrator.VIBRATION_EFFECT_SUPPORT_YES - : Vibrator.VIBRATION_EFFECT_SUPPORT_NO; - } - } - return supported; - } - - /** - * Check against this vibrator supported primitives. - * - * @param primitiveIds list of primitives, one of VibrationEffect.Composition.EFFECT_* - * @return one entry per requested primitiveId, with true if it is supported - */ - public boolean[] arePrimitivesSupported(int[] primitiveIds) { - boolean[] supported = new boolean[primitiveIds.length]; - if (mSupportedPrimitives != null && hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) { - for (int i = 0; i < primitiveIds.length; i++) { - supported[i] = mSupportedPrimitives.contains(primitiveIds[i]); - } - } - return supported; + return mVibratorInfo.hasCapability(capability); } /** Return {@code true} if the underlying vibrator is currently available, false otherwise. */ @@ -234,7 +187,7 @@ public final class VibratorController { * <p>This will affect the state of {@link #isUnderExternalControl()}. */ public void setExternalControl(boolean externalControl) { - if (!hasCapability(IVibrator.CAP_EXTERNAL_CONTROL)) { + if (!mVibratorInfo.hasCapability(IVibrator.CAP_EXTERNAL_CONTROL)) { return; } synchronized (mLock) { @@ -248,7 +201,7 @@ public final class VibratorController { * if given {@code effect} is {@code null}. */ public void updateAlwaysOn(int id, @Nullable VibrationEffect.Prebaked effect) { - if (!hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) { + if (!mVibratorInfo.hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) { return; } synchronized (mLock) { @@ -263,7 +216,7 @@ public final class VibratorController { /** Set the vibration amplitude. This will NOT affect the state of {@link #isVibrating()}. */ public void setAmplitude(int amplitude) { synchronized (mLock) { - if (hasCapability(IVibrator.CAP_AMPLITUDE_CONTROL)) { + if (mVibratorInfo.hasCapability(IVibrator.CAP_AMPLITUDE_CONTROL)) { mNativeWrapper.setAmplitude(amplitude); } } @@ -306,7 +259,7 @@ public final class VibratorController { * <p>This will affect the state of {@link #isVibrating()}. */ public void on(VibrationEffect.Composed effect, long vibrationId) { - if (!hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) { + if (!mVibratorInfo.hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) { return; } synchronized (mLock) { @@ -327,10 +280,7 @@ public final class VibratorController { @Override public String toString() { return "VibratorController{" - + "mVibratorId=" + mVibratorId - + ", mCapabilities=" + mCapabilities - + ", mSupportedEffects=" + mSupportedEffects - + ", mSupportedPrimitives=" + mSupportedPrimitives + + "mVibratorInfo=" + mVibratorInfo + ", mIsVibrating=" + mIsVibrating + ", mIsUnderExternalControl=" + mIsUnderExternalControl + ", mVibratorStateListeners count=" @@ -375,18 +325,6 @@ public final class VibratorController { } } - @Nullable - private static Set<Integer> asSet(int[] values) { - if (values == null) { - return null; - } - HashSet<Integer> set = new HashSet<>(); - for (int value : values) { - set.add(value); - } - return set; - } - /** Wrapper around the static-native methods of {@link VibratorController} for tests. */ @VisibleForTesting public static class NativeWrapper { diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java index 9f1152c8e371..85fcd3dbe501 100644 --- a/services/core/java/com/android/server/wm/ActivityClientController.java +++ b/services/core/java/com/android/server/wm/ActivityClientController.java @@ -538,6 +538,22 @@ class ActivityClientController extends IActivityClientController.Stub { } @Override + public int getLaunchedFromUid(IBinder token) { + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.forTokenLocked(token); + return r != null ? r.launchedFromUid : android.os.Process.INVALID_UID; + } + } + + @Override + public String getLaunchedFromPackage(IBinder token) { + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.forTokenLocked(token); + return r != null ? r.launchedFromPackage : null; + } + } + + @Override public Bundle getActivityOptions(IBinder token) { final long origId = Binder.clearCallingIdentity(); try { diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java index 6a50b793de0f..b0847879f456 100644 --- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java @@ -631,6 +631,10 @@ class ActivityMetricsLogger { if (info.mLoggedTransitionStarting && info.allDrawn()) { done(false /* abort */, info, "notifyWindowsDrawn - all windows drawn", timestampNs); } + if (r.mWmService.isRecentsAnimationTarget(r)) { + r.mWmService.getRecentsAnimationController().logRecentsAnimationStartTime( + info.mSourceEventDelayMs + info.mWindowsDrawnDelayMs); + } return infoSnapshot; } diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 113f4d856bdd..4c18310df226 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -95,18 +95,18 @@ import static android.view.Display.COLOR_MODE_DEFAULT; import static android.view.Display.INVALID_DISPLAY; import static android.view.Surface.ROTATION_270; import static android.view.Surface.ROTATION_90; -import static android.view.WindowManager.TRANSIT_CLOSE; -import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_CLOSE; -import static android.view.WindowManager.TRANSIT_OLD_TASK_CLOSE; -import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN_BEHIND; -import static android.view.WindowManager.TRANSIT_OLD_UNSET; +import static android.view.SurfaceControl.getGlobalTransaction; import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; +import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_FLAG_OPEN_BEHIND; +import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_CLOSE; +import static android.view.WindowManager.TRANSIT_OLD_TASK_CLOSE; +import static android.view.WindowManager.TRANSIT_OLD_UNSET; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS; @@ -182,7 +182,6 @@ import static com.android.server.wm.IdentifierProto.USER_ID; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION; -import static com.android.server.wm.Task.TASK_VISIBILITY_VISIBLE; import static com.android.server.wm.Task.ActivityState.DESTROYED; import static com.android.server.wm.Task.ActivityState.DESTROYING; import static com.android.server.wm.Task.ActivityState.FINISHING; @@ -194,6 +193,7 @@ import static com.android.server.wm.Task.ActivityState.RESUMED; import static com.android.server.wm.Task.ActivityState.STARTED; import static com.android.server.wm.Task.ActivityState.STOPPED; import static com.android.server.wm.Task.ActivityState.STOPPING; +import static com.android.server.wm.Task.TASK_VISIBILITY_VISIBLE; import static com.android.server.wm.TaskPersister.DEBUG; import static com.android.server.wm.TaskPersister.IMAGE_EXTENSION; import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN; @@ -1366,19 +1366,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } else if (mLetterbox != null) { mLetterbox.hide(); } - maybeUpdateLetterboxInTaskOrganizer(w); - } - - private void maybeUpdateLetterboxInTaskOrganizer(WindowState w) { - boolean isLetterboxed = w.isLetterboxedAppWindow() && fillsParent(); - if (!isLetterboxed) { - task.maybeUpdateLetterboxInTaskOrganizer( - this, /* activityBounds= */ null, /* activityInsets= */ null); - return; - } - final Rect insets = w.getInsetsStateWithVisibilityOverride().calculateInsets( - getBounds(), Type.systemBars(), false /* ignoreVisibility */); - task.maybeUpdateLetterboxInTaskOrganizer(this, getBounds(), insets); } void updateLetterboxSurface(WindowState winHint) { @@ -2568,7 +2555,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } final Task rootTask = getRootTask(); - final boolean mayAdjustTop = (isState(RESUMED) || rootTask.mResumedActivity == null) + final boolean mayAdjustTop = (isState(RESUMED) || rootTask.getResumedActivity() == null) && rootTask.isFocusedStackOnDisplay() // Do not adjust focus task because the task will be reused to launch new activity. && !task.isClearingToReuseTask(); @@ -2640,12 +2627,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // Tell window manager to prepare for this one to be removed. setVisibility(false); - if (rootTask.mPausingActivity == null) { + if (task.getPausingActivity() == null) { ProtoLog.v(WM_DEBUG_STATES, "Finish needs to pause: %s", this); if (DEBUG_USER_LEAVING) { Slog.v(TAG_USER_LEAVING, "finish() => pause with userLeaving=false"); } - rootTask.startPausingLocked(false /* userLeaving */, false /* uiSleeping */, + task.startPausingLocked(false /* userLeaving */, false /* uiSleeping */, null /* resuming */, "finish"); } @@ -2733,7 +2720,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A final boolean isCurrentVisible = mVisibleRequested || isState(PAUSED); if (isCurrentVisible) { final Task stack = getStack(); - final ActivityRecord activity = stack.mResumedActivity; + final ActivityRecord activity = stack.getResumedActivity(); boolean ensureVisibility = false; if (activity != null && !activity.occludesParent()) { // If the resume activity is not opaque, we need to make sure the visibilities of @@ -2961,10 +2948,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A boolean safelyDestroy(String reason) { if (isDestroyable()) { if (DEBUG_SWITCH) { - final Task stack = getRootTask(); + final Task task = getTask(); Slog.v(TAG_SWITCH, "Safely destroying " + this + " in state " + getState() - + " resumed=" + stack.mResumedActivity - + " pausing=" + stack.mPausingActivity + + " resumed=" + task.getResumedActivity() + + " pausing=" + task.getPausingActivity() + " for reason " + reason); } return destroyImmediately(reason); @@ -3137,7 +3124,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A SurfaceControl.openTransaction(); for (int i = mChildren.size() - 1; i >= 0; i--) { final WindowState w = mChildren.get(i); - w.mWinAnimator.detachChildren(); + w.mWinAnimator.detachChildren(getGlobalTransaction()); } SurfaceControl.closeTransaction(); } @@ -4449,7 +4436,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A SurfaceControl.openTransaction(); try { forAllWindows(win -> { - win.mWinAnimator.hide("immediately hidden"); }, true); + win.mWinAnimator.hide(getGlobalTransaction(), "immediately hidden"); + }, true); } finally { SurfaceControl.closeTransaction(); } @@ -4841,7 +4829,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // If the app is capable of entering PIP, we should try pausing it now // so it can PIP correctly. if (deferHidingClient) { - getRootTask().startPausingLocked(userLeaving, false /* uiSleeping */, + task.startPausingLocked(userLeaving, false /* uiSleeping */, null /* resuming */, "makeInvisible"); break; } @@ -5072,25 +5060,24 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A ProtoLog.v(WM_DEBUG_STATES, "Activity paused: token=%s, timeout=%b", appToken, timeout); - final Task stack = getStack(); - - if (stack != null) { + if (task != null) { removePauseTimeout(); - if (stack.mPausingActivity == this) { + final ActivityRecord pausingActivity = task.getPausingActivity(); + if (pausingActivity == this) { ProtoLog.v(WM_DEBUG_STATES, "Moving to PAUSED: %s %s", this, (timeout ? "(due to timeout)" : " (pause complete)")); mAtmService.deferWindowLayout(); try { - stack.completePauseLocked(true /* resumeNext */, null /* resumingActivity */); + task.completePauseLocked(true /* resumeNext */, null /* resumingActivity */); } finally { mAtmService.continueWindowLayout(); } return; } else { EventLogTags.writeWmFailedToPause(mUserId, System.identityHashCode(this), - shortComponentName, stack.mPausingActivity != null - ? stack.mPausingActivity.shortComponentName : "(none)"); + shortComponentName, pausingActivity != null + ? pausingActivity.shortComponentName : "(none)"); if (isState(PAUSING)) { setState(PAUSED, "activityPausedLocked"); if (finishing) { @@ -5188,10 +5175,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A void activityStopped(Bundle newIcicle, PersistableBundle newPersistentState, CharSequence description) { - final Task stack = getRootTask(); final boolean isStopping = mState == STOPPING; if (!isStopping && mState != RESTARTING_PROCESS) { - Slog.i(TAG, "Activity reported stop, but no longer stopping: " + this); + Slog.i(TAG, "Activity reported stop, but no longer stopping: " + this + " " + mState); removeStopTimeout(); return; } @@ -5228,6 +5214,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mRootWindowContainer.updatePreviousProcess(this); } } + mTaskSupervisor.checkReadyForSleepLocked(true /* allowDelay */); } } @@ -5720,14 +5707,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // First find the real culprit... if this activity has stopped, then the key dispatching // timeout should not be caused by this. if (stopped) { - final Task stack = mRootWindowContainer.getTopDisplayFocusedRootTask(); - if (stack == null) { + final Task rootTask = mRootWindowContainer.getTopDisplayFocusedRootTask(); + if (rootTask == null) { return this; } // Try to use the one which is closest to top. - ActivityRecord r = stack.getResumedActivity(); + ActivityRecord r = rootTask.getResumedActivity(); if (r == null) { - r = stack.mPausingActivity; + r = rootTask.getPausingActivity(); } if (r != null) { return r; @@ -5805,9 +5792,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // This would be redundant. return false; } - final Task stack = getRootTask(); - if (isState(RESUMED) || stack == null || this == stack.mPausingActivity || !mHaveState - || !stopped) { + if (isState(RESUMED) || getRootTask() == null || this == task.getPausingActivity() + || !mHaveState || !stopped) { // We're not ready for this kind of thing. 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 1ff3a3fb1d35..ecbf266c89cb 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -2647,7 +2647,11 @@ class ActivityStarter { if (next != null) { next.setCurrentLaunchCanTurnScreenOn(true); } - mRootWindowContainer.resumeFocusedTasksTopActivities(mTargetStack, null, mOptions); + if (mTargetStack.isFocusable()) { + mRootWindowContainer.resumeFocusedTasksTopActivities(mTargetStack, null, mOptions); + } else { + mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS); + } } else { ActivityOptions.abort(mOptions); } diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java index a5df2a604808..f8b3c1ba856f 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java @@ -386,6 +386,10 @@ public abstract class ActivityTaskManagerInternal { public abstract void clearPendingResultForActivity( IBinder activityToken, WeakReference<PendingIntentRecord> pir); + /** Returns the component name of the activity token. */ + @Nullable + public abstract ComponentName getActivityName(IBinder activityToken); + /** * @return the activity token and IApplicationThread for the top activity in the task or null * if there isn't a top activity with a valid process. diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 5fed940bb540..a2b09908e22d 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -1133,9 +1133,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { synchronized (mGlobalLock) { // If this is coming from the currently resumed activity, it is // effectively saying that app switches are allowed at this point. - final Task stack = getTopDisplayFocusedRootTask(); - if (stack != null && stack.mResumedActivity != null - && stack.mResumedActivity.info.applicationInfo.uid == Binder.getCallingUid()) { + final Task topFocusedRootTask = getTopDisplayFocusedRootTask(); + if (topFocusedRootTask != null && topFocusedRootTask.getResumedActivity() != null + && topFocusedRootTask.getResumedActivity().info.applicationInfo.uid + == Binder.getCallingUid()) { mAppSwitchesAllowedTime = 0; } } @@ -1743,29 +1744,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } - @Override - public int getLaunchedFromUid(IBinder activityToken) { - ActivityRecord srec; - synchronized (mGlobalLock) { - srec = ActivityRecord.forTokenLocked(activityToken); - } - if (srec == null) { - return -1; - } - return srec.launchedFromUid; - } - - @Override - public String getLaunchedFromPackage(IBinder activityToken) { - ActivityRecord srec; - synchronized (mGlobalLock) { - srec = ActivityRecord.forTokenLocked(activityToken); - } - if (srec == null) { - return null; - } - return srec.launchedFromPackage; - } @Override public RootTaskInfo getFocusedRootTaskInfo() throws RemoteException { @@ -2560,9 +2538,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { @Override public int getLockTaskModeState() { - synchronized (mGlobalLock) { - return getLockTaskController().getLockTaskModeState(); - } + return getLockTaskController().getLockTaskModeState(); } @Override @@ -3228,28 +3204,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } @Override - public ComponentName getActivityClassForToken(IBinder token) { - synchronized (mGlobalLock) { - ActivityRecord r = ActivityRecord.isInStackLocked(token); - if (r == null) { - return null; - } - return r.intent.getComponent(); - } - } - - @Override - public String getPackageForToken(IBinder token) { - synchronized (mGlobalLock) { - ActivityRecord r = ActivityRecord.isInStackLocked(token); - if (r == null) { - return null; - } - return r.packageName; - } - } - - @Override public void keyguardGoingAway(int flags) { enforceNotIsolatedCaller("keyguardGoingAway"); final long token = Binder.clearCallingIdentity(); @@ -5599,6 +5553,14 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } @Override + public ComponentName getActivityName(IBinder activityToken) { + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.isInStackLocked(activityToken); + return r != null ? r.intent.getComponent() : null; + } + } + + @Override public ActivityTokens getTopActivityForTask(int taskId) { synchronized (mGlobalLock) { final Task task = mRootWindowContainer.anyTaskForId(taskId); diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java index 73d99724c65f..400633c849ab 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java @@ -88,6 +88,7 @@ import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.ActivityOptions; import android.app.AppOpsManager; +import android.app.IActivityClientController; import android.app.ProfilerInfo; import android.app.ResultInfo; import android.app.WaitResult; @@ -795,6 +796,11 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { + " old=" + r.app + " new=" + proc); } + // Send the controller to client if the process is the first time to launch activity. + // So the client can save binder transactions of getting the controller from activity + // task manager service. + final IActivityClientController activityClientController = + proc.hasEverLaunchedActivity() ? null : mService.mActivityClientController; r.launchCount++; r.lastLaunchTime = SystemClock.uptimeMillis(); proc.setLastActivityLaunchTime(r.lastLaunchTime); @@ -863,7 +869,8 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(), r.getSavedState(), r.getPersistentSavedState(), results, newIntents, dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(), - r.assistToken, r.createFixedRotationAdjustmentsIfNeeded())); + r.assistToken, activityClientController, + r.createFixedRotationAdjustmentsIfNeeded())); // Set desired final state. final ActivityLifecycleItem lifecycleItem; @@ -2059,7 +2066,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { void updateTopResumedActivityIfNeeded() { final ActivityRecord prevTopActivity = mTopResumedActivity; final Task topStack = mRootWindowContainer.getTopDisplayFocusedRootTask(); - if (topStack == null || topStack.mResumedActivity == prevTopActivity) { + if (topStack == null || topStack.getResumedActivity() == prevTopActivity) { if (mService.isSleepingLocked()) { // There won't be a next resumed activity. The top process should still be updated // according to the current top focused activity. @@ -2081,7 +2088,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { } // Update the current top activity. - mTopResumedActivity = topStack.mResumedActivity; + mTopResumedActivity = topStack.getResumedActivity(); scheduleTopResumedActivityStateIfNeeded(); mService.updateTopApp(mTopResumedActivity); diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java index 758aaa0fee9a..605a23e065a5 100644 --- a/services/core/java/com/android/server/wm/AppTransition.java +++ b/services/core/java/com/android/server/wm/AppTransition.java @@ -17,7 +17,7 @@ package com.android.server.wm; import static android.view.WindowManager.LayoutParams; -import static android.view.WindowManager.TRANSIT_CHANGE_WINDOWING_MODE; +import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_FLAG_APP_CRASHED; import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION; @@ -2092,8 +2092,8 @@ public class AppTransition implements Dump { case TRANSIT_RELAUNCH: { return "TRANSIT_RELAUNCH"; } - case TRANSIT_CHANGE_WINDOWING_MODE: { - return "TRANSIT_CHANGE_WINDOWING_MODE"; + case TRANSIT_CHANGE: { + return "TRANSIT_CHANGE"; } case TRANSIT_KEYGUARD_GOING_AWAY: { return "TRANSIT_KEYGUARD_GOING_AWAY"; diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java index 64cbb0dec635..dde527d161e0 100644 --- a/services/core/java/com/android/server/wm/AppTransitionController.java +++ b/services/core/java/com/android/server/wm/AppTransitionController.java @@ -17,7 +17,7 @@ package com.android.server.wm; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; -import static android.view.WindowManager.TRANSIT_CHANGE_WINDOWING_MODE; +import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_FLAG_APP_CRASHED; import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION; @@ -303,7 +303,7 @@ public class AppTransitionController { // Special transitions // TODO(new-app-transitions): Revisit if those can be rewritten by using flags. - if (appTransition.containsTransitRequest(TRANSIT_CHANGE_WINDOWING_MODE)) { + if (appTransition.containsTransitRequest(TRANSIT_CHANGE)) { return TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE; } if ((flags & TRANSIT_FLAG_APP_CRASHED) != 0) { diff --git a/services/core/java/com/android/server/wm/DisplayAreaPolicy.java b/services/core/java/com/android/server/wm/DisplayAreaPolicy.java index d4b319a525da..f8c375497b7b 100644 --- a/services/core/java/com/android/server/wm/DisplayAreaPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayAreaPolicy.java @@ -99,23 +99,41 @@ public abstract class DisplayAreaPolicy { // 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. - 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()) + 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 .addFeature(new Feature.Builder(wmService.mPolicy, "OneHanded", FEATURE_ONE_HANDED) .all() @@ -131,13 +149,7 @@ public abstract class DisplayAreaPolicy { .addFeature(new Feature.Builder(wmService.mPolicy, "ImePlaceholder", FEATURE_IME_PLACEHOLDER) .and(TYPE_INPUT_METHOD, TYPE_INPUT_METHOD_DIALOG) - .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); + .build()); } } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 0678a5e4383b..8d6d981be2b8 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -80,6 +80,7 @@ import static android.view.WindowManager.TRANSIT_TO_FRONT; import static android.window.DisplayAreaOrganizer.FEATURE_ROOT; import static android.window.DisplayAreaOrganizer.FEATURE_WINDOWED_MAGNIFICATION; +import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BOOT; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS; @@ -552,24 +553,56 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp * This just indicates the window the input method is on top of, not * necessarily the window its input is going to. */ - WindowState mInputMethodTarget; + private WindowState mImeLayeringTarget; /** * The window which receives input from the input method. This is also a candidate of the * input method control target. */ - WindowState mInputMethodInputTarget; + private WindowState mImeInputTarget; /** * This controls the visibility and animation of the input method window. */ - InsetsControlTarget mInputMethodControlTarget; + private InsetsControlTarget mImeControlTarget; + + /** + * Used by {@link #getImeTarget} to return the IME target which the input method window on + * top of for adjusting input method window surface layer Z-Ordering. + * + * @see #mImeLayeringTarget + */ + static final int IME_TARGET_LAYERING = 0; + + /** + * Used by {@link #getImeTarget} to return the IME target which received the input connection + * from IME. + * + * @see #mImeInputTarget + */ + static final int IME_TARGET_INPUT = 1; + + /** + * Used by {@link #getImeTarget} to return the IME target which controls the IME insets + * visibility and animation. + * + * @see #mImeControlTarget + */ + static final int IME_TARGET_CONTROL = 2; + + @IntDef(flag = false, prefix = { "IME_TARGET_" }, value = { + IME_TARGET_LAYERING, + IME_TARGET_INPUT, + IME_TARGET_CONTROL, + }) + @Retention(RetentionPolicy.SOURCE) + @interface InputMethodTarget {} /** The surface parent of the IME container. */ private SurfaceControl mInputMethodSurfaceParent; - /** If true hold off on modifying the animation layer of mInputMethodTarget */ - boolean mInputMethodTargetWaitingAnim; + /** If {@code true} hold off on modifying the animation layer of {@link #mImeLayeringTarget} */ + boolean mImeLayeringTargetWaitingAnim; private final PointerEventDispatcher mPointerEventDispatcher; @@ -814,7 +847,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp private final Consumer<WindowState> mApplyPostLayoutPolicy = w -> getDisplayPolicy().applyPostLayoutPolicyLw(w, w.mAttrs, w.getParentWindow(), - mInputMethodTarget); + mImeLayeringTarget); private final Consumer<WindowState> mApplySurfaceChangesTransaction = w -> { final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked; @@ -2256,13 +2289,15 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp @Nullable Task getRootTask(int rootTaskId) { - return getItemFromTaskDisplayAreas(taskDisplayArea -> - taskDisplayArea.getRootTask(rootTaskId)); + return getRootTask(rootTask -> rootTask.getRootTaskId() == rootTaskId); } - protected int getRootTaskCount() { - return reduceOnAllTaskDisplayAreas((taskDisplayArea, count) -> - count + taskDisplayArea.getRootTaskCount(), 0 /* initValue */); + int getRootTaskCount() { + final int[] count = new int[1]; + forAllRootTasks(task -> { + count[0]++; + }); + return count[0]; } @VisibleForTesting @@ -2831,7 +2866,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } void prepareFreezingTaskBounds() { - forAllTaskDisplayAreas(TaskDisplayArea::prepareFreezingTaskBounds); + forAllRootTasks(Task::prepareFreezingTaskBounds); } void rotateBounds(int oldRotation, int newRotation, Rect bounds) { @@ -2940,15 +2975,15 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp proto.write(FOCUSED_ROOT_TASK_ID, INVALID_TASK_ID); } proto.write(DISPLAY_READY, isReady()); - if (mInputMethodTarget != null) { - mInputMethodTarget.dumpDebug(proto, INPUT_METHOD_TARGET, logLevel); + if (mImeLayeringTarget != null) { + mImeLayeringTarget.dumpDebug(proto, INPUT_METHOD_TARGET, logLevel); } - if (mInputMethodInputTarget != null) { - mInputMethodInputTarget.dumpDebug(proto, INPUT_METHOD_INPUT_TARGET, logLevel); + if (mImeInputTarget != null) { + mImeInputTarget.dumpDebug(proto, INPUT_METHOD_INPUT_TARGET, logLevel); } - if (mInputMethodControlTarget != null - && mInputMethodControlTarget.getWindow() != null) { - mInputMethodControlTarget.getWindow().dumpDebug(proto, INPUT_METHOD_CONTROL_TARGET, + if (mImeControlTarget != null + && mImeControlTarget.getWindow() != null) { + mImeControlTarget.getWindow().dumpDebug(proto, INPUT_METHOD_CONTROL_TARGET, logLevel); } if (mCurrentFocus != null) { @@ -3204,7 +3239,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp boolean imWindowChanged = false; final WindowState imWindow = mInputMethodWindow; if (imWindow != null) { - final WindowState prevTarget = mInputMethodTarget; + final WindowState prevTarget = mImeLayeringTarget; final WindowState newTarget = computeImeTarget(true /* updateImeTarget*/); imWindowChanged = prevTarget != newTarget; @@ -3401,6 +3436,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp boolean destroyLeakedSurfaces() { // Used to indicate that a surface was leaked. mTmpWindow = null; + final Transaction t = mWmService.mTransactionFactory.get(); forAllWindows(w -> { final WindowStateAnimator wsa = w.mWinAnimator; if (wsa.mSurfaceController == null) { @@ -3412,7 +3448,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp + " token=" + w.mToken + " pid=" + w.mSession.mPid + " uid=" + w.mSession.mUid); - wsa.destroySurface(); + wsa.destroySurface(t); mWmService.mForceRemoves.add(w); mTmpWindow = w; } else if (w.mActivityRecord != null && !w.mActivityRecord.isClientVisible()) { @@ -3420,10 +3456,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp + w + " surface=" + wsa.mSurfaceController + " token=" + w.mActivityRecord); ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE LEAK DESTROY: %s", w); - wsa.destroySurface(); + wsa.destroySurface(t); mTmpWindow = w; } }, false /* traverseTopToBottom */); + t.apply(); return mTmpWindow != null; } @@ -3456,7 +3493,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } /** - * Determine and return the window that should be the IME target. + * Determine and return the window that should be the IME target for layering the IME window. * @param updateImeTarget If true the system IME target will be updated to match what we found. * @return The window that should be used as the IME target or null if there isn't any. */ @@ -3465,13 +3502,13 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp // There isn't an IME so there shouldn't be a target...That was easy! if (updateImeTarget) { if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " - + mInputMethodTarget + " to null since mInputMethodWindow is null"); - setInputMethodTarget(null, mInputMethodTargetWaitingAnim); + + mImeLayeringTarget + " to null since mInputMethodWindow is null"); + setImeLayeringTarget(null, mImeLayeringTargetWaitingAnim); } return null; } - final WindowState curTarget = mInputMethodTarget; + final WindowState curTarget = mImeLayeringTarget; if (!canUpdateImeTarget()) { if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Defer updating IME target"); return curTarget; @@ -3526,7 +3563,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to null." + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : "")); - setInputMethodTarget(null, mInputMethodTargetWaitingAnim); + setImeLayeringTarget(null, mImeLayeringTargetWaitingAnim); } return null; @@ -3553,7 +3590,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp if (mAppTransition.isTransitionSet()) { // If we are currently setting up for an animation, hold everything until we // can find out what will happen. - setInputMethodTarget(highestTarget, true); + setImeLayeringTarget(highestTarget, true); return highestTarget; } } @@ -3561,7 +3598,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to " + target + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : "")); - setInputMethodTarget(target, false); + setImeLayeringTarget(target, false); } return target; @@ -3572,24 +3609,24 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp * the candidate app window token if needed. */ void computeImeTargetIfNeeded(ActivityRecord candidate) { - if (mInputMethodTarget != null && mInputMethodTarget.mActivityRecord == candidate) { + if (mImeLayeringTarget != null && mImeLayeringTarget.mActivityRecord == candidate) { computeImeTarget(true /* updateImeTarget */); } } private boolean isImeControlledByApp() { - return mInputMethodInputTarget != null && !WindowConfiguration.isSplitScreenWindowingMode( - mInputMethodInputTarget.getWindowingMode()); + return mImeInputTarget != null && !WindowConfiguration.isSplitScreenWindowingMode( + mImeInputTarget.getWindowingMode()); } boolean isImeAttachedToApp() { return isImeControlledByApp() - && mInputMethodTarget != null - && mInputMethodTarget.mActivityRecord != null - && mInputMethodTarget.getWindowingMode() == WINDOWING_MODE_FULLSCREEN + && mImeLayeringTarget != null + && mImeLayeringTarget.mActivityRecord != null + && mImeLayeringTarget.getWindowingMode() == WINDOWING_MODE_FULLSCREEN // An activity with override bounds should be letterboxed inside its parent bounds, // so it doesn't fill the screen. - && mInputMethodTarget.mActivityRecord.matchParentBounds(); + && mImeLayeringTarget.mActivityRecord.matchParentBounds(); } /** @@ -3616,6 +3653,24 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp return statusBar != null ? statusBar : defaultDc.mRemoteInsetsControlTarget; } + /** + * Returns the corresponding IME insets control target according the IME target type. + * + * @param type The type of the IME target. + * @see #IME_TARGET_LAYERING + * @see #IME_TARGET_INPUT + * @see #IME_TARGET_CONTROL + */ + InsetsControlTarget getImeTarget(@InputMethodTarget int type) { + switch (type) { + case IME_TARGET_LAYERING: return mImeLayeringTarget; + case IME_TARGET_INPUT: return mImeInputTarget; + case IME_TARGET_CONTROL: return mImeControlTarget; + default: + return null; + } + } + @DisplayImePolicy int getImePolicy() { if (!isTrusted()) { return DISPLAY_IME_POLICY_FALLBACK_DISPLAY; @@ -3633,6 +3688,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp return mWmService.mForceDesktopModeOnExternalDisplays && !isDefaultDisplay && !isPrivate(); } + @VisibleForTesting + void setImeLayeringTarget(WindowState target) { + mImeLayeringTarget = target; + } + /** * Sets the window the IME is on top of. * @param target window to place the IME surface on top of. If {@code null}, the IME will be @@ -3640,13 +3700,13 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp * @param targetWaitingAnim if {@code true}, hold off on modifying the animation layer of * the target. */ - private void setInputMethodTarget(@Nullable WindowState target, boolean targetWaitingAnim) { - if (target == mInputMethodTarget && mInputMethodTargetWaitingAnim == targetWaitingAnim) { + private void setImeLayeringTarget(@Nullable WindowState target, boolean targetWaitingAnim) { + if (target == mImeLayeringTarget && mImeLayeringTargetWaitingAnim == targetWaitingAnim) { return; } ProtoLog.i(WM_DEBUG_IME, "setInputMethodTarget %s", target); - mInputMethodTarget = target; - mInputMethodTargetWaitingAnim = targetWaitingAnim; + mImeLayeringTarget = target; + mImeLayeringTargetWaitingAnim = targetWaitingAnim; // 1. Reparent the IME container window to the target root DA to get the correct bounds and // config. (Only happens when the target window is in a different root DA) @@ -3668,23 +3728,33 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp updateImeControlTarget(); } + @VisibleForTesting + void setImeInputTarget(WindowState target) { + mImeInputTarget = target; + } + + @VisibleForTesting + void setImeControlTarget(InsetsControlTarget target) { + mImeControlTarget = target; + } + /** * The IME input target is the window which receives input from IME. It is also a candidate * which controls the visibility and animation of the input method window. */ - void setInputMethodInputTarget(WindowState target) { - if (mInputMethodInputTarget != target) { + void updateImeInputAndControlTarget(WindowState target) { + if (mImeInputTarget != target) { ProtoLog.i(WM_DEBUG_IME, "setInputMethodInputTarget %s", target); - mInputMethodInputTarget = target; + mImeInputTarget = target; updateImeControlTarget(); } } void updateImeControlTarget() { - mInputMethodControlTarget = computeImeControlTarget(); - mInsetsStateController.onImeControlTargetChanged(mInputMethodControlTarget); + mImeControlTarget = computeImeControlTarget(); + mInsetsStateController.onImeControlTargetChanged(mImeControlTarget); - final WindowState win = InsetsControlTarget.asWindowOrNull(mInputMethodControlTarget); + final WindowState win = InsetsControlTarget.asWindowOrNull(mImeControlTarget); final IBinder token = win != null ? win.mClient.asBinder() : null; // Note: not allowed to call into IMMS with the WM lock held, hence the post. mWmService.mH.post(() -> @@ -3707,12 +3777,12 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp @VisibleForTesting InsetsControlTarget computeImeControlTarget() { if (!isImeControlledByApp() && mRemoteInsetsControlTarget != null - || (mInputMethodInputTarget != null - && getImeHostOrFallback(mInputMethodInputTarget.getWindow()) + || (mImeInputTarget != null + && getImeHostOrFallback(mImeInputTarget.getWindow()) == mRemoteInsetsControlTarget)) { return mRemoteInsetsControlTarget; } else { - return mInputMethodInputTarget; + return mImeInputTarget; } } @@ -3729,7 +3799,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp // screen. If it's not covering the entire screen the IME might extend beyond the apps // bounds. if (allowAttachToApp && isImeAttachedToApp()) { - return mInputMethodTarget.mActivityRecord.getSurfaceControl(); + return mImeLayeringTarget.mActivityRecord.getSurfaceControl(); } // Otherwise, we just attach it to where the display area policy put it. @@ -4186,8 +4256,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } // Initialize state of exiting applications. - forAllTaskDisplayAreas(taskDisplayArea -> { - taskDisplayArea.setExitingTokensHasVisible(hasVisible); + forAllRootTasks(task -> { + final ArrayList<ActivityRecord> activities = task.mExitingActivities; + for (int j = activities.size() - 1; j >= 0; --j) { + activities.get(j).hasVisible = hasVisible; + } }); } @@ -4200,7 +4273,22 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } // Time to remove any exiting applications? - forAllTaskDisplayAreas(TaskDisplayArea::removeExistingAppTokensIfPossible); + forAllRootTasks(task -> { + final ArrayList<ActivityRecord> activities = task.mExitingActivities; + for (int j = activities.size() - 1; j >= 0; --j) { + final ActivityRecord activity = activities.get(j); + if (!activity.hasVisible && !mDisplayContent.mClosingApps.contains(activity) + && (!activity.mIsExiting || activity.isEmpty())) { + // Make sure there is no animation running on this activity, so any windows + // associated with it will be removed as soon as their animations are + // complete. + cancelAnimation(); + ProtoLog.v(WM_DEBUG_ADD_REMOVE, + "performLayout: Activity exiting now removed %s", activity); + activity.removeIfPossible(); + } + } + }); } @Override @@ -4350,7 +4438,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp private boolean skipImeWindowsDuringTraversal(DisplayContent dc) { // We skip IME windows so they're processed just above their target, except // in split-screen mode where we process the IME containers above the docked divider. - return dc.mInputMethodTarget != null + return dc.getImeTarget(IME_TARGET_LAYERING) != null && !dc.getDefaultTaskDisplayArea().isSplitScreenModeActivated(); } @@ -4465,7 +4553,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp @Override void assignChildLayers(SurfaceControl.Transaction t) { mImeWindowsContainers.setNeedsLayer(); - final WindowState imeTarget = mInputMethodTarget; + final WindowState imeTarget = mImeLayeringTarget; // In the case where we have an IME target that is not in split-screen mode IME // assignment is easy. We just need the IME to go directly above the target. This way // children of the target will naturally go above the IME and everyone is happy. @@ -5123,15 +5211,56 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED */ void removeRootTasksInWindowingModes(int... windowingModes) { - forAllTaskDisplayAreas(taskDisplayArea -> { - taskDisplayArea.removeRootTasksInWindowingModes(windowingModes); + if (windowingModes == null || windowingModes.length == 0) { + return; + } + + // Collect the root tasks that are necessary to be removed instead of performing the removal + // by looping the children, so that we don't miss any root tasks after the children size + // changed or reordered. + final ArrayList<Task> rootTasks = new ArrayList<>(); + forAllRootTasks(rootTask -> { + for (int windowingMode : windowingModes) { + if (rootTask.mCreatedByOrganizer + || rootTask.getWindowingMode() != windowingMode + || !rootTask.isActivityTypeStandardOrUndefined()) { + continue; + } + rootTasks.add(rootTask); + } }); + for (int i = rootTasks.size() - 1; i >= 0; --i) { + mRootWindowContainer.mTaskSupervisor.removeRootTask(rootTasks.get(i)); + } } void removeRootTasksWithActivityTypes(int... activityTypes) { - forAllTaskDisplayAreas(taskDisplayArea -> { - taskDisplayArea.removeRootTasksWithActivityTypes(activityTypes); + if (activityTypes == null || activityTypes.length == 0) { + return; + } + + // Collect the root tasks that are necessary to be removed instead of performing the removal + // by looping the children, so that we don't miss any root tasks after the children size + // changed or reordered. + final ArrayList<Task> rootTasks = new ArrayList<>(); + forAllRootTasks(rootTask -> { + for (int activityType : activityTypes) { + // Collect the root tasks that are currently being organized. + if (rootTask.mCreatedByOrganizer) { + for (int k = rootTask.getChildCount() - 1; k >= 0; --k) { + final Task task = (Task) rootTask.getChildAt(k); + if (task.getActivityType() == activityType) { + rootTasks.add(task); + } + } + } else if (rootTask.getActivityType() == activityType) { + rootTasks.add(rootTask); + } + } }); + for (int i = rootTasks.size() - 1; i >= 0; --i) { + mRootWindowContainer.mTaskSupervisor.removeRootTask(rootTasks.get(i)); + } } ActivityRecord topRunningActivity() { @@ -5351,19 +5480,12 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } // Check if all task display areas have only the empty home stacks left. - boolean hasNonEmptyHomeStack = forAllTaskDisplayAreas(taskDisplayArea -> { - if (taskDisplayArea.getRootTaskCount() != 1) { - return true; - } - final Task stack = taskDisplayArea.getRootTaskAt(0); - return !stack.isActivityTypeHome() || stack.hasChild(); - }); - if (!hasNonEmptyHomeStack) { + 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. - forAllTaskDisplayAreas(taskDisplayArea -> { - taskDisplayArea.getRootTaskAt(0).removeIfPossible(); - }); + forAllRootTasks(Task::removeIfPossible); } else if (getTopRootTask() == null) { removeIfPossible(); mRootWindowContainer.mTaskSupervisor diff --git a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java index 91106eff9805..17c3b20c9e40 100644 --- a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java @@ -19,10 +19,14 @@ package com.android.server.wm; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME; +import static com.android.server.wm.DisplayContent.IME_TARGET_CONTROL; +import static com.android.server.wm.DisplayContent.IME_TARGET_INPUT; +import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING; import static com.android.server.wm.ImeInsetsSourceProviderProto.IME_TARGET_FROM_IME; import static com.android.server.wm.ImeInsetsSourceProviderProto.INSETS_SOURCE_PROVIDER; import static com.android.server.wm.ImeInsetsSourceProviderProto.IS_IME_LAYOUT_DRAWN; +import android.annotation.NonNull; import android.os.Trace; import android.util.proto.ProtoOutputStream; import android.view.InsetsSource; @@ -37,9 +41,9 @@ import java.io.PrintWriter; * Controller for IME inset source on the server. It's called provider as it provides the * {@link InsetsSource} to the client that uses it in {@link InsetsSourceConsumer}. */ -class ImeInsetsSourceProvider extends InsetsSourceProvider { +final class ImeInsetsSourceProvider extends InsetsSourceProvider { - private InsetsControlTarget mImeTargetFromIme; + private InsetsControlTarget mImeRequester; private Runnable mShowImeRunner; private boolean mIsImeLayoutDrawn; private boolean mImeShowing; @@ -56,12 +60,8 @@ class ImeInsetsSourceProvider extends InsetsSourceProvider { * @param imeTarget imeTarget on which IME request is coming from. */ void scheduleShowImePostLayout(InsetsControlTarget imeTarget) { - boolean targetChanged = mImeTargetFromIme != imeTarget - && mImeTargetFromIme != null && imeTarget != null && mShowImeRunner != null - && imeTarget.getWindow() != null && mImeTargetFromIme.getWindow() != null - && mImeTargetFromIme.getWindow().mActivityRecord - == imeTarget.getWindow().mActivityRecord; - mImeTargetFromIme = imeTarget; + boolean targetChanged = isTargetChangedWithinActivity(imeTarget); + mImeRequester = imeTarget; if (targetChanged) { // target changed, check if new target can show IME. ProtoLog.d(WM_DEBUG_IME, "IME target changed within ActivityRecord"); @@ -72,24 +72,24 @@ class ImeInsetsSourceProvider extends InsetsSourceProvider { return; } - ProtoLog.d(WM_DEBUG_IME, "Schedule IME show for %s", mImeTargetFromIme.getWindow() == null - ? mImeTargetFromIme : mImeTargetFromIme.getWindow().getName()); + ProtoLog.d(WM_DEBUG_IME, "Schedule IME show for %s", mImeRequester.getWindow() == null + ? mImeRequester : mImeRequester.getWindow().getName()); mShowImeRunner = () -> { ProtoLog.d(WM_DEBUG_IME, "Run showImeRunner"); // Target should still be the same. - if (isImeTargetFromDisplayContentAndImeSame()) { - final InsetsControlTarget target = mDisplayContent.mInputMethodControlTarget; + if (isReadyToShowIme()) { + final InsetsControlTarget target = mDisplayContent.getImeTarget(IME_TARGET_CONTROL); ProtoLog.i(WM_DEBUG_IME, "call showInsets(ime) on %s", target.getWindow() != null ? target.getWindow().getName() : ""); setImeShowing(true); target.showInsets(WindowInsets.Type.ime(), true /* fromIme */); Trace.asyncTraceEnd(TRACE_TAG_WINDOW_MANAGER, "WMS.showImePostLayout", 0); - if (target != mImeTargetFromIme && mImeTargetFromIme != null) { + if (target != mImeRequester && mImeRequester != null) { ProtoLog.w(WM_DEBUG_IME, "showInsets(ime) was requested by different window: %s ", - (mImeTargetFromIme.getWindow() != null - ? mImeTargetFromIme.getWindow().getName() : "")); + (mImeRequester.getWindow() != null + ? mImeRequester.getWindow().getName() : "")); } } abortShowImePostLayout(); @@ -100,8 +100,7 @@ class ImeInsetsSourceProvider extends InsetsSourceProvider { void checkShowImePostLayout() { // check if IME is drawn if (mIsImeLayoutDrawn - || (mImeTargetFromIme != null - && isImeTargetFromDisplayContentAndImeSame() + || (isReadyToShowIme() && mWin != null && mWin.isDrawn() && !mWin.mGivenInsetsPending)) { @@ -118,13 +117,13 @@ class ImeInsetsSourceProvider extends InsetsSourceProvider { */ void abortShowImePostLayout() { ProtoLog.d(WM_DEBUG_IME, "abortShowImePostLayout"); - mImeTargetFromIme = null; + mImeRequester = null; mIsImeLayoutDrawn = false; mShowImeRunner = null; } @VisibleForTesting - boolean isImeTargetFromDisplayContentAndImeSame() { + boolean isReadyToShowIme() { // IMMS#mLastImeTargetWindow always considers focused window as // IME target, however DisplayContent#computeImeTarget() can compute // a different IME target. @@ -134,35 +133,75 @@ class ImeInsetsSourceProvider extends InsetsSourceProvider { // Also, if imeTarget is closing, it would be considered as outdated target. // TODO(b/139861270): Remove the child & sublayer check once IMMS is aware of // actual IME target. - final WindowState dcTarget = mDisplayContent.mInputMethodTarget; - final InsetsControlTarget controlTarget = mDisplayContent.mInputMethodControlTarget; - if (dcTarget == null || mImeTargetFromIme == null) { + final InsetsControlTarget dcTarget = mDisplayContent.getImeTarget(IME_TARGET_LAYERING); + if (dcTarget == null || mImeRequester == null) { return false; } - ProtoLog.d(WM_DEBUG_IME, "dcTarget: %s mImeTargetFromIme: %s", - dcTarget.getName(), mImeTargetFromIme.getWindow() == null - ? mImeTargetFromIme : mImeTargetFromIme.getWindow().getName()); - - return (!dcTarget.isClosing() && mImeTargetFromIme == dcTarget) - || (mImeTargetFromIme != null && mImeTargetFromIme.getWindow() != null - && dcTarget.getParentWindow() == mImeTargetFromIme - && dcTarget.mSubLayer > mImeTargetFromIme.getWindow().mSubLayer) - || mImeTargetFromIme == mDisplayContent.getImeFallback() - || mImeTargetFromIme == mDisplayContent.mInputMethodInputTarget - || controlTarget == mImeTargetFromIme - && (mImeTargetFromIme.getWindow() == null - || !mImeTargetFromIme.getWindow().isClosing()); + ProtoLog.d(WM_DEBUG_IME, "dcTarget: %s mImeRequester: %s", + dcTarget.getWindow().getName(), mImeRequester.getWindow() == null + ? mImeRequester : mImeRequester.getWindow().getName()); + + return isImeLayeringTarget(mImeRequester, dcTarget) + || isAboveImeLayeringTarget(mImeRequester, dcTarget) + || isImeFallbackTarget(mImeRequester) + || isImeInputTarget(mImeRequester) + || sameAsImeControlTarget(); } + // --------------------------------------------------------------------------------------- + // Methods for checking IME insets target changing state. + // + private static boolean isImeLayeringTarget(@NonNull InsetsControlTarget target, + @NonNull InsetsControlTarget dcTarget) { + return !dcTarget.getWindow().isClosing() && target == dcTarget; + } + + private static boolean isAboveImeLayeringTarget(@NonNull InsetsControlTarget target, + @NonNull InsetsControlTarget dcTarget) { + return target.getWindow() != null + && dcTarget.getWindow().getParentWindow() == target + && dcTarget.getWindow().mSubLayer > target.getWindow().mSubLayer; + } + + private boolean isImeFallbackTarget(InsetsControlTarget target) { + return target == mDisplayContent.getImeFallback(); + } + + private boolean isImeInputTarget(InsetsControlTarget target) { + return target == mDisplayContent.getImeTarget(IME_TARGET_INPUT); + } + + private boolean sameAsImeControlTarget() { + final InsetsControlTarget target = mDisplayContent.getImeTarget(IME_TARGET_CONTROL); + return target == mImeRequester + && (mImeRequester.getWindow() == null + || !mImeRequester.getWindow().isClosing()); + } + + private boolean isTargetChangedWithinActivity(InsetsControlTarget target) { + // We don't consider the target out of the activity. + if (target == null || target.getWindow() == null) { + return false; + } + return mImeRequester != target + && mImeRequester != null && mShowImeRunner != null + && mImeRequester.getWindow() != null + && mImeRequester.getWindow().mActivityRecord + == target.getWindow().mActivityRecord; + } + // --------------------------------------------------------------------------------------- + @Override public void dump(PrintWriter pw, String prefix) { super.dump(pw, prefix); pw.print(prefix); pw.print("mImeShowing="); pw.print(mImeShowing); - if (mImeTargetFromIme != null) { - pw.print(" showImePostLayout pending for mImeTargetFromIme="); - pw.print(mImeTargetFromIme); + if (mImeRequester != null) { + pw.print(prefix); + pw.print("showImePostLayout pending for mImeRequester="); + pw.print(mImeRequester); + pw.println(); } pw.println(); } @@ -171,8 +210,8 @@ class ImeInsetsSourceProvider extends InsetsSourceProvider { void dumpDebug(ProtoOutputStream proto, long fieldId, @WindowTraceLogLevel int logLevel) { final long token = proto.start(fieldId); super.dumpDebug(proto, INSETS_SOURCE_PROVIDER, logLevel); - if (mImeTargetFromIme != null) { - mImeTargetFromIme.getWindow().dumpDebug(proto, IME_TARGET_FROM_IME, logLevel); + if (mImeRequester != null) { + mImeRequester.getWindow().dumpDebug(proto, IME_TARGET_FROM_IME, logLevel); } proto.write(IS_IME_LAYOUT_DRAWN, mIsImeLayoutDrawn); proto.end(token); diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java index e45310a99fbd..57f263885ef2 100644 --- a/services/core/java/com/android/server/wm/KeyguardController.java +++ b/services/core/java/com/android/server/wm/KeyguardController.java @@ -594,16 +594,8 @@ class KeyguardController { */ @Nullable private Task getRootTaskForControllingOccluding(DisplayContent display) { - return display.getItemFromTaskDisplayAreas(taskDisplayArea -> { - for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { - final Task task = taskDisplayArea.getRootTaskAt(sNdx); - if (task != null && task.isFocusableAndVisible() - && !task.inPinnedWindowingMode()) { - return task; - } - } - return null; - }); + return display.getRootTask(task -> + task != null && task.isFocusableAndVisible() && !task.inPinnedWindowingMode()); } void dumpStatus(PrintWriter pw, String prefix) { diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java index 067c772dad93..05dcd366dbac 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimation.java +++ b/services/core/java/com/android/server/wm/RecentsAnimation.java @@ -468,14 +468,8 @@ class RecentsAnimation implements RecentsAnimationCallbacks, OnRootTaskOrderChan * @return The top stack that is not always-on-top. */ private Task getTopNonAlwaysOnTopStack() { - for (int i = mDefaultTaskDisplayArea.getRootTaskCount() - 1; i >= 0; i--) { - final Task s = mDefaultTaskDisplayArea.getRootTaskAt(i); - if (s.getWindowConfiguration().isAlwaysOnTop()) { - continue; - } - return s; - } - return null; + return mDefaultTaskDisplayArea.getRootTask(task -> + !task.getWindowConfiguration().isAlwaysOnTop()); } /** diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java index 16c722653960..edd01ebee42f 100644 --- a/services/core/java/com/android/server/wm/RecentsAnimationController.java +++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java @@ -57,7 +57,9 @@ import android.view.WindowInsets.Type; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.inputmethod.SoftInputShowHideReason; +import com.android.internal.os.BackgroundThread; import com.android.internal.protolog.common.ProtoLog; +import com.android.internal.util.LatencyTracker; import com.android.internal.util.function.pooled.PooledConsumer; import com.android.internal.util.function.pooled.PooledFunction; import com.android.internal.util.function.pooled.PooledLambda; @@ -84,6 +86,11 @@ import java.util.stream.Collectors; public class RecentsAnimationController implements DeathRecipient { private static final String TAG = RecentsAnimationController.class.getSimpleName(); private static final long FAILSAFE_DELAY = 1000; + /** + * If the recents animation is canceled before the delay since the window drawn, do not log the + * action because the duration is too small that may be just a mistouch, + */ + private static final long LATENCY_TRACKER_LOG_DELAY_MS = 300; public static final int REORDER_KEEP_IN_PLACE = 0; public static final int REORDER_MOVE_TO_TOP = 1; @@ -123,7 +130,7 @@ public class RecentsAnimationController implements DeathRecipient { private boolean mPendingStart = true; // Set when the animation has been canceled - private boolean mCanceled; + private volatile boolean mCanceled; // Whether or not the input consumer is enabled. The input consumer must be both registered and // enabled for it to start intercepting touch events. @@ -364,6 +371,9 @@ public class RecentsAnimationController implements DeathRecipient { Binder.restoreCallingIdentity(token); } } + + @Override + public void detachNavigationBarFromApp() {} }; /** @@ -592,6 +602,15 @@ public class RecentsAnimationController implements DeathRecipient { return adapter.createRemoteAnimationTarget(); } + void logRecentsAnimationStartTime(int durationMs) { + BackgroundThread.getHandler().postDelayed(() -> { + if (!mCanceled) { + mService.mLatencyTracker.logAction(LatencyTracker.ACTION_START_RECENTS_ANIMATION, + durationMs); + } + }, LATENCY_TRACKER_LOG_DELAY_MS); + } + private boolean removeTaskInternal(int taskId) { boolean result = false; for (int i = mPendingAnimations.size() - 1; i >= 0; i--) { @@ -763,7 +782,7 @@ public class RecentsAnimationController implements DeathRecipient { taskAdapter.mTask.dontAnimateDimExit(); } removeAnimation(taskAdapter); - taskAdapter.maybeApplyFinishBounds(); + taskAdapter.onCleanup(); } for (int i = mPendingWallpaperAnimations.size() - 1; i >= 0; i--) { @@ -987,14 +1006,19 @@ public class RecentsAnimationController implements DeathRecipient { return mTarget; } - void maybeApplyFinishBounds() { + void onCleanup() { if (!mFinishBounds.isEmpty()) { + // Apply any pending bounds changes final SurfaceControl taskSurface = mTask.getSurfaceControl(); mTask.getPendingTransaction() .setPosition(taskSurface, mFinishBounds.left, mFinishBounds.top) .setWindowCrop(taskSurface, mFinishBounds.width(), mFinishBounds.height()) .apply(); mFinishBounds.setEmpty(); + } else if (!mTask.isAttached()) { + // Apply the task's pending transaction in case it is detached and its transaction + // is not reachable. + mTask.getPendingTransaction().apply(); } } diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 497087a967f3..d652393dbdc1 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -778,7 +778,9 @@ class RootWindowContainer extends WindowContainer<DisplayContent> if (surfaceController != null) { ProtoLog.i(WM_SHOW_SURFACE_ALLOC, "SURFACE RECOVER DESTROY: %s", winAnimator.mWin); - winAnimator.destroySurface(); + SurfaceControl.Transaction t = mWmService.mTransactionFactory.get(); + winAnimator.destroySurface(t); + t.apply(); if (winAnimator.mWin.mActivityRecord != null) { winAnimator.mWin.mActivityRecord.removeStartingWindow(); } @@ -926,7 +928,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; } win.destroySurfaceUnchecked(); - win.mWinAnimator.destroyPreservedSurfaceLocked(); + win.mWinAnimator.destroyPreservedSurfaceLocked(win.getSyncTransaction()); } while (i > 0); mWmService.mDestroySurface.clear(); } @@ -1833,19 +1835,15 @@ class RootWindowContainer extends WindowContainer<DisplayContent> final ArrayList<IBinder> topActivityTokens = new ArrayList<>(); final Task topFocusedStack = getTopDisplayFocusedRootTask(); // Traverse all displays. - forAllTaskDisplayAreas(taskDisplayArea -> { - // Traverse all stacks on a display area. - for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { - final Task stack = taskDisplayArea.getRootTaskAt(sNdx); - // Get top activity from a visible stack and add it to the list. - if (stack.shouldBeVisible(null /* starting */)) { - final ActivityRecord top = stack.getTopNonFinishingActivity(); - if (top != null) { - if (stack == topFocusedStack) { - topActivityTokens.add(0, top.appToken); - } else { - topActivityTokens.add(top.appToken); - } + 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(); + if (top != null) { + if (stack == topFocusedStack) { + topActivityTokens.add(0, top.appToken); + } else { + topActivityTokens.add(top.appToken); } } } @@ -1890,21 +1888,17 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // First, found out what is currently the foreground app, so that we don't blow away the // previous app if this activity is being hosted by the process that is actually still the // foreground. - WindowProcessController fgApp = reduceOnAllTaskDisplayAreas((taskDisplayArea, app) -> { - for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { - final Task stack = taskDisplayArea.getRootTaskAt(sNdx); - if (isTopDisplayFocusedRootTask(stack)) { - final ActivityRecord resumedActivity = stack.getResumedActivity(); - if (resumedActivity != null) { - app = resumedActivity.app; - } else if (stack.mPausingActivity != null) { - app = stack.mPausingActivity.app; - } - break; + WindowProcessController fgApp = getItemFromRootTasks(rootTask -> { + if (isTopDisplayFocusedRootTask(rootTask)) { + final ActivityRecord resumedActivity = rootTask.getResumedActivity(); + if (resumedActivity != null) { + return resumedActivity.app; + } else if (rootTask.getPausingActivity() != null) { + return rootTask.getPausingActivity().app; } } - return app; - }, null /* initValue */); + return null; + }); // Now set this one as the previous process, only if that really makes sense to. if (r.hasProcess() && fgApp != null && r.app != fgApp @@ -1921,27 +1915,21 @@ class RootWindowContainer extends WindowContainer<DisplayContent> mTmpRemoteException = null; mTmpBoolean = false; // Set to true if an activity was started. final DisplayContent display = getChildAt(displayNdx); - display.forAllTaskDisplayAreas(displayArea -> { + display.forAllRootTasks(rootTask -> { if (mTmpRemoteException != null) { return; } - for (int taskNdx = displayArea.getRootTaskCount() - 1; taskNdx >= 0; --taskNdx) { - final Task rootTask = displayArea.getRootTaskAt(taskNdx); - if (rootTask.getVisibility(null /*starting*/) == TASK_VISIBILITY_INVISIBLE) { - break; - } - - final PooledFunction c = PooledLambda.obtainFunction( - RootWindowContainer::startActivityForAttachedApplicationIfNeeded, this, - PooledLambda.__(ActivityRecord.class), app, - rootTask.topRunningActivity()); - rootTask.forAllActivities(c); - c.recycle(); - if (mTmpRemoteException != null) { - return; - } + if (rootTask.getVisibility(null /*starting*/) == TASK_VISIBILITY_INVISIBLE) { + return; } + + final PooledFunction c = PooledLambda.obtainFunction( + RootWindowContainer::startActivityForAttachedApplicationIfNeeded, this, + PooledLambda.__(ActivityRecord.class), app, + rootTask.topRunningActivity()); + rootTask.forAllActivities(c); + c.recycle(); }); if (mTmpRemoteException != null) { throw mTmpRemoteException; @@ -2025,11 +2013,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent> mCurrentUser = userId; mTaskSupervisor.mStartingUsers.add(uss); - forAllTaskDisplayAreas(taskDisplayArea -> { - for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { - final Task stack = taskDisplayArea.getRootTaskAt(sNdx); - stack.switchUser(userId); - } + forAllRootTasks(stack -> { + stack.switchUser(userId); }); final int restoreStackId = mUserRootTaskInFront.get(userId); @@ -2292,20 +2277,14 @@ class RootWindowContainer extends WindowContainer<DisplayContent> */ int finishTopCrashedActivities(WindowProcessController app, String reason) { Task focusedStack = getTopDisplayFocusedRootTask(); - Task finishedTask = reduceOnAllTaskDisplayAreas((taskDisplayArea, task) -> { - // It is possible that request to finish activity might also remove its task and - // stack, so we need to be careful with indexes in the loop and check child count - // every time. - for (int stackNdx = 0; stackNdx < taskDisplayArea.getRootTaskCount(); ++stackNdx) { - final Task stack = taskDisplayArea.getRootTaskAt(stackNdx); - final Task t = stack.finishTopCrashedActivityLocked(app, reason); - if (stack == focusedStack || task == null) { - task = t; - } + final Task[] finishedTask = new Task[1]; + forAllTasks(stack -> { + final Task t = stack.finishTopCrashedActivityLocked(app, reason); + if (stack == focusedStack || finishedTask[0] == null) { + finishedTask[0] = t; } - return task; - }, null /* initValue */); - return finishedTask != null ? finishedTask.mTaskId : INVALID_TASK_ID; + }); + return finishedTask[0] != null ? finishedTask[0].mTaskId : INVALID_TASK_ID; } boolean resumeFocusedTasksTopActivities() { @@ -2328,36 +2307,32 @@ class RootWindowContainer extends WindowContainer<DisplayContent> for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) { final DisplayContent display = getChildAt(displayNdx); final boolean curResult = result; - boolean resumedOnDisplay = display.reduceOnAllTaskDisplayAreas( - (taskDisplayArea, resumed) -> { - for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { - final Task rootTask = taskDisplayArea.getRootTaskAt(sNdx); - final ActivityRecord topRunningActivity = rootTask.topRunningActivity(); - if (!rootTask.isFocusableAndVisible() || topRunningActivity == null) { - continue; - } - if (rootTask == targetRootTask) { - // Simply update the result for targetStack because the targetStack - // had already resumed in above. We don't want to resume it again, - // especially in some cases, it would cause a second launch failure - // if app process was dead. - resumed |= curResult; - continue; - } - if (taskDisplayArea.isTopRootTask(rootTask) - && topRunningActivity.isState(RESUMED)) { - // Kick off any lingering app transitions form the MoveTaskToFront - // operation, but only consider the top task and stack on that - // display. - rootTask.executeAppTransition(targetOptions); - } else { - resumed |= topRunningActivity.makeActiveIfNeeded(target); - } - } - return resumed; - }, false /* initValue */); - result |= resumedOnDisplay; - if (!resumedOnDisplay) { + boolean[] resumedOnDisplay = new boolean[1]; + display.forAllRootTasks(rootTask -> { + final ActivityRecord topRunningActivity = rootTask.topRunningActivity(); + if (!rootTask.isFocusableAndVisible() || topRunningActivity == null) { + return; + } + if (rootTask == targetRootTask) { + // Simply update the result for targetStack because the targetStack + // had already resumed in above. We don't want to resume it again, + // especially in some cases, it would cause a second launch failure + // if app process was dead. + resumedOnDisplay[0] |= curResult; + return; + } + if (rootTask.getDisplayArea().isTopRootTask(rootTask) + && topRunningActivity.isState(RESUMED)) { + // Kick off any lingering app transitions form the MoveTaskToFront + // operation, but only consider the top task and stack on that + // display. + rootTask.executeAppTransition(targetOptions); + } else { + resumedOnDisplay[0] |= topRunningActivity.makeActiveIfNeeded(target); + } + }); + result |= resumedOnDisplay[0]; + if (!resumedOnDisplay[0]) { // In cases when there are no valid activities (e.g. device just booted or launcher // crashed) it's possible that nothing was resumed on a display. Requesting resume // of top activity in focused stack explicitly will make sure that at least home @@ -2390,30 +2365,27 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } // Set the sleeping state of the stacks on the display. - display.forAllTaskDisplayAreas(taskDisplayArea -> { - for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { - final Task stack = taskDisplayArea.getRootTaskAt(sNdx); - if (displayShouldSleep) { - stack.goToSleepIfPossible(false /* shuttingDown */); - } else { - stack.awakeFromSleepingLocked(); - if (stack.isFocusedStackOnDisplay() - && !mTaskSupervisor.getKeyguardController() - .isKeyguardOrAodShowing(display.mDisplayId)) { - // If the keyguard is unlocked - resume immediately. - // It is possible that the display will not be awake at the time we - // 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); - } - // 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 */, - false /* preserveWindows */); + display.forAllRootTasks(stack -> { + if (displayShouldSleep) { + stack.goToSleepIfPossible(false /* shuttingDown */); + } else { + stack.awakeFromSleepingLocked(); + if (stack.isFocusedStackOnDisplay() + && !mTaskSupervisor.getKeyguardController() + .isKeyguardOrAodShowing(display.mDisplayId)) { + // If the keyguard is unlocked - resume immediately. + // It is possible that the display will not be awake at the time we + // 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); } + // 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 */, + false /* preserveWindows */); } }); } @@ -2510,13 +2482,10 @@ class RootWindowContainer extends WindowContainer<DisplayContent> /** If displayId == INVALID_DISPLAY, this will get root task infos on all displays */ ArrayList<RootTaskInfo> getAllRootTaskInfos(int displayId) { - ArrayList<RootTaskInfo> list = new ArrayList<>(); + final ArrayList<RootTaskInfo> list = new ArrayList<>(); if (displayId == INVALID_DISPLAY) { - forAllTaskDisplayAreas(taskDisplayArea -> { - for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { - final Task stack = taskDisplayArea.getRootTaskAt(sNdx); - list.add(getRootTaskInfo(stack)); - } + forAllRootTasks(stack -> { + list.add(getRootTaskInfo(stack)); }); return list; } @@ -2524,11 +2493,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent> if (display == null) { return list; } - display.forAllTaskDisplayAreas(taskDisplayArea -> { - for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { - final Task stack = taskDisplayArea.getRootTaskAt(sNdx); - list.add(getRootTaskInfo(stack)); - } + display.forAllRootTasks(stack -> { + list.add(getRootTaskInfo(stack)); }); return list; } @@ -2601,10 +2567,17 @@ class RootWindowContainer extends WindowContainer<DisplayContent> Task findRootTaskBehind(Task rootTask) { final TaskDisplayArea taskDisplayArea = rootTask.getDisplayArea(); if (taskDisplayArea != null) { - for (int i = taskDisplayArea.getRootTaskCount() - 1; i >= 0; i--) { - if (taskDisplayArea.getRootTaskAt(i) == rootTask && i > 0) { - return taskDisplayArea.getRootTaskAt(i - 1); + final boolean[] hasFound = new boolean[1]; + // TODO(b/175136051): should this be only the direct child root task? + final Task rootTaskBehind = taskDisplayArea.getRootTask(task -> { + if (hasFound[0]) { + return true; } + hasFound[0] = task == rootTask; + return false; + }); + if (rootTaskBehind != null) { + return rootTaskBehind; } } throw new IllegalStateException("Failed to find a root task behind root task =" + rootTask @@ -2736,8 +2709,9 @@ class RootWindowContainer extends WindowContainer<DisplayContent> if (DEBUG_SWITCH) { Slog.v(TAG_SWITCH, "Destroying " + r + " in state " + r.getState() - + " resumed=" + r.getStack().mResumedActivity + " pausing=" - + r.getStack().mPausingActivity + " for reason " + mDestroyAllActivitiesReason); + + " resumed=" + r.getTask().getResumedActivity() + " pausing=" + + r.getTask().getPausingActivity() + " for reason " + + mDestroyAllActivitiesReason); } r.destroyImmediately(mDestroyAllActivitiesReason); @@ -2746,24 +2720,16 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // Tries to put all activity tasks to sleep. Returns true if all tasks were // successfully put to sleep. boolean putTasksToSleep(boolean allowDelay, boolean shuttingDown) { - return reduceOnAllTaskDisplayAreas((taskDisplayArea, result) -> { - for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { - // Stacks and activities could be removed while putting activities to sleep if - // the app process was gone. This prevents us getting exception by accessing an - // invalid stack index. - if (sNdx >= taskDisplayArea.getRootTaskCount()) { - continue; - } - final Task task = taskDisplayArea.getRootTaskAt(sNdx); - if (allowDelay) { - result &= task.goToSleepIfPossible(shuttingDown); - } else { - task.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, - !PRESERVE_WINDOWS); - } + final boolean[] result = {true}; + forAllRootTasks(task -> { + if (allowDelay) { + result[0] &= task.goToSleepIfPossible(shuttingDown); + } else { + task.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, + !PRESERVE_WINDOWS); } - return result; - }, true /* initValue */); + }); + return result[0]; } void handleAppCrash(WindowProcessController app) { @@ -3019,11 +2985,11 @@ class RootWindowContainer extends WindowContainer<DisplayContent> r.getActivityType()); // Return the topmost valid stack on the display. - for (int i = taskDisplayArea.getRootTaskCount() - 1; i >= 0; --i) { - final Task stack = taskDisplayArea.getRootTaskAt(i); - if (isValidLaunchRootTask(stack, r, windowingMode)) { - return stack; - } + final int targetWindowingMode = windowingMode; + final Task topmostValidStack = taskDisplayArea.getRootTask(stack -> + isValidLaunchRootTask(stack, r, targetWindowingMode)); + if (topmostValidStack != null) { + return topmostValidStack; } // If there is no valid stack on the secondary display area - check if new dynamic stack @@ -3258,12 +3224,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } void finishVoiceTask(IVoiceInteractionSession session) { - forAllTaskDisplayAreas(taskDisplayArea -> { - final int numStacks = taskDisplayArea.getRootTaskCount(); - for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { - final Task stack = taskDisplayArea.getRootTaskAt(stackNdx); - stack.finishVoiceTask(session); - } + forAllRootTasks(stack -> { + stack.finishVoiceTask(session); }); } @@ -3322,20 +3284,16 @@ class RootWindowContainer extends WindowContainer<DisplayContent> boolean allResumedActivitiesVisible() { boolean[] foundResumed = {false}; - final boolean foundInvisibleResumedActivity = forAllTaskDisplayAreas( - taskDisplayArea -> { - for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { - final Task stack = taskDisplayArea.getRootTaskAt(sNdx); - final ActivityRecord r = stack.getResumedActivity(); - if (r != null) { - if (!r.nowVisible) { - return true; - } - foundResumed[0] = true; - } - } - return false; - }); + final boolean foundInvisibleResumedActivity = forAllRootTasks(stack -> { + final ActivityRecord r = stack.getResumedActivity(); + if (r != null) { + if (!r.nowVisible) { + return true; + } + foundResumed[0] = true; + } + return false; + }); if (foundInvisibleResumedActivity) { return false; } @@ -3344,23 +3302,19 @@ class RootWindowContainer extends WindowContainer<DisplayContent> boolean allPausedActivitiesComplete() { boolean[] pausing = {true}; - final boolean hasActivityNotCompleted = forAllTaskDisplayAreas( - taskDisplayArea -> { - for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { - final Task stack = taskDisplayArea.getRootTaskAt(sNdx); - final ActivityRecord r = stack.mPausingActivity; - if (r != null && !r.isState(PAUSED, STOPPED, STOPPING, FINISHING)) { - ProtoLog.d(WM_DEBUG_STATES, "allPausedActivitiesComplete: " - + "r=%s state=%s", r, r.getState()); - if (WM_DEBUG_STATES.isEnabled()) { - pausing[0] = false; - } else { - return true; - } - } - } - return false; - }); + final boolean hasActivityNotCompleted = forAllLeafTasks(task -> { + final ActivityRecord r = task.getPausingActivity(); + if (r != null && !r.isState(PAUSED, STOPPED, STOPPING, FINISHING)) { + ProtoLog.d(WM_DEBUG_STATES, "allPausedActivitiesComplete: " + + "r=%s state=%s", r, r.getState()); + if (WM_DEBUG_STATES.isEnabled()) { + pausing[0] = false; + } else { + return true; + } + } + return false; + }); if (hasActivityNotCompleted) { return false; } @@ -3411,13 +3365,10 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } void cancelInitializingActivities() { - forAllTaskDisplayAreas(taskDisplayArea -> { - for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { - // We don't want to clear starting window for activities that aren't occluded - // as we need to display their starting window until they are done initializing. - taskDisplayArea.getRootTaskAt(sNdx).forAllOccludedActivities( - ActivityRecord::cancelInitializing); - } + forAllRootTasks(task -> { + // We don't want to clear starting window for activities that aren't occluded + // as we need to display their starting window until they are done initializing. + task.forAllOccludedActivities(ActivityRecord::cancelInitializing); }); } @@ -3577,13 +3528,10 @@ class RootWindowContainer extends WindowContainer<DisplayContent> return new ArrayList<>(); } } else { - ArrayList<ActivityRecord> activities = new ArrayList<>(); - forAllTaskDisplayAreas(taskDisplayArea -> { - for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { - final Task stack = taskDisplayArea.getRootTaskAt(sNdx); - if (!dumpVisibleStacksOnly || stack.shouldBeVisible(null)) { - activities.addAll(stack.getDumpActivitiesLocked(name)); - } + final ArrayList<ActivityRecord> activities = new ArrayList<>(); + forAllRootTasks(stack -> { + if (!dumpVisibleStacksOnly || stack.shouldBeVisible(null)) { + activities.addAll(stack.getDumpActivitiesLocked(name)); } }); return activities; @@ -3633,15 +3581,12 @@ class RootWindowContainer extends WindowContainer<DisplayContent> pw.print("Display #"); pw.print(displayContent.mDisplayId); pw.println(" (activities from top to bottom):"); - displayContent.forAllTaskDisplayAreas(taskDisplayArea -> { - for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { - final Task stack = taskDisplayArea.getRootTaskAt(sNdx); - if (needSep[0]) { - pw.println(); - } - needSep[0] = stack.dump(fd, pw, dumpAll, dumpClient, dumpPackage, false); - printed[0] |= needSep[0]; + displayContent.forAllRootTasks(stack -> { + if (needSep[0]) { + pw.println(); } + needSep[0] = stack.dump(fd, pw, dumpAll, dumpClient, dumpPackage, false); + printed[0] |= needSep[0]; }); displayContent.forAllTaskDisplayAreas(taskDisplayArea -> { printed[0] |= printThisActivity(pw, taskDisplayArea.getFocusedActivity(), diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index c414c6421dc8..57d48c6bb9f4 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -18,6 +18,7 @@ package com.android.server.wm; import static android.Manifest.permission.DEVICE_POWER; import static android.Manifest.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS; +import static android.Manifest.permission.HIDE_OVERLAY_WINDOWS; import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; import static android.Manifest.permission.START_TASKS_FROM_RECENTS; import static android.app.ActivityTaskManager.INVALID_TASK_ID; @@ -124,7 +125,9 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { mCanAddInternalSystemWindow = service.mContext.checkCallingOrSelfPermission( INTERNAL_SYSTEM_WINDOW) == PERMISSION_GRANTED; mCanHideNonSystemOverlayWindows = service.mContext.checkCallingOrSelfPermission( - HIDE_NON_SYSTEM_OVERLAY_WINDOWS) == PERMISSION_GRANTED; + HIDE_NON_SYSTEM_OVERLAY_WINDOWS) == PERMISSION_GRANTED + || service.mContext.checkCallingOrSelfPermission(HIDE_OVERLAY_WINDOWS) + == PERMISSION_GRANTED; mOverlaysCanBeHidden = !mCanAddInternalSystemWindow && !mService.mAtmInternal.isCallerRecents(mUid); mCanAcquireSleepToken = service.mContext.checkCallingOrSelfPermission(DEVICE_POWER) diff --git a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java index 34d084a3f9f8..92e2ee6f8af9 100644 --- a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java +++ b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java @@ -259,6 +259,7 @@ class SurfaceAnimationRunner { private void applyTransaction() { mFrameTransaction.setAnimationTransaction(); + mFrameTransaction.setFrameTimelineVsync(mChoreographer.getVsyncId()); mFrameTransaction.apply(); mApplyScheduled = false; } diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 8564cbc02df8..69723ff99d06 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -59,7 +59,7 @@ import static android.provider.Settings.Secure.USER_SETUP_COMPLETE; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; import static android.view.SurfaceControl.METADATA_TASK_ID; -import static android.view.WindowManager.TRANSIT_CHANGE_WINDOWING_MODE; +import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_FLAG_APP_CRASHED; import static android.view.WindowManager.TRANSIT_FLAG_OPEN_BEHIND; @@ -514,16 +514,6 @@ class Task extends WindowContainer<WindowContainer> { // {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE} flag of the root activity. boolean mSupportsPictureInPicture; - // Activity bounds if this task or its top activity is presented in letterbox mode and - // {@code null} otherwise. - @Nullable - private Rect mLetterboxActivityBounds; - - // Activity insets if this task or its top activity is presented in letterbox mode and - // {@code null} otherwise. - @Nullable - private Rect mLetterboxActivityInsets; - // Whether the task is currently being drag-resized private boolean mDragResizing; private int mDragResizeMode; @@ -553,8 +543,11 @@ class Task extends WindowContainer<WindowContainer> { /** * When we are in the process of pausing an activity, before starting the * next one, this variable holds the activity that is currently being paused. + * + * Only set at leaf tasks. */ - ActivityRecord mPausingActivity = null; + @Nullable + private ActivityRecord mPausingActivity = null; /** * This is the last activity that we put into the paused state. This is @@ -570,8 +563,12 @@ class Task extends WindowContainer<WindowContainer> { */ ActivityRecord mLastNoHistoryActivity = null; - /** Current activity that is resumed, or null if there is none. */ - ActivityRecord mResumedActivity = null; + /** + * Current activity that is resumed, or null if there is none. + * Only set at leaf tasks. + */ + @Nullable + private ActivityRecord mResumedActivity = null; /** Last activity that is used to compute the Task bounds. */ @Nullable @@ -1111,14 +1108,6 @@ class Task extends WindowContainer<WindowContainer> { return false; } - final boolean toTopOfStack = position == MAX_VALUE; - if (toTopOfStack && toStack.getResumedActivity() != null - && toStack.topRunningActivity() != null) { - // Pause the resumed activity on the target stack while re-parenting task on top of it. - toStack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */, - null /* resuming */, "reparent"); - } - final int toStackWindowingMode = toStack.getWindowingMode(); final ActivityRecord topActivity = getTopNonFinishingActivity(); @@ -1142,8 +1131,6 @@ class Task extends WindowContainer<WindowContainer> { final ActivityRecord r = topRunningActivityLocked(); final boolean wasFocused = r != null && root.isTopDisplayFocusedRootTask(sourceStack) && (topRunningActivityLocked() == r); - final boolean wasResumed = r != null && sourceStack.getResumedActivity() == r; - final boolean wasPaused = r != null && sourceStack.mPausingActivity == r; // In some cases the focused stack isn't the front stack. E.g. pinned stack. // Whenever we are moving the top activity from the front stack we want to make sure to @@ -1164,9 +1151,15 @@ class Task extends WindowContainer<WindowContainer> { // If the task had focus before (or we're requested to move focus), move focus to the // new stack by moving the stack to the front. - if (r != null) { - toStack.moveToFrontAndResumeStateIfNeeded(r, moveStackToFront, wasResumed, - wasPaused, reason); + if (r != null && moveStackToFront) { + // Move the stack in which we are placing the activity to the front. + toStack.moveToFront(reason); + + // If the original state is resumed, there is no state change to update focused app. + // So here makes sure the activity focus is set if it is the top. + if (r.isState(RESUMED) && r == mRootWindowContainer.getTopResumedActivity()) { + mAtmService.setResumedActivityUncheckLocked(r, reason); + } } if (!animate) { mTaskSupervisor.mNoAnimActivities.add(topActivity); @@ -1462,15 +1455,6 @@ class Task extends WindowContainer<WindowContainer> { } if (newParent != null) { - final Task newParentTask = ((WindowContainer) newParent).asTask(); - if (newParentTask != null) { - final ActivityRecord top = newParentTask.getTopNonFinishingActivity( - false /* includeOverlays */); - if (top != null && top.isState(RESUMED)) { - newParentTask.setResumedActivity(top, "addedToTask"); - } - } - // TODO: Ensure that this is actually necessary here // Notify the voice session if required if (voiceSession != null) { @@ -1507,6 +1491,15 @@ class Task extends WindowContainer<WindowContainer> { mLastTaskBoundsComputeActivity = null; } + // mPausingActivity is set at leaf task + if (mPausingActivity != null && mPausingActivity == r) { + mPausingActivity = null; + } + + if (mResumedActivity != null && mResumedActivity == r) { + setResumedActivity(null, "cleanUpActivityReferences"); + } + final WindowContainer parent = getParent(); if (parent != null && parent.asTask() != null) { parent.asTask().cleanUpActivityReferences(r); @@ -1514,21 +1507,38 @@ class Task extends WindowContainer<WindowContainer> { } r.removeTimeouts(); mExitingActivities.remove(r); - - if (mResumedActivity != null && mResumedActivity == r) { - setResumedActivity(null, "cleanUpActivityReferences"); - } - if (mPausingActivity != null && mPausingActivity == r) { - mPausingActivity = null; - } } /** @return the currently resumed activity. */ ActivityRecord getResumedActivity() { - return mResumedActivity; + if (isLeafTask()) { + return mResumedActivity; + } + + final Task task = getTask(t -> t.mResumedActivity != null, true /* traverseTopToBottom */); + return task != null ? task.mResumedActivity : null; + } + + @VisibleForTesting + void setPausingActivity(ActivityRecord pausing) { + mPausingActivity = pausing; + } + + /** + * @return the currently pausing activity of this task or the topmost pausing activity of the + * child tasks + */ + ActivityRecord getPausingActivity() { + if (isLeafTask()) { + return mPausingActivity; + } + + final Task task = getTask(t -> t.mPausingActivity != null, true /* traverseTopToBottom */); + return task != null ? task.mPausingActivity : null; } void setResumedActivity(ActivityRecord r, String reason) { + warnForNonLeafTask("setResumedActivity"); if (mResumedActivity == r) { return; } @@ -2168,17 +2178,7 @@ class Task extends WindowContainer<WindowContainer> { * @param reason The reason for the change. */ void onActivityStateChanged(ActivityRecord record, ActivityState state, String reason) { - final Task parentTask = getParent().asTask(); - if (parentTask != null) { - parentTask.onActivityStateChanged(record, state, reason); - // We still want to update the resumed activity if the parent task is created by - // organizer in order to keep the information synced once got reparented out from the - // organized task. - if (!parentTask.mCreatedByOrganizer) { - return; - } - } - + warnForNonLeafTask("onActivityStateChanged"); if (record == mResumedActivity && state != RESUMED) { setResumedActivity(null, reason + " - onActivityStateChanged"); } @@ -2356,7 +2356,7 @@ class Task extends WindowContainer<WindowContainer> { * Initializes a change transition. See {@link SurfaceFreezer} for more information. */ private void initializeChangeTransition(Rect startBounds) { - mDisplayContent.prepareAppTransition(TRANSIT_CHANGE_WINDOWING_MODE); + mDisplayContent.prepareAppTransition(TRANSIT_CHANGE); mDisplayContent.mChangingContainers.add(this); mSurfaceFreezer.freeze(getPendingTransaction(), startBounds); @@ -2440,8 +2440,7 @@ class Task extends WindowContainer<WindowContainer> { @Override public SurfaceControl getFreezeSnapshotTarget() { - if (!mDisplayContent.mAppTransition.containsTransitRequest( - TRANSIT_CHANGE_WINDOWING_MODE)) { + if (!mDisplayContent.mAppTransition.containsTransitRequest(TRANSIT_CHANGE)) { return null; } // Skip creating snapshot if this transition is controlled by a remote animator which @@ -3135,12 +3134,12 @@ class Task extends WindowContainer<WindowContainer> { // and focused application if needed. focusableTask.moveToFront(myReason); // Top display focused stack is changed, update top resumed activity if needed. - if (rootTask.mResumedActivity != null) { + if (rootTask.getResumedActivity() != null) { mTaskSupervisor.updateTopResumedActivityIfNeeded(); // Set focused app directly because if the next focused activity is already resumed // (e.g. the next top activity is on a different display), there won't have activity // state change to update it. - mAtmService.setResumedActivityUncheckLocked(rootTask.mResumedActivity, reason); + mAtmService.setResumedActivityUncheckLocked(rootTask.getResumedActivity(), reason); } return rootTask; } @@ -3879,6 +3878,13 @@ class Task extends WindowContainer<WindowContainer> { } @Override + void forAllRootTasks(Consumer<Task> callback, boolean traverseTopToBottom) { + if (isRootTask()) { + callback.accept(this); + } + } + + @Override boolean forAllTasks(Function<Task, Boolean> callback) { if (super.forAllTasks(callback)) return true; return callback.apply(this); @@ -3903,12 +3909,29 @@ class Task extends WindowContainer<WindowContainer> { } @Override + boolean forAllRootTasks(Function<Task, Boolean> callback, boolean traverseTopToBottom) { + return isRootTask() ? callback.apply(this) : false; + } + + @Override Task getTask(Predicate<Task> callback, boolean traverseTopToBottom) { final Task t = super.getTask(callback, traverseTopToBottom); if (t != null) return t; return callback.test(this) ? this : null; } + @Nullable + @Override + Task getRootTask(Predicate<Task> callback, boolean traverseTopToBottom) { + return isRootTask() && callback.test(this) ? this : null; + } + + @Nullable + @Override + <R> R getItemFromRootTasks(Function<Task, R> callback, boolean traverseTopToBottom) { + return isRootTask() ? callback.apply(this) : null; + } + /** * @param canAffectSystemUiFlags If false, all windows in this task can not affect SystemUI * flags. See {@link WindowState#canAffectSystemUiFlags()}. @@ -4083,16 +4106,10 @@ class Task extends WindowContainer<WindowContainer> { info.resizeMode = top != null ? top.mResizeMode : mResizeMode; info.topActivityType = top.getActivityType(); info.isResizeable = isResizeable(); - // Don't query getTopNonFinishingActivity().getBounds() directly because when fillTaskInfo - // is triggered for the first time after activities change, getBounds() may return non final - // bounds, e.g. fullscreen bounds instead of letterboxed bounds. To work around this, - // assigning bounds from ActivityRecord#layoutLetterbox when they are ready. - info.letterboxActivityBounds = Rect.copyOrNull(mLetterboxActivityBounds); - info.letterboxActivityInsets = Rect.copyOrNull(mLetterboxActivityInsets); + info.positionInParent = getRelativePosition(); - info.parentBounds = getParentBounds(); - info.pictureInPictureParams = getPictureInPictureParams(); + info.pictureInPictureParams = getPictureInPictureParams(top); info.topActivityInfo = mReuseActivitiesReport.top != null ? mReuseActivitiesReport.top.info : null; @@ -4109,34 +4126,16 @@ class Task extends WindowContainer<WindowContainer> { } @Nullable PictureInPictureParams getPictureInPictureParams() { - final Task top = getTopMostTask(); + return getPictureInPictureParams(getTopMostTask()); + } + + private @Nullable PictureInPictureParams getPictureInPictureParams(Task top) { if (top == null) return null; final ActivityRecord rootActivity = top.getRootActivity(); return (rootActivity == null || rootActivity.pictureInPictureArgs.empty()) ? null : new PictureInPictureParams(rootActivity.pictureInPictureArgs); } - void maybeUpdateLetterboxInTaskOrganizer( - ActivityRecord activityRecord, - @Nullable Rect activityBounds, - @Nullable Rect activityInsets) { - if (isOrganized() - && mReuseActivitiesReport.top == activityRecord - // Want to force update only if letterbox bounds have changed. - && (!Objects.equals(mLetterboxActivityBounds, activityBounds) - || !Objects.equals(mLetterboxActivityInsets, activityInsets))) { - mLetterboxActivityBounds = Rect.copyOrNull(activityBounds); - mLetterboxActivityInsets = Rect.copyOrNull(activityInsets); - // Forcing update to reduce visual jank during the transition. - dispatchTaskInfoChangedIfNeeded(true /* force */); - } - } - - private Rect getParentBounds() { - final WindowContainer parent = getParent(); - return parent != null ? new Rect(parent.getBounds()) : new Rect(); - } - /** * Returns a {@link TaskInfo} with information from this task. */ @@ -5422,6 +5421,12 @@ class Task extends WindowContainer<WindowContainer> { } void awakeFromSleepingLocked() { + if (!isLeafTask()) { + forAllLeafTasks((task) -> task.awakeFromSleepingLocked(), + true /* traverseTopToBottom */); + return; + } + if (mPausingActivity != null) { Slog.d(TAG, "awakeFromSleepingLocked: previously pausing activity didn't pause"); mPausingActivity.activityPaused(true); @@ -5446,8 +5451,17 @@ class Task extends WindowContainer<WindowContainer> { * process of going to sleep (checkReadyForSleep will be called when that process finishes). */ boolean goToSleepIfPossible(boolean shuttingDown) { - boolean shouldSleep = true; + if (!isLeafTask()) { + final int[] sleepInProgress = {0}; + forAllLeafTasks((t) -> { + if (!t.goToSleepIfPossible(shuttingDown)) { + sleepInProgress[0]++; + } + }, true); + return sleepInProgress[0] == 0; + } + boolean shouldSleep = true; if (mResumedActivity != null) { // Still have something resumed; can't sleep until it is paused. ProtoLog.v(WM_DEBUG_STATES, "Sleep needs to pause %s", mResumedActivity); @@ -5507,6 +5521,16 @@ class Task extends WindowContainer<WindowContainer> { */ final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, ActivityRecord resuming, String reason) { + if (!isLeafTask()) { + final int[] pausing = {0}; + forAllLeafTasks((t) -> { + if (t.startPausingLocked(userLeaving, uiSleeping, resuming, reason)) { + pausing[0]++; + } + }, true /* traverseTopToBottom */); + return pausing[0] > 0; + } + if (mPausingActivity != null) { Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity + " state=" + mPausingActivity.getState()); @@ -5637,6 +5661,10 @@ class Task extends WindowContainer<WindowContainer> { @VisibleForTesting void completePauseLocked(boolean resumeNext, ActivityRecord resuming) { + // Complete the pausing process of a pausing activity, so it doesn't make sense to + // operate on non-leaf tasks. + warnForNonLeafTask("completePauseLocked"); + ActivityRecord prev = mPausingActivity; ProtoLog.v(WM_DEBUG_STATES, "Complete pause: %s", prev); @@ -5896,24 +5924,34 @@ class Task extends WindowContainer<WindowContainer> { return false; } - boolean result = false; + boolean someActivityResumed = false; try { // Protect against recursion. mInResumeTopActivity = true; - // TODO(b/172885410): Allow the top activities of all visible leaf tasks to be resumed - if (mCreatedByOrganizer && !isLeafTask() - && getConfiguration().windowConfiguration.getWindowingMode() - == WINDOWING_MODE_FULLSCREEN) { - for (int i = mChildren.size() - 1; i >= 0; i--) { - final Task child = (Task) getChildAt(i); - if (!child.shouldBeVisible(null /* starting */)) { + if (isLeafTask()) { + someActivityResumed = resumeTopActivityInnerLocked(prev, options); + } else { + int idx = mChildren.size() - 1; + while (idx >= 0) { + final Task child = (Task) getChildAt(idx--); + if (!child.isFocusableAndVisible()) { break; } - result |= child.resumeTopActivityUncheckedLocked(prev, options); + + // Only allow one activity to be resumed among sibling tasks in split-screen. + if (inSplitScreenWindowingMode() && someActivityResumed) { + break; + } + + someActivityResumed |= child.resumeTopActivityUncheckedLocked(prev, options); + // Doing so in order to prevent IndexOOB since hierarchy might changes while + // resuming activities, for example dismissing split-screen while starting + // non-resizeable activity. + if (idx >= mChildren.size()) { + idx = mChildren.size() - 1; + } } - } else { - result = resumeTopActivityInnerLocked(prev, options); } // When resuming the top activity, it may be necessary to pause the top activity (for @@ -5931,7 +5969,7 @@ class Task extends WindowContainer<WindowContainer> { mInResumeTopActivity = false; } - return result; + return someActivityResumed; } @GuardedBy("mService") @@ -6045,7 +6083,7 @@ class Task extends WindowContainer<WindowContainer> { // So, why aren't we using prev here??? See the param comment on the method. prev // doesn't represent the last resumed activity. However, the last focus stack does if // it isn't null. - lastResumed = lastFocusedStack.mResumedActivity; + lastResumed = lastFocusedStack.getResumedActivity(); if (userLeaving && inMultiWindowMode() && lastFocusedStack.shouldBeVisible(next)) { // The user isn't leaving if this stack is the multi-window mode and the last // focused stack should still be visible. @@ -6214,7 +6252,7 @@ class Task extends WindowContainer<WindowContainer> { next.startLaunchTickingLocked(); ActivityRecord lastResumedActivity = - lastFocusedStack == null ? null : lastFocusedStack.mResumedActivity; + lastFocusedStack == null ? null : lastFocusedStack.getResumedActivity(); final ActivityState lastState = next.getState(); mAtmService.updateCpuStats(); @@ -7068,6 +7106,7 @@ class Task extends WindowContainer<WindowContainer> { * @return {@code true} if the process of the pausing activity is died. */ boolean handleAppDied(WindowProcessController app) { + warnForNonLeafTask("handleAppDied"); boolean isPausingDied = false; if (mPausingActivity != null && mPausingActivity.app == app) { ProtoLog.v(WM_DEBUG_STATES, "App died while pausing: %s", @@ -7105,7 +7144,7 @@ class Task extends WindowContainer<WindowContainer> { printed = true; } - printed |= printThisActivity(pw, mPausingActivity, dumpPackage, false, + printed |= printThisActivity(pw, getPausingActivity(), dumpPackage, false, " mPausingActivity: ", null); printed |= printThisActivity(pw, getResumedActivity(), dumpPackage, false, " mResumedActivity: ", null); @@ -7284,7 +7323,7 @@ class Task extends WindowContainer<WindowContainer> { task.updateOverrideConfigurationForStack(this); final ActivityRecord topRunningActivity = task.topRunningActivityLocked(); - final boolean wasResumed = topRunningActivity == task.getRootTask().mResumedActivity; + final boolean wasResumed = topRunningActivity == task.mResumedActivity; boolean toTop = position >= getChildCount(); boolean includingParents = toTop || getDisplayArea().getNextFocusableRootTask(this, @@ -7307,7 +7346,7 @@ class Task extends WindowContainer<WindowContainer> { if (wasResumed) { if (mResumedActivity != null) { Log.wtf(TAG, "mResumedActivity was already set when moving mResumedActivity from" - + " other stack to this stack mResumedActivity=" + mResumedActivity + + " other stack to this task mResumedActivity=" + mResumedActivity + " other mResumedActivity=" + topRunningActivity); } topRunningActivity.setState(RESUMED, "positionChildAt"); @@ -7333,34 +7372,6 @@ class Task extends WindowContainer<WindowContainer> { taskDisplayArea.positionChildAt(POSITION_TOP, this, false /* includingParents */); } - /** NOTE: Should only be called from {@link Task#reparent}. */ - void moveToFrontAndResumeStateIfNeeded(ActivityRecord r, boolean moveToFront, boolean setResume, - boolean setPause, String reason) { - if (!moveToFront) { - return; - } - - final ActivityState origState = r.getState(); - // If the activity owns the last resumed activity, transfer that together, - // so that we don't resume the same activity again in the new stack. - // Apps may depend on onResume()/onPause() being called in pairs. - if (setResume) { - r.setState(RESUMED, "moveToFrontAndResumeStateIfNeeded"); - } - // If the activity was previously pausing, then ensure we transfer that as well - if (setPause) { - mPausingActivity = r; - r.schedulePauseTimeout(); - } - // Move the stack in which we are placing the activity to the front. - moveToFront(reason); - // If the original state is resumed, there is no state change to update focused app. - // So here makes sure the activity focus is set if it is the top. - if (origState == RESUMED && r == mRootWindowContainer.getTopResumedActivity()) { - mAtmService.setResumedActivityUncheckLocked(r, reason); - } - } - void dismissPip() { if (!isActivityTypeStandardOrUndefined()) { throw new IllegalArgumentException( @@ -7510,6 +7521,15 @@ class Task extends WindowContainer<WindowContainer> { } /** + * Simply check and give warning logs if this is not operated on leaf task. + */ + private void warnForNonLeafTask(String func) { + if (!isLeafTask()) { + Slog.w(TAG, func + " on non-leaf task " + this); + } + } + + /** * Sets the current picture-in-picture aspect ratio. */ void setPictureInPictureAspectRatio(float aspectRatio) { diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java index 9425602763c5..7fed84015e8b 100644 --- a/services/core/java/com/android/server/wm/TaskDisplayArea.java +++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java @@ -33,7 +33,6 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; -import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_TASKS; @@ -474,7 +473,7 @@ final class TaskDisplayArea extends DisplayArea<Task> { private int findMinPositionForRootTask(Task rootTask) { int minPosition = POSITION_BOTTOM; for (int i = 0; i < mChildren.size(); ++i) { - if (getPriority(getRootTaskAt(i)) < getPriority(rootTask)) { + if (getPriority(mChildren.get(i)) < getPriority(rootTask)) { minPosition = i; } else { break; @@ -495,7 +494,7 @@ final class TaskDisplayArea extends DisplayArea<Task> { private int findMaxPositionForRootTask(Task rootTask) { for (int i = mChildren.size() - 1; i >= 0; --i) { - final Task curr = getRootTaskAt(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 boolean sameRootTask = curr == rootTask; @@ -610,34 +609,6 @@ final class TaskDisplayArea extends DisplayArea<Task> { return false; } - void setExitingTokensHasVisible(boolean hasVisible) { - for (int i = mChildren.size() - 1; i >= 0; --i) { - final ArrayList<ActivityRecord> activities = mChildren.get(i).mExitingActivities; - for (int j = activities.size() - 1; j >= 0; --j) { - activities.get(j).hasVisible = hasVisible; - } - } - } - - void removeExistingAppTokensIfPossible() { - for (int i = mChildren.size() - 1; i >= 0; --i) { - final ArrayList<ActivityRecord> activities = mChildren.get(i).mExitingActivities; - for (int j = activities.size() - 1; j >= 0; --j) { - final ActivityRecord activity = activities.get(j); - if (!activity.hasVisible && !mDisplayContent.mClosingApps.contains(activity) - && (!activity.mIsExiting || activity.isEmpty())) { - // Make sure there is no animation running on this activity, so any windows - // associated with it will be removed as soon as their animations are - // complete. - cancelAnimation(); - ProtoLog.v(WM_DEBUG_ADD_REMOVE, - "performLayout: Activity exiting now removed %s", activity); - activity.removeIfPossible(); - } - } - } - } - @Override int getOrientation(int candidate) { mLastOrientationSource = null; @@ -894,16 +865,6 @@ final class TaskDisplayArea extends DisplayArea<Task> { } } - Task getRootTask(int rootTaskId) { - for (int i = getRootTaskCount() - 1; i >= 0; --i) { - final Task stack = getRootTaskAt(i); - if (stack.getRootTaskId() == rootTaskId) { - return stack; - } - } - return null; - } - /** * Returns an existing stack compatible with the windowing mode and activity type or creates one * if a compatible stack doesn't exist. @@ -1065,15 +1026,15 @@ final class TaskDisplayArea extends DisplayArea<Task> { // Only split-screen windowing modes can do this currently... return null; } - for (int i = getRootTaskCount() - 1; i >= 0; --i) { - final Task t = getRootTaskAt(i); + for (int i = mChildren.size() - 1; i >= 0; --i) { + final Task t = mChildren.get(i); if (!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 = getRootTaskCount(); j < n; ++j) { - final Task tt = getRootTaskAt(j); + for (int j = 0, n = mChildren.size(); j < n; ++j) { + final Task tt = mChildren.get(j); if (tt.mCreatedByOrganizer && tt != t) { mLaunchRootTask = tt; break; @@ -1128,8 +1089,8 @@ final class TaskDisplayArea extends DisplayArea<Task> { return mPreferredTopFocusableRootTask; } - for (int i = getRootTaskCount() - 1; i >= 0; --i) { - final Task stack = getRootTaskAt(i); + for (int i = mChildren.size() - 1; i >= 0; --i) { + final Task stack = mChildren.get(i); if (stack.isFocusableAndVisible()) { return stack; } @@ -1143,8 +1104,8 @@ final class TaskDisplayArea extends DisplayArea<Task> { ? currentFocus.getWindowingMode() : WINDOWING_MODE_UNDEFINED; Task candidate = null; - for (int i = getRootTaskCount() - 1; i >= 0; --i) { - final Task rootTask = getRootTaskAt(i); + for (int i = mChildren.size() - 1; i >= 0; --i) { + final Task rootTask = mChildren.get(i); if (ignoreCurrent && rootTask == currentFocus) { continue; } @@ -1184,7 +1145,7 @@ final class TaskDisplayArea extends DisplayArea<Task> { if (resumedActivity == null || resumedActivity.app == null) { // If there is no registered resumed activity in the stack or it is not running - // try to use previously resumed one. - resumedActivity = focusedStack.mPausingActivity; + resumedActivity = focusedStack.getPausingActivity(); if (resumedActivity == null || resumedActivity.app == null) { // If previously resumed activity doesn't work either - find the topmost running // activity that can be focused. @@ -1223,8 +1184,8 @@ final class TaskDisplayArea extends DisplayArea<Task> { } boolean allResumedActivitiesComplete() { - for (int stackNdx = getRootTaskCount() - 1; stackNdx >= 0; --stackNdx) { - final ActivityRecord r = getRootTaskAt(stackNdx).getResumedActivity(); + for (int stackNdx = mChildren.size() - 1; stackNdx >= 0; --stackNdx) { + final ActivityRecord r = mChildren.get(stackNdx).getResumedActivity(); if (r != null && !r.isState(RESUMED)) { return false; } @@ -1250,20 +1211,21 @@ final class TaskDisplayArea extends DisplayArea<Task> { * @return {@code true} if any activity was paused as a result of this call. */ boolean pauseBackTasks(boolean userLeaving, ActivityRecord resuming) { - boolean someActivityPaused = false; - for (int stackNdx = getRootTaskCount() - 1; stackNdx >= 0; --stackNdx) { - final Task stack = getRootTaskAt(stackNdx); - final ActivityRecord resumedActivity = stack.getResumedActivity(); + final int[] someActivityPaused = {0}; + forAllLeafTasks((task) -> { + final ActivityRecord resumedActivity = task.getResumedActivity(); if (resumedActivity != null - && (stack.getVisibility(resuming) != TASK_VISIBILITY_VISIBLE - || !stack.isTopActivityFocusable())) { - ProtoLog.d(WM_DEBUG_STATES, "pauseBackStacks: stack=%s " - + "mResumedActivity=%s", stack, resumedActivity); - someActivityPaused |= stack.startPausingLocked(userLeaving, false /* uiSleeping*/, - resuming, "pauseBackStacks"); + && (task.getVisibility(resuming) != TASK_VISIBILITY_VISIBLE + || !task.isTopActivityFocusable())) { + ProtoLog.d(WM_DEBUG_STATES, "pauseBackStacks: task=%s " + + "mResumedActivity=%s", task, resumedActivity); + if (task.startPausingLocked(userLeaving, false /* uiSleeping*/, + resuming, "pauseBackStacks")) { + someActivityPaused[0]++; + } } - } - return someActivityPaused; + }, true /* traverseTopToBottom */); + return someActivityPaused[0] > 0; } /** @@ -1272,8 +1234,8 @@ final class TaskDisplayArea extends DisplayArea<Task> { void findTaskLocked(final ActivityRecord r, final boolean isPreferredDisplayArea, RootWindowContainer.FindTaskResult result) { mTmpFindTaskResult.clear(); - for (int stackNdx = getRootTaskCount() - 1; stackNdx >= 0; --stackNdx) { - final Task stack = getRootTaskAt(stackNdx); + 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); @@ -1300,69 +1262,6 @@ final class TaskDisplayArea extends DisplayArea<Task> { } } - /** - * Removes root tasks in the input windowing modes from the system if they are of activity type - * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED - */ - void removeRootTasksInWindowingModes(int... windowingModes) { - if (windowingModes == null || windowingModes.length == 0) { - return; - } - - // Collect the root tasks that are necessary to be removed instead of performing the removal - // by looping the children, so that we don't miss any root tasks after the children size - // changed or reordered. - final ArrayList<Task> rootTasks = new ArrayList<>(); - for (int j = windowingModes.length - 1; j >= 0; --j) { - final int windowingMode = windowingModes[j]; - for (int i = mChildren.size() - 1; i >= 0; --i) { - final Task rootTask = mChildren.get(i); - if (rootTask.mCreatedByOrganizer - || !rootTask.isActivityTypeStandardOrUndefined() - || rootTask.getWindowingMode() != windowingMode) { - continue; - } - rootTasks.add(rootTask); - } - } - - for (int i = rootTasks.size() - 1; i >= 0; --i) { - mRootWindowContainer.mTaskSupervisor.removeRootTask(rootTasks.get(i)); - } - } - - void removeRootTasksWithActivityTypes(int... activityTypes) { - if (activityTypes == null || activityTypes.length == 0) { - return; - } - - // Collect the root tasks that are necessary to be removed instead of performing the removal - // by looping the children, so that we don't miss any root tasks after the children size - // changed or reordered. - final ArrayList<Task> rootTasks = new ArrayList<>(); - for (int j = activityTypes.length - 1; j >= 0; --j) { - final int activityType = activityTypes[j]; - for (int i = mChildren.size() - 1; i >= 0; --i) { - final Task rootTask = mChildren.get(i); - // Collect the root tasks that are currently being organized. - if (rootTask.mCreatedByOrganizer) { - for (int k = rootTask.getChildCount() - 1; k >= 0; --k) { - final Task task = (Task) rootTask.getChildAt(k); - if (task.getActivityType() == activityType) { - rootTasks.add(task); - } - } - } else if (rootTask.getActivityType() == activityType) { - rootTasks.add(rootTask); - } - } - } - - for (int i = rootTasks.size() - 1; i >= 0; --i) { - mRootWindowContainer.mTaskSupervisor.removeRootTask(rootTasks.get(i)); - } - } - void onSplitScreenModeDismissed() { // The focused task could be a non-resizeable fullscreen root task that is on top of the // other split-screen tasks, therefore had to dismiss split-screen, make sure the current @@ -1582,8 +1481,8 @@ final class TaskDisplayArea extends DisplayArea<Task> { // Look in other focusable stacks. if (topRunning == null) { - for (int i = getRootTaskCount() - 1; i >= 0; --i) { - final Task stack = getRootTaskAt(i); + 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()) { continue; @@ -1608,11 +1507,11 @@ final class TaskDisplayArea extends DisplayArea<Task> { } protected int getRootTaskCount() { - return mChildren.size(); - } - - protected Task getRootTaskAt(int index) { - return mChildren.get(index); + final int[] count = new int[1]; + forAllRootTasks(task -> { + count[0]++; + }); + return count[0]; } @Nullable @@ -1711,9 +1610,9 @@ final class TaskDisplayArea extends DisplayArea<Task> { // Find the next position where the stack should be placed final boolean isRootTask = rootTask.isRootTask(); final int numRootTasks = - isRootTask ? getRootTaskCount() : rootTask.getParent().getChildCount(); + isRootTask ? mChildren.size() : rootTask.getParent().getChildCount(); for (int rootTaskNdx = 0; rootTaskNdx < numRootTasks; rootTaskNdx++) { - final Task s = isRootTask ? getRootTaskAt(rootTaskNdx) + final Task s = isRootTask ? mChildren.get(rootTaskNdx) : (Task) rootTask.getParent().getChildAt(rootTaskNdx); if (s == rootTask) { continue; @@ -1836,8 +1735,8 @@ final class TaskDisplayArea extends DisplayArea<Task> { boolean preserveWindows, boolean notifyClients, boolean userLeaving) { mAtmService.mTaskSupervisor.beginActivityVisibilityUpdate(); try { - for (int stackNdx = getRootTaskCount() - 1; stackNdx >= 0; --stackNdx) { - final Task stack = getRootTaskAt(stackNdx); + for (int stackNdx = mChildren.size() - 1; stackNdx >= 0; --stackNdx) { + final Task stack = mChildren.get(stackNdx); stack.ensureActivitiesVisible(starting, configChanges, preserveWindows, notifyClients, userLeaving); } @@ -1846,13 +1745,6 @@ final class TaskDisplayArea extends DisplayArea<Task> { } } - void prepareFreezingTaskBounds() { - for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) { - final Task stack = getChildAt(stackNdx); - stack.prepareFreezingTaskBounds(); - } - } - /** * Removes the stacks in the node applying the content removal node from the display. * @@ -1871,13 +1763,13 @@ final class TaskDisplayArea extends DisplayArea<Task> { // related WindowContainer will also be removed. So, we set display area as removed after // reparenting stack finished. // Keep the order from bottom to top. - int numStacks = getRootTaskCount(); + int numStacks = mChildren.size(); final boolean splitScreenActivated = toDisplayArea.isSplitScreenModeActivated(); final Task rootStack = splitScreenActivated ? toDisplayArea .getTopRootTaskInWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) : null; for (int stackNdx = 0; stackNdx < numStacks; stackNdx++) { - final Task stack = getRootTaskAt(stackNdx); + final Task stack = mChildren.get(stackNdx); // Always finish non-standard type stacks and stacks created by a organizer. // TODO: For stacks created by organizer, consider reparenting children tasks if the use // case arises in the future. @@ -1897,8 +1789,8 @@ final class TaskDisplayArea extends DisplayArea<Task> { } // Stacks may be removed from this display. Ensure each stack will be processed // and the loop will end. - stackNdx -= numStacks - getRootTaskCount(); - numStacks = getRootTaskCount(); + stackNdx -= numStacks - mChildren.size(); + numStacks = mChildren.size(); } if (lastReparentedStack != null && splitScreenActivated) { if (!lastReparentedStack.supportsSplitScreenWindowingMode()) { diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java index 9d36b84431f3..a7306c97bd2a 100644 --- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java +++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java @@ -795,17 +795,13 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { private void adjustBoundsToAvoidConflictInDisplay(@NonNull DisplayContent display, @NonNull Rect inOutBounds) { final List<Rect> taskBoundsToCheck = new ArrayList<>(); - display.forAllTaskDisplayAreas(taskDisplayArea -> { - int numStacks = taskDisplayArea.getRootTaskCount(); - for (int sNdx = 0; sNdx < numStacks; ++sNdx) { - final Task task = taskDisplayArea.getRootTaskAt(sNdx); - if (!task.inFreeformWindowingMode()) { - continue; - } + display.forAllRootTasks(task -> { + if (!task.inFreeformWindowingMode()) { + return; + } - for (int j = 0; j < task.getChildCount(); ++j) { - taskBoundsToCheck.add(task.getChildAt(j).getBounds()); - } + for (int j = 0; j < task.getChildCount(); ++j) { + taskBoundsToCheck.add(task.getChildAt(j).getBounds()); } }, false /* traverseTopToBottom */); adjustBoundsToAvoidConflict(display.getBounds(), taskBoundsToCheck, inOutBounds); diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java index 2095d1925e4b..58aca20af926 100644 --- a/services/core/java/com/android/server/wm/TaskOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java @@ -21,6 +21,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER; +import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING; import static com.android.server.wm.WindowOrganizerController.CONTROLLABLE_CONFIGS; import static com.android.server.wm.WindowOrganizerController.CONTROLLABLE_WINDOW_CONFIGS; @@ -580,11 +581,11 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { synchronized (mGlobalLock) { DisplayContent dc = mService.mWindowManager.mRoot .getDisplayContent(displayId); - if (dc == null || dc.mInputMethodTarget == null) { + if (dc == null || dc.getImeTarget(IME_TARGET_LAYERING) == null) { return null; } // Avoid WindowState#getRootTask() so we don't attribute system windows to a task. - final Task task = dc.mInputMethodTarget.getTask(); + final Task task = dc.getImeTarget(IME_TARGET_LAYERING).getWindow().getTask(); if (task == null) { return null; } @@ -687,16 +688,13 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { if (dc == null) { throw new IllegalArgumentException("Display " + displayId + " doesn't exist"); } - ArrayList<RunningTaskInfo> out = new ArrayList<>(); - dc.forAllTaskDisplayAreas(taskDisplayArea -> { - for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { - final Task task = taskDisplayArea.getRootTaskAt(sNdx); - if (activityTypes != null - && !ArrayUtils.contains(activityTypes, task.getActivityType())) { - continue; - } - out.add(task.getTaskInfo()); + final ArrayList<RunningTaskInfo> out = new ArrayList<>(); + dc.forAllRootTasks(task -> { + if (activityTypes != null + && !ArrayUtils.contains(activityTypes, task.getActivityType())) { + return; } + out.add(task.getTaskInfo()); }); return out; } diff --git a/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java b/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java index 3def0911bd76..1779d2a394eb 100644 --- a/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java +++ b/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java @@ -60,7 +60,7 @@ class TaskScreenshotAnimatable implements SurfaceAnimator.Animatable { surface.attachAndQueueBufferWithColorSpace(buffer, screenshotBuffer.getColorSpace()); surface.release(); final float scale = 1.0f * mTask.getBounds().width() / mWidth; - mSurfaceControl.setMatrix(scale, 0, 0, scale); + getPendingTransaction().setMatrix(mSurfaceControl, scale, 0, 0, scale); } getPendingTransaction().show(mSurfaceControl); } diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index 0cdd055d4052..14504d896052 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -18,11 +18,18 @@ package com.android.server.wm; import static android.view.Display.DEFAULT_DISPLAY; +import static android.view.WindowManager.TRANSIT_CHANGE; +import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION; import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION; import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE; import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER; +import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_LOCKED; import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY; +import static android.view.WindowManager.TRANSIT_NONE; +import static android.view.WindowManager.TRANSIT_OPEN; +import static android.view.WindowManager.TRANSIT_TO_BACK; +import static android.view.WindowManager.TRANSIT_TO_FRONT; import android.annotation.IntDef; import android.annotation.NonNull; @@ -282,9 +289,13 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe mState = STATE_PLAYING; mController.moveToPlaying(this); + if (mController.mAtm.mTaskSupervisor.getKeyguardController().isKeyguardLocked()) { + mFlags |= TRANSIT_FLAG_KEYGUARD_LOCKED; + } + // Resolve the animating targets from the participants mTargets = calculateTargets(mParticipants, mChanges); - final TransitionInfo info = calculateTransitionInfo(mType, mTargets, mChanges); + final TransitionInfo info = calculateTransitionInfo(mType, mFlags, mTargets, mChanges); mRootLeash = info.getRootLeash(); handleNonAppWindowsInTransition(displayId, mType, mFlags); @@ -337,6 +348,9 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe mController.mAtm.mWindowManager.mPolicy.startKeyguardExitAnimation( SystemClock.uptimeMillis(), 0 /* duration */); } + if ((flags & TRANSIT_FLAG_KEYGUARD_LOCKED) != 0) { + mController.mAtm.mWindowManager.mPolicy.applyKeyguardOcclusionChange(); + } } @Override @@ -389,7 +403,7 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe parent == null ? "no parent" : ("parent can't be target " + parent)); return false; } - @TransitionInfo.TransitionMode int mode = TransitionInfo.TRANSIT_NONE; + @TransitionInfo.TransitionMode int mode = TRANSIT_NONE; // Go through all siblings of this target to see if any of them would prevent // the target from promoting. siblingLoop: @@ -403,11 +417,11 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe if (depth < 0) continue; if (depth == 0) { final int siblingMode = sibling.isVisibleRequested() - ? TransitionInfo.TRANSIT_OPEN : TransitionInfo.TRANSIT_CLOSE; + ? TRANSIT_OPEN : TRANSIT_CLOSE; ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, " sibling is a top target with mode %s", TransitionInfo.modeToString(siblingMode)); - if (mode == TransitionInfo.TRANSIT_NONE) { + if (mode == TRANSIT_NONE) { ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, " no common mode yet, so set it"); mode = siblingMode; @@ -587,9 +601,9 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe */ @VisibleForTesting @NonNull - static TransitionInfo calculateTransitionInfo(int type, ArraySet<WindowContainer> targets, - ArrayMap<WindowContainer, ChangeInfo> changes) { - final TransitionInfo out = new TransitionInfo(type); + static TransitionInfo calculateTransitionInfo(int type, int flags, + ArraySet<WindowContainer> targets, ArrayMap<WindowContainer, ChangeInfo> changes) { + final TransitionInfo out = new TransitionInfo(type, flags); if (targets.isEmpty()) { out.setRootLeash(new SurfaceControl(), 0, 0); return out; @@ -693,12 +707,12 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe int getTransitMode(@NonNull WindowContainer wc) { final boolean nowVisible = wc.isVisibleRequested(); if (nowVisible == mVisible) { - return TransitionInfo.TRANSIT_CHANGE; + return TRANSIT_CHANGE; } if (mExistenceChanged) { - return nowVisible ? TransitionInfo.TRANSIT_OPEN : TransitionInfo.TRANSIT_CLOSE; + return nowVisible ? TRANSIT_OPEN : TRANSIT_CLOSE; } else { - return nowVisible ? TransitionInfo.TRANSIT_SHOW : TransitionInfo.TRANSIT_HIDE; + return nowVisible ? TRANSIT_TO_FRONT : TRANSIT_TO_BACK; } } diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index adc7a227861a..6e0fec1c80fa 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -1664,6 +1664,39 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< } /** + * For all root tasks at or below this container call the callback. + * + * @param callback Calls the {@link ToBooleanFunction#apply} method for each root task found and + * stops the search if {@link ToBooleanFunction#apply} returns {@code true}. + */ + boolean forAllRootTasks(Function<Task, Boolean> callback) { + return forAllRootTasks(callback, true /* traverseTopToBottom */); + } + + boolean forAllRootTasks(Function<Task, Boolean> callback, boolean traverseTopToBottom) { + int count = mChildren.size(); + if (traverseTopToBottom) { + for (int i = count - 1; i >= 0; --i) { + if (mChildren.get(i).forAllRootTasks(callback)) { + return true; + } + } + } else { + for (int i = 0; i < count; i++) { + if (mChildren.get(i).forAllRootTasks(callback)) { + return true; + } + // Root tasks may be removed from this display. Ensure each task will be processed + // and the loop will end. + int newCount = mChildren.size(); + i -= count - newCount; + count = newCount; + } + } + return false; + } + + /** * For all tasks at or below this container call the callback. * * @param callback Callback to be called for every task. @@ -1698,6 +1731,33 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< } } + /** + * For all root tasks at or below this container call the callback. + * + * @param callback Callback to be called for every root task. + */ + void forAllRootTasks(Consumer<Task> callback) { + forAllRootTasks(callback, true /* traverseTopToBottom */); + } + + void forAllRootTasks(Consumer<Task> callback, boolean traverseTopToBottom) { + int count = mChildren.size(); + if (traverseTopToBottom) { + for (int i = count - 1; i >= 0; --i) { + mChildren.get(i).forAllRootTasks(callback, traverseTopToBottom); + } + } else { + for (int i = 0; i < count; i++) { + mChildren.get(i).forAllRootTasks(callback, traverseTopToBottom); + // Root tasks may be removed from this display. Ensure each task will be processed + // and the loop will end. + int newCount = mChildren.size(); + i -= count - newCount; + count = newCount; + } + } + } + Task getTaskAbove(Task t) { return getTask( (above) -> true, t, false /*includeBoundary*/, false /*traverseTopToBottom*/); @@ -1780,6 +1840,44 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< return null; } + /** + * Gets a root task in a branch of the tree. + * + * @param callback called to test if this is the task that should be returned. + * @return The root task if found or null. + */ + @Nullable + Task getRootTask(Predicate<Task> callback) { + return getRootTask(callback, true /*traverseTopToBottom*/); + } + + @Nullable + Task getRootTask(Predicate<Task> callback, boolean traverseTopToBottom) { + int count = mChildren.size(); + if (traverseTopToBottom) { + for (int i = count - 1; i >= 0; --i) { + final Task t = mChildren.get(i).getRootTask(callback, traverseTopToBottom); + if (t != null) { + return t; + } + } + } else { + for (int i = 0; i < count; i++) { + final Task t = mChildren.get(i).getRootTask(callback, traverseTopToBottom); + if (t != null) { + return t; + } + // Root tasks may be removed from this display. Ensure each task will be processed + // and the loop will end. + int newCount = mChildren.size(); + i -= count - newCount; + count = newCount; + } + } + + return null; + } + private Task processGetTaskWithBoundary(Predicate<Task> callback, WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom, boolean[] boundaryFound, WindowContainer wc) { @@ -1973,6 +2071,47 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< } /** + * Finds the first non {@code null} return value from calling the callback on all root + * {@link Task} at or below this container. + * @param callback Applies on each root {@link Task} found and stops the search if it + * returns non {@code null}. + * @param traverseTopToBottom If {@code true}, traverses the hierarchy from top-to-bottom in + * terms of z-order, else from bottom-to-top. + * @return the first returned object that is not {@code null}. Returns {@code null} if not + * found. + */ + @Nullable + <R> R getItemFromRootTasks(Function<Task, R> callback, boolean traverseTopToBottom) { + int count = mChildren.size(); + if (traverseTopToBottom) { + for (int i = count - 1; i >= 0; --i) { + R result = (R) mChildren.get(i).getItemFromRootTasks(callback, traverseTopToBottom); + if (result != null) { + return result; + } + } + } else { + for (int i = 0; i < count; i++) { + R result = (R) mChildren.get(i).getItemFromRootTasks(callback, traverseTopToBottom); + if (result != null) { + return result; + } + // Root tasks may be removed from this display. Ensure each task will be processed + // and the loop will end. + int newCount = mChildren.size(); + i -= count - newCount; + count = newCount; + } + } + return null; + } + + @Nullable + <R> R getItemFromRootTasks(Function<Task, R> callback) { + return getItemFromRootTasks(callback, true /* traverseTopToBottom */); + } + + /** * Returns 1, 0, or -1 depending on if this container is greater than, equal to, or lesser than * the input container in terms of z-order. */ diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 8fd342c25bc3..6f10edfc59e5 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -48,6 +48,7 @@ import static android.provider.Settings.Global.DEVELOPMENT_RENDER_SHADOWS_IN_COM import static android.provider.Settings.Global.DEVELOPMENT_WM_DISPLAY_SETTINGS_PATH; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; +import static android.view.SurfaceControl.getGlobalTransaction; import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY; import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; @@ -104,6 +105,9 @@ import static com.android.internal.util.LatencyTracker.ACTION_ROTATE_SCREEN; import static com.android.server.LockGuard.INDEX_WINDOW; import static com.android.server.LockGuard.installLock; import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; +import static com.android.server.wm.DisplayContent.IME_TARGET_CONTROL; +import static com.android.server.wm.DisplayContent.IME_TARGET_INPUT; +import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING; import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN; import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; @@ -1036,7 +1040,7 @@ public class WindowManagerService extends IWindowManager.Stub private WindowContentFrameStats mTempWindowRenderStats; - private final LatencyTracker mLatencyTracker; + final LatencyTracker mLatencyTracker; /** * Whether the UI is currently running in touch mode (not showing @@ -1120,18 +1124,16 @@ public class WindowManagerService extends IWindowManager.Stub // While running a recents animation, this will get called early because we show the // recents animation target activity immediately when the animation starts. Defer the // mLaunchTaskBehind updates until recents animation finishes. - final boolean isRecentsAnimationTarget = getRecentsAnimationController() != null - && getRecentsAnimationController().isTargetApp(atoken); - if (atoken.mLaunchTaskBehind && !isRecentsAnimationTarget) { + if (atoken.mLaunchTaskBehind && !isRecentsAnimationTarget(atoken)) { mAtmService.mTaskSupervisor.scheduleLaunchTaskBehindComplete(atoken.token); atoken.mLaunchTaskBehind = false; } else { atoken.updateReportedVisibilityLocked(); // We should also defer sending the finished callback until the recents animation // successfully finishes. - if (atoken.mEnteringAnimation && !isRecentsAnimationTarget) { + if (atoken.mEnteringAnimation && !isRecentsAnimationTarget(atoken)) { atoken.mEnteringAnimation = false; - if (atoken != null && atoken.attachedToProcess()) { + if (atoken.attachedToProcess()) { try { atoken.app.getThread().scheduleEnterAnimationComplete(atoken.appToken); } catch (RemoteException e) { @@ -2557,7 +2559,7 @@ public class WindowManagerService extends IWindowManager.Stub // side child surfaces, so they will remain preserved in their current state // (rather than be cleaned up immediately by the app code). SurfaceControl.openTransaction(); - winAnimator.detachChildren(); + winAnimator.detachChildren(getGlobalTransaction()); SurfaceControl.closeTransaction(); return focusMayChange; @@ -2968,6 +2970,10 @@ public class WindowManagerService extends IWindowManager.Stub } } + boolean isRecentsAnimationTarget(ActivityRecord r) { + return mRecentsAnimationController != null && mRecentsAnimationController.isTargetApp(r); + } + void setWindowOpaqueLocked(IBinder token, boolean isOpaque) { final ActivityRecord wtoken = mRoot.getActivityRecord(token); if (wtoken != null) { @@ -5349,7 +5355,7 @@ public class WindowManagerService extends IWindowManager.Stub void destroyPreservedSurfaceLocked() { for (int i = mDestroyPreservedSurface.size() - 1; i >= 0 ; i--) { final WindowState w = mDestroyPreservedSurface.get(i); - w.mWinAnimator.destroyPreservedSurfaceLocked(); + w.mWinAnimator.destroyPreservedSurfaceLocked(w.getSyncTransaction()); } mDestroyPreservedSurface.clear(); } @@ -6321,20 +6327,20 @@ public class WindowManagerService extends IWindowManager.Stub mRoot.dumpTopFocusedDisplayId(pw); mRoot.forAllDisplays(dc -> { final int displayId = dc.getDisplayId(); - final WindowState inputMethodTarget = dc.mInputMethodTarget; - final WindowState inputMethodInputTarget = dc.mInputMethodInputTarget; - final InsetsControlTarget inputMethodControlTarget = dc.mInputMethodControlTarget; - if (inputMethodTarget != null) { - pw.print(" mInputMethodTarget in display# "); pw.print(displayId); - pw.print(' '); pw.println(inputMethodTarget); + final InsetsControlTarget imeLayeringTarget = dc.getImeTarget(IME_TARGET_LAYERING); + final InsetsControlTarget imeInputTarget = dc.getImeTarget(IME_TARGET_INPUT); + final InsetsControlTarget imeControlTarget = dc.getImeTarget(IME_TARGET_CONTROL); + if (imeLayeringTarget != null) { + pw.print(" imeLayeringTarget in display# "); pw.print(displayId); + pw.print(' '); pw.println(imeLayeringTarget); } - if (inputMethodInputTarget != null) { - pw.print(" mInputMethodInputTarget in display# "); pw.print(displayId); - pw.print(' '); pw.println(inputMethodInputTarget); + if (imeInputTarget != null) { + pw.print(" imeInputTarget in display# "); pw.print(displayId); + pw.print(' '); pw.println(imeInputTarget); } - if (inputMethodControlTarget != null) { - pw.print(" inputMethodControlTarget in display# "); pw.print(displayId); - pw.print(' '); pw.println(inputMethodControlTarget); + if (imeControlTarget != null) { + pw.print(" imeControlTarget in display# "); pw.print(displayId); + pw.print(' '); pw.println(imeControlTarget); } }); pw.print(" mInTouchMode="); pw.println(mInTouchMode); @@ -7629,7 +7635,7 @@ public class WindowManagerService extends IWindowManager.Stub synchronized (mGlobalLock) { final WindowState imeTarget = mWindowMap.get(imeTargetWindowToken); if (imeTarget != null) { - imeTarget.getDisplayContent().setInputMethodInputTarget(imeTarget); + imeTarget.getDisplayContent().updateImeInputAndControlTarget(imeTarget); } } } @@ -7772,10 +7778,10 @@ public class WindowManagerService extends IWindowManager.Stub // requested to be hidden. dc.getInsetsStateController().getImeSourceProvider().abortShowImePostLayout(); } - if (dc != null && dc.mInputMethodControlTarget != null) { + if (dc != null && dc.getImeTarget(IME_TARGET_CONTROL) != null) { ProtoLog.d(WM_DEBUG_IME, "hideIme Control target: %s ", - dc.mInputMethodControlTarget); - dc.mInputMethodControlTarget.hideInsets( + dc.getImeTarget(IME_TARGET_CONTROL)); + dc.getImeTarget(IME_TARGET_CONTROL).hideInsets( WindowInsets.Type.ime(), true /* fromIme */); } if (dc != null) { @@ -7899,7 +7905,7 @@ public class WindowManagerService extends IWindowManager.Stub if (dc == null) { return null; } - final InsetsControlTarget target = dc.mInputMethodControlTarget; + final InsetsControlTarget target = dc.getImeTarget(IME_TARGET_CONTROL); if (target == null) { return null; } @@ -7912,10 +7918,10 @@ public class WindowManagerService extends IWindowManager.Stub public String getImeTargetNameForLogging(int displayId) { synchronized (mGlobalLock) { final DisplayContent dc = mRoot.getDisplayContent(displayId); - if (dc == null) { + if (dc == null || dc.getImeTarget(IME_TARGET_LAYERING) == null) { return null; } - return dc.mInputMethodTarget != null ? dc.mInputMethodTarget.getName() : null; + return dc.getImeTarget(IME_TARGET_LAYERING).getWindow().getName(); } } } diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java index 8f8fea34e620..835e8036ddbd 100644 --- a/services/core/java/com/android/server/wm/WindowProcessController.java +++ b/services/core/java/com/android/server/wm/WindowProcessController.java @@ -463,6 +463,10 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio return mUsingWrapper; } + boolean hasEverLaunchedActivity() { + return mLastActivityLaunchTime > 0; + } + void setLastActivityLaunchTime(long launchTime) { if (launchTime <= mLastActivityLaunchTime) { if (launchTime < mLastActivityLaunchTime) { @@ -815,9 +819,9 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio if (canUpdate) { // Make sure the previous top activity in the process no longer be resumed. if (mPreQTopResumedActivity != null && mPreQTopResumedActivity.isState(RESUMED)) { - final Task stack = mPreQTopResumedActivity.getRootTask(); - if (stack != null) { - stack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */, + final Task task = mPreQTopResumedActivity.getTask(); + if (task != null) { + task.startPausingLocked(false /* userLeaving */, false /* uiSleeping */, activity, "top-resumed-changed"); } } @@ -1282,12 +1286,12 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio hasVisibleActivities = true; } - final Task rootTask = r.getRootTask(); - if (rootTask != null) { + final Task task = r.getTask(); + if (task != null) { // There may be a pausing activity that hasn't shown any window and was requested // to be hidden. But pausing is also a visible state, it should be regarded as // visible, so the caller can know the next activity should be resumed. - hasVisibleActivities |= rootTask.handleAppDied(this); + hasVisibleActivities |= task.handleAppDied(this); } r.handleAppDied(); } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index bc8699e2ee39..32b84a8d0a2c 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -32,6 +32,7 @@ import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.view.InsetsState.ITYPE_IME; import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; import static android.view.SurfaceControl.Transaction; +import static android.view.SurfaceControl.getGlobalTransaction; import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT; import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME; import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION; @@ -118,6 +119,8 @@ import static com.android.server.policy.WindowManagerPolicy.TRANSIT_ENTER; import static com.android.server.policy.WindowManagerPolicy.TRANSIT_EXIT; import static com.android.server.policy.WindowManagerPolicy.TRANSIT_PREVIEW_DONE; import static com.android.server.wm.AnimationSpecProto.MOVE; +import static com.android.server.wm.DisplayContent.IME_TARGET_INPUT; +import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING; import static com.android.server.wm.DisplayContent.logsGestureExclusionRestrictions; import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER; import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM; @@ -617,6 +620,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP private final Rect mTmpRect = new Rect(); private final Point mTmpPoint = new Point(); + private final Transaction mTmpTransaction; + /** * If a window is on a display which has been re-parented to a view in another window, * use this offset to indicate the correct location. @@ -861,6 +866,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP int ownerId, int showUserId, boolean ownerCanAddInternalSystemWindow, PowerManagerWrapper powerManagerWrapper) { super(service); + mTmpTransaction = service.mTransactionFactory.get(); mSession = s; mClient = c; mAppOp = appOp; @@ -1108,9 +1114,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP final int layoutXDiff; final int layoutYDiff; final WindowState imeWin = mWmService.mRoot.getCurrentInputMethodWindow(); + final InsetsControlTarget imeTarget = dc.getImeTarget(IME_TARGET_LAYERING); final boolean isInputMethodAdjustTarget = windowsAreFloating - ? dc.mInputMethodTarget != null && task == dc.mInputMethodTarget.getTask() - : isInputMethodTarget(); + ? imeTarget != null && task == imeTarget.getWindow().getTask() + : isImeLayeringTarget(); final boolean isImeTarget = imeWin != null && imeWin.isVisibleNow() && isInputMethodAdjustTarget; if (isFullscreenAndFillsDisplay || layoutInParentFrame()) { @@ -1447,9 +1454,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP @Override void onDisplayChanged(DisplayContent dc) { if (dc != null && mDisplayContent != null && dc != mDisplayContent - && mDisplayContent.mInputMethodInputTarget == this) { - dc.setInputMethodInputTarget(mDisplayContent.mInputMethodInputTarget); - mDisplayContent.mInputMethodInputTarget = null; + && getImeInputTarget() == this) { + dc.updateImeInputAndControlTarget(getImeInputTarget()); + mDisplayContent.setImeInputTarget(null); } super.onDisplayChanged(dc); // Window was not laid out for this display yet, so make sure mLayoutSeq does not match. @@ -2154,14 +2161,14 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } final DisplayContent dc = getDisplayContent(); - if (isInputMethodTarget()) { - // Make sure to set mInputMethodTarget as null when the removed window is the IME - // target, in case computeImeTarget may use the outdated target. - dc.mInputMethodTarget = null; + if (isImeLayeringTarget()) { + // Make sure to set mImeLayeringTarget as null when the removed window is the + // IME target, in case computeImeTarget may use the outdated target. + dc.setImeLayeringTarget(null); dc.computeImeTarget(true /* updateImeTarget */); } - if (dc.mInputMethodInputTarget == this) { - dc.setInputMethodInputTarget(null); + if (dc.getImeTarget(IME_TARGET_INPUT) == this) { + dc.updateImeInputAndControlTarget(null); } final int type = mAttrs.type; @@ -2176,8 +2183,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP disposeInputChannel(); - mWinAnimator.destroyDeferredSurfaceLocked(); - mWinAnimator.destroySurfaceLocked(); + mWinAnimator.destroyDeferredSurfaceLocked(mTmpTransaction); + mWinAnimator.destroySurfaceLocked(mTmpTransaction); + mTmpTransaction.apply(); mSession.windowRemovedLocked(); try { mClient.asBinder().unlinkToDeath(mDeathRecipient, 0); @@ -2645,7 +2653,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP clearPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY); } if (!isVisibleByPolicy()) { - mWinAnimator.hide("checkPolicyVisibilityChange"); + mWinAnimator.hide(getGlobalTransaction(), "checkPolicyVisibilityChange"); if (isFocused()) { ProtoLog.i(WM_DEBUG_FOCUS_LIGHT, "setAnimationLocked: setting mFocusMayChange true"); @@ -3176,10 +3184,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // detaching any surface control the client added from the client. for (int i = mChildren.size() - 1; i >= 0; --i) { final WindowState c = mChildren.get(i); - c.mWinAnimator.detachChildren(); + c.mWinAnimator.detachChildren(getGlobalTransaction()); } - mWinAnimator.detachChildren(); + mWinAnimator.detachChildren(getGlobalTransaction()); } try { @@ -3238,7 +3246,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } if (appStopped || mWindowRemovalAllowed) { - mWinAnimator.destroyPreservedSurfaceLocked(); + mWinAnimator.destroyPreservedSurfaceLocked(mTmpTransaction); + mTmpTransaction.apply(); } if (mDestroying) { @@ -3274,7 +3283,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // various indicators of whether the client has released the surface. // This is in general unsafe, and most callers should use {@link #destroySurface} void destroySurfaceUnchecked() { - mWinAnimator.destroySurfaceLocked(); + mWinAnimator.destroySurfaceLocked(mTmpTransaction); + mTmpTransaction.apply(); // Clear animating flags now, since the surface is now gone. (Note this is true even // if the surface is saved, to outside world the surface is still NO_SURFACE.) @@ -4608,7 +4618,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // directly above it. The exception is if we are in split screen // in which case we process the IME at the DisplayContent level to // ensure it is above the docked divider. - if (isInputMethodTarget() && !inSplitScreenWindowingMode()) { + if (isImeLayeringTarget() && !inSplitScreenWindowingMode()) { if (getDisplayContent().forAllImeWindows(callback, traverseTopToBottom)) { return true; } @@ -4800,7 +4810,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP c.hideWallpaperWindow(wasDeferred, reason); } if (!mWinAnimator.mLastHidden || wasDeferred) { - mWinAnimator.hide(reason); + mWinAnimator.hide(getGlobalTransaction(), reason); getDisplayContent().mWallpaperController.mDeferredHideWallpaper = null; dispatchWallpaperVisibility(false); final DisplayContent displayContent = getDisplayContent(); @@ -4942,7 +4952,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // on the new one. This prevents blinking when we change elevation of freeform and // pinned windows. if (!mWinAnimator.tryChangeFormatInPlaceLocked()) { - mWinAnimator.preserveSurfaceLocked(getPendingTransaction()); + mWinAnimator.preserveSurfaceLocked(getSyncTransaction()); result |= RELAYOUT_RES_SURFACE_CHANGED | RELAYOUT_RES_FIRST_TIME; scheduleAnimation(); @@ -4961,7 +4971,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // to preserve and destroy windows which are attached to another, they // will keep their surface and its size may change over time. if (mHasSurface && !isChildWindow()) { - mWinAnimator.preserveSurfaceLocked(getPendingTransaction()); + mWinAnimator.preserveSurfaceLocked(getSyncTransaction()); result |= RELAYOUT_RES_SURFACE_CHANGED | RELAYOUT_RES_FIRST_TIME; scheduleAnimation(); @@ -5204,9 +5214,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP @Override boolean needsZBoost() { - final WindowState inputMethodTarget = getDisplayContent().mInputMethodTarget; - if (mIsImWindow && inputMethodTarget != null) { - final ActivityRecord activity = inputMethodTarget.mActivityRecord; + final InsetsControlTarget target = getDisplayContent().getImeTarget(IME_TARGET_LAYERING); + if (mIsImWindow && target != null) { + final ActivityRecord activity = target.getWindow().mActivityRecord; if (activity != null) { return activity.needsZBoost(); } @@ -5264,7 +5274,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP updateFrameRateSelectionPriorityIfNeeded(); updateGlobalScaleIfNeeded(); - mWinAnimator.prepareSurfaceLocked(SurfaceControl.getGlobalTransaction(), true); + mWinAnimator.prepareSurfaceLocked(getSyncTransaction()); super.prepareSurfaces(); } @@ -5358,14 +5368,14 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP if (isChildWindow()) { // If we are a child of the input method target we need this promotion. - if (getParentWindow().isInputMethodTarget()) { + if (getParentWindow().isImeLayeringTarget()) { return true; } } else if (mActivityRecord != null) { // Likewise if we share a token with the Input method target and are ordered // above it but not necessarily a child (e.g. a Dialog) then we also need // this promotion. - final WindowState imeTarget = getDisplayContent().mInputMethodTarget; + final WindowState imeTarget = getImeLayeringTarget(); boolean inTokenWithAndAboveImeTarget = imeTarget != null && imeTarget != this && imeTarget.mToken == mToken && mAttrs.type != TYPE_APPLICATION_STARTING @@ -5492,8 +5502,18 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return !mTapExcludeRegion.isEmpty(); } - boolean isInputMethodTarget() { - return getDisplayContent().mInputMethodTarget == this; + boolean isImeLayeringTarget() { + return getDisplayContent().getImeTarget(IME_TARGET_LAYERING) == this; + } + + WindowState getImeLayeringTarget() { + final InsetsControlTarget target = getDisplayContent().getImeTarget(IME_TARGET_LAYERING); + return target != null ? target.getWindow() : null; + } + + WindowState getImeInputTarget() { + final InsetsControlTarget target = mDisplayContent.getImeTarget(IME_TARGET_INPUT); + return target != null ? target.getWindow() : null; } long getFrameNumber() { diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 9cc72a2ddf7c..068d0dfd0602 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -57,7 +57,6 @@ import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_C import android.content.Context; import android.graphics.Matrix; import android.graphics.PixelFormat; -import android.graphics.Point; import android.graphics.Rect; import android.graphics.Region; import android.os.Debug; @@ -130,10 +129,6 @@ class WindowStateAnimator { float mAlpha = 0; float mLastAlpha = 0; - Rect mTmpStackBounds = new Rect(); - private Rect mTmpAnimatingBounds = new Rect(); - private Rect mTmpSourceBounds = new Rect(); - /** * This is rectangle of the window's surface that is not covered by * system decorations. @@ -154,8 +149,6 @@ class WindowStateAnimator { * window is first added or shown, cleared when the callback has been made. */ boolean mEnteringAnimation; - private final SurfaceControl.Transaction mTmpTransaction; - /** The pixel format of the underlying SurfaceControl */ int mSurfaceFormat; @@ -201,12 +194,6 @@ class WindowStateAnimator { // region. float mWallpaperScale = 1f; - /** - * A flag to determine if the WSA needs to offset its position to compensate for the stack's - * position update before the WSA surface has resized. - */ - private boolean mOffsetPositionForStackResize; - private final Rect mTmpSize = new Rect(); /** @@ -220,13 +207,10 @@ class WindowStateAnimator { private final SurfaceControl.Transaction mPostDrawTransaction = new SurfaceControl.Transaction(); - private final Point mTmpPos = new Point(); - WindowStateAnimator(final WindowState win) { final WindowManagerService service = win.mWmService; mService = service; - mTmpTransaction = service.mTransactionFactory.get(); mAnimator = service.mAnimator; mPolicy = service.mPolicy; mContext = service.mContext; @@ -243,7 +227,7 @@ class WindowStateAnimator { if (DEBUG_ANIM) Slog.v( TAG, "Animation done in " + this + ": exiting=" + mWin.mAnimatingExit + ", reportedVisible=" - + (mWin.mActivityRecord != null ? mWin.mActivityRecord.reportedVisible : false)); + + (mWin.mActivityRecord != null && mWin.mActivityRecord.reportedVisible)); mWin.checkPolicyVisibilityChange(); final DisplayContent displayContent = mWin.getDisplayContent(); @@ -284,11 +268,6 @@ class WindowStateAnimator { } } - void hide(String reason) { - hide(mTmpTransaction, reason); - SurfaceControl.mergeToGlobalTransaction(mTmpTransaction); - } - boolean finishDrawingLocked(SurfaceControl.Transaction postDrawTransaction) { final boolean startingWindow = mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; @@ -362,7 +341,7 @@ class WindowStateAnimator { mSurfaceController.mSurfaceControl, mPendingDestroySurface.mSurfaceControl).apply(); } - destroySurfaceLocked(); + destroySurfaceLocked(t); mSurfaceDestroyDeferred = true; return; } @@ -375,10 +354,10 @@ class WindowStateAnimator { } mDestroyPreservedSurfaceUponRedraw = true; mSurfaceDestroyDeferred = true; - destroySurfaceLocked(); + destroySurfaceLocked(t); } - void destroyPreservedSurfaceLocked() { + void destroyPreservedSurfaceLocked(SurfaceControl.Transaction t) { if (!mDestroyPreservedSurfaceUponRedraw) { return; } @@ -397,7 +376,7 @@ class WindowStateAnimator { mSurfaceController.mSurfaceControl).apply(); } - destroyDeferredSurfaceLocked(); + destroyDeferredSurfaceLocked(t); mDestroyPreservedSurfaceUponRedraw = false; } @@ -484,7 +463,6 @@ class WindowStateAnimator { mSurfaceController.setColorSpaceAgnostic((attrs.privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC) != 0); - setOffsetPositionForStackResize(false); mSurfaceFormat = format; w.setHasSurface(true); @@ -529,7 +507,7 @@ class WindowStateAnimator { return mSurfaceController != null && mSurfaceController.hasSurface(); } - void destroySurfaceLocked() { + void destroySurfaceLocked(SurfaceControl.Transaction t) { final ActivityRecord activity = mWin.mActivityRecord; if (activity != null) { if (mWin == activity.mStartingWindow) { @@ -557,14 +535,14 @@ class WindowStateAnimator { if (mPendingDestroySurface != null) { ProtoLog.i(WM_SHOW_SURFACE_ALLOC, "SURFACE DESTROY PENDING: %s. %s", mWin, new RuntimeException().fillInStackTrace()); - mPendingDestroySurface.destroyNotInTransaction(); + mPendingDestroySurface.destroy(t); } mPendingDestroySurface = mSurfaceController; } } else { ProtoLog.i(WM_SHOW_SURFACE_ALLOC, "SURFACE DESTROY: %s. %s", mWin, new RuntimeException().fillInStackTrace()); - destroySurface(); + destroySurface(t); } // Don't hide wallpaper if we're deferring the surface destroy // because of a surface change. @@ -587,12 +565,12 @@ class WindowStateAnimator { mDrawState = NO_SURFACE; } - void destroyDeferredSurfaceLocked() { + void destroyDeferredSurfaceLocked(SurfaceControl.Transaction t) { try { if (mPendingDestroySurface != null) { ProtoLog.i(WM_SHOW_SURFACE_ALLOC, "SURFACE DESTROY PENDING: %s. %s", mWin, new RuntimeException().fillInStackTrace()); - mPendingDestroySurface.destroyNotInTransaction(); + mPendingDestroySurface.destroy(t); // Don't hide wallpaper if we're destroying a deferred surface // after a surface mode change. if (!mDestroyPreservedSurfaceUponRedraw) { @@ -655,93 +633,49 @@ class WindowStateAnimator { return true; } - void setSurfaceBoundariesLocked(SurfaceControl.Transaction t, final boolean recoveringMemory) { + void setSurfaceBoundariesLocked(SurfaceControl.Transaction t) { if (mSurfaceController == null) { return; } final WindowState w = mWin; - final LayoutParams attrs = mWin.getAttrs(); final Task task = w.getTask(); if (shouldConsumeMainWindowSizeTransaction()) { - t.deferTransactionUntil(task.getMainWindowSizeChangeTask().getSurfaceControl(), - mWin.getClientViewRootSurface(), mWin.getFrameNumber()); - t.deferTransactionUntil(mSurfaceController.mSurfaceControl, - mWin.getClientViewRootSurface(), mWin.getFrameNumber()); - t.merge(task.getMainWindowSizeChangeTransaction()); + // 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); } - float surfaceWidth = mSurfaceController.getWidth(); - float surfaceHeight = mSurfaceController.getHeight(); - - final Rect insets = attrs.surfaceInsets; - - // getFrameNumber is only valid in the call-stack of relayoutWindow - // as this is the only-time we know the client renderer - // is paused. - final boolean relayout = !w.mRelayoutCalled || w.mInRelayout; - if (!w.mSeamlesslyRotated) { // Used to offset the WSA when stack position changes before a resize. int xOffset = mXOffset; int yOffset = mYOffset; - if (mOffsetPositionForStackResize) { - if (relayout) { - // Once a relayout is called, reset the offset back to 0 and defer - // setting it until a new frame with the updated size. This ensures that - // the WS position is reset (so the stack position is shown) at the same - // time that the buffer size changes. - setOffsetPositionForStackResize(false); - t.deferTransactionUntil(mSurfaceController.mSurfaceControl, - mWin.getClientViewRootSurface(), mWin.getFrameNumber()); - } else { - final Task stack = mWin.getRootTask(); - mTmpPos.x = 0; - mTmpPos.y = 0; - if (stack != null) { - stack.getRelativePosition(mTmpPos); - } - xOffset = -mTmpPos.x; - yOffset = -mTmpPos.y; - } - } - if (!mIsWallpaper) { - mSurfaceController.setPosition(t, xOffset, yOffset, recoveringMemory); - } else { - setWallpaperPositionAndScale(t, - xOffset, yOffset, mWallpaperScale, recoveringMemory); - } - } - - if (!w.mSeamlesslyRotated) { - // Wallpaper is already updated above when calling setWallpaperPositionAndScale so - // we only need to consider the non-wallpaper case here. if (!mIsWallpaper) { + mSurfaceController.setPosition(t, xOffset, yOffset); + // Wallpaper is already updated above when calling setWallpaperPositionAndScale so + // we only need to consider the non-wallpaper case here. mSurfaceController.setMatrix(t, - mDsDx * w.mHScale, - mDtDx * w.mVScale, - mDtDy * w.mHScale, - mDsDy * w.mVScale, recoveringMemory); + mDsDx * w.mHScale, + mDtDx * w.mVScale, + mDtDy * w.mHScale, + mDsDy * w.mVScale); + } else { + setWallpaperPositionAndScale(t, xOffset, yOffset, mWallpaperScale); } } } - /** - * Get rect of the task this window is currently in. If there is no task, rect will be set to - * empty. - */ - void getContainerRect(Rect rect) { - final Task task = mWin.getTask(); - if (task != null) { - task.getDimBounds(rect); - } else { - rect.left = rect.top = rect.right = rect.bottom = 0; - } - } - - void prepareSurfaceLocked(SurfaceControl.Transaction t, final boolean recoveringMemory) { + void prepareSurfaceLocked(SurfaceControl.Transaction t) { final WindowState w = mWin; if (!hasSurface()) { @@ -758,13 +692,13 @@ class WindowStateAnimator { computeShownFrameLocked(); - setSurfaceBoundariesLocked(t, recoveringMemory); + setSurfaceBoundariesLocked(t); if (mIsWallpaper && !w.mWallpaperVisible) { // Wallpaper is no longer visible and there is no wp target => hide it. - hide("prepareSurfaceLocked"); + hide(t, "prepareSurfaceLocked"); } else if (w.isParentWindowHidden() || !w.isOnScreen()) { - hide("prepareSurfaceLocked"); + hide(t, "prepareSurfaceLocked"); mWallpaperControllerLocked.hideWallpapers(w); // If we are waiting for this window to handle an orientation change. If this window is @@ -800,21 +734,20 @@ class WindowStateAnimator { boolean prepared = true; if (mIsWallpaper) { - setWallpaperPositionAndScale(t, - mXOffset, mYOffset, mWallpaperScale, recoveringMemory); + setWallpaperPositionAndScale(t, mXOffset, mYOffset, mWallpaperScale); } else { prepared = - mSurfaceController.prepareToShowInTransaction(mShownAlpha, + mSurfaceController.prepareToShowInTransaction(t, mShownAlpha, mDsDx * w.mHScale, mDtDx * w.mVScale, mDtDy * w.mHScale, - mDsDy * w.mVScale, - recoveringMemory); + mDsDy * w.mVScale + ); } if (prepared && mDrawState == HAS_DRAWN) { if (mLastHidden) { - if (showSurfaceRobustlyLocked()) { + if (showSurfaceRobustlyLocked(t)) { markPreservedSurfaceForDestroy(); mAnimator.requestRemovalOfReplacedWindows(w); mLastHidden = false; @@ -888,8 +821,7 @@ class WindowStateAnimator { Slog.i(TAG, ">>> OPEN TRANSACTION setWallpaperOffset"); } mService.openSurfaceTransaction(); - setWallpaperPositionAndScale(SurfaceControl.getGlobalTransaction(), - dx, dy, scale, false); + setWallpaperPositionAndScale(SurfaceControl.getGlobalTransaction(), dx, dy, scale); } catch (RuntimeException e) { Slog.w(TAG, "Error positioning surface of " + mWin + " pos=(" + dx + "," + dy + ")", e); @@ -904,8 +836,8 @@ class WindowStateAnimator { return true; } - private void setWallpaperPositionAndScale(SurfaceControl.Transaction t, - int dx, int dy, float scale, boolean recoveringMemory) { + private void setWallpaperPositionAndScale(SurfaceControl.Transaction t, int dx, int dy, + float scale) { DisplayInfo displayInfo = mWin.getDisplayInfo(); Matrix matrix = mWin.mTmpMatrix; matrix.setTranslate(dx, dy); @@ -915,13 +847,12 @@ class WindowStateAnimator { matrix.reset(); mSurfaceController.setPosition(t,mWin.mTmpMatrixArray[MTRANS_X], - mWin.mTmpMatrixArray[MTRANS_Y], recoveringMemory); + mWin.mTmpMatrixArray[MTRANS_Y]); mSurfaceController.setMatrix(t, mDsDx * mWin.mTmpMatrixArray[MSCALE_X] * mWin.mHScale, mDtDx * mWin.mTmpMatrixArray[MSKEW_Y] * mWin.mVScale, mDtDy * mWin.mTmpMatrixArray[MSKEW_X] * mWin.mHScale, - mDsDy * mWin.mTmpMatrixArray[MSCALE_Y] * mWin.mVScale, - recoveringMemory); + mDsDy * mWin.mTmpMatrixArray[MSCALE_Y] * mWin.mVScale); } /** @@ -974,8 +905,8 @@ class WindowStateAnimator { * * @return Returns true if the surface was successfully shown. */ - private boolean showSurfaceRobustlyLocked() { - boolean shown = mSurfaceController.showRobustlyInTransaction(); + private boolean showSurfaceRobustlyLocked(SurfaceControl.Transaction t) { + boolean shown = mSurfaceController.showRobustly(t); if (!shown) return false; @@ -993,7 +924,7 @@ class WindowStateAnimator { } } - SurfaceControl.mergeToGlobalTransaction(mPostDrawTransaction); + t.merge(mPostDrawTransaction); return true; } @@ -1163,10 +1094,6 @@ class WindowStateAnimator { return sb.toString(); } - void reclaimSomeSurfaceMemory(String operation, boolean secure) { - mService.mRoot.reclaimSomeSurfaceMemory(this, operation, secure); - } - boolean getShown() { if (mSurfaceController != null) { return mSurfaceController.getShown(); @@ -1174,10 +1101,10 @@ class WindowStateAnimator { return false; } - void destroySurface() { + void destroySurface(SurfaceControl.Transaction t) { try { if (mSurfaceController != null) { - mSurfaceController.destroyNotInTransaction(); + mSurfaceController.destroy(t); } } catch (RuntimeException e) { Slog.w(TAG, "Exception thrown when destroying surface " + this @@ -1189,7 +1116,7 @@ class WindowStateAnimator { } } - void detachChildren() { + void detachChildren(SurfaceControl.Transaction t) { // Do not detach children of starting windows, as their lifecycle is well under control and // it may lead to issues in case we relaunch when we just added the starting window. @@ -1197,14 +1124,10 @@ class WindowStateAnimator { return; } if (mSurfaceController != null) { - mSurfaceController.detachChildren(); + mSurfaceController.detachChildren(t); } } - void setOffsetPositionForStackResize(boolean offsetPositionForStackResize) { - mOffsetPositionForStackResize = offsetPositionForStackResize; - } - SurfaceControl getSurfaceControl() { if (!hasSurface()) { return null; diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java index ec79c5999a3f..788f00407671 100644 --- a/services/core/java/com/android/server/wm/WindowSurfaceController.java +++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java @@ -20,6 +20,7 @@ import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.view.SurfaceControl.METADATA_OWNER_PID; import static android.view.SurfaceControl.METADATA_OWNER_UID; import static android.view.SurfaceControl.METADATA_WINDOW_TYPE; +import static android.view.SurfaceControl.getGlobalTransaction; import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC; import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS; @@ -76,8 +77,6 @@ class WindowSurfaceController { private final int mWindowType; private final Session mWindowSession; - private final SurfaceControl.Transaction mTmpTransaction; - // Used to track whether we have called detach children on the way to invisibility. boolean mChildrenDetached; @@ -94,7 +93,6 @@ class WindowSurfaceController { final WindowState win = animator.mWin; mWindowType = windowType; mWindowSession = win.mSession; - mTmpTransaction = mService.mTransactionFactory.get(); Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "new SurfaceControl"); final SurfaceControl.Builder b = win.makeSurface() @@ -120,18 +118,18 @@ class WindowSurfaceController { Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); } - void detachChildren() { + void detachChildren(SurfaceControl.Transaction t) { ProtoLog.i(WM_SHOW_TRANSACTIONS, "SEVER CHILDREN"); mChildrenDetached = true; if (mSurfaceControl != null) { - mSurfaceControl.detachChildren(); + t.detachChildren(mSurfaceControl); } } void hide(SurfaceControl.Transaction transaction, String reason) { ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE HIDE ( %s ): %s", reason, title); - mAnimator.destroyPreservedSurfaceLocked(); + mAnimator.destroyPreservedSurfaceLocked(transaction); if (mSurfaceShown) { hideSurface(transaction); } @@ -149,12 +147,12 @@ class WindowSurfaceController { } } - void destroyNotInTransaction() { + void destroy(SurfaceControl.Transaction t) { ProtoLog.i(WM_SHOW_SURFACE_ALLOC, - "Destroying surface %s called by %s", this, Debug.getCallers(8)); + "Destroying surface %s called by %s", this, Debug.getCallers(8)); try { if (mSurfaceControl != null) { - mTmpTransaction.remove(mSurfaceControl).apply(); + t.remove(mSurfaceControl); } } catch (RuntimeException e) { Slog.w(TAG, "Error destroying surface in: " + this, e); @@ -164,30 +162,22 @@ class WindowSurfaceController { } } - void setPosition(SurfaceControl.Transaction t, float left, float top, - boolean recoveringMemory) { + void setPosition(SurfaceControl.Transaction t, float left, float top) { final boolean surfaceMoved = mSurfaceX != left || mSurfaceY != top; - if (surfaceMoved) { - mSurfaceX = left; - mSurfaceY = top; - - try { - ProtoLog.i(WM_SHOW_TRANSACTIONS, - "SURFACE POS (setPositionInTransaction) @ (%f,%f): %s", left, top, title); - - t.setPosition(mSurfaceControl, left, top); - } catch (RuntimeException e) { - Slog.w(TAG, "Error positioning surface of " + this - + " pos=(" + left + "," + top + ")", e); - if (!recoveringMemory) { - mAnimator.reclaimSomeSurfaceMemory("position", true); - } - } + if (!surfaceMoved) { + return; } + + mSurfaceX = left; + mSurfaceY = top; + + ProtoLog.i(WM_SHOW_TRANSACTIONS, + "SURFACE POS (setPositionInTransaction) @ (%f,%f): %s", left, top, title); + + t.setPosition(mSurfaceControl, left, top); } - void setMatrix(SurfaceControl.Transaction t, float dsdx, float dtdx, - float dtdy, float dsdy, boolean recoveringMemory) { + void setMatrix(SurfaceControl.Transaction t, float dsdx, float dtdx, float dtdy, float dsdy) { final boolean matrixChanged = mLastDsdx != dsdx || mLastDtdx != dtdx || mLastDtdy != dtdy || mLastDsdy != dsdy; if (!matrixChanged) { @@ -199,43 +189,24 @@ class WindowSurfaceController { mLastDtdy = dtdy; mLastDsdy = dsdy; - try { - ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE MATRIX [%f,%f,%f,%f]: %s", - dsdx, dtdx, dtdy, dsdy, title); - t.setMatrix(mSurfaceControl, dsdx, dtdx, dtdy, dsdy); - } catch (RuntimeException e) { - // If something goes wrong with the surface (such - // as running out of memory), don't take down the - // entire system. - Slog.e(TAG, "Error setting matrix on surface surface" + title - + " MATRIX [" + dsdx + "," + dtdx + "," + dtdy + "," + dsdy + "]", null); - if (!recoveringMemory) { - mAnimator.reclaimSomeSurfaceMemory("matrix", true); - } - } + ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE MATRIX [%f,%f,%f,%f]: %s", + dsdx, dtdx, dtdy, dsdy, title); + t.setMatrix(mSurfaceControl, dsdx, dtdx, dtdy, dsdy); } - boolean prepareToShowInTransaction(float alpha, - float dsdx, float dtdx, float dsdy, - float dtdy, boolean recoveringMemory) { - if (mSurfaceControl != null) { - try { - mSurfaceAlpha = alpha; - mSurfaceControl.setAlpha(alpha); - mLastDsdx = dsdx; - mLastDtdx = dtdx; - mLastDsdy = dsdy; - mLastDtdy = dtdy; - mSurfaceControl.setMatrix( - dsdx, dtdx, dsdy, dtdy); - } catch (RuntimeException e) { - Slog.w(TAG, "Error updating surface in " + title, e); - if (!recoveringMemory) { - mAnimator.reclaimSomeSurfaceMemory("update", true); - } - return false; - } + boolean prepareToShowInTransaction(SurfaceControl.Transaction t, float alpha, float dsdx, + float dtdx, float dsdy, float dtdy) { + if (mSurfaceControl == null) { + return false; } + + mSurfaceAlpha = alpha; + t.setAlpha(mSurfaceControl, alpha); + mLastDsdx = dsdx; + mLastDtdx = dtdx; + mLastDsdy = dsdy; + mLastDtdy = dtdy; + t.setMatrix(mSurfaceControl, dsdx, dtdx, dsdy, dtdy); return true; } @@ -247,7 +218,7 @@ class WindowSurfaceController { if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setTransparentRegion"); mService.openSurfaceTransaction(); try { - mSurfaceControl.setTransparentRegionHint(region); + getGlobalTransaction().setTransparentRegionHint(mSurfaceControl, region); } finally { mService.closeSurfaceTransaction("setTransparentRegion"); if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, @@ -264,7 +235,7 @@ class WindowSurfaceController { if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setOpaqueLocked"); mService.openSurfaceTransaction(); try { - mSurfaceControl.setOpaque(isOpaque); + getGlobalTransaction().setOpaque(mSurfaceControl, isOpaque); } finally { mService.closeSurfaceTransaction("setOpaqueLocked"); if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION setOpaqueLocked"); @@ -282,7 +253,7 @@ class WindowSurfaceController { if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setBackgroundBlurRadius"); mService.openSurfaceTransaction(); try { - mSurfaceControl.setBackgroundBlurRadius(radius); + getGlobalTransaction().setBackgroundBlurRadius(mSurfaceControl, radius); } finally { mService.closeSurfaceTransaction("setBackgroundBlurRadius"); if (SHOW_LIGHT_TRANSACTIONS) { @@ -300,7 +271,7 @@ class WindowSurfaceController { if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setSecureLocked"); mService.openSurfaceTransaction(); try { - mSurfaceControl.setSecure(isSecure); + getGlobalTransaction().setSecure(mSurfaceControl, isSecure); } finally { mService.closeSurfaceTransaction("setSecure"); if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION setSecureLocked"); @@ -318,7 +289,7 @@ class WindowSurfaceController { } mService.openSurfaceTransaction(); try { - mSurfaceControl.setColorSpaceAgnostic(agnostic); + getGlobalTransaction().setColorSpaceAgnostic(mSurfaceControl, agnostic); } finally { mService.closeSurfaceTransaction("setColorSpaceAgnostic"); if (SHOW_LIGHT_TRANSACTIONS) { @@ -327,7 +298,7 @@ class WindowSurfaceController { } } - boolean showRobustlyInTransaction() { + boolean showRobustly(SurfaceControl.Transaction t) { ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE SHOW (performLayout): %s", title); if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this + " during relayout"); @@ -336,21 +307,9 @@ class WindowSurfaceController { return true; } - try { - setShown(true); - mSurfaceControl.show(); - return true; - } catch (RuntimeException e) { - Slog.w(TAG, "Failure showing surface " + mSurfaceControl + " in " + this, e); - } - - mAnimator.reclaimSomeSurfaceMemory("show", true); - return false; - } - - void deferTransactionUntil(SurfaceControl barrier, long frame) { - // TODO: Logging - mSurfaceControl.deferTransactionUntil(barrier, frame); + setShown(true); + t.show(mSurfaceControl); + return true; } boolean clearWindowContentFrameStats() { @@ -391,14 +350,6 @@ class WindowSurfaceController { } } - int getWidth() { - return mSurfaceW; - } - - int getHeight() { - return mSurfaceH; - } - void dumpDebug(ProtoOutputStream proto, long fieldId) { final long token = proto.start(fieldId); proto.write(SHOWN, mSurfaceShown); diff --git a/services/core/jni/com_android_server_VibratorManagerService.cpp b/services/core/jni/com_android_server_VibratorManagerService.cpp index dae9cefdd1f4..71de9bda3c4f 100644 --- a/services/core/jni/com_android_server_VibratorManagerService.cpp +++ b/services/core/jni/com_android_server_VibratorManagerService.cpp @@ -26,8 +26,13 @@ #include <vibratorservice/VibratorManagerHalWrapper.h> +#include "com_android_server_VibratorManagerService.h" + namespace android { +static std::mutex gManagerMutex; +static vibrator::ManagerHalWrapper* gManager GUARDED_BY(gManagerMutex) = nullptr; + class NativeVibratorManagerService { public: NativeVibratorManagerService() : mHal(std::make_unique<vibrator::LegacyManagerHalWrapper>()) {} @@ -39,9 +44,16 @@ private: const std::unique_ptr<vibrator::ManagerHalWrapper> mHal; }; +vibrator::ManagerHalWrapper* android_server_VibratorManagerService_getManager() { + std::lock_guard<std::mutex> lock(gManagerMutex); + return gManager; +} + static void destroyNativeService(void* ptr) { NativeVibratorManagerService* service = reinterpret_cast<NativeVibratorManagerService*>(ptr); if (service) { + std::lock_guard<std::mutex> lock(gManagerMutex); + gManager = nullptr; delete service; } } @@ -49,6 +61,10 @@ static void destroyNativeService(void* ptr) { static jlong nativeInit(JNIEnv* /* env */, jclass /* clazz */) { std::unique_ptr<NativeVibratorManagerService> service = std::make_unique<NativeVibratorManagerService>(); + { + std::lock_guard<std::mutex> lock(gManagerMutex); + gManager = service->hal(); + } return reinterpret_cast<jlong>(service.release()); } diff --git a/services/core/jni/com_android_server_VibratorManagerService.h b/services/core/jni/com_android_server_VibratorManagerService.h new file mode 100644 index 000000000000..3f2a322b19ee --- /dev/null +++ b/services/core/jni/com_android_server_VibratorManagerService.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _ANDROID_SERVER_VIBRATOR_MANAGER_SERVICE_H +#define _ANDROID_SERVER_VIBRATOR_MANAGER_SERVICE_H + +#include <vibratorservice/VibratorManagerHalWrapper.h> + +namespace android { + +extern vibrator::ManagerHalWrapper* android_server_VibratorManagerService_getManager(); + +} // namespace android + +#endif // _ANDROID_SERVER_VIBRATOR_MANAGER_SERVICE_H diff --git a/services/core/jni/com_android_server_vibrator_VibratorController.cpp b/services/core/jni/com_android_server_vibrator_VibratorController.cpp index afce5379febb..7ed37481f8cb 100644 --- a/services/core/jni/com_android_server_vibrator_VibratorController.cpp +++ b/services/core/jni/com_android_server_vibrator_VibratorController.cpp @@ -29,6 +29,8 @@ #include <vibratorservice/VibratorHalController.h> +#include "com_android_server_VibratorManagerService.h" + namespace V1_0 = android::hardware::vibrator::V1_0; namespace V1_1 = android::hardware::vibrator::V1_1; namespace V1_2 = android::hardware::vibrator::V1_2; @@ -70,13 +72,26 @@ static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_15) == static_assert(static_cast<uint8_t>(V1_3::Effect::TEXTURE_TICK) == static_cast<uint8_t>(aidl::Effect::TEXTURE_TICK)); +static std::shared_ptr<vibrator::HalController> findVibrator(int32_t vibratorId) { + // TODO(b/167946816): remove this once VibratorService is removed. + if (vibratorId < 0) { + return std::move(std::make_unique<vibrator::HalController>()); + } + vibrator::ManagerHalWrapper* manager = android_server_VibratorManagerService_getManager(); + if (manager == nullptr) { + return nullptr; + } + auto result = manager->getVibrator(vibratorId); + return result.isOk() ? std::move(result.value()) : nullptr; +} + class VibratorControllerWrapper { public: VibratorControllerWrapper(JNIEnv* env, int32_t vibratorId, jobject callbackListener) - // TODO(b/167946816): use ManagerHalController to get vibrator by id - : mHal(std::make_unique<vibrator::HalController>()), + : mHal(std::move(findVibrator(vibratorId))), mVibratorId(vibratorId), mCallbackListener(env->NewGlobalRef(callbackListener)) { + LOG_ALWAYS_FATAL_IF(mHal == nullptr, "Unable to find reference to vibrator hal"); LOG_ALWAYS_FATAL_IF(mCallbackListener == nullptr, "Unable to create global reference to vibration callback handler"); } @@ -97,7 +112,7 @@ public: } private: - const std::unique_ptr<vibrator::HalController> mHal; + const std::shared_ptr<vibrator::HalController> mHal; const int32_t mVibratorId; const jobject mCallbackListener; }; diff --git a/services/core/xsd/device-state-config/OWNERS b/services/core/xsd/device-state-config/OWNERS new file mode 100644 index 000000000000..d9b0e2e5ffa5 --- /dev/null +++ b/services/core/xsd/device-state-config/OWNERS @@ -0,0 +1 @@ +include /services/core/java/com/android/server/devicestate/OWNERS diff --git a/services/core/xsd/device-state-config/device-state-config.xsd b/services/core/xsd/device-state-config/device-state-config.xsd index 501450398fc3..94a398f2cdb7 100644 --- a/services/core/xsd/device-state-config/device-state-config.xsd +++ b/services/core/xsd/device-state-config/device-state-config.xsd @@ -37,15 +37,21 @@ </xs:restriction> </xs:simpleType> </xs:element> - <xs:element name="name" type="xs:string" minOccurs="0" /> + <xs:element name="name" type="xs:string" minOccurs="0"> + <xs:annotation name="nullable" /> + </xs:element> <xs:element name="conditions" type="conditions" /> </xs:sequence> </xs:complexType> <xs:complexType name="conditions"> <xs:sequence> - <xs:element name="lid-switch" type="lidSwitchCondition" minOccurs="0" /> - <xs:element name="sensor" type="sensorCondition" minOccurs="0" maxOccurs="unbounded" /> + <xs:element name="lid-switch" type="lidSwitchCondition" minOccurs="0"> + <xs:annotation name="nullable" /> + </xs:element> + <xs:element name="sensor" type="sensorCondition" minOccurs="0" maxOccurs="unbounded"> + <xs:annotation name="nullable" /> + </xs:element> </xs:sequence> </xs:complexType> @@ -66,12 +72,20 @@ <xs:complexType name="numericRange"> <xs:sequence> <xs:choice minOccurs="0"> - <xs:element name="min" type="xs:decimal" /> - <xs:element name="min-inclusive" type="xs:decimal" /> + <xs:element name="min" type="xs:decimal"> + <xs:annotation name="nullable" /> + </xs:element> + <xs:element name="min-inclusive" type="xs:decimal"> + <xs:annotation name="nullable" /> + </xs:element> </xs:choice> <xs:choice minOccurs="0"> - <xs:element name="max" type="xs:decimal" /> - <xs:element name="max-inclusive" type="xs:decimal"/> + <xs:element name="max" type="xs:decimal"> + <xs:annotation name="nullable" /> + </xs:element> + <xs:element name="max-inclusive" type="xs:decimal"> + <xs:annotation name="nullable" /> + </xs:element> </xs:choice> </xs:sequence> </xs:complexType> diff --git a/services/core/xsd/device-state-config/schema/current.txt b/services/core/xsd/device-state-config/schema/current.txt index b396af0fa0c6..08fccf8ad949 100644 --- a/services/core/xsd/device-state-config/schema/current.txt +++ b/services/core/xsd/device-state-config/schema/current.txt @@ -3,19 +3,19 @@ package com.android.server.policy.devicestate.config { public class Conditions { ctor public Conditions(); - method public com.android.server.policy.devicestate.config.LidSwitchCondition getLidSwitch(); - method public java.util.List<com.android.server.policy.devicestate.config.SensorCondition> getSensor(); - method public void setLidSwitch(com.android.server.policy.devicestate.config.LidSwitchCondition); + method @Nullable public com.android.server.policy.devicestate.config.LidSwitchCondition getLidSwitch(); + method @Nullable public java.util.List<com.android.server.policy.devicestate.config.SensorCondition> getSensor(); + method public void setLidSwitch(@Nullable com.android.server.policy.devicestate.config.LidSwitchCondition); } public class DeviceState { ctor public DeviceState(); method public com.android.server.policy.devicestate.config.Conditions getConditions(); method public java.math.BigInteger getIdentifier(); - method public String getName(); + method @Nullable public String getName(); method public void setConditions(com.android.server.policy.devicestate.config.Conditions); method public void setIdentifier(java.math.BigInteger); - method public void setName(String); + method public void setName(@Nullable String); } public class DeviceStateConfig { @@ -31,14 +31,14 @@ package com.android.server.policy.devicestate.config { public class NumericRange { ctor public NumericRange(); - method public java.math.BigDecimal getMaxInclusive_optional(); - method public java.math.BigDecimal getMax_optional(); - method public java.math.BigDecimal getMinInclusive_optional(); - method public java.math.BigDecimal getMin_optional(); - method public void setMaxInclusive_optional(java.math.BigDecimal); - method public void setMax_optional(java.math.BigDecimal); - method public void setMinInclusive_optional(java.math.BigDecimal); - method public void setMin_optional(java.math.BigDecimal); + method @Nullable public java.math.BigDecimal getMaxInclusive_optional(); + method @Nullable public java.math.BigDecimal getMax_optional(); + method @Nullable public java.math.BigDecimal getMinInclusive_optional(); + method @Nullable public java.math.BigDecimal getMin_optional(); + method public void setMaxInclusive_optional(@Nullable java.math.BigDecimal); + method public void setMax_optional(@Nullable java.math.BigDecimal); + method public void setMinInclusive_optional(@Nullable java.math.BigDecimal); + method public void setMin_optional(@Nullable java.math.BigDecimal); } public class SensorCondition { diff --git a/services/core/xsd/display-device-config/OWNERS b/services/core/xsd/display-device-config/OWNERS new file mode 100644 index 000000000000..20b75be9f11f --- /dev/null +++ b/services/core/xsd/display-device-config/OWNERS @@ -0,0 +1,3 @@ +include /services/core/java/com/android/server/display/OWNERS + +flc@google.com diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java index f2e5878e5705..6f1d451e7224 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java @@ -22,8 +22,6 @@ import android.util.Slog; import com.android.server.SystemService; -import java.util.List; - /** * Defines the required interface for IDevicePolicyManager implemenation. * @@ -103,9 +101,4 @@ abstract class BaseIDevicePolicyManager extends IDevicePolicyManager.Stub { public boolean canProfileOwnerResetPasswordWhenLocked(int userId) { return false; } - - public List<String> getKeyPairGrants(String callerPackage, String alias) { - // STOPSHIP: implement delegation code in ArcDevicePolicyManagerWrapperService & nuke this. - return null; - } } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java index 31ba1991ee72..c766ca07029c 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java @@ -16,14 +16,15 @@ package com.android.server.devicepolicy; +import android.annotation.UserIdInt; import android.app.admin.DeviceAdminInfo; import android.app.admin.DevicePolicyManager; import android.content.ComponentName; import android.os.FileUtils; import android.os.PersistableBundle; -import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; +import android.util.IndentingPrintWriter; import android.util.Slog; import android.util.TypedXmlPullParser; import android.util.TypedXmlSerializer; @@ -77,13 +78,14 @@ class DevicePolicyData { private static final String ATTR_DEVICE_PROVISIONING_CONFIG_APPLIED = "device-provisioning-config-applied"; private static final String ATTR_DEVICE_PAIRED = "device-paired"; + private static final String TAG = DevicePolicyManagerService.LOG_TAG; private static final boolean VERBOSE_LOG = false; // DO NOT SUBMIT WITH TRUE int mFailedPasswordAttempts = 0; boolean mPasswordValidAtLastCheckpoint = true; - int mUserHandle; + final @UserIdInt int mUserId; int mPasswordOwner = -1; long mLastMaximumTimeToLock = -1; boolean mUserSetupComplete = false; @@ -144,8 +146,8 @@ class DevicePolicyData { // apps were suspended or unsuspended. boolean mAppsSuspended = false; - DevicePolicyData(int userHandle) { - mUserHandle = userHandle; + DevicePolicyData(@UserIdInt int userId) { + mUserId = userId; } /** @@ -156,7 +158,7 @@ class DevicePolicyData { try { File chooseForWrite = file.chooseForWrite(); if (VERBOSE_LOG) { - Slog.v(TAG, "Storing data for user " + policyData.mUserHandle + " on " + Slog.v(TAG, "Storing data for user " + policyData.mUserId + " on " + chooseForWrite); } stream = new FileOutputStream(chooseForWrite, false); @@ -365,7 +367,7 @@ class DevicePolicyData { FileInputStream stream = null; File file = journaledFile.chooseForRead(); if (VERBOSE_LOG) { - Slog.v(TAG, "Loading data for user " + policy.mUserHandle + " from " + file); + Slog.v(TAG, "Loading data for user " + policy.mUserId + " from " + file); } boolean needsRewrite = false; try { @@ -556,4 +558,37 @@ class DevicePolicyData { } } } + + void dump(IndentingPrintWriter pw) { + pw.println(); + pw.println("Enabled Device Admins (User " + mUserId + ", provisioningState: " + + mUserProvisioningState + "):"); + final int n = mAdminList.size(); + for (int i = 0; i < n; i++) { + ActiveAdmin ap = mAdminList.get(i); + if (ap != null) { + pw.increaseIndent(); + pw.print(ap.info.getComponent().flattenToShortString()); + pw.println(":"); + pw.increaseIndent(); + ap.dump(pw); + pw.decreaseIndent(); + pw.decreaseIndent(); + } + } + if (!mRemovingAdmins.isEmpty()) { + pw.increaseIndent(); + pw.println("Removing Device Admins (User " + mUserId + "): " + mRemovingAdmins); + pw.decreaseIndent(); + } + pw.println(); + pw.increaseIndent(); + pw.print("mPasswordOwner="); pw.println(mPasswordOwner); + pw.print("mUserControlDisabledPackages="); + pw.println(mUserControlDisabledPackages); + pw.print("mAppsSuspended="); pw.println(mAppsSuspended); + pw.print("mUserSetupComplete="); pw.println(mUserSetupComplete); + pw.print("mAffiliationIds="); pw.println(mAffiliationIds); + pw.decreaseIndent(); + } } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 6d2cb9cc5cd9..8c66137b9b10 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -940,7 +940,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { // Persist updates if the removed package was an admin or delegate. if (removedAdmin || removedDelegate) { - saveSettingsLocked(policy.mUserHandle); + saveSettingsLocked(policy.mUserId); } } if (removedAdmin) { @@ -3368,7 +3368,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final boolean qualityMayApplyToParent = canSetPasswordQualityOnParent(who.getPackageName(), caller.getUserId()); if (!qualityMayApplyToParent) { - Preconditions.checkArgument(!parent, + Preconditions.checkCallAuthorization(!parent, "Profile Owner may not apply password quality requirements device-wide"); } @@ -8746,37 +8746,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { int userCount = mUserData.size(); for (int u = 0; u < userCount; u++) { DevicePolicyData policy = getUserData(mUserData.keyAt(u)); - pw.println(); - pw.println("Enabled Device Admins (User " + policy.mUserHandle - + ", provisioningState: " + policy.mUserProvisioningState + "):"); - final int n = policy.mAdminList.size(); - for (int i = 0; i < n; i++) { - ActiveAdmin ap = policy.mAdminList.get(i); - if (ap != null) { - pw.increaseIndent(); - pw.print(ap.info.getComponent().flattenToShortString()); - pw.println(":"); - pw.increaseIndent(); - ap.dump(pw); - pw.decreaseIndent(); - pw.decreaseIndent(); - } - } - if (!policy.mRemovingAdmins.isEmpty()) { - pw.increaseIndent(); - pw.println("Removing Device Admins (User " + policy.mUserHandle + "): " - + policy.mRemovingAdmins); - pw.decreaseIndent(); - } - pw.println(); - pw.increaseIndent(); - pw.print("mPasswordOwner="); pw.println(policy.mPasswordOwner); - pw.print("mUserControlDisabledPackages="); - pw.println(policy.mUserControlDisabledPackages); - pw.print("mAppsSuspended="); pw.println(policy.mAppsSuspended); - pw.print("mUserSetupComplete="); pw.println(policy.mUserSetupComplete); - pw.print("mAffiliationIds="); pw.println(policy.mAffiliationIds); - pw.decreaseIndent(); + policy.dump(pw); } } @@ -12564,7 +12534,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { Objects.requireNonNull(admin, "ComponentName is null"); final CallerIdentity caller = getCallerIdentity(admin); Preconditions.checkCallAuthorization(isDeviceOwner(caller)); - + checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_REBOOT); mInjector.binderWithCleanCallingIdentity(() -> { // Make sure there are no ongoing calls on the device. if (mTelephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) { @@ -13478,14 +13448,16 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final CallerIdentity caller = getCallerIdentity(admin); Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller)); - synchronized (getLockObject()) { - try { - IBackupManager ibm = mInjector.getIBackupManager(); - return ibm != null && ibm.isBackupServiceActive(caller.getUserId()); - } catch (RemoteException e) { - throw new IllegalStateException("Failed requesting backup service state.", e); + return mInjector.binderWithCleanCallingIdentity(() -> { + synchronized (getLockObject()) { + try { + IBackupManager ibm = mInjector.getIBackupManager(); + return ibm != null && ibm.isBackupServiceActive(caller.getUserId()); + } catch (RemoteException e) { + throw new IllegalStateException("Failed requesting backup service state.", e); + } } - } + }); } @Override diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 6525e1126478..242cee8eaccd 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -1252,6 +1252,10 @@ public final class SystemServer implements Dumpable { mSystemServiceManager.startService(DropBoxManagerService.class); t.traceEnd(); + t.traceBegin("StartVibratorManagerService"); + mSystemServiceManager.startService(VibratorManagerService.Lifecycle.class); + t.traceEnd(); + t.traceBegin("StartVibratorService"); vibrator = new VibratorService(context); ServiceManager.addService("vibrator", vibrator); @@ -1277,6 +1281,10 @@ public final class SystemServer implements Dumpable { inputManager = new InputManagerService(context); t.traceEnd(); + t.traceBegin("DeviceStateManagerService"); + mSystemServiceManager.startService(DeviceStateManagerService.class); + t.traceEnd(); + if (!disableCameraService) { t.traceBegin("StartCameraServiceProxy"); mSystemServiceManager.startService(CameraServiceProxy.class); @@ -1370,10 +1378,6 @@ public final class SystemServer implements Dumpable { mSystemServiceManager.startService(AppIntegrityManagerService.class); t.traceEnd(); - t.traceBegin("DeviceStateManagerService"); - mSystemServiceManager.startService(DeviceStateManagerService.class); - t.traceEnd(); - } catch (Throwable e) { Slog.e("System", "******************************************"); Slog.e("System", "************ Failure starting core service"); diff --git a/services/robotests/src/com/android/server/location/OWNERS b/services/robotests/src/com/android/server/location/OWNERS new file mode 100644 index 000000000000..696a0c22c605 --- /dev/null +++ b/services/robotests/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/display/LocalDisplayAdapterTest.java b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java index dbdee979b6a4..af4130d92cfe 100644 --- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java @@ -19,11 +19,14 @@ package com.android.server.display; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.mockito.ArgumentMatchers.anyFloat; +import static org.mockito.Mockito.never; import android.content.Context; import android.content.res.Resources; @@ -40,7 +43,9 @@ import androidx.test.runner.AndroidJUnit4; import com.android.dx.mockito.inline.extended.StaticMockitoSession; import com.android.server.LocalServices; +import com.android.server.display.LocalDisplayAdapter.BacklightAdapter; import com.android.server.lights.LightsManager; +import com.android.server.lights.LogicalLight; import com.google.common.truth.Truth; @@ -78,6 +83,8 @@ public class LocalDisplayAdapterTest { private Resources mMockedResources; @Mock private LightsManager mMockedLightsManager; + @Mock + private LogicalLight mMockedBacklight; private Handler mHandler; @@ -492,6 +499,49 @@ public class LocalDisplayAdapterTest { waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS); } + @Test + public void testBacklightAdapter_withSurfaceControlSupport() { + final Binder displayToken = new Binder(); + doReturn(true).when(() -> SurfaceControl.getDisplayBrightnessSupport(displayToken)); + + // Test as default display + BacklightAdapter ba = new BacklightAdapter(displayToken, true /*isDefault*/); + ba.setBrightness(0.514f); + verify(() -> SurfaceControl.setDisplayBrightness(displayToken, 0.514f)); + + // Test as not default display + BacklightAdapter ba2 = new BacklightAdapter(displayToken, + false /*isDefault*/); + ba2.setBrightness(0.323f); + verify(() -> SurfaceControl.setDisplayBrightness(displayToken, 0.323f)); + } + + @Test + public void testBacklightAdapter_withoutSourceControlSupport_defaultDisplay() { + final Binder displayToken = new Binder(); + doReturn(false).when(() -> SurfaceControl.getDisplayBrightnessSupport(displayToken)); + doReturn(mMockedBacklight).when(mMockedLightsManager) + .getLight(LightsManager.LIGHT_ID_BACKLIGHT); + + BacklightAdapter ba = new BacklightAdapter(displayToken, true /*isDefault*/); + ba.setBrightness(0.123f); + verify(mMockedBacklight).setBrightness(0.123f); + } + + @Test + public void testBacklightAdapter_withoutSourceControlSupport_nonDefaultDisplay() { + final Binder displayToken = new Binder(); + doReturn(false).when(() -> SurfaceControl.getDisplayBrightnessSupport(displayToken)); + doReturn(mMockedBacklight).when(mMockedLightsManager) + .getLight(LightsManager.LIGHT_ID_BACKLIGHT); + + BacklightAdapter ba = new BacklightAdapter(displayToken, false /*isDefault*/); + ba.setBrightness(0.456f); + + // Adapter does not forward any brightness in this case. + verify(mMockedBacklight, never()).setBrightness(anyFloat()); + } + private void assertDisplayDpi(DisplayDeviceInfo info, int expectedPort, float expectedXdpi, float expectedYDpi, diff --git a/services/tests/servicestests/res/raw/a11y_three_finger_swipe_down_gesture.log b/services/tests/servicestests/res/raw/a11y_three_finger_swipe_down_gesture.log new file mode 100644 index 000000000000..cf791f2f3ecb --- /dev/null +++ b/services/tests/servicestests/res/raw/a11y_three_finger_swipe_down_gesture.log @@ -0,0 +1,29 @@ + * Gesture6_id30:Swipe down with 3 finger +MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=500.0, y[0]=696.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=5273700, downTime=5273700, deviceId=4, source=0x1002, displayId=0 } +MotionEvent { action=ACTION_POINTER_DOWN(1), actionButton=0, id[0]=0, x[0]=500.0, y[0]=696.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=764.0, y[1]=801.0, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=5273700, downTime=5273700, deviceId=4, source=0x1002, displayId=0 } +MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=500.0, y[0]=696.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=764.0, y[1]=801.0, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=5273709, downTime=5273700, deviceId=4, source=0x1002, displayId=0 } +MotionEvent { action=ACTION_POINTER_DOWN(2), actionButton=0, id[0]=0, x[0]=500.0, y[0]=696.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=764.0, y[1]=801.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=294.0, y[2]=849.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273709, downTime=5273700, deviceId=4, source=0x1002, displayId=0 } +MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=500.0, y[0]=696.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=766.0, y[1]=811.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=294.0, y[2]=849.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273715, downTime=5273700, deviceId=4, source=0x1002, displayId=0 } +MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=503.0, y[0]=699.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=773.0, y[1]=838.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=294.0, y[2]=849.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273725, downTime=5273700, deviceId=4, source=0x1002, displayId=0 } +MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=521.0, y[0]=728.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=776.0, y[1]=862.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=305.0, y[2]=876.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273734, downTime=5273700, deviceId=4, source=0x1002, displayId=0 } +MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=535.0, y[0]=765.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=782.0, y[1]=898.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=313.0, y[2]=911.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273741, downTime=5273700, deviceId=4, source=0x1002, displayId=0 } +MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=545.0, y[0]=795.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=786.0, y[1]=918.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=323.0, y[2]=941.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273750, downTime=5273700, deviceId=4, source=0x1002, displayId=0 } +MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=555.0, y[0]=832.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=790.0, y[1]=959.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=333.0, y[2]=976.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273758, downTime=5273700, deviceId=4, source=0x1002, displayId=0 } +MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=560.0, y[0]=870.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=794.0, y[1]=988.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=339.0, y[2]=1020.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273767, downTime=5273700, deviceId=4, source=0x1002, displayId=0 } +MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=565.0, y[0]=909.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=797.0, y[1]=1031.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=345.0, y[2]=1052.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273776, downTime=5273700, deviceId=4, source=0x1002, displayId=0 } +MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=568.0, y[0]=948.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=801.0, y[1]=1060.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=348.0, y[2]=1102.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273784, downTime=5273700, deviceId=4, source=0x1002, displayId=0 } +MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=570.0, y[0]=985.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=804.0, y[1]=1103.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=352.0, y[2]=1130.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273793, downTime=5273700, deviceId=4, source=0x1002, displayId=0 } +MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=571.0, y[0]=1028.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=807.0, y[1]=1133.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=355.0, y[2]=1178.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273801, downTime=5273700, deviceId=4, source=0x1002, displayId=0 } +MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=572.0, y[0]=1061.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=809.0, y[1]=1175.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=358.0, y[2]=1212.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273810, downTime=5273700, deviceId=4, source=0x1002, displayId=0 } +MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=574.0, y[0]=1108.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=811.0, y[1]=1206.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=360.0, y[2]=1260.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273822, downTime=5273700, deviceId=4, source=0x1002, displayId=0 } +MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=575.0, y[0]=1141.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=812.0, y[1]=1249.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=363.0, y[2]=1294.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273831, downTime=5273700, deviceId=4, source=0x1002, displayId=0 } +MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=576.0, y[0]=1191.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=815.0, y[1]=1281.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=364.0, y[2]=1343.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273836, downTime=5273700, deviceId=4, source=0x1002, displayId=0 } +MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=578.0, y[0]=1227.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=816.0, y[1]=1324.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=368.0, y[2]=1374.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273844, downTime=5273700, deviceId=4, source=0x1002, displayId=0 } +MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=581.0, y[0]=1276.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=820.0, y[1]=1360.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=371.0, y[2]=1421.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273853, downTime=5273700, deviceId=4, source=0x1002, displayId=0 } +MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=581.0, y[0]=1324.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=823.0, y[1]=1406.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=372.0, y[2]=1464.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273862, downTime=5273700, deviceId=4, source=0x1002, displayId=0 } +MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=584.0, y[0]=1369.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=824.0, y[1]=1445.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=379.0, y[2]=1506.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273870, downTime=5273700, deviceId=4, source=0x1002, displayId=0 } +MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=586.0, y[0]=1417.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=826.0, y[1]=1493.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=387.0, y[2]=1553.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273879, downTime=5273700, deviceId=4, source=0x1002, displayId=0 } +MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=586.0, y[0]=1417.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=826.0, y[1]=1493.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=387.0, y[2]=1553.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273888, downTime=5273700, deviceId=4, source=0x1002, displayId=0 } +MotionEvent { action=ACTION_POINTER_UP(0), actionButton=0, id[0]=0, x[0]=586.0, y[0]=1417.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=1, x[1]=826.0, y[1]=1493.0, toolType[1]=TOOL_TYPE_FINGER, id[2]=2, x[2]=387.0, y[2]=1553.0, toolType[2]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=3, historySize=0, eventTime=5273895, downTime=5273700, deviceId=4, source=0x1002, displayId=0 } +MotionEvent { action=ACTION_POINTER_UP(0), actionButton=0, id[0]=1, x[0]=826.0, y[0]=1493.0, toolType[0]=TOOL_TYPE_FINGER, id[1]=2, x[1]=387.0, y[1]=1553.0, toolType[1]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=2, historySize=0, eventTime=5273895, downTime=5273700, deviceId=4, source=0x1002, displayId=0 } +MotionEvent { action=ACTION_UP, actionButton=0, id[0]=2, x[0]=387.0, y[0]=1553.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=5273895, downTime=5273700, deviceId=4, source=0x1002, displayId=0 }
\ No newline at end of file diff --git a/services/tests/servicestests/res/raw/a11y_touch_explore_gesture.log b/services/tests/servicestests/res/raw/a11y_touch_explore_gesture.log new file mode 100644 index 000000000000..3cfb0a72181f --- /dev/null +++ b/services/tests/servicestests/res/raw/a11y_touch_explore_gesture.log @@ -0,0 +1,4 @@ +* Gesture4_id-2:Touch explore +MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=825.0, y[0]=2028.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=5258108, downTime=5258108, deviceId=4, source=0x1002, displayId=0 } +MotionEvent { action=ACTION_MOVE, actionButton=0, id[0]=0, x[0]=825.0, y[0]=2028.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=5258133, downTime=5258108, deviceId=4, source=0x1002, displayId=0 } +MotionEvent { action=ACTION_UP, actionButton=0, id[0]=0, x[0]=825.0, y[0]=2028.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, classification=NONE, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=5258141, downTime=5258108, deviceId=4, source=0x1002, displayId=0 }
\ No newline at end of file diff --git a/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java b/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java index a02c53336da0..6814c050a845 100644 --- a/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java @@ -163,16 +163,26 @@ public class GestureLauncherServiceTest { } @Test - public void testIsEmergencyGestureEnabled_settingDisabled() { + public void testIsEmergencyGestureSettingEnabled_settingDisabled() { + withEmergencyGestureEnabledConfigValue(true); withEmergencyGestureEnabledSettingValue(false); - assertFalse(mGestureLauncherService.isEmergencyGestureEnabled( + assertFalse(mGestureLauncherService.isEmergencyGestureSettingEnabled( mContext, FAKE_USER_ID)); } @Test - public void testIsEmergencyGestureEnabled_settingEnabled() { + public void testIsEmergencyGestureSettingEnabled_settingEnabled() { + withEmergencyGestureEnabledConfigValue(true); withEmergencyGestureEnabledSettingValue(true); - assertTrue(mGestureLauncherService.isEmergencyGestureEnabled( + assertTrue(mGestureLauncherService.isEmergencyGestureSettingEnabled( + mContext, FAKE_USER_ID)); + } + + @Test + public void testIsEmergencyGestureSettingEnabled_supportDisabled() { + withEmergencyGestureEnabledConfigValue(false); + withEmergencyGestureEnabledSettingValue(true); + assertFalse(mGestureLauncherService.isEmergencyGestureSettingEnabled( mContext, FAKE_USER_ID)); } @@ -438,6 +448,7 @@ public class GestureLauncherServiceTest { testInterceptPowerKeyDown_fiveInboundPresses_cameraAndEmergencyEnabled_bothLaunch() { withCameraDoubleTapPowerEnableConfigValue(true); withCameraDoubleTapPowerDisableSettingValue(0); + withEmergencyGestureEnabledConfigValue(true); withEmergencyGestureEnabledSettingValue(true); mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); mGestureLauncherService.updateEmergencyGestureEnabled(); @@ -527,6 +538,7 @@ public class GestureLauncherServiceTest { @Test public void testInterceptPowerKeyDown_fiveInboundPresses_emergencyGestureEnabled_launchesFlow() { + withEmergencyGestureEnabledConfigValue(true); withEmergencyGestureEnabledSettingValue(true); mGestureLauncherService.updateEmergencyGestureEnabled(); withUserSetupCompleteValue(true); @@ -580,6 +592,7 @@ public class GestureLauncherServiceTest { @Test public void testInterceptPowerKeyDown_tenInboundPresses_emergencyGestureEnabled_keyIntercepted() { + withEmergencyGestureEnabledConfigValue(true); withEmergencyGestureEnabledSettingValue(true); mGestureLauncherService.updateEmergencyGestureEnabled(); withUserSetupCompleteValue(true); @@ -1146,6 +1159,12 @@ public class GestureLauncherServiceTest { .thenReturn(enableConfigValue); } + private void withEmergencyGestureEnabledConfigValue(boolean enableConfigValue) { + when(mResources.getBoolean( + com.android.internal.R.bool.config_emergencyGestureEnabled)) + .thenReturn(enableConfigValue); + } + private void withCameraDoubleTapPowerDisableSettingValue(int disableSettingValue) { Settings.Secure.putIntForUser( mContentResolver, diff --git a/services/tests/servicestests/src/com/android/server/OWNERS b/services/tests/servicestests/src/com/android/server/OWNERS index 2463fc617f0b..6561778cb47d 100644 --- a/services/tests/servicestests/src/com/android/server/OWNERS +++ b/services/tests/servicestests/src/com/android/server/OWNERS @@ -1,5 +1,5 @@ per-file *Alarm* = file:/apex/jobscheduler/OWNERS -per-file *AppOps* = file:/core/java/android/permission/OWNERS +per-file *AppOp* = file:/core/java/android/permission/OWNERS per-file *Bluetooth* = file:/core/java/android/bluetooth/OWNERS per-file *Gnss* = file:/services/core/java/com/android/server/location/OWNERS per-file *Network* = file:/services/core/java/com/android/server/net/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/VibratorManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/VibratorManagerServiceTest.java index 044bdbadb946..726536db859e 100644 --- a/services/tests/servicestests/src/com/android/server/VibratorManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/VibratorManagerServiceTest.java @@ -19,17 +19,38 @@ package com.android.server; import static com.android.server.testutils.TestUtils.assertExpectException; 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.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.hardware.vibrator.IVibrator; import android.os.CombinedVibrationEffect; +import android.os.Handler; +import android.os.Looper; +import android.os.PowerManager; +import android.os.PowerManagerInternal; +import android.os.PowerSaveState; import android.os.Process; import android.os.VibrationAttributes; import android.os.VibrationEffect; +import android.os.Vibrator; +import android.os.VibratorInfo; +import android.os.test.TestLooper; import android.platform.test.annotations.Presubmit; import androidx.test.InstrumentationRegistry; +import com.android.server.vibrator.VibratorController; + +import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -37,6 +58,9 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; +import java.util.HashMap; +import java.util.Map; + /** * Tests for {@link VibratorManagerService}. * @@ -51,24 +75,54 @@ public class VibratorManagerServiceTest { private static final VibrationAttributes ALARM_ATTRS = new VibrationAttributes.Builder().setUsage(VibrationAttributes.USAGE_ALARM).build(); - @Rule - public MockitoRule rule = MockitoJUnit.rule(); + @Rule public MockitoRule rule = MockitoJUnit.rule(); + + @Mock private VibratorManagerService.NativeWrapper mNativeWrapperMock; + @Mock private PowerManagerInternal mPowerManagerInternalMock; + @Mock private PowerSaveState mPowerSaveStateMock; + + private final Map<Integer, VibratorController.NativeWrapper> mNativeWrappers = new HashMap<>(); - @Mock - private VibratorManagerService.NativeWrapper mNativeWrapperMock; + private TestLooper mTestLooper; @Before public void setUp() throws Exception { + mTestLooper = new TestLooper(); + + when(mPowerManagerInternalMock.getLowPowerState(PowerManager.ServiceType.VIBRATION)) + .thenReturn(mPowerSaveStateMock); + + addLocalServiceMock(PowerManagerInternal.class, mPowerManagerInternalMock); + } + + @After + public void tearDown() throws Exception { + LocalServices.removeServiceForTest(PowerManagerInternal.class); } private VibratorManagerService createService() { - return new VibratorManagerService(InstrumentationRegistry.getContext(), + VibratorManagerService service = new VibratorManagerService( + InstrumentationRegistry.getContext(), new VibratorManagerService.Injector() { @Override VibratorManagerService.NativeWrapper getNativeWrapper() { return mNativeWrapperMock; } + + @Override + Handler createHandler(Looper looper) { + return new Handler(mTestLooper.getLooper()); + } + + @Override + VibratorController createVibratorController(int vibratorId, + VibratorController.OnVibrationCompleteListener listener) { + return new VibratorController( + vibratorId, listener, mNativeWrappers.get(vibratorId)); + } }); + service.systemReady(); + return service; } @Test @@ -85,8 +139,156 @@ public class VibratorManagerServiceTest { @Test public void getVibratorIds_withNonEmptyResultFromNative_returnsSameArray() { - when(mNativeWrapperMock.getVibratorIds()).thenReturn(new int[]{1, 2}); - assertArrayEquals(new int[]{1, 2}, createService().getVibratorIds()); + mNativeWrappers.put(1, mockVibrator(/* capabilities= */ 0)); + mNativeWrappers.put(2, mockVibrator(/* capabilities= */ 0)); + when(mNativeWrapperMock.getVibratorIds()).thenReturn(new int[]{2, 1}); + assertArrayEquals(new int[]{2, 1}, createService().getVibratorIds()); + } + + @Test + public void getVibratorInfo_withMissingVibratorId_returnsNull() { + mockVibrators(mockVibrator(/* capabilities= */ 0)); + assertNull(createService().getVibratorInfo(2)); + } + + @Test + public void getVibratorInfo_withExistingVibratorId_returnsHalInfoForVibrator() { + VibratorController.NativeWrapper vibratorMock = mockVibrator( + IVibrator.CAP_COMPOSE_EFFECTS | IVibrator.CAP_AMPLITUDE_CONTROL); + when(vibratorMock.getSupportedEffects()).thenReturn( + new int[]{VibrationEffect.EFFECT_CLICK}); + when(vibratorMock.getSupportedPrimitives()).thenReturn( + new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK}); + mNativeWrappers.put(1, vibratorMock); + when(mNativeWrapperMock.getVibratorIds()).thenReturn(new int[]{1}); + VibratorInfo info = createService().getVibratorInfo(1); + + assertNotNull(info); + assertEquals(1, info.getId()); + assertTrue(info.hasAmplitudeControl()); + assertTrue(info.hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)); + assertFalse(info.hasCapability(IVibrator.CAP_ON_CALLBACK)); + assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_YES, + info.isEffectSupported(VibrationEffect.EFFECT_CLICK)); + assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_NO, + info.isEffectSupported(VibrationEffect.EFFECT_TICK)); + assertTrue(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_CLICK)); + assertFalse(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_TICK)); + } + + @Test + public void setAlwaysOnEffect_withMono_enablesAlwaysOnEffectToAllVibratorsWithCapability() { + VibratorController.NativeWrapper[] vibratorMocks = new VibratorController.NativeWrapper[]{ + mockVibrator(IVibrator.CAP_ALWAYS_ON_CONTROL), + mockVibrator(/* capabilities= */ 0), + mockVibrator(IVibrator.CAP_ALWAYS_ON_CONTROL), + }; + mockVibrators(vibratorMocks); + + CombinedVibrationEffect effect = CombinedVibrationEffect.createSynced( + VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK)); + assertTrue(createService().setAlwaysOnEffect(UID, PACKAGE_NAME, 1, effect, ALARM_ATTRS)); + + // Only vibrators 0 and 2 have always-on capabilities. + verify(vibratorMocks[0]).alwaysOnEnable( + eq(1L), eq((long) VibrationEffect.EFFECT_CLICK), + eq((long) VibrationEffect.EFFECT_STRENGTH_STRONG)); + verify(vibratorMocks[1], never()).alwaysOnEnable(anyLong(), anyLong(), anyLong()); + verify(vibratorMocks[2]).alwaysOnEnable( + eq(1L), eq((long) VibrationEffect.EFFECT_CLICK), + eq((long) VibrationEffect.EFFECT_STRENGTH_STRONG)); + } + + @Test + public void setAlwaysOnEffect_withStereo_enablesAlwaysOnEffectToAllVibratorsWithCapability() { + VibratorController.NativeWrapper[] vibratorMocks = new VibratorController.NativeWrapper[] { + mockVibrator(IVibrator.CAP_ALWAYS_ON_CONTROL), + mockVibrator(IVibrator.CAP_ALWAYS_ON_CONTROL), + mockVibrator(0), + mockVibrator(IVibrator.CAP_ALWAYS_ON_CONTROL), + }; + mockVibrators(vibratorMocks); + + CombinedVibrationEffect effect = CombinedVibrationEffect.startSynced() + .addVibrator(0, VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK)) + .addVibrator(1, VibrationEffect.createPredefined(VibrationEffect.EFFECT_TICK)) + .addVibrator(2, VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK)) + .combine(); + assertTrue(createService().setAlwaysOnEffect(UID, PACKAGE_NAME, 1, effect, ALARM_ATTRS)); + + // Enables click on vibrator 0 and tick on vibrator 1 only. + verify(vibratorMocks[0]).alwaysOnEnable( + eq(1L), eq((long) VibrationEffect.EFFECT_CLICK), + eq((long) VibrationEffect.EFFECT_STRENGTH_STRONG)); + verify(vibratorMocks[1]).alwaysOnEnable( + eq(1L), eq((long) VibrationEffect.EFFECT_TICK), + eq((long) VibrationEffect.EFFECT_STRENGTH_STRONG)); + verify(vibratorMocks[2], never()).alwaysOnEnable(anyLong(), anyLong(), anyLong()); + verify(vibratorMocks[3], never()).alwaysOnEnable(anyLong(), anyLong(), anyLong()); + } + + @Test + public void setAlwaysOnEffect_withNullEffect_disablesAlwaysOnEffects() { + VibratorController.NativeWrapper[] vibratorMocks = new VibratorController.NativeWrapper[] { + mockVibrator(IVibrator.CAP_ALWAYS_ON_CONTROL), + mockVibrator(0), + mockVibrator(IVibrator.CAP_ALWAYS_ON_CONTROL), + }; + mockVibrators(vibratorMocks); + + assertTrue(createService().setAlwaysOnEffect(UID, PACKAGE_NAME, 1, null, ALARM_ATTRS)); + + // Disables only 0 and 2 that have capability. + verify(vibratorMocks[0]).alwaysOnDisable(eq(1L)); + verify(vibratorMocks[1], never()).alwaysOnDisable(anyLong()); + verify(vibratorMocks[2]).alwaysOnDisable(eq(1L)); + } + + @Test + public void setAlwaysOnEffect_withNonPrebakedEffect_ignoresEffect() { + VibratorController.NativeWrapper vibratorMock = + mockVibrator(IVibrator.CAP_ALWAYS_ON_CONTROL); + mockVibrators(vibratorMock); + + CombinedVibrationEffect effect = CombinedVibrationEffect.createSynced( + VibrationEffect.createOneShot(100, VibrationEffect.DEFAULT_AMPLITUDE)); + assertFalse(createService().setAlwaysOnEffect(UID, PACKAGE_NAME, 1, effect, ALARM_ATTRS)); + + verify(vibratorMock, never()).alwaysOnEnable(anyLong(), anyLong(), anyLong()); + verify(vibratorMock, never()).alwaysOnDisable(anyLong()); + } + + @Test + public void setAlwaysOnEffect_withNonSyncedEffect_ignoresEffect() { + VibratorController.NativeWrapper vibratorMock = + mockVibrator(IVibrator.CAP_ALWAYS_ON_CONTROL); + mockVibrators(vibratorMock); + + CombinedVibrationEffect effect = CombinedVibrationEffect.startSequential() + .addNext(0, VibrationEffect.get(VibrationEffect.EFFECT_CLICK)) + .combine(); + assertFalse(createService().setAlwaysOnEffect(UID, PACKAGE_NAME, 1, effect, ALARM_ATTRS)); + + verify(vibratorMock, never()).alwaysOnEnable(anyLong(), anyLong(), anyLong()); + verify(vibratorMock, never()).alwaysOnDisable(anyLong()); + } + + @Test + public void setAlwaysOnEffect_withNoVibratorWithCapability_ignoresEffect() { + VibratorController.NativeWrapper vibratorMock = mockVibrator(0); + mockVibrators(vibratorMock); + VibratorManagerService service = createService(); + + CombinedVibrationEffect mono = CombinedVibrationEffect.createSynced( + VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK)); + CombinedVibrationEffect stereo = CombinedVibrationEffect.startSynced() + .addVibrator(0, VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK)) + .combine(); + assertFalse(service.setAlwaysOnEffect(UID, PACKAGE_NAME, 1, mono, ALARM_ATTRS)); + assertFalse(service.setAlwaysOnEffect(UID, PACKAGE_NAME, 2, stereo, ALARM_ATTRS)); + + verify(vibratorMock, never()).alwaysOnEnable(anyLong(), anyLong(), anyLong()); + verify(vibratorMock, never()).alwaysOnDisable(anyLong()); } @Test @@ -107,4 +309,24 @@ public class VibratorManagerServiceTest { assertExpectException(UnsupportedOperationException.class, "Not implemented", () -> service.cancelVibrate(service)); } + + private VibratorController.NativeWrapper mockVibrator(int capabilities) { + VibratorController.NativeWrapper wrapper = mock(VibratorController.NativeWrapper.class); + when(wrapper.getCapabilities()).thenReturn((long) capabilities); + return wrapper; + } + + private void mockVibrators(VibratorController.NativeWrapper... wrappers) { + int[] ids = new int[wrappers.length]; + for (int i = 0; i < wrappers.length; i++) { + ids[i] = i; + mNativeWrappers.put(i, wrappers[i]); + } + when(mNativeWrapperMock.getVibratorIds()).thenReturn(ids); + } + + private static <T> void addLocalServiceMock(Class<T> clazz, T mock) { + LocalServices.removeServiceForTest(clazz); + LocalServices.addService(clazz, mock); + } } diff --git a/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java b/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java index 64f31358ccb3..68adacd8478f 100644 --- a/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/VibratorServiceTest.java @@ -16,7 +16,6 @@ package com.android.server; -import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -52,7 +51,6 @@ import android.os.Handler; import android.os.IBinder; import android.os.IVibratorStateListener; import android.os.Looper; -import android.os.PowerManager; import android.os.PowerManagerInternal; import android.os.PowerSaveState; import android.os.Process; @@ -62,6 +60,7 @@ import android.os.UserHandle; import android.os.VibrationAttributes; import android.os.VibrationEffect; import android.os.Vibrator; +import android.os.VibratorInfo; import android.os.test.TestLooper; import android.platform.test.annotations.Presubmit; import android.provider.Settings; @@ -101,6 +100,9 @@ public class VibratorServiceTest { private static final int UID = Process.ROOT_UID; private static final String PACKAGE_NAME = "package"; + private static final PowerSaveState NORMAL_POWER_STATE = new PowerSaveState.Builder().build(); + private static final PowerSaveState LOW_POWER_STATE = new PowerSaveState.Builder() + .setBatterySaverEnabled(true).build(); private static final VibrationAttributes ALARM_ATTRS = new VibrationAttributes.Builder().setUsage(VibrationAttributes.USAGE_ALARM).build(); private static final VibrationAttributes HAPTIC_FEEDBACK_ATTRS = @@ -118,7 +120,6 @@ public class VibratorServiceTest { @Mock private PackageManagerInternal mPackageManagerInternalMock; @Mock private PowerManagerInternal mPowerManagerInternalMock; - @Mock private PowerSaveState mPowerSaveStateMock; // TODO(b/131311651): replace with a FakeVibrator instead. @Mock private Vibrator mVibratorMock; @Mock private AppOpsManager mAppOpsManagerMock; @@ -129,6 +130,7 @@ public class VibratorServiceTest { private TestLooper mTestLooper; private ContextWrapper mContextSpy; + private PowerManagerInternal.LowPowerModeListener mRegisteredPowerModeListener; @Before public void setUp() throws Exception { @@ -150,8 +152,10 @@ public class VibratorServiceTest { when(mVibratorStateListenerMock.asBinder()).thenReturn(mVibratorStateListenerBinderMock); when(mPackageManagerInternalMock.getSystemUiServiceComponent()) .thenReturn(new ComponentName("", "")); - when(mPowerManagerInternalMock.getLowPowerState(PowerManager.ServiceType.VIBRATION)) - .thenReturn(mPowerSaveStateMock); + doAnswer(invocation -> { + mRegisteredPowerModeListener = invocation.getArgument(0); + return null; + }).when(mPowerManagerInternalMock).registerLowPowerModeObserver(any()); when(mIInputManagerMock.getInputDeviceIds()).thenReturn(new int[0]); setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 1); @@ -199,7 +203,7 @@ public class VibratorServiceTest { public void createService_initializesNativeService() { createService(); verify(mNativeWrapperMock).init(eq(0), notNull()); - verify(mNativeWrapperMock).off(); + verify(mNativeWrapperMock, times(2)).off(); // Called from constructor and onSystemReady } @Test @@ -235,93 +239,21 @@ public class VibratorServiceTest { } @Test - public void areEffectsSupported_withNullResultFromNative_returnsSupportUnknown() { - when(mNativeWrapperMock.getSupportedEffects()).thenReturn(null); - assertArrayEquals(new int[]{Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN}, - createService().areEffectsSupported(new int[]{VibrationEffect.EFFECT_CLICK})); - } - - @Test - public void areEffectsSupported_withSomeEffectsSupported_returnsSupportYesAndNoForEffects() { - int[] effects = new int[]{VibrationEffect.EFFECT_CLICK, VibrationEffect.EFFECT_TICK}; - + public void getVibratorInfo_returnsSameInfoFromNative() { + mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS | IVibrator.CAP_AMPLITUDE_CONTROL); when(mNativeWrapperMock.getSupportedEffects()) .thenReturn(new int[]{VibrationEffect.EFFECT_CLICK}); - assertArrayEquals( - new int[]{Vibrator.VIBRATION_EFFECT_SUPPORT_YES, - Vibrator.VIBRATION_EFFECT_SUPPORT_NO}, - createService().areEffectsSupported(effects)); - } - - @Test - public void arePrimitivesSupported_withoutComposeCapability_returnsAlwaysFalse() { - assertArrayEquals(new boolean[]{false, false}, - createService().arePrimitivesSupported(new int[]{ - VibrationEffect.Composition.PRIMITIVE_CLICK, - VibrationEffect.Composition.PRIMITIVE_TICK - })); - } - - @Test - public void arePrimitivesSupported_withNullResultFromNative_returnsAlwaysFalse() { - mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS); - when(mNativeWrapperMock.getSupportedPrimitives()).thenReturn(null); - - assertArrayEquals(new boolean[]{false, false}, - createService().arePrimitivesSupported(new int[]{ - VibrationEffect.Composition.PRIMITIVE_CLICK, - VibrationEffect.Composition.PRIMITIVE_QUICK_RISE - })); - } - - @Test - public void arePrimitivesSupported_withSomeSupportedPrimitives_returnsBasedOnNativeResult() { - mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS); when(mNativeWrapperMock.getSupportedPrimitives()) .thenReturn(new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK}); - assertArrayEquals(new boolean[]{true, false}, - createService().arePrimitivesSupported(new int[]{ - VibrationEffect.Composition.PRIMITIVE_CLICK, - VibrationEffect.Composition.PRIMITIVE_QUICK_RISE - })); - } - - @Test - public void setAlwaysOnEffect_withCapabilityAndValidEffect_enablesAlwaysOnEffect() { - mockVibratorCapabilities(IVibrator.CAP_ALWAYS_ON_CONTROL); - - assertTrue(createService().setAlwaysOnEffect(UID, PACKAGE_NAME, 1, - VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK), ALARM_ATTRS)); - verify(mNativeWrapperMock).alwaysOnEnable( - eq(1L), eq((long) VibrationEffect.EFFECT_CLICK), - eq((long) VibrationEffect.EFFECT_STRENGTH_STRONG)); - } - - @Test - public void setAlwaysOnEffect_withNonPrebakedEffect_ignoresEffect() { - mockVibratorCapabilities(IVibrator.CAP_ALWAYS_ON_CONTROL); - - assertFalse(createService().setAlwaysOnEffect(UID, PACKAGE_NAME, 1, - VibrationEffect.createOneShot(100, 255), ALARM_ATTRS)); - verify(mNativeWrapperMock, never()).alwaysOnDisable(anyLong()); - verify(mNativeWrapperMock, never()).alwaysOnEnable(anyLong(), anyLong(), anyLong()); - } - - @Test - public void setAlwaysOnEffect_withNullEffect_disablesAlwaysOnEffect() { - mockVibratorCapabilities(IVibrator.CAP_ALWAYS_ON_CONTROL); - - assertTrue(createService().setAlwaysOnEffect(UID, PACKAGE_NAME, 1, null, ALARM_ATTRS)); - verify(mNativeWrapperMock).alwaysOnDisable(eq(1L)); - } - - @Test - public void setAlwaysOnEffect_withoutCapability_ignoresEffect() { - assertFalse(createService().setAlwaysOnEffect(UID, PACKAGE_NAME, 1, - VibrationEffect.get(VibrationEffect.EFFECT_CLICK), ALARM_ATTRS)); - verify(mNativeWrapperMock, never()).alwaysOnDisable(anyLong()); - verify(mNativeWrapperMock, never()).alwaysOnEnable(anyLong(), anyLong(), anyLong()); + VibratorInfo info = createService().getVibratorInfo(); + assertTrue(info.hasAmplitudeControl()); + assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_YES, + info.isEffectSupported(VibrationEffect.EFFECT_CLICK)); + assertEquals(Vibrator.VIBRATION_EFFECT_SUPPORT_NO, + info.isEffectSupported(VibrationEffect.EFFECT_TICK)); + assertTrue(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_CLICK)); + assertFalse(info.isPrimitiveSupported(VibrationEffect.Composition.PRIMITIVE_TICK)); } @Test @@ -346,6 +278,24 @@ public class VibratorServiceTest { } @Test + public void vibrate_withPowerModeChange_usesLowPowerModeState() { + VibratorService service = createService(); + mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE); + vibrate(service, VibrationEffect.createOneShot(1, 1), HAPTIC_FEEDBACK_ATTRS); + vibrate(service, VibrationEffect.createOneShot(2, 2), RINGTONE_ATTRS); + + mRegisteredPowerModeListener.onLowPowerModeChanged(NORMAL_POWER_STATE); + vibrate(service, VibrationEffect.createOneShot(3, 3), /* attributes= */ null); + vibrate(service, VibrationEffect.createOneShot(4, 4), NOTIFICATION_ATTRS); + + InOrder inOrderVerifier = inOrder(mNativeWrapperMock); + inOrderVerifier.verify(mNativeWrapperMock, never()).on(eq(1L), anyLong()); + inOrderVerifier.verify(mNativeWrapperMock).on(eq(2L), anyLong()); + inOrderVerifier.verify(mNativeWrapperMock).on(eq(3L), anyLong()); + inOrderVerifier.verify(mNativeWrapperMock).on(eq(4L), anyLong()); + } + + @Test public void vibrate_withAudioAttributes_usesOriginalAudioUsageInAppOpsManager() { VibratorService service = createService(); diff --git a/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java index 89bd625c8289..7bf0bb873fc3 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java @@ -35,7 +35,10 @@ import static com.android.server.accessibility.gestures.TouchState.STATE_TOUCH_E import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.verify; +import android.accessibilityservice.AccessibilityGestureEvent; +import android.accessibilityservice.AccessibilityService; import android.content.Context; import android.graphics.PointF; import android.os.Looper; @@ -51,6 +54,7 @@ import androidx.test.runner.AndroidJUnit4; import com.android.server.accessibility.AccessibilityManagerService; import com.android.server.accessibility.EventStreamTransformation; +import com.android.server.accessibility.utils.GestureLogParser; import com.android.server.testutils.OffsettableClock; import org.junit.Before; @@ -58,7 +62,15 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; - +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; @@ -93,6 +105,11 @@ public class TouchExplorerTest { private int mTouchSlop; private long mLastDownTime = Integer.MIN_VALUE; + @Mock + private AccessibilityManagerService mMockAms; + @Captor + private ArgumentCaptor<AccessibilityGestureEvent> mGestureCaptor; + // mock package-private GestureManifold class @Rule public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule = @@ -122,6 +139,7 @@ public class TouchExplorerTest { @Before public void setUp() { + MockitoAnnotations.initMocks(this); if (Looper.myLooper() == null) { Looper.prepare(); } @@ -130,7 +148,7 @@ public class TouchExplorerTest { AccessibilityManagerService ams = new AccessibilityManagerService(mContext); mCaptor = new EventCaptor(); mHandler = new TestHandler(); - mTouchExplorer = new TouchExplorer(mContext, ams, null, mHandler); + mTouchExplorer = new TouchExplorer(mContext, mMockAms, null, mHandler); mTouchExplorer.setNext(mCaptor); } @@ -395,6 +413,61 @@ public class TouchExplorerTest { mTouchExplorer.setMultiFingerGesturesEnabled(false); } + @Test + public void testTouchExploreGestureLog() { + passInGesture(com.android.frameworks.servicestests.R.raw.a11y_touch_explore_gesture, + AccessibilityService.GESTURE_TOUCH_EXPLORATION); + } + @Test + public void testThreeFingerSwipeDownGestureLog() { + passInGesture( + com.android.frameworks.servicestests.R.raw.a11y_three_finger_swipe_down_gesture, + AccessibilityService.GESTURE_3_FINGER_SWIPE_DOWN); + } + + /** + * Used to play back event data of a gesture by parsing the log into MotionEvents and sending + * them to TouchExplorer. + * @param resourceId a raw resource that corresponds to a text file + * @param gestureId the id of the gesture expected to be dispatched + */ + private void passInGesture(int resourceId, int gestureId) { + mTouchExplorer.setMultiFingerGesturesEnabled(true); + mTouchExplorer.setSendMotionEventsEnabled(true); + mTouchExplorer.setTwoFingerPassthroughEnabled(true); + List<Integer> actions = new ArrayList<>(); + try ( + InputStream fis = mContext.getResources().openRawResource(resourceId); + InputStreamReader isr = new InputStreamReader(fis, Charset.forName("UTF-8")); + BufferedReader br = new BufferedReader(isr); + ) { + String line; + while ((line = br.readLine()) != null) { + if (line.isEmpty() || !line.contains("MotionEvent")) { + continue; + } + + MotionEvent motionEvent = GestureLogParser.getMotionEventFromLogLine(line); + actions.add(motionEvent.getAction()); + send(motionEvent); + } + + // Fast forward to dispatch GESTURE_TOUCH_EXPLORATION + mHandler.fastForward(USER_INTENT_TIMEOUT); + } catch (IOException ioException) { + ioException.printStackTrace(); + } + + verify(mMockAms).onGesture(mGestureCaptor.capture()); + AccessibilityGestureEvent gestureEvent = mGestureCaptor.getValue(); + assertEquals(gestureId, gestureEvent.getGestureId()); + List<MotionEvent> motionEvents = gestureEvent.getMotionEvents(); + assertEquals(actions.size(), motionEvents.size()); + for (int i = 0; i < actions.size(); i++) { + assertEquals((int) actions.get(i), motionEvents.get(i).getAction()); + } + } + private static MotionEvent fromTouchscreen(MotionEvent ev) { ev.setSource(InputDevice.SOURCE_TOUCHSCREEN); return ev; diff --git a/services/tests/servicestests/src/com/android/server/accessibility/utils/GestureLogParser.java b/services/tests/servicestests/src/com/android/server/accessibility/utils/GestureLogParser.java new file mode 100644 index 000000000000..cd848f4a018d --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/accessibility/utils/GestureLogParser.java @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.accessibility.utils; + +import android.view.MotionEvent; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * This class helps parse a gesture event log into its individual MotionEvents + */ +public class GestureLogParser { + /** Gets a MotionEvent from a log line */ + public static MotionEvent getMotionEventFromLogLine(String line) { + final int downTime; + final int eventTime; + int action; + final int pointerCount; + + final MotionEvent.PointerProperties[] properties; + final MotionEvent.PointerCoords[] pointerCoords; + final int metaState; + final int buttonState = 0; + final int xPrecision = 1; + final int yPrecision = 1; + final int deviceId; + final int edgeFlags; + final int source; + final int flags; + final int actionIndex; + + downTime = findInt(line, "downTime=(\\d+)"); + eventTime = findInt(line, "eventTime=(\\d+)"); + action = stringToAction(findString(line, "action=(\\w+)")); + + // For pointer indices + Pattern p = Pattern.compile("action=(\\w+)\\((\\d)"); + Matcher matcher = p.matcher(line); + if (matcher.find()) { + actionIndex = Integer.decode(matcher.group(2)); + action = action | (actionIndex << MotionEvent.ACTION_POINTER_INDEX_SHIFT); + } + + pointerCount = findInt(line, "pointerCount=(\\d+)"); + metaState = findInt(line, "metaState=(\\d+)"); + deviceId = findInt(line, "deviceId=(\\d+)"); + edgeFlags = Integer.decode(findString(line, "edgeFlags=(\\w+)")); + source = Integer.decode(findString(line, "source=(\\w+)")); + flags = Integer.decode(findString(line, "flags=(\\w+)")); + properties = findProperties(line, pointerCount); + pointerCoords = findCoordinates(line, pointerCount); + + return MotionEvent.obtain(downTime, eventTime, action, + pointerCount, properties, pointerCoords, metaState, buttonState, + xPrecision, yPrecision, deviceId, edgeFlags, source, flags); + } + + private static int findInt(String eventText, String pattern) { + final Pattern p = Pattern.compile(pattern); + final Matcher matcher = p.matcher(eventText); + matcher.find(); + return Integer.decode(matcher.group(1)); + } + + private static float findFloat(String eventText, String pattern) { + final Pattern p = Pattern.compile(pattern); + final Matcher matcher = p.matcher(eventText); + matcher.find(); + return Float.parseFloat(matcher.group(1)); + } + + private static String findString(String eventText, String pattern) { + final Pattern p = Pattern.compile(pattern); + final Matcher matcher = p.matcher(eventText); + matcher.find(); + return matcher.group(1); + } + + private static MotionEvent.PointerCoords[] findCoordinates(String eventText, int pointerCount) { + if (pointerCount == 0) { + return null; + } + + final MotionEvent.PointerCoords[] coords = new MotionEvent.PointerCoords[pointerCount]; + float x; + float y; + for (int i = 0; i < pointerCount; i++) { + + x = findFloat(eventText, "x\\[" + i + "\\]=([\\d.]+)"); + y = findFloat(eventText, "y\\[" + i + "\\]=([\\d.]+)"); + + MotionEvent.PointerCoords pointerCoords = new MotionEvent.PointerCoords(); + pointerCoords.x = x; + pointerCoords.y = y; + pointerCoords.pressure = 1; + pointerCoords.size = 1; + + coords[i] = pointerCoords; + } + return coords; + } + + private static MotionEvent.PointerProperties[] findProperties( + String eventText, int pointerCount) { + if (pointerCount == 0) { + return null; + } + + final MotionEvent.PointerProperties[] props = + new MotionEvent.PointerProperties[pointerCount]; + int id; + for (int i = 0; i < pointerCount; i++) { + id = findInt(eventText, "id\\[" + i + "\\]=([\\d])"); + MotionEvent.PointerProperties pointerProps = new MotionEvent.PointerProperties(); + pointerProps.id = id; + pointerProps.toolType = MotionEvent.TOOL_TYPE_FINGER; + props[i] = pointerProps; + } + return props; + } + + private static int stringToAction(String action) { + switch (action) { + case "ACTION_DOWN": + return MotionEvent.ACTION_DOWN; + case "ACTION_UP": + return MotionEvent.ACTION_UP; + case "ACTION_CANCEL": + return MotionEvent.ACTION_CANCEL; + case "ACTION_OUTSIDE": + return MotionEvent.ACTION_OUTSIDE; + case "ACTION_MOVE": + return MotionEvent.ACTION_MOVE; + case "ACTION_HOVER_MOVE": + return MotionEvent.ACTION_HOVER_MOVE; + case "ACTION_SCROLL": + return MotionEvent.ACTION_SCROLL; + case "ACTION_HOVER_ENTER": + return MotionEvent.ACTION_HOVER_ENTER; + case "ACTION_HOVER_EXIT": + return MotionEvent.ACTION_HOVER_EXIT; + case "ACTION_BUTTON_PRESS": + return MotionEvent.ACTION_BUTTON_PRESS; + case "ACTION_BUTTON_RELEASE": + return MotionEvent.ACTION_BUTTON_RELEASE; + case "ACTION_POINTER_DOWN": + return MotionEvent.ACTION_POINTER_DOWN; + case "ACTION_POINTER_UP": + return MotionEvent.ACTION_POINTER_UP; + default: + return -1; + } + } +} diff --git a/services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java b/services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java index 1e602f84071d..41e15631d258 100644 --- a/services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java +++ b/services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java @@ -66,11 +66,11 @@ public class AppOpsNotedWatcherTest { inOrder.verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS) .times(1)).onOpNoted(eq(AppOpsManager.OP_FINE_LOCATION), eq(Process.myUid()), eq(getContext().getPackageName()), - eq(AppOpsManager.MODE_ALLOWED)); + eq(AppOpsManager.OP_FLAG_SELF), eq(AppOpsManager.MODE_ALLOWED)); inOrder.verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS) .times(1)).onOpNoted(eq(AppOpsManager.OP_CAMERA), eq(Process.myUid()), eq(getContext().getPackageName()), - eq(AppOpsManager.MODE_ALLOWED)); + eq(AppOpsManager.OP_FLAG_SELF), eq(AppOpsManager.MODE_ALLOWED)); // Stop watching appOpsManager.stopWatchingNoted(listener); @@ -94,7 +94,7 @@ public class AppOpsNotedWatcherTest { verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS) .times(2)).onOpNoted(eq(AppOpsManager.OP_FINE_LOCATION), eq(Process.myUid()), eq(getContext().getPackageName()), - eq(AppOpsManager.MODE_ALLOWED)); + eq(AppOpsManager.OP_FLAG_SELF), eq(AppOpsManager.MODE_ALLOWED)); // Finish up appOpsManager.stopWatchingNoted(listener); diff --git a/services/tests/servicestests/src/com/android/server/appop/AppOpsStartedWatcherTest.java b/services/tests/servicestests/src/com/android/server/appop/AppOpsStartedWatcherTest.java index 1aa697b04f1d..fec8aa9ceaff 100644 --- a/services/tests/servicestests/src/com/android/server/appop/AppOpsStartedWatcherTest.java +++ b/services/tests/servicestests/src/com/android/server/appop/AppOpsStartedWatcherTest.java @@ -63,11 +63,11 @@ public class AppOpsStartedWatcherTest { inOrder.verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS) .times(1)).onOpStarted(eq(AppOpsManager.OP_FINE_LOCATION), eq(Process.myUid()), eq(getContext().getPackageName()), - eq(AppOpsManager.MODE_ALLOWED)); + eq(AppOpsManager.OP_FLAG_SELF), eq(AppOpsManager.MODE_ALLOWED)); inOrder.verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS) .times(1)).onOpStarted(eq(AppOpsManager.OP_CAMERA), eq(Process.myUid()), eq(getContext().getPackageName()), - eq(AppOpsManager.MODE_ALLOWED)); + eq(AppOpsManager.OP_FLAG_SELF), eq(AppOpsManager.MODE_ALLOWED)); // Stop watching appOpsManager.stopWatchingStarted(listener); @@ -91,7 +91,7 @@ public class AppOpsStartedWatcherTest { verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS) .times(2)).onOpStarted(eq(AppOpsManager.OP_CAMERA), eq(Process.myUid()), eq(getContext().getPackageName()), - eq(AppOpsManager.MODE_ALLOWED)); + eq(AppOpsManager.OP_FLAG_SELF), eq(AppOpsManager.MODE_ALLOWED)); verifyNoMoreInteractions(listener); // Finish up diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java index e2c5e97b8896..d9daf17058c9 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java @@ -5127,7 +5127,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { admin1.getPackageName(), managedProfileUserId); try { - assertExpectException(IllegalArgumentException.class, null, () -> + assertExpectException(SecurityException.class, null, () -> parentDpm.setPasswordQuality( admin1, DevicePolicyManager.PASSWORD_QUALITY_COMPLEX)); } finally { diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java index 2f49fb79c3dc..ef77f32bb211 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTest.java @@ -25,6 +25,8 @@ import static com.android.server.hdmi.Constants.ADDR_UNREGISTERED; import static com.android.server.hdmi.Constants.MESSAGE_DEVICE_VENDOR_ID; import static com.android.server.hdmi.Constants.MESSAGE_REPORT_PHYSICAL_ADDRESS; +import static com.google.common.truth.Truth.assertThat; + import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; @@ -110,6 +112,7 @@ public class HdmiCecLocalDeviceTest { private HdmiCecMessageValidator mMessageValidator; private static byte[] param; private boolean mStandbyMessageReceived; + private boolean mWakeupMessageReceived; private boolean isControlEnabled; private int mPowerStatus; @@ -129,9 +132,21 @@ public class HdmiCecLocalDeviceTest { } @Override + boolean isPowerStandbyOrTransient() { + return mPowerStatus == HdmiControlManager.POWER_STATUS_STANDBY + || mPowerStatus + == HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY; + } + + @Override void standby() { mStandbyMessageReceived = true; } + + @Override + void wakeUp() { + mWakeupMessageReceived = true; + } }; mHdmiControlService.setIoLooper(mTestLooper.getLooper()); mHdmiCecController = HdmiCecController.createWithNativeWrapper( @@ -264,4 +279,109 @@ public class HdmiCecLocalDeviceTest { assertFalse(result); } + + @Test + public void handleCecVersion_isHandled() { + boolean result = mHdmiLocalDevice.onMessage( + HdmiCecMessageBuilder.buildCecVersion(ADDR_PLAYBACK_1, mHdmiLocalDevice.mAddress, + HdmiControlManager.HDMI_CEC_VERSION_1_4_b)); + + assertThat(result).isTrue(); + } + + @Test + public void handleUserControlPressed_power_localDeviceInStandby_shouldTurnOn() { + mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY; + boolean result = mHdmiLocalDevice.handleUserControlPressed( + HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1, + HdmiCecKeycode.CEC_KEYCODE_POWER)); + + assertThat(result).isTrue(); + assertThat(mWakeupMessageReceived).isTrue(); + assertThat(mStandbyMessageReceived).isFalse(); + } + + @Test + public void handleUserControlPressed_power_localDeviceOn_shouldNotChangePowerStatus() { + mPowerStatus = HdmiControlManager.POWER_STATUS_ON; + boolean result = mHdmiLocalDevice.handleUserControlPressed( + HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1, + HdmiCecKeycode.CEC_KEYCODE_POWER)); + + assertThat(result).isTrue(); + assertThat(mWakeupMessageReceived).isFalse(); + assertThat(mStandbyMessageReceived).isFalse(); + } + + @Test + public void handleUserControlPressed_powerToggleFunction_localDeviceInStandby_shouldTurnOn() { + mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY; + boolean result = mHdmiLocalDevice.handleUserControlPressed( + HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1, + HdmiCecKeycode.CEC_KEYCODE_POWER_TOGGLE_FUNCTION)); + + assertThat(result).isTrue(); + assertThat(mWakeupMessageReceived).isTrue(); + assertThat(mStandbyMessageReceived).isFalse(); + } + + @Test + public void handleUserControlPressed_powerToggleFunction_localDeviceOn_shouldTurnOff() { + mPowerStatus = HdmiControlManager.POWER_STATUS_ON; + boolean result = mHdmiLocalDevice.handleUserControlPressed( + HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1, + HdmiCecKeycode.CEC_KEYCODE_POWER_TOGGLE_FUNCTION)); + + assertThat(result).isTrue(); + assertThat(mWakeupMessageReceived).isFalse(); + assertThat(mStandbyMessageReceived).isTrue(); + } + + @Test + public void handleUserControlPressed_powerOnFunction_localDeviceInStandby_shouldTurnOn() { + mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY; + boolean result = mHdmiLocalDevice.handleUserControlPressed( + HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1, + HdmiCecKeycode.CEC_KEYCODE_POWER_ON_FUNCTION)); + + assertThat(result).isTrue(); + assertThat(mWakeupMessageReceived).isTrue(); + assertThat(mStandbyMessageReceived).isFalse(); + } + + @Test + public void handleUserControlPressed_powerOnFunction_localDeviceOn_noPowerStatusChange() { + mPowerStatus = HdmiControlManager.POWER_STATUS_ON; + boolean result = mHdmiLocalDevice.handleUserControlPressed( + HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1, + HdmiCecKeycode.CEC_KEYCODE_POWER_ON_FUNCTION)); + + assertThat(result).isTrue(); + assertThat(mWakeupMessageReceived).isFalse(); + assertThat(mStandbyMessageReceived).isFalse(); + } + + @Test + public void handleUserControlPressed_powerOffFunction_localDeviceStandby_noPowerStatusChange() { + mPowerStatus = HdmiControlManager.POWER_STATUS_STANDBY; + boolean result = mHdmiLocalDevice.handleUserControlPressed( + HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1, + HdmiCecKeycode.CEC_KEYCODE_POWER_OFF_FUNCTION)); + + assertThat(result).isTrue(); + assertThat(mWakeupMessageReceived).isFalse(); + assertThat(mStandbyMessageReceived).isFalse(); + } + + @Test + public void handleUserControlPressed_powerOffFunction_localDeviceOn_shouldTurnOff() { + mPowerStatus = HdmiControlManager.POWER_STATUS_ON; + boolean result = mHdmiLocalDevice.handleUserControlPressed( + HdmiCecMessageBuilder.buildUserControlPressed(ADDR_TV, ADDR_PLAYBACK_1, + HdmiCecKeycode.CEC_KEYCODE_POWER_OFF_FUNCTION)); + + assertThat(result).isTrue(); + assertThat(mWakeupMessageReceived).isFalse(); + assertThat(mStandbyMessageReceived).isTrue(); + } } diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java index 080b52bbbc6a..e37001805398 100644 --- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java +++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecNetworkTest.java @@ -36,6 +36,7 @@ import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import java.util.ArrayList; +import java.util.Collections; import java.util.List; /** @@ -313,6 +314,7 @@ public class HdmiCecNetworkTest { int powerStatus = HdmiControlManager.POWER_STATUS_ON; String osdName = "Test Device"; int vendorId = 1234; + int cecVersion = HdmiControlManager.HDMI_CEC_VERSION_2_0; mHdmiCecNetwork.handleCecMessage( HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(logicalAddress, @@ -325,6 +327,8 @@ public class HdmiCecNetworkTest { Constants.ADDR_BROADCAST, osdName)); mHdmiCecNetwork.handleCecMessage( HdmiCecMessageBuilder.buildDeviceVendorIdCommand(logicalAddress, vendorId)); + mHdmiCecNetwork.handleCecMessage(HdmiCecMessageBuilder.buildCecVersion(logicalAddress, + Constants.ADDR_BROADCAST, cecVersion)); assertThat(mHdmiCecNetwork.getSafeCecDevicesLocked()).hasSize(1); @@ -335,6 +339,7 @@ public class HdmiCecNetworkTest { assertThat(cecDeviceInfo.getDisplayName()).isEqualTo(osdName); assertThat(cecDeviceInfo.getVendorId()).isEqualTo(vendorId); assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo(powerStatus); + assertThat(cecDeviceInfo.getCecVersion()).isEqualTo(cecVersion); } @Test @@ -374,16 +379,18 @@ public class HdmiCecNetworkTest { mHdmiCecNetwork.handleCecMessage( HdmiCecMessageBuilder.buildReportPowerStatus(logicalAddress, - Constants.ADDR_BROADCAST, powerStatus)); + Constants.ADDR_TV, powerStatus)); mHdmiCecNetwork.handleCecMessage( HdmiCecMessageBuilder.buildReportPowerStatus(logicalAddress, - Constants.ADDR_BROADCAST, updatedPowerStatus)); + Constants.ADDR_TV, updatedPowerStatus)); assertThat(mHdmiCecNetwork.getSafeCecDevicesLocked()).hasSize(1); HdmiDeviceInfo cecDeviceInfo = mHdmiCecNetwork.getCecDeviceInfo(logicalAddress); assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress); assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo(updatedPowerStatus); + assertThat(cecDeviceInfo.getCecVersion()).isEqualTo( + HdmiControlManager.HDMI_CEC_VERSION_1_4_b); } @Test @@ -428,6 +435,8 @@ public class HdmiCecNetworkTest { assertThat(cecDeviceInfo.getVendorId()).isEqualTo(updatedVendorId); assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo( HdmiControlManager.POWER_STATUS_UNKNOWN); + assertThat(cecDeviceInfo.getCecVersion()).isEqualTo( + HdmiControlManager.HDMI_CEC_VERSION_1_4_b); } @Test @@ -446,4 +455,91 @@ public class HdmiCecNetworkTest { HdmiControlManager.DEVICE_EVENT_ADD_DEVICE, HdmiControlManager.DEVICE_EVENT_REMOVE_DEVICE); } + + @Test + public void cecDevices_tracking_reportPowerStatus_broadcast_infersCec2() { + int logicalAddress = Constants.ADDR_PLAYBACK_1; + int powerStatus = HdmiControlManager.POWER_STATUS_ON; + mHdmiCecNetwork.handleCecMessage( + HdmiCecMessageBuilder.buildReportPowerStatus(logicalAddress, + Constants.ADDR_BROADCAST, powerStatus)); + + assertThat(mHdmiCecNetwork.getSafeCecDevicesLocked()).hasSize(1); + + HdmiDeviceInfo cecDeviceInfo = mHdmiCecNetwork.getCecDeviceInfo(logicalAddress); + assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress); + assertThat(cecDeviceInfo.getPhysicalAddress()).isEqualTo( + Constants.INVALID_PHYSICAL_ADDRESS); + assertThat(cecDeviceInfo.getDeviceType()).isEqualTo(HdmiDeviceInfo.DEVICE_RESERVED); + assertThat(cecDeviceInfo.getVendorId()).isEqualTo(Constants.UNKNOWN_VENDOR_ID); + assertThat(cecDeviceInfo.getDisplayName()).isEqualTo( + HdmiUtils.getDefaultDeviceName(logicalAddress)); + assertThat(cecDeviceInfo.getDevicePowerStatus()).isEqualTo(powerStatus); + assertThat(cecDeviceInfo.getCecVersion()).isEqualTo( + HdmiControlManager.HDMI_CEC_VERSION_2_0); + } + + @Test + public void cecDevices_tracking_reportCecVersion_tracksCecVersion_cec14() { + int logicalAddress = Constants.ADDR_PLAYBACK_1; + int cecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_b; + mHdmiCecNetwork.handleCecMessage( + HdmiCecMessageBuilder.buildCecVersion(logicalAddress, Constants.ADDR_BROADCAST, + cecVersion)); + + assertThat(mHdmiCecNetwork.getSafeCecDevicesLocked()).hasSize(1); + + HdmiDeviceInfo cecDeviceInfo = mHdmiCecNetwork.getCecDeviceInfo(logicalAddress); + assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress); + assertThat(cecDeviceInfo.getCecVersion()).isEqualTo(cecVersion); + } + + @Test + public void cecDevices_tracking_reportCecVersion_tracksCecVersion_cec20() { + int logicalAddress = Constants.ADDR_PLAYBACK_1; + int cecVersion = HdmiControlManager.HDMI_CEC_VERSION_2_0; + mHdmiCecNetwork.handleCecMessage( + HdmiCecMessageBuilder.buildCecVersion(logicalAddress, Constants.ADDR_BROADCAST, + cecVersion)); + + assertThat(mHdmiCecNetwork.getSafeCecDevicesLocked()).hasSize(1); + + HdmiDeviceInfo cecDeviceInfo = mHdmiCecNetwork.getCecDeviceInfo(logicalAddress); + assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress); + assertThat(cecDeviceInfo.getCecVersion()).isEqualTo(cecVersion); + } + + @Test + public void cecDevices_tracking_reportFeatures_tracksCecVersion_cec14() { + int logicalAddress = Constants.ADDR_PLAYBACK_1; + int cecVersion = HdmiControlManager.HDMI_CEC_VERSION_1_4_b; + mHdmiCecNetwork.handleCecMessage( + HdmiCecMessageBuilder.buildReportFeatures(logicalAddress, + cecVersion, Collections.emptyList(), + Constants.RC_PROFILE_SOURCE, Collections.emptyList(), + Collections.emptyList())); + + assertThat(mHdmiCecNetwork.getSafeCecDevicesLocked()).hasSize(1); + + HdmiDeviceInfo cecDeviceInfo = mHdmiCecNetwork.getCecDeviceInfo(logicalAddress); + assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress); + assertThat(cecDeviceInfo.getCecVersion()).isEqualTo(cecVersion); + } + + @Test + public void cecDevices_tracking_reportFeatures_tracksCecVersion_cec20() { + int logicalAddress = Constants.ADDR_PLAYBACK_1; + int cecVersion = HdmiControlManager.HDMI_CEC_VERSION_2_0; + mHdmiCecNetwork.handleCecMessage( + HdmiCecMessageBuilder.buildReportFeatures(logicalAddress, + cecVersion, Collections.emptyList(), + Constants.RC_PROFILE_SOURCE, Collections.emptyList(), + Collections.emptyList())); + + assertThat(mHdmiCecNetwork.getSafeCecDevicesLocked()).hasSize(1); + + HdmiDeviceInfo cecDeviceInfo = mHdmiCecNetwork.getCecDeviceInfo(logicalAddress); + assertThat(cecDeviceInfo.getLogicalAddress()).isEqualTo(logicalAddress); + assertThat(cecDeviceInfo.getCecVersion()).isEqualTo(cecVersion); + } } diff --git a/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java index c4d121170624..98d64524d87a 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java @@ -95,13 +95,24 @@ public class RebootEscrowManagerTests { static class MockInjector extends RebootEscrowManager.Injector { private final IRebootEscrow mRebootEscrow; + private final RebootEscrowProviderInterface mRebootEscrowProvider; private final UserManager mUserManager; private final MockableRebootEscrowInjected mInjected; - MockInjector(Context context, UserManager userManager, IRebootEscrow rebootEscrow, + MockInjector(Context context, UserManager userManager, + IRebootEscrow rebootEscrow, MockableRebootEscrowInjected injected) { super(context); mRebootEscrow = rebootEscrow; + + RebootEscrowProviderHalImpl.Injector halInjector = + new RebootEscrowProviderHalImpl.Injector() { + @Override + public IRebootEscrow getRebootEscrow() { + return mRebootEscrow; + } + }; + mRebootEscrowProvider = new RebootEscrowProviderHalImpl(halInjector); mUserManager = userManager; mInjected = injected; } @@ -112,8 +123,8 @@ public class RebootEscrowManagerTests { } @Override - public IRebootEscrow getRebootEscrow() { - return mRebootEscrow; + public RebootEscrowProviderInterface getRebootEscrowProvider() { + return mRebootEscrowProvider; } @Override diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java index 11d00f0fd406..5719dd2b0288 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageInstallerSessionTest.java @@ -173,6 +173,7 @@ public class PackageInstallerSessionTest { /* installSource */ installSource, /* sessionParams */ params, /* createdMillis */ 0L, + /* committedMillis */ 0L, /* stageDir */ mTmpDir, /* stageCid */ null, /* files */ null, diff --git a/services/tests/servicestests/src/com/android/server/pm/StagingManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/StagingManagerTest.java new file mode 100644 index 000000000000..4870c9e070cd --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/pm/StagingManagerTest.java @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.pm; + +import android.content.Context; +import android.content.pm.PackageInstaller; +import android.os.storage.StorageManager; +import android.platform.test.annotations.Presubmit; + +import com.android.internal.os.BackgroundThread; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; + +import java.io.File; + +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; +import static org.testng.Assert.assertThrows; + +@Presubmit +@RunWith(JUnit4.class) +public class StagingManagerTest { + @Rule + public TemporaryFolder mTemporaryFolder = new TemporaryFolder(); + + private File mTmpDir; + private StagingManager mStagingManager; + + @Before + public void setup() throws Exception { + MockitoAnnotations.initMocks(this); + StorageManager storageManager = Mockito.mock(StorageManager.class); + Context context = Mockito.mock(Context.class); + when(storageManager.isCheckpointSupported()).thenReturn(true); + when(context.getSystemService(eq(Context.POWER_SERVICE))).thenReturn(null); + when(context.getSystemService(eq(Context.STORAGE_SERVICE))).thenReturn(storageManager); + + mTmpDir = mTemporaryFolder.newFolder("StagingManagerTest"); + mStagingManager = new StagingManager(context, null); + } + + /** + * Tests that sessions committed later shouldn't cause earlier ones to fail the overlapping + * check. + */ + @Test + public void checkNonOverlappingWithStagedSessions_laterSessionShouldNotFailEarlierOnes() + throws Exception { + // Create 2 sessions with overlapping packages + PackageInstallerSession session1 = createSession(111, "com.foo", 1); + PackageInstallerSession session2 = createSession(222, "com.foo", 2); + + mStagingManager.createSession(session1); + mStagingManager.createSession(session2); + // Session1 should not fail in spite of the overlapping packages + mStagingManager.checkNonOverlappingWithStagedSessions(session1); + // Session2 should fail due to overlapping packages + assertThrows(PackageManagerException.class, + () -> mStagingManager.checkNonOverlappingWithStagedSessions(session2)); + } + + private PackageInstallerSession createSession(int sessionId, String packageName, + long committedMillis) { + PackageInstaller.SessionParams params = new PackageInstaller.SessionParams( + PackageInstaller.SessionParams.MODE_FULL_INSTALL); + params.isStaged = true; + + InstallSource installSource = InstallSource.create("testInstallInitiator", + "testInstallOriginator", "testInstaller", "testAttributionTag"); + + PackageInstallerSession session = new PackageInstallerSession( + /* callback */ null, + /* context */ null, + /* pm */ null, + /* sessionProvider */ null, + /* looper */ BackgroundThread.getHandler().getLooper(), + /* stagingManager */ null, + /* sessionId */ sessionId, + /* userId */ 456, + /* installerUid */ -1, + /* installSource */ installSource, + /* sessionParams */ params, + /* createdMillis */ 0L, + /* committedMillis */ committedMillis, + /* stageDir */ mTmpDir, + /* stageCid */ null, + /* files */ null, + /* checksums */ null, + /* prepared */ true, + /* committed */ true, + /* destroyed */ false, + /* sealed */ false, // Setting to true would trigger some PM logic. + /* childSessionIds */ null, + /* parentSessionId */ -1, + /* isReady */ false, + /* isFailed */ false, + /* isApplied */false, + /* stagedSessionErrorCode */ PackageInstaller.SessionInfo.STAGED_SESSION_NO_ERROR, + /* stagedSessionErrorMessage */ "no error"); + + session = spy(session); + doReturn(packageName).when(session).getPackageName(); + return session; + } +} diff --git a/services/tests/servicestests/src/com/android/server/pm/permission/PermissionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/permission/LegacyPermissionManagerServiceTest.java index 6cea9280f080..4f6441ff4e62 100644 --- a/services/tests/servicestests/src/com/android/server/pm/permission/PermissionManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/permission/LegacyPermissionManagerServiceTest.java @@ -29,14 +29,10 @@ import android.app.admin.DevicePolicyManager; import android.content.Context; import android.content.pm.PackageManager; import android.os.Process; -import android.permission.PermissionManagerInternal; import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; -import com.android.server.LocalServices; - -import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -44,19 +40,17 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; @RunWith(AndroidJUnit4.class) -public class PermissionManagerServiceTest { - private static final String TAG = "PermissionManagerServiceTag"; - +public class LegacyPermissionManagerServiceTest { private static final int SYSTEM_UID = 1000; private static final int SYSTEM_PID = 1234; private static final int APP_UID = Process.FIRST_APPLICATION_UID; private static final int APP_PID = 5678; - private PermissionManagerService mPermissionManagerService; + private LegacyPermissionManagerService mLegacyPermissionManagerService; private Context mContext; @Mock - private PermissionManagerService.Injector mInjector; + private LegacyPermissionManagerService.Injector mInjector; @Mock private AppOpsManager mAppOpsManager; @@ -69,16 +63,7 @@ public class PermissionManagerServiceTest { MockitoAnnotations.initMocks(this); mContext = InstrumentationRegistry.getContext(); - mPermissionManagerService = new PermissionManagerService(mContext, mInjector); - } - - @After - public void tearDown() { - // The LocalServices added by the constructor of the PermissionManagerService can either be - // removed here after each test when tests are run serially, or to run them in parallel - // the Injector can provide methods to add these that can be ignored by the mock. - LocalServices.removeServiceForTest(PermissionManagerServiceInternal.class); - LocalServices.removeServiceForTest(PermissionManagerInternal.class); + mLegacyPermissionManagerService = new LegacyPermissionManagerService(mContext, mInjector); } @Test @@ -88,7 +73,7 @@ public class PermissionManagerServiceTest { setupCheckDeviceIdentifierAccessTest(APP_PID, APP_UID); assertThrows(SecurityException.class, - () -> mPermissionManagerService.checkDeviceIdentifierAccess( + () -> mLegacyPermissionManagerService.checkDeviceIdentifierAccess( mContext.getPackageName(), "testCheckDeviceIdentifierAccess", null, APP_PID, SYSTEM_UID)); } @@ -100,7 +85,7 @@ public class PermissionManagerServiceTest { setupCheckDeviceIdentifierAccessTest(APP_PID, APP_UID); assertThrows(SecurityException.class, - () -> mPermissionManagerService.checkDeviceIdentifierAccess( + () -> mLegacyPermissionManagerService.checkDeviceIdentifierAccess( mContext.getPackageName(), "testCheckDeviceIdentifierAccess", null, SYSTEM_PID, APP_UID)); } @@ -111,7 +96,7 @@ public class PermissionManagerServiceTest { // checks can run through completion and return denied. setupCheckDeviceIdentifierAccessTest(APP_PID, APP_UID); - int result = mPermissionManagerService.checkDeviceIdentifierAccess( + int result = mLegacyPermissionManagerService.checkDeviceIdentifierAccess( mContext.getPackageName(), "testCheckDeviceIdentifierAccess", null, APP_PID, APP_UID); @@ -122,7 +107,7 @@ public class PermissionManagerServiceTest { public void checkDeviceIdentifierAccess_systemUid_returnsGranted() { // The system UID should always have access to device identifiers. setupCheckDeviceIdentifierAccessTest(SYSTEM_PID, SYSTEM_UID); - int result = mPermissionManagerService.checkDeviceIdentifierAccess( + int result = mLegacyPermissionManagerService.checkDeviceIdentifierAccess( mContext.getPackageName(), "testCheckDeviceIdentifierAccess", null, SYSTEM_PID, SYSTEM_UID); @@ -137,7 +122,7 @@ public class PermissionManagerServiceTest { when(mInjector.checkPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, APP_PID, APP_UID)).thenReturn(PackageManager.PERMISSION_GRANTED); - int result = mPermissionManagerService.checkDeviceIdentifierAccess( + int result = mLegacyPermissionManagerService.checkDeviceIdentifierAccess( mContext.getPackageName(), "testCheckDeviceIdentifierAccess", null, APP_PID, APP_UID); @@ -153,7 +138,7 @@ public class PermissionManagerServiceTest { eq(APP_UID), eq(mContext.getPackageName()), any(), any())).thenReturn( AppOpsManager.MODE_ALLOWED); - int result = mPermissionManagerService.checkDeviceIdentifierAccess( + int result = mLegacyPermissionManagerService.checkDeviceIdentifierAccess( mContext.getPackageName(), "testCheckDeviceIdentifierAccess", null, APP_PID, APP_UID); @@ -168,7 +153,7 @@ public class PermissionManagerServiceTest { when(mDevicePolicyManager.hasDeviceIdentifierAccess(mContext.getPackageName(), APP_PID, APP_UID)).thenReturn(true); - int result = mPermissionManagerService.checkDeviceIdentifierAccess( + int result = mLegacyPermissionManagerService.checkDeviceIdentifierAccess( mContext.getPackageName(), "testCheckDeviceIdentifierAccess", null, APP_PID, APP_UID); diff --git a/services/tests/servicestests/src/com/android/server/timedetector/OWNERS b/services/tests/servicestests/src/com/android/server/timedetector/OWNERS index 09447a971bdd..8f8089717e3b 100644 --- a/services/tests/servicestests/src/com/android/server/timedetector/OWNERS +++ b/services/tests/servicestests/src/com/android/server/timedetector/OWNERS @@ -1 +1,3 @@ -include /core/java/android/app/timezone/OWNERS +# Bug component: 847766 +mingaleev@google.com +include /core/java/android/app/timedetector/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java index 4a44005e9602..5276ac4e98c1 100644 --- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java @@ -28,6 +28,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.app.timedetector.GnssTimeSuggestion; import android.app.timedetector.ManualTimeSuggestion; import android.app.timedetector.NetworkTimeSuggestion; import android.app.timedetector.TelephonyTimeSuggestion; @@ -174,6 +175,36 @@ public class TimeDetectorServiceTest { mStubbedTimeDetectorStrategy.verifySuggestNetworkTimeCalled(NetworkTimeSuggestion); } + @Test(expected = SecurityException.class) + public void testSuggestGnssTime_withoutPermission() { + doThrow(new SecurityException("Mock")) + .when(mMockContext).enforceCallingOrSelfPermission(anyString(), any()); + GnssTimeSuggestion gnssTimeSuggestion = createGnssTimeSuggestion(); + + try { + mTimeDetectorService.suggestGnssTime(gnssTimeSuggestion); + fail(); + } finally { + verify(mMockContext).enforceCallingOrSelfPermission( + eq(android.Manifest.permission.SET_TIME), anyString()); + } + } + + @Test + public void testSuggestGnssTime() throws Exception { + doNothing().when(mMockContext).enforceCallingOrSelfPermission(anyString(), any()); + + GnssTimeSuggestion gnssTimeSuggestion = createGnssTimeSuggestion(); + mTimeDetectorService.suggestGnssTime(gnssTimeSuggestion); + mTestHandler.assertTotalMessagesEnqueued(1); + + verify(mMockContext).enforceCallingOrSelfPermission( + eq(android.Manifest.permission.SET_TIME), anyString()); + + mTestHandler.waitForMessagesToBeProcessed(); + mStubbedTimeDetectorStrategy.verifySuggestGnssTimeCalled(gnssTimeSuggestion); + } + @Test public void testDump() { when(mMockContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)) @@ -219,12 +250,18 @@ public class TimeDetectorServiceTest { return new NetworkTimeSuggestion(timeValue); } + private static GnssTimeSuggestion createGnssTimeSuggestion() { + TimestampedValue<Long> timeValue = new TimestampedValue<>(100L, 1_000_000L); + return new GnssTimeSuggestion(timeValue); + } + private static class StubbedTimeDetectorStrategy implements TimeDetectorStrategy { // Call tracking. private TelephonyTimeSuggestion mLastTelephonySuggestion; private ManualTimeSuggestion mLastManualSuggestion; private NetworkTimeSuggestion mLastNetworkSuggestion; + private GnssTimeSuggestion mLastGnssSuggestion; private boolean mHandleAutoTimeDetectionChangedCalled; private boolean mDumpCalled; @@ -245,6 +282,11 @@ public class TimeDetectorServiceTest { } @Override + public void suggestGnssTime(GnssTimeSuggestion timeSuggestion) { + mLastGnssSuggestion = timeSuggestion; + } + + @Override public void handleAutoTimeConfigChanged() { mHandleAutoTimeDetectionChangedCalled = true; } @@ -258,6 +300,7 @@ public class TimeDetectorServiceTest { mLastTelephonySuggestion = null; mLastManualSuggestion = null; mLastNetworkSuggestion = null; + mLastGnssSuggestion = null; mHandleAutoTimeDetectionChangedCalled = false; mDumpCalled = false; } @@ -274,6 +317,10 @@ public class TimeDetectorServiceTest { assertEquals(expectedSuggestion, mLastNetworkSuggestion); } + void verifySuggestGnssTimeCalled(GnssTimeSuggestion expectedSuggestion) { + assertEquals(expectedSuggestion, mLastGnssSuggestion); + } + void verifyHandleAutoTimeDetectionChangedCalled() { assertTrue(mHandleAutoTimeDetectionChangedCalled); } diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java index 21396fd0516e..b1adb0b4ce60 100644 --- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java +++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java @@ -16,6 +16,7 @@ package com.android.server.timedetector; +import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_GNSS; import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_NETWORK; import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_TELEPHONY; @@ -25,6 +26,7 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import android.app.timedetector.GnssTimeSuggestion; import android.app.timedetector.ManualTimeSuggestion; import android.app.timedetector.NetworkTimeSuggestion; import android.app.timedetector.TelephonyTimeSuggestion; @@ -569,7 +571,53 @@ public class TimeDetectorStrategyImplTest { } @Test - public void highPrioritySuggestionsShouldBeatLowerPrioritySuggestions() { + public void testSuggestGnssTime_autoTimeEnabled() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoOriginPriorities(ORIGIN_GNSS) + .pokeAutoTimeDetectionEnabled(true); + + GnssTimeSuggestion timeSuggestion = + mScript.generateGnssTimeSuggestion(ARBITRARY_TEST_TIME); + + mScript.simulateTimePassing(); + + long expectedSystemClockMillis = + mScript.calculateTimeInMillisForNow(timeSuggestion.getUtcTime()); + mScript.simulateGnssTimeSuggestion(timeSuggestion) + .verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis); + } + + @Test + public void testSuggestGnssTime_autoTimeDisabled() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoOriginPriorities(ORIGIN_GNSS) + .pokeAutoTimeDetectionEnabled(false); + + GnssTimeSuggestion timeSuggestion = + mScript.generateGnssTimeSuggestion(ARBITRARY_TEST_TIME); + + mScript.simulateTimePassing() + .simulateGnssTimeSuggestion(timeSuggestion) + .verifySystemClockWasNotSetAndResetCallTracking(); + } + + @Test + public void gnssTimeSuggestion_ignoredWhenReferencedTimeIsInThePast() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoOriginPriorities(ORIGIN_GNSS) + .pokeAutoTimeDetectionEnabled(true); + + Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1)); + GnssTimeSuggestion timeSuggestion = mScript + .generateGnssTimeSuggestion(suggestedTime); + + mScript.simulateGnssTimeSuggestion(timeSuggestion) + .verifySystemClockWasNotSetAndResetCallTracking() + .assertLatestGnssSuggestion(null); + } + + @Test + public void highPrioritySuggestionsBeatLowerPrioritySuggestions_telephonyNetworkOrigins() { mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) .pokeAutoTimeDetectionEnabled(true) .pokeAutoOriginPriorities(ORIGIN_TELEPHONY, ORIGIN_NETWORK); @@ -672,22 +720,130 @@ public class TimeDetectorStrategyImplTest { } @Test + public void highPrioritySuggestionsBeatLowerPrioritySuggestions_networkGnssOrigins() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoTimeDetectionEnabled(true) + .pokeAutoOriginPriorities(ORIGIN_NETWORK, ORIGIN_GNSS); + + // Three obviously different times that could not be mistaken for each other. + Instant gnssTime1 = ARBITRARY_TEST_TIME; + Instant gnssTime2 = ARBITRARY_TEST_TIME.plus(Duration.ofDays(30)); + Instant networkTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(60)); + // A small increment used to simulate the passage of time, but not enough to interfere with + // macro-level time changes associated with suggestion age. + final long smallTimeIncrementMillis = 101; + + // A gnss suggestion is made. It should be used because there is no network suggestion. + GnssTimeSuggestion gnssTimeSuggestion1 = + mScript.generateGnssTimeSuggestion(gnssTime1); + mScript.simulateTimePassing(smallTimeIncrementMillis) + .simulateGnssTimeSuggestion(gnssTimeSuggestion1) + .verifySystemClockWasSetAndResetCallTracking( + mScript.calculateTimeInMillisForNow(gnssTimeSuggestion1.getUtcTime())); + + // Check internal state. + mScript.assertLatestNetworkSuggestion(null) + .assertLatestGnssSuggestion(gnssTimeSuggestion1); + assertEquals(gnssTimeSuggestion1, mScript.peekLatestValidGnssSuggestion()); + assertNull("No network suggestions were made:", mScript.peekLatestValidNetworkSuggestion()); + + // Simulate a little time passing. + mScript.simulateTimePassing(smallTimeIncrementMillis) + .verifySystemClockWasNotSetAndResetCallTracking(); + + // Now a network suggestion is made. Network suggestions are prioritized over gnss + // suggestions so it should "win". + NetworkTimeSuggestion networkTimeSuggestion = + mScript.generateNetworkTimeSuggestion(networkTime); + mScript.simulateTimePassing(smallTimeIncrementMillis) + .simulateNetworkTimeSuggestion(networkTimeSuggestion) + .verifySystemClockWasSetAndResetCallTracking( + mScript.calculateTimeInMillisForNow(networkTimeSuggestion.getUtcTime())); + + // Check internal state. + mScript.assertLatestNetworkSuggestion(networkTimeSuggestion) + .assertLatestGnssSuggestion(gnssTimeSuggestion1); + assertEquals(gnssTimeSuggestion1, mScript.peekLatestValidGnssSuggestion()); + assertEquals(networkTimeSuggestion, mScript.peekLatestValidNetworkSuggestion()); + + // Simulate some significant time passing: half the time allowed before a time signal + // becomes "too old to use". + mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_UTC_TIME_AGE_MILLIS / 2) + .verifySystemClockWasNotSetAndResetCallTracking(); + + // Now another gnss suggestion is made. Network suggestions are prioritized over + // gnss suggestions so the latest network suggestion should still "win". + GnssTimeSuggestion gnssTimeSuggestion2 = + mScript.generateGnssTimeSuggestion(gnssTime2); + mScript.simulateTimePassing(smallTimeIncrementMillis) + .simulateGnssTimeSuggestion(gnssTimeSuggestion2) + .verifySystemClockWasNotSetAndResetCallTracking(); + + // Check internal state. + mScript.assertLatestNetworkSuggestion(networkTimeSuggestion) + .assertLatestGnssSuggestion(gnssTimeSuggestion2); + assertEquals(gnssTimeSuggestion2, mScript.peekLatestValidGnssSuggestion()); + assertEquals(networkTimeSuggestion, mScript.peekLatestValidNetworkSuggestion()); + + // Simulate some significant time passing: half the time allowed before a time signal + // becomes "too old to use". This should mean that telephonyTimeSuggestion is now too old to + // be used but networkTimeSuggestion2 is not. + mScript.simulateTimePassing(TimeDetectorStrategyImpl.MAX_UTC_TIME_AGE_MILLIS / 2); + + // NOTE: The TimeDetectorStrategyImpl doesn't set an alarm for the point when the last + // suggestion it used becomes too old: it requires a new suggestion or an auto-time toggle + // to re-run the detection logic. This may change in future but until then we rely on a + // steady stream of suggestions to re-evaluate. + mScript.verifySystemClockWasNotSetAndResetCallTracking(); + + // Check internal state. + mScript.assertLatestNetworkSuggestion(networkTimeSuggestion) + .assertLatestGnssSuggestion(gnssTimeSuggestion2); + assertEquals(gnssTimeSuggestion2, mScript.peekLatestValidGnssSuggestion()); + assertNull( + "Network suggestion should be expired:", + mScript.peekLatestValidNetworkSuggestion()); + + // Toggle auto-time off and on to force the detection logic to run. + mScript.simulateAutoTimeDetectionToggle() + .simulateTimePassing(smallTimeIncrementMillis) + .simulateAutoTimeDetectionToggle(); + + // Verify the latest gnss time now wins. + mScript.verifySystemClockWasSetAndResetCallTracking( + mScript.calculateTimeInMillisForNow(gnssTimeSuggestion2.getUtcTime())); + + // Check internal state. + mScript.assertLatestNetworkSuggestion(networkTimeSuggestion) + .assertLatestGnssSuggestion(gnssTimeSuggestion2); + assertEquals(gnssTimeSuggestion2, mScript.peekLatestValidGnssSuggestion()); + assertNull( + "Network suggestion should still be expired:", + mScript.peekLatestValidNetworkSuggestion()); + } + + @Test public void whenAllTimeSuggestionsAreAvailable_higherPriorityWins_lowerPriorityComesFirst() { mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) .pokeAutoTimeDetectionEnabled(true) - .pokeAutoOriginPriorities(ORIGIN_TELEPHONY, ORIGIN_NETWORK); + .pokeAutoOriginPriorities(ORIGIN_TELEPHONY, ORIGIN_NETWORK, ORIGIN_GNSS); Instant networkTime = ARBITRARY_TEST_TIME; - Instant telephonyTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(30)); + Instant gnssTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(30)); + Instant telephonyTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(60)); NetworkTimeSuggestion networkTimeSuggestion = mScript.generateNetworkTimeSuggestion(networkTime); + GnssTimeSuggestion gnssTimeSuggestion = + mScript.generateGnssTimeSuggestion(gnssTime); TelephonyTimeSuggestion telephonyTimeSuggestion = mScript.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, telephonyTime); mScript.simulateNetworkTimeSuggestion(networkTimeSuggestion) + .simulateGnssTimeSuggestion(gnssTimeSuggestion) .simulateTelephonyTimeSuggestion(telephonyTimeSuggestion) .assertLatestNetworkSuggestion(networkTimeSuggestion) + .assertLatestGnssSuggestion(gnssTimeSuggestion) .assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion) .verifySystemClockWasSetAndResetCallTracking(telephonyTime.toEpochMilli()); } @@ -696,20 +852,25 @@ public class TimeDetectorStrategyImplTest { public void whenAllTimeSuggestionsAreAvailable_higherPriorityWins_higherPriorityComesFirst() { mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) .pokeAutoTimeDetectionEnabled(true) - .pokeAutoOriginPriorities(ORIGIN_TELEPHONY, ORIGIN_NETWORK); + .pokeAutoOriginPriorities(ORIGIN_TELEPHONY, ORIGIN_NETWORK, ORIGIN_GNSS); Instant networkTime = ARBITRARY_TEST_TIME; Instant telephonyTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(30)); + Instant gnssTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(60)); NetworkTimeSuggestion networkTimeSuggestion = mScript.generateNetworkTimeSuggestion(networkTime); TelephonyTimeSuggestion telephonyTimeSuggestion = mScript.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, telephonyTime); + GnssTimeSuggestion gnssTimeSuggestion = + mScript.generateGnssTimeSuggestion(gnssTime); mScript.simulateTelephonyTimeSuggestion(telephonyTimeSuggestion) .simulateNetworkTimeSuggestion(networkTimeSuggestion) + .simulateGnssTimeSuggestion(gnssTimeSuggestion) .assertLatestNetworkSuggestion(networkTimeSuggestion) .assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion) + .assertLatestGnssSuggestion(gnssTimeSuggestion) .verifySystemClockWasSetAndResetCallTracking(telephonyTime.toEpochMilli()); } @@ -728,7 +889,37 @@ public class TimeDetectorStrategyImplTest { } @Test - public void suggestionsFromSourceNotListedInPrioritiesList_areIgnored() { + public void whenHigherPrioritySuggestionsAreNotAvailable_fallbacksToNext() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoTimeDetectionEnabled(true) + .pokeAutoOriginPriorities(ORIGIN_TELEPHONY, ORIGIN_NETWORK, ORIGIN_GNSS); + + GnssTimeSuggestion timeSuggestion = + mScript.generateGnssTimeSuggestion(ARBITRARY_TEST_TIME); + + mScript.simulateGnssTimeSuggestion(timeSuggestion) + .assertLatestGnssSuggestion(timeSuggestion) + .verifySystemClockWasSetAndResetCallTracking(ARBITRARY_TEST_TIME.toEpochMilli()); + } + + @Test + public void suggestionsFromTelephonyOriginNotInPriorityList_areIgnored() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoTimeDetectionEnabled(true) + .pokeAutoOriginPriorities(ORIGIN_NETWORK); + + int slotIndex = ARBITRARY_SLOT_INDEX; + Instant testTime = ARBITRARY_TEST_TIME; + TelephonyTimeSuggestion timeSuggestion = + mScript.generateTelephonyTimeSuggestion(slotIndex, testTime); + + mScript.simulateTelephonyTimeSuggestion(timeSuggestion) + .assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, timeSuggestion) + .verifySystemClockWasNotSetAndResetCallTracking(); + } + + @Test + public void suggestionsFromNetworkOriginNotInPriorityList_areIgnored() { mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) .pokeAutoTimeDetectionEnabled(true) .pokeAutoOriginPriorities(ORIGIN_TELEPHONY); @@ -742,6 +933,20 @@ public class TimeDetectorStrategyImplTest { } @Test + public void suggestionsFromGnssOriginNotInPriorityList_areIgnored() { + mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) + .pokeAutoTimeDetectionEnabled(true) + .pokeAutoOriginPriorities(ORIGIN_TELEPHONY); + + GnssTimeSuggestion timeSuggestion = mScript.generateGnssTimeSuggestion( + ARBITRARY_TEST_TIME); + + mScript.simulateGnssTimeSuggestion(timeSuggestion) + .assertLatestGnssSuggestion(timeSuggestion) + .verifySystemClockWasNotSetAndResetCallTracking(); + } + + @Test public void autoOriginPrioritiesList_doesNotAffectManualSuggestion() { mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO) .pokeAutoTimeDetectionEnabled(false) @@ -945,6 +1150,11 @@ public class TimeDetectorStrategyImplTest { return this; } + Script simulateGnssTimeSuggestion(GnssTimeSuggestion timeSuggestion) { + mTimeDetectorStrategy.suggestGnssTime(timeSuggestion); + return this; + } + Script simulateAutoTimeDetectionToggle() { mFakeCallback.simulateAutoTimeZoneDetectionToggle(); mTimeDetectorStrategy.handleAutoTimeConfigChanged(); @@ -995,6 +1205,14 @@ public class TimeDetectorStrategyImplTest { } /** + * White box test info: Asserts the latest gnss suggestion is as expected. + */ + Script assertLatestGnssSuggestion(GnssTimeSuggestion expected) { + assertEquals(expected, mTimeDetectorStrategy.getLatestGnssSuggestion()); + return this; + } + + /** * White box test info: Returns the telephony suggestion that would be used, if any, given * the current elapsed real time clock and regardless of origin prioritization. */ @@ -1011,6 +1229,14 @@ public class TimeDetectorStrategyImplTest { } /** + * White box test info: Returns the gnss suggestion that would be used, if any, given the + * current elapsed real time clock and regardless of origin prioritization. + */ + GnssTimeSuggestion peekLatestValidGnssSuggestion() { + return mTimeDetectorStrategy.findLatestValidGnssSuggestionForTests(); + } + + /** * Generates a ManualTimeSuggestion using the current elapsed realtime clock for the * reference time. */ @@ -1057,6 +1283,18 @@ public class TimeDetectorStrategyImplTest { } /** + * Generates a GnssTimeSuggestion using the current elapsed realtime clock for the + * reference time. + */ + GnssTimeSuggestion generateGnssTimeSuggestion(Instant suggestedTime) { + TimestampedValue<Long> utcTime = + new TimestampedValue<>( + mFakeCallback.peekElapsedRealtimeMillis(), + suggestedTime.toEpochMilli()); + return new GnssTimeSuggestion(utcTime); + } + + /** * Calculates what the supplied time would be when adjusted for the movement of the fake * elapsed realtime clock. */ diff --git a/services/tests/servicestests/src/com/android/server/timezone/OWNERS b/services/tests/servicestests/src/com/android/server/timezone/OWNERS index 09447a971bdd..8f8089717e3b 100644 --- a/services/tests/servicestests/src/com/android/server/timezone/OWNERS +++ b/services/tests/servicestests/src/com/android/server/timezone/OWNERS @@ -1 +1,3 @@ -include /core/java/android/app/timezone/OWNERS +# Bug component: 847766 +mingaleev@google.com +include /core/java/android/app/timedetector/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/OWNERS b/services/tests/servicestests/src/com/android/server/timezonedetector/OWNERS index 09447a971bdd..8f8089717e3b 100644 --- a/services/tests/servicestests/src/com/android/server/timezonedetector/OWNERS +++ b/services/tests/servicestests/src/com/android/server/timezonedetector/OWNERS @@ -1 +1,3 @@ -include /core/java/android/app/timezone/OWNERS +# Bug component: 847766 +mingaleev@google.com +include /core/java/android/app/timedetector/OWNERS diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationScalerTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationScalerTest.java index fa171fdeaece..1a4ac0777ba5 100644 --- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationScalerTest.java +++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationScalerTest.java @@ -28,6 +28,7 @@ import android.content.Context; import android.content.ContextWrapper; import android.os.Handler; import android.os.IExternalVibratorService; +import android.os.PowerManagerInternal; import android.os.UserHandle; import android.os.VibrationAttributes; import android.os.VibrationEffect; @@ -40,7 +41,9 @@ import androidx.test.InstrumentationRegistry; import com.android.internal.util.test.FakeSettingsProvider; import com.android.internal.util.test.FakeSettingsProviderRule; +import com.android.server.LocalServices; +import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -62,6 +65,7 @@ public class VibrationScalerTest { // TODO(b/131311651): replace with a FakeVibrator instead. @Mock private Vibrator mVibratorMock; + @Mock private PowerManagerInternal mPowerManagerInternalMock; private TestLooper mTestLooper; private ContextWrapper mContextSpy; @@ -77,11 +81,19 @@ public class VibrationScalerTest { when(mContextSpy.getContentResolver()).thenReturn(contentResolver); when(mContextSpy.getSystemService(eq(Context.VIBRATOR_SERVICE))).thenReturn(mVibratorMock); + LocalServices.removeServiceForTest(PowerManagerInternal.class); + LocalServices.addService(PowerManagerInternal.class, mPowerManagerInternalMock); + mVibrationSettings = new VibrationSettings( mContextSpy, new Handler(mTestLooper.getLooper())); mVibrationScaler = new VibrationScaler(mContextSpy, mVibrationSettings); } + @After + public void tearDown() throws Exception { + LocalServices.removeServiceForTest(PowerManagerInternal.class); + } + @Test public void testGetExternalVibrationScale() { when(mVibratorMock.getDefaultHapticFeedbackIntensity()) diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java index 04c2cb3b1148..ecdb8bc71bd8 100644 --- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java +++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java @@ -20,7 +20,9 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -32,6 +34,9 @@ import android.content.Context; import android.content.ContextWrapper; import android.media.AudioManager; import android.os.Handler; +import android.os.PowerManagerInternal; +import android.os.PowerSaveState; +import android.os.RemoteException; import android.os.UserHandle; import android.os.VibrationAttributes; import android.os.VibrationEffect; @@ -44,6 +49,7 @@ import androidx.test.InstrumentationRegistry; import com.android.internal.util.test.FakeSettingsProvider; import com.android.internal.util.test.FakeSettingsProviderRule; +import com.android.server.LocalServices; import org.junit.After; import org.junit.Before; @@ -62,17 +68,24 @@ import org.mockito.junit.MockitoRule; @Presubmit public class VibrationSettingsTest { + private static final int UID = 1; + private static final PowerSaveState NORMAL_POWER_STATE = new PowerSaveState.Builder().build(); + private static final PowerSaveState LOW_POWER_STATE = new PowerSaveState.Builder() + .setBatterySaverEnabled(true).build(); + @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule(); @Rule public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule(); // TODO(b/131311651): replace with a FakeVibrator instead. @Mock private Vibrator mVibratorMock; @Mock private VibrationSettings.OnVibratorSettingsChanged mListenerMock; + @Mock private PowerManagerInternal mPowerManagerInternalMock; private TestLooper mTestLooper; private ContextWrapper mContextSpy; private AudioManager mAudioManager; private VibrationSettings mVibrationSettings; + private PowerManagerInternal.LowPowerModeListener mRegisteredPowerModeListener; @Before public void setUp() throws Exception { @@ -83,10 +96,17 @@ public class VibrationSettingsTest { when(mContextSpy.getContentResolver()).thenReturn(contentResolver); when(mContextSpy.getSystemService(eq(Context.VIBRATOR_SERVICE))).thenReturn(mVibratorMock); when(mVibratorMock.hasVibrator()).thenReturn(true); + doAnswer(invocation -> { + mRegisteredPowerModeListener = invocation.getArgument(0); + return null; + }).when(mPowerManagerInternalMock).registerLowPowerModeObserver(any()); + + LocalServices.removeServiceForTest(PowerManagerInternal.class); + LocalServices.addService(PowerManagerInternal.class, mPowerManagerInternalMock); mAudioManager = mContextSpy.getSystemService(AudioManager.class); - mVibrationSettings = new VibrationSettings( - mContextSpy, new Handler(mTestLooper.getLooper())); + mVibrationSettings = new VibrationSettings(mContextSpy, + new Handler(mTestLooper.getLooper())); setUserSetting(Settings.System.VIBRATE_INPUT_DEVICES, 0); setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0); @@ -96,7 +116,7 @@ public class VibrationSettingsTest { @After public void tearDown() throws Exception { - FakeSettingsProvider.clearSettingsProvider(); + LocalServices.removeServiceForTest(PowerManagerInternal.class); } @Test @@ -118,6 +138,17 @@ public class VibrationSettingsTest { } @Test + public void addListener_lowPowerModeChangeTriggerListener() { + mVibrationSettings.addListener(mListenerMock); + + mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE); + mRegisteredPowerModeListener.onLowPowerModeChanged(NORMAL_POWER_STATE); + mRegisteredPowerModeListener.onLowPowerModeChanged(NORMAL_POWER_STATE); // No change. + + verify(mListenerMock, times(2)).onChange(); + } + + @Test public void removeListener_noMoreCallbacksToListener() { mVibrationSettings.addListener(mListenerMock); @@ -132,56 +163,103 @@ public class VibrationSettingsTest { } @Test - public void shouldVibrateForRingtones_withVibrateWhenRinging_onlyIgnoreSettingsForSilentMode() { + public void shouldVibrateForRingerMode_withoutRingtoneUsage_returnsTrue() { + assertTrue(mVibrationSettings.shouldVibrateForRingerMode(VibrationAttributes.USAGE_ALARM)); + assertTrue(mVibrationSettings.shouldVibrateForRingerMode(VibrationAttributes.USAGE_TOUCH)); + assertTrue(mVibrationSettings.shouldVibrateForRingerMode( + VibrationAttributes.USAGE_NOTIFICATION)); + assertTrue(mVibrationSettings.shouldVibrateForRingerMode( + VibrationAttributes.USAGE_COMMUNICATION_REQUEST)); + } + + @Test + public void shouldVibrateForRingerMode_withVibrateWhenRinging_ignoreSettingsForSilentMode() { + int usageRingtone = VibrationAttributes.USAGE_RINGTONE; setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 1); setRingerMode(AudioManager.RINGER_MODE_SILENT); - assertFalse(mVibrationSettings.shouldVibrateForRingtone()); + assertFalse(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone)); setRingerMode(AudioManager.RINGER_MODE_MAX); - assertTrue(mVibrationSettings.shouldVibrateForRingtone()); + assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone)); setRingerMode(AudioManager.RINGER_MODE_NORMAL); - assertTrue(mVibrationSettings.shouldVibrateForRingtone()); + assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone)); setRingerMode(AudioManager.RINGER_MODE_VIBRATE); - assertTrue(mVibrationSettings.shouldVibrateForRingtone()); + assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone)); } @Test - public void shouldVibrateForRingtones_withApplyRampingRinger_onlyIgnoreSettingsForSilentMode() { + public void shouldVibrateForRingerMode_withApplyRampingRinger_ignoreSettingsForSilentMode() { + int usageRingtone = VibrationAttributes.USAGE_RINGTONE; setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0); setGlobalSetting(Settings.Global.APPLY_RAMPING_RINGER, 1); setRingerMode(AudioManager.RINGER_MODE_SILENT); - assertFalse(mVibrationSettings.shouldVibrateForRingtone()); + assertFalse(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone)); setRingerMode(AudioManager.RINGER_MODE_MAX); - assertTrue(mVibrationSettings.shouldVibrateForRingtone()); + assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone)); setRingerMode(AudioManager.RINGER_MODE_NORMAL); - assertTrue(mVibrationSettings.shouldVibrateForRingtone()); + assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone)); setRingerMode(AudioManager.RINGER_MODE_VIBRATE); - assertTrue(mVibrationSettings.shouldVibrateForRingtone()); + assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone)); } @Test - public void shouldVibrateForRingtones_withAllSettingsOff_onlyVibratesForVibrateMode() { + public void shouldVibrateForRingerMode_withAllSettingsOff_onlyVibratesForVibrateMode() { + int usageRingtone = VibrationAttributes.USAGE_RINGTONE; setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0); setGlobalSetting(Settings.Global.APPLY_RAMPING_RINGER, 0); setRingerMode(AudioManager.RINGER_MODE_VIBRATE); - assertTrue(mVibrationSettings.shouldVibrateForRingtone()); + assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone)); setRingerMode(AudioManager.RINGER_MODE_SILENT); - assertFalse(mVibrationSettings.shouldVibrateForRingtone()); + assertFalse(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone)); setRingerMode(AudioManager.RINGER_MODE_MAX); - assertFalse(mVibrationSettings.shouldVibrateForRingtone()); + assertFalse(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone)); setRingerMode(AudioManager.RINGER_MODE_NORMAL); - assertFalse(mVibrationSettings.shouldVibrateForRingtone()); + assertFalse(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone)); + } + + @Test + public void shouldVibrateForUid_withBackgroundAllowedUsage_returnTrue() throws RemoteException { + assertTrue(mVibrationSettings.shouldVibrateForUid(UID, VibrationAttributes.USAGE_ALARM)); + assertTrue(mVibrationSettings.shouldVibrateForUid(UID, + VibrationAttributes.USAGE_NOTIFICATION)); + assertTrue(mVibrationSettings.shouldVibrateForUid(UID, VibrationAttributes.USAGE_RINGTONE)); + } + + @Test + public void shouldVibrateForPowerMode_withLowPowerAndAllowedUsage_returnTrue() { + mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE); + + assertTrue(mVibrationSettings.shouldVibrateForPowerMode(VibrationAttributes.USAGE_ALARM)); + assertTrue(mVibrationSettings.shouldVibrateForPowerMode( + VibrationAttributes.USAGE_RINGTONE)); + assertTrue(mVibrationSettings.shouldVibrateForPowerMode( + VibrationAttributes.USAGE_COMMUNICATION_REQUEST)); + } + + @Test + public void shouldVibrateForPowerMode_withRestrictedUsage_returnsFalseWhileInLowPowerMode() { + mRegisteredPowerModeListener.onLowPowerModeChanged(NORMAL_POWER_STATE); + + assertTrue(mVibrationSettings.shouldVibrateForPowerMode(VibrationAttributes.USAGE_TOUCH)); + assertTrue(mVibrationSettings.shouldVibrateForPowerMode( + VibrationAttributes.USAGE_NOTIFICATION)); + + mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE); + + assertFalse(mVibrationSettings.shouldVibrateForPowerMode(VibrationAttributes.USAGE_TOUCH)); + assertFalse(mVibrationSettings.shouldVibrateForPowerMode( + VibrationAttributes.USAGE_NOTIFICATION)); } @Test @@ -299,4 +377,5 @@ public class VibrationSettingsTest { mAudioManager.setRingerModeInternal(ringerMode); assertEquals(ringerMode, mAudioManager.getRingerModeInternal()); } + } diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java index 1f163bd3282b..815aa8ee66ae 100644 --- a/services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java @@ -16,7 +16,6 @@ package com.android.server.vibrator; -import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -38,7 +37,6 @@ import android.hardware.vibrator.IVibrator; import android.os.IBinder; import android.os.IVibratorStateListener; import android.os.VibrationEffect; -import android.os.Vibrator; import android.os.test.TestLooper; import android.platform.test.annotations.Presubmit; @@ -100,7 +98,7 @@ public class VibratorControllerTest { public void createController_initializesNativeWrapper() { int vibratorId = 13; VibratorController controller = createController(vibratorId); - assertEquals(vibratorId, controller.getVibratorId()); + assertEquals(vibratorId, controller.getVibratorInfo().getId()); verify(mNativeWrapperMock).init(eq(vibratorId), notNull()); } @@ -132,59 +130,6 @@ public class VibratorControllerTest { } @Test - public void areEffectsSupported_withNullResultFromNative_returnsSupportUnknown() { - when(mNativeWrapperMock.getSupportedEffects()).thenReturn(null); - assertArrayEquals(new int[]{Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN}, - createController().areEffectsSupported(new int[]{VibrationEffect.EFFECT_CLICK})); - } - - @Test - public void areEffectsSupported_withSomeEffectsSupported_returnsSupportYesAndNoForEffects() { - int[] effects = new int[]{VibrationEffect.EFFECT_CLICK, VibrationEffect.EFFECT_TICK}; - - when(mNativeWrapperMock.getSupportedEffects()) - .thenReturn(new int[]{VibrationEffect.EFFECT_CLICK}); - assertArrayEquals( - new int[]{Vibrator.VIBRATION_EFFECT_SUPPORT_YES, - Vibrator.VIBRATION_EFFECT_SUPPORT_NO}, - createController().areEffectsSupported(effects)); - } - - @Test - public void arePrimitivesSupported_withoutComposeCapability_returnsAlwaysFalse() { - assertArrayEquals(new boolean[]{false, false}, - createController().arePrimitivesSupported(new int[]{ - VibrationEffect.Composition.PRIMITIVE_CLICK, - VibrationEffect.Composition.PRIMITIVE_TICK - })); - } - - @Test - public void arePrimitivesSupported_withNullResultFromNative_returnsAlwaysFalse() { - mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS); - when(mNativeWrapperMock.getSupportedPrimitives()).thenReturn(null); - - assertArrayEquals(new boolean[]{false, false}, - createController().arePrimitivesSupported(new int[]{ - VibrationEffect.Composition.PRIMITIVE_CLICK, - VibrationEffect.Composition.PRIMITIVE_QUICK_RISE - })); - } - - @Test - public void arePrimitivesSupported_withSomeSupportedPrimitives_returnsBasedOnNativeResult() { - mockVibratorCapabilities(IVibrator.CAP_COMPOSE_EFFECTS); - when(mNativeWrapperMock.getSupportedPrimitives()) - .thenReturn(new int[]{VibrationEffect.Composition.PRIMITIVE_CLICK}); - - assertArrayEquals(new boolean[]{true, false}, - createController().arePrimitivesSupported(new int[]{ - VibrationEffect.Composition.PRIMITIVE_CLICK, - VibrationEffect.Composition.PRIMITIVE_QUICK_RISE - })); - } - - @Test public void setExternalControl_withCapability_enablesExternalControl() { mockVibratorCapabilities(IVibrator.CAP_EXTERNAL_CONTROL); VibratorController controller = createController(); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java index 824c05e4ae47..18ca09be235c 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAdjustmentExtractorTest.java @@ -127,6 +127,6 @@ public class NotificationAdjustmentExtractorTest extends UiServiceTestCase { Icon.createWithResource(getContext(), android.R.drawable.sym_def_app_icon), "action", PendingIntent.getBroadcast(getContext(), 0, new Intent("Action"), - PendingIntent.FLAG_MUTABLE_UNAUDITED)).build(); + PendingIntent.FLAG_IMMUTABLE)).build(); } } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationIntrusivenessExtractorTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationIntrusivenessExtractorTest.java index a9a3b2b0ed22..ac9a77bc5cb7 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationIntrusivenessExtractorTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationIntrusivenessExtractorTest.java @@ -58,10 +58,8 @@ public class NotificationIntrusivenessExtractorTest extends UiServiceTestCase { NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_DEFAULT); final Notification.Builder builder = new Notification.Builder(getContext()) .setContentTitle("foo") - // TODO(b/174258141) Please replace FLAG_MUTABLE_UNAUDITED below - // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. .setFullScreenIntent(PendingIntent.getActivity( - getContext(), 0, new Intent(""), PendingIntent.FLAG_MUTABLE_UNAUDITED), + getContext(), 0, new Intent(""), PendingIntent.FLAG_IMMUTABLE), true) .setSmallIcon(android.R.drawable.sym_def_app_icon); @@ -79,10 +77,8 @@ public class NotificationIntrusivenessExtractorTest extends UiServiceTestCase { NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_DEFAULT); final Notification.Builder builder = new Notification.Builder(getContext()) .setContentTitle("foo") - // TODO(b/174258141) Please replace FLAG_MUTABLE_UNAUDITED below - // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. .setFullScreenIntent(PendingIntent.getActivity( - getContext(), 0, new Intent(""), PendingIntent.FLAG_MUTABLE_UNAUDITED), + getContext(), 0, new Intent(""), PendingIntent.FLAG_IMMUTABLE), true) .setSmallIcon(android.R.drawable.sym_def_app_icon); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java index c63470617288..be489c3bcd12 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java @@ -357,13 +357,11 @@ public class NotificationListenerServiceTest extends UiServiceTestCase { private ArrayList<Notification.Action> getSmartActions(String key, int index) { ArrayList<Notification.Action> actions = new ArrayList<>(); for (int i = 0; i < index; i++) { - // TODO(b/174935955) Please replace FLAG_MUTABLE_UNAUDITED below - // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. PendingIntent intent = PendingIntent.getBroadcast( getContext(), index /*requestCode*/, new Intent("ACTION_" + key), - PendingIntent.FLAG_MUTABLE_UNAUDITED /*flags*/); + PendingIntent.FLAG_IMMUTABLE /*flags*/); actions.add(new Notification.Action.Builder(null /*icon*/, key, intent).build()); } return actions; 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 849477c924bb..f7c655f6ab2b 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -305,6 +305,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { @Mock StatusBarManagerInternal mStatusBar; + private NotificationManagerService.WorkerHandler mWorkerHandler; + // Use a Testable subclass so we can simulate calls from the system without failing. private static class TestableNotificationManagerService extends NotificationManagerService { int countSystemChecks = 0; @@ -482,14 +484,13 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { when(mAssistants.isAdjustmentAllowed(anyString())).thenReturn(true); - mService.init(mService.new WorkerHandler(mTestableLooper.getLooper()), - mRankingHandler, mPackageManager, mPackageManagerClient, mockLightsManager, - mListeners, mAssistants, mConditionProviders, - mCompanionMgr, mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager, - mGroupHelper, mAm, mAtm, mAppUsageStats, - mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal, - mAppOpsManager, mUm, mHistoryManager, mStatsManager, - mock(TelephonyManager.class), mAmi, mToastRateLimiter); + mWorkerHandler = mService.new WorkerHandler(mTestableLooper.getLooper()); + mService.init(mWorkerHandler, mRankingHandler, mPackageManager, mPackageManagerClient, + mockLightsManager, mListeners, mAssistants, mConditionProviders, mCompanionMgr, + mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager, mGroupHelper, mAm, mAtm, + mAppUsageStats, mock(DevicePolicyManagerInternal.class), mUgm, mUgmInternal, + mAppOpsManager, mUm, mHistoryManager, mStatsManager, mock(TelephonyManager.class), + mAmi, mToastRateLimiter); mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY); mService.setAudioManager(mAudioManager); @@ -575,6 +576,10 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { InstrumentationRegistry.getInstrumentation() .getUiAutomation().dropShellPermissionIdentity(); + // Remove scheduled messages that would be processed when the test is already done, and + // could cause issues, for example, messages that remove/cancel shown toasts (this causes + // problematic interactions with mocks when they're no longer working as expected). + mWorkerHandler.removeCallbacksAndMessages(null); } private void simulatePackageSuspendBroadcast(boolean suspend, String pkg, @@ -790,10 +795,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { .setName("bubblebot") .build(); RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build(); - // TODO(b/174965245) Please replace FLAG_MUTABLE_UNAUDITED below - // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), - PendingIntent.FLAG_MUTABLE_UNAUDITED); + PendingIntent.FLAG_MUTABLE); Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon); Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply", inputIntent).addRemoteInput(remoteInput) @@ -1498,20 +1501,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @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); @@ -4980,6 +4969,40 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test + public void testCustomToastPostedWhileInForeground_blockedIfAppGoesToBackground() + throws Exception { + final String testPackage = "testPackageName"; + assertEquals(0, mService.mToastQueue.size()); + mService.isSystemUid = false; + setToastRateIsWithinQuota(true); + + // package is not suspended + when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid))) + .thenReturn(false); + + setAppInForegroundForToasts(mUid, true); + + Binder token1 = new Binder(); + Binder token2 = new Binder(); + ITransientNotification callback1 = mock(ITransientNotification.class); + ITransientNotification callback2 = mock(ITransientNotification.class); + INotificationManager nmService = (INotificationManager) mService.mService; + + nmService.enqueueToast(testPackage, token1, callback1, 2000, 0); + nmService.enqueueToast(testPackage, token2, callback2, 2000, 0); + + assertEquals(2, mService.mToastQueue.size()); // Both toasts enqueued. + verify(callback1, times(1)).show(any()); // First toast shown. + + setAppInForegroundForToasts(mUid, false); + + mService.cancelToastLocked(0); // Remove the first toast, and show next. + + assertEquals(0, mService.mToastQueue.size()); // Both toasts processed. + verify(callback2, never()).show(any()); // Second toast was never shown. + } + + @Test public void testAllowForegroundTextToasts() throws Exception { final String testPackage = "testPackageName"; assertEquals(0, mService.mToastQueue.size()); @@ -7369,10 +7392,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); ArrayList<Notification.Action> extraAction = new ArrayList<>(); RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build(); - // TODO(b/174965245) Please replace FLAG_MUTABLE_UNAUDITED below - // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), - PendingIntent.FLAG_MUTABLE_UNAUDITED); + PendingIntent.FLAG_IMMUTABLE); Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon); Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply", inputIntent).addRemoteInput(remoteInput) @@ -7402,10 +7423,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { NotificationRecord r = generateNotificationRecord(mTestNotificationChannel); ArrayList<Notification.Action> extraAction = new ArrayList<>(); RemoteInput remoteInput = new RemoteInput.Builder("reply_key").setLabel("reply").build(); - // TODO(b/174965245) Please replace FLAG_MUTABLE_UNAUDITED below - // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. PendingIntent inputIntent = PendingIntent.getActivity(mContext, 0, new Intent(), - PendingIntent.FLAG_MUTABLE_UNAUDITED); + PendingIntent.FLAG_MUTABLE); Icon icon = Icon.createWithResource(mContext, android.R.drawable.sym_def_app_icon); Notification.Action replyAction = new Notification.Action.Builder(icon, "Reply", inputIntent).addRemoteInput(remoteInput) diff --git a/services/tests/wmtests/Android.bp b/services/tests/wmtests/Android.bp index 4ca5b9e4b14f..1ecf850adb1f 100644 --- a/services/tests/wmtests/Android.bp +++ b/services/tests/wmtests/Android.bp @@ -47,7 +47,6 @@ android_test { "testables", "ub-uiautomator", "hamcrest-library", - "compatibility-device-util-axt", ], libs: [ 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 99bd0d7198c0..466b86117fdc 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 @@ public class ActivityDisplayTests extends WindowTestsBase { 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(anotherAlwaysOnTopStack, taskDisplayArea.getRootTaskAt(topPosition - 1)); + assertEquals(topPosition - 1, taskDisplayArea.getIndexOf(anotherAlwaysOnTopStack)); final Task nonAlwaysOnTopStack = taskDisplayArea.createRootTask( WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, true /* onTop */); @@ -256,7 +256,7 @@ public class ActivityDisplayTests extends WindowTestsBase { 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(nonAlwaysOnTopStack, taskDisplayArea.getRootTaskAt(topPosition - 3)); + assertEquals(topPosition - 3, taskDisplayArea.getIndexOf(nonAlwaysOnTopStack)); anotherAlwaysOnTopStack.setAlwaysOnTop(false); taskDisplayArea.positionChildAt(POSITION_TOP, anotherAlwaysOnTopStack, @@ -264,16 +264,16 @@ public class ActivityDisplayTests extends WindowTestsBase { 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(anotherAlwaysOnTopStack, taskDisplayArea.getRootTaskAt(topPosition - 2)); + assertEquals(topPosition - 2, taskDisplayArea.getIndexOf(anotherAlwaysOnTopStack)); anotherAlwaysOnTopStack.setAlwaysOnTop(true); // Ensure always on top state changes properly when windowing mode changes. anotherAlwaysOnTopStack.setWindowingMode(WINDOWING_MODE_FULLSCREEN); assertFalse(anotherAlwaysOnTopStack.isAlwaysOnTop()); - assertEquals(anotherAlwaysOnTopStack, taskDisplayArea.getRootTaskAt(topPosition - 2)); + assertEquals(topPosition - 2, taskDisplayArea.getIndexOf(anotherAlwaysOnTopStack)); anotherAlwaysOnTopStack.setWindowingMode(WINDOWING_MODE_FREEFORM); assertTrue(anotherAlwaysOnTopStack.isAlwaysOnTop()); - assertEquals(anotherAlwaysOnTopStack, taskDisplayArea.getRootTaskAt(topPosition - 1)); + assertEquals(topPosition - 1, taskDisplayArea.getIndexOf(anotherAlwaysOnTopStack)); final Task dreamStack = taskDisplayArea.createRootTask( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_DREAM, true /* onTop */); @@ -282,7 +282,7 @@ public class ActivityDisplayTests extends WindowTestsBase { topPosition = taskDisplayArea.getRootTaskCount() - 1; // Ensure dream shows above all activities, including PiP assertEquals(dreamStack, taskDisplayArea.getTopRootTask()); - assertEquals(pinnedStack, taskDisplayArea.getRootTaskAt(topPosition - 1)); + assertEquals(topPosition - 1, taskDisplayArea.getIndexOf(pinnedStack)); final Task assistStack = taskDisplayArea.createRootTask( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_ASSISTANT, true /* onTop */); @@ -294,8 +294,8 @@ public class ActivityDisplayTests extends WindowTestsBase { // is false and on top of everything when true. final boolean isAssistantOnTop = mContext.getResources() .getBoolean(com.android.internal.R.bool.config_assistantOnTopOfDream); - assertEquals(assistStack, taskDisplayArea.getRootTaskAt( - isAssistantOnTop ? topPosition : topPosition - 4)); + assertEquals(isAssistantOnTop ? topPosition : topPosition - 4, + taskDisplayArea.getIndexOf(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 2f34f708a562..78cebf3568c2 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -1051,7 +1051,7 @@ public class ActivityRecordTests extends WindowTestsBase { final ActivityRecord nextTop = nextStack.getTopNonFinishingActivity(); nextTop.setState(STOPPED, "test"); - task.mPausingActivity = currentTop; + task.setPausingActivity(currentTop); currentTop.finishing = true; currentTop.setState(PAUSED, "test"); currentTop.completeFinishing("completePauseLocked"); @@ -1211,7 +1211,7 @@ public class ActivityRecordTests extends WindowTestsBase { focusedActivity.nowVisible = true; focusedActivity.mVisibleRequested = true; focusedActivity.setState(RESUMED, "test"); - stack.mResumedActivity = focusedActivity; + stack.setResumedActivity(focusedActivity, "test"); topActivity.completeFinishing("test"); 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 8e3e668804ff..5504460f1036 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java @@ -1014,7 +1014,7 @@ public class ActivityStackTests extends WindowTestsBase { final ActivityRecord secondActivity = new ActivityBuilder(mAtm).setTask(task).build(); firstActivity.setState(STOPPED, "testFinishDisabledPackageActivities"); secondActivity.setState(RESUMED, "testFinishDisabledPackageActivities"); - task.mResumedActivity = secondActivity; + task.setResumedActivity(secondActivity, "test"); // Note the activities have non-null ActivityRecord.app, so it won't remove directly. mRootWindowContainer.mFinishDisabledPackageActivitiesHelper.process( @@ -1140,8 +1140,8 @@ public class ActivityStackTests extends WindowTestsBase { final Task task = new TaskBuilder(mSupervisor).build(); final ActivityRecord bottomActivity = new ActivityBuilder(mAtm).setTask(task).build(); doReturn(true).when(bottomActivity).attachedToProcess(); - task.mPausingActivity = null; - task.mResumedActivity = bottomActivity; + task.setPausingActivity(null); + task.setResumedActivity(bottomActivity, "test"); final ActivityRecord topActivity = new ActivityBuilder(mAtm).setTask(task).build(); topActivity.info.flags |= FLAG_RESUME_WHILE_PAUSING; 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 ef2e88913914..5695412394ce 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java @@ -512,11 +512,8 @@ public class ActivityStarterTests extends WindowTestsBase { } private void assertNoTasks(DisplayContent display) { - display.forAllTaskDisplayAreas(taskDisplayArea -> { - for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { - final Task stack = taskDisplayArea.getRootTaskAt(sNdx); - assertFalse(stack.hasChild()); - } + display.forAllRootTasks(stack -> { + assertFalse(stack.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 080f04efa9b4..d34e2c4923dc 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java @@ -247,7 +247,7 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase { activity.finishing = true; activity.mVisibleRequested = false; activity.setVisible(false); - activity.getRootTask().mPausingActivity = activity; + activity.getTask().setPausingActivity(activity); homeActivity.setState(Task.ActivityState.PAUSED, "test"); // Even the visibility states are invisible, the next activity should be resumed because @@ -262,8 +262,8 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase { public void testUpdateSleep() { doCallRealMethod().when(mWm.mRoot).hasAwakeDisplay(); mSupervisor.mGoingToSleepWakeLock = mock(PowerManager.WakeLock.class); - final ActivityRecord homeActivity = new ActivityBuilder(mAtm) - .setTask(mWm.mRoot.getDefaultTaskDisplayArea().getOrCreateRootHomeTask()).build(); + final Task rootHomeTask = mWm.mRoot.getDefaultTaskDisplayArea().getOrCreateRootHomeTask(); + final ActivityRecord homeActivity = new ActivityBuilder(mAtm).setTask(rootHomeTask).build(); final ActivityRecord topActivity = new ActivityBuilder(mAtm).setCreateTask(true).build(); topActivity.setState(Task.ActivityState.RESUMED, "test"); @@ -277,6 +277,9 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase { // Sleep all displays. mWm.mRoot.forAllDisplays(display -> doReturn(true).when(display).shouldSleep()); mAtm.updateSleepIfNeededLocked(); + // Simulate holding sleep wake lock if it is acquired. + verify(mSupervisor.mGoingToSleepWakeLock).acquire(); + doReturn(true).when(mSupervisor.mGoingToSleepWakeLock).isHeld(); assertEquals(Task.ActivityState.PAUSING, topActivity.getState()); assertTrue(mAtm.mInternal.isSleeping()); @@ -285,8 +288,17 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase { // The top app should not change while sleeping. assertEquals(topActivity.app, mAtm.mInternal.getTopApp()); + // If all activities are stopped, the sleep wake lock must be released. + final Task topRootTask = topActivity.getRootTask(); + doReturn(true).when(rootHomeTask).goToSleepIfPossible(anyBoolean()); + doReturn(true).when(topRootTask).goToSleepIfPossible(anyBoolean()); + topActivity.setState(Task.ActivityState.STOPPING, "test"); + topActivity.activityStopped(null /* newIcicle */, null /* newPersistentState */, + null /* description */); + verify(mSupervisor.mGoingToSleepWakeLock).release(); + // Move the current top to back, the top app should update to the next activity. - topActivity.getRootTask().moveToBack("test", null /* self */); + topRootTask.moveToBack("test", null /* self */); assertEquals(homeActivity.app, mAtm.mInternal.getTopApp()); // Wake all displays. diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java index 8cad56a45518..295c50bcda55 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java @@ -20,7 +20,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; -import static android.view.WindowManager.TRANSIT_CHANGE_WINDOWING_MODE; +import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN; import static android.view.WindowManager.TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE; @@ -111,7 +111,7 @@ public class AppTransitionControllerTest extends WindowTestsBase { WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD); translucentOpening.setOccludesParent(false); translucentOpening.setVisible(false); - mDisplayContent.prepareAppTransition(TRANSIT_CHANGE_WINDOWING_MODE); + mDisplayContent.prepareAppTransition(TRANSIT_CHANGE); mDisplayContent.mOpeningApps.add(behind); mDisplayContent.mOpeningApps.add(translucentOpening); assertEquals(TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE, 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 e47913fba7ab..8e78dce39ac7 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java @@ -40,6 +40,7 @@ import static com.android.server.wm.DisplayAreaPolicyBuilder.Feature; 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; @@ -100,6 +101,7 @@ public class DisplayAreaPolicyBuilderTest { 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<>(); 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 496b2b744712..d451180c7269 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyTests.java @@ -22,15 +22,18 @@ import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER 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; @@ -38,9 +41,8 @@ import com.android.server.wm.DisplayAreaPolicyBuilderTest.SurfacelessDisplayArea 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; @@ -54,78 +56,65 @@ import java.util.List; */ @SmallTest @Presubmit -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); - } +@RunWith(WindowTestRunner.class) +public class DisplayAreaPolicyTests extends WindowTestsBase { @Test public void testGetDefaultTaskDisplayArea() { - assertEquals(mTaskDisplayArea1, mPolicy.getDefaultTaskDisplayArea()); + final Pair<DisplayAreaPolicy, List<TaskDisplayArea>> result = + createPolicyWith2TaskDisplayAreas(); + final DisplayAreaPolicy policy = result.first; + final TaskDisplayArea taskDisplayArea1 = result.second.get(0); + assertEquals(taskDisplayArea1, policy.getDefaultTaskDisplayArea()); } @Test public void testTaskDisplayArea_taskPositionChanged_updatesTaskDisplayAreaPosition() { - final Task stack1 = mTaskDisplayArea1.createRootTask( + 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( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); - final Task stack2 = mTaskDisplayArea2.createRootTask( + final Task stack2 = taskDisplayArea2.createRootTask( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */); // Initial order - assertTaskDisplayAreasOrder(mPolicy, mTaskDisplayArea1, mTaskDisplayArea2); + assertTaskDisplayAreasOrder(policy, taskDisplayArea1, taskDisplayArea2); // Move stack in tda1 to top stack1.getParent().positionChildAt(POSITION_TOP, stack1, true /* includingParents */); - assertTaskDisplayAreasOrder(mPolicy, mTaskDisplayArea2, mTaskDisplayArea1); + assertTaskDisplayAreasOrder(policy, taskDisplayArea2, taskDisplayArea1); // Move stack in tda2 to top, but not including parents stack2.getParent().positionChildAt(POSITION_TOP, stack2, false /* includingParents */); - assertTaskDisplayAreasOrder(mPolicy, mTaskDisplayArea2, mTaskDisplayArea1); + assertTaskDisplayAreasOrder(policy, taskDisplayArea2, taskDisplayArea1); // Move stack in tda1 to bottom stack1.getParent().positionChildAt(POSITION_BOTTOM, stack1, true /* includingParents */); - assertTaskDisplayAreasOrder(mPolicy, mTaskDisplayArea1, mTaskDisplayArea2); + assertTaskDisplayAreasOrder(policy, taskDisplayArea1, taskDisplayArea2); // Move stack in tda2 to bottom, but not including parents stack2.getParent().positionChildAt(POSITION_BOTTOM, stack2, false /* includingParents */); - assertTaskDisplayAreasOrder(mPolicy, mTaskDisplayArea1, mTaskDisplayArea2); + 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()); } @Test public void testDisplayAreaGroup_taskPositionChanged_updatesDisplayAreaGroupPosition() { - final WindowManagerService wms = mSystemServices.getWindowManagerService(); + final WindowManagerService wms = mWm; final DisplayContent displayContent = mock(DisplayContent.class); doReturn(true).when(displayContent).isTrusted(); final RootDisplayArea root = new SurfacelessDisplayAreaRoot(wms); @@ -203,4 +192,24 @@ public class DisplayAreaPolicyTests { }, 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/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index 2053bfb45884..b451d9f4aaf0 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -62,6 +62,8 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.same; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.times; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; +import static com.android.server.wm.DisplayContent.IME_TARGET_INPUT; +import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_FIXED_TRANSFORM; import static com.android.server.wm.WindowContainer.POSITION_TOP; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL; @@ -168,7 +170,7 @@ public class DisplayContentTests extends WindowTestsBase { final WindowState imeAppTarget = createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget"); - mDisplayContent.mInputMethodTarget = imeAppTarget; + mDisplayContent.setImeLayeringTarget(imeAppTarget); assertForAllWindowsOrder(Arrays.asList( mWallpaperWindow, @@ -187,7 +189,7 @@ public class DisplayContentTests extends WindowTestsBase { @UseTestDisplay(addAllCommonWindows = true) @Test public void testForAllWindows_WithChildWindowImeTarget() throws Exception { - mDisplayContent.mInputMethodTarget = mChildAppWindowAbove; + mDisplayContent.setImeLayeringTarget(mChildAppWindowAbove); assertForAllWindowsOrder(Arrays.asList( mWallpaperWindow, @@ -205,7 +207,7 @@ public class DisplayContentTests extends WindowTestsBase { @UseTestDisplay(addAllCommonWindows = true) @Test public void testForAllWindows_WithStatusBarImeTarget() throws Exception { - mDisplayContent.mInputMethodTarget = mStatusBarWindow; + mDisplayContent.setImeLayeringTarget(mStatusBarWindow); assertForAllWindowsOrder(Arrays.asList( mWallpaperWindow, @@ -223,7 +225,7 @@ public class DisplayContentTests extends WindowTestsBase { @UseTestDisplay(addAllCommonWindows = true) @Test public void testForAllWindows_WithNotificationShadeImeTarget() throws Exception { - mDisplayContent.mInputMethodTarget = mNotificationShadeWindow; + mDisplayContent.setImeLayeringTarget(mNotificationShadeWindow); assertForAllWindowsOrder(Arrays.asList( mWallpaperWindow, @@ -855,15 +857,17 @@ public class DisplayContentTests extends WindowTestsBase { mDisplayContent.setInputMethodWindowLocked(mImeWindow); newDisplay.setInputMethodWindowLocked(null); assertEquals("appWin should be IME target window", - appWin, mDisplayContent.mInputMethodTarget); - assertNull("newDisplay Ime target: ", newDisplay.mInputMethodTarget); + appWin, mDisplayContent.getImeTarget(IME_TARGET_LAYERING)); + assertNull("newDisplay Ime target: ", newDisplay.getImeTarget(IME_TARGET_LAYERING)); // Switch input method window on new display & make sure the input method target also // switched as expected. newDisplay.setInputMethodWindowLocked(mImeWindow); mDisplayContent.setInputMethodWindowLocked(null); - assertEquals("appWin1 should be IME target window", appWin1, newDisplay.mInputMethodTarget); - assertNull("default display Ime target: ", mDisplayContent.mInputMethodTarget); + assertEquals("appWin1 should be IME target window", appWin1, + newDisplay.getImeTarget(IME_TARGET_LAYERING)); + assertNull("default display Ime target: ", + mDisplayContent.getImeTarget(IME_TARGET_LAYERING)); } @Test @@ -937,17 +941,17 @@ public class DisplayContentTests extends WindowTestsBase { @Test public void testComputeImeParent_app() throws Exception { final DisplayContent dc = createNewDisplay(); - dc.mInputMethodTarget = createWindow(null, TYPE_BASE_APPLICATION, "app"); - dc.mInputMethodInputTarget = dc.mInputMethodTarget; - assertEquals(dc.mInputMethodTarget.mActivityRecord.getSurfaceControl(), - dc.computeImeParent()); + dc.setImeLayeringTarget(createWindow(null, TYPE_BASE_APPLICATION, "app")); + dc.setImeInputTarget(dc.getImeTarget(IME_TARGET_LAYERING).getWindow()); + assertEquals(dc.getImeTarget(IME_TARGET_LAYERING).getWindow() + .mActivityRecord.getSurfaceControl(), dc.computeImeParent()); } @Test public void testComputeImeParent_app_notFullscreen() throws Exception { final DisplayContent dc = createNewDisplay(); - dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "app"); - dc.mInputMethodTarget.setWindowingMode( + dc.setImeLayeringTarget(createWindow(null, TYPE_STATUS_BAR, "app")); + dc.getImeTarget(IME_TARGET_LAYERING).getWindow().setWindowingMode( WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); assertEquals(dc.getImeContainer().getParentSurfaceControl(), dc.computeImeParent()); } @@ -957,7 +961,7 @@ public class DisplayContentTests extends WindowTestsBase { public void testComputeImeParent_app_notMatchParentBounds() { spyOn(mAppWindow.mActivityRecord); doReturn(false).when(mAppWindow.mActivityRecord).matchParentBounds(); - mDisplayContent.mInputMethodTarget = mAppWindow; + mDisplayContent.setImeLayeringTarget(mAppWindow); // The surface parent of IME should be the display instead of app window. assertEquals(mDisplayContent.getImeContainer().getParentSurfaceControl(), mDisplayContent.computeImeParent()); @@ -966,7 +970,7 @@ public class DisplayContentTests extends WindowTestsBase { @Test public void testComputeImeParent_noApp() throws Exception { final DisplayContent dc = createNewDisplay(); - dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "statusBar"); + dc.setImeLayeringTarget(createWindow(null, TYPE_STATUS_BAR, "statusBar")); assertEquals(dc.getImeContainer().getParentSurfaceControl(), dc.computeImeParent()); } @@ -976,12 +980,12 @@ public class DisplayContentTests extends WindowTestsBase { WindowState app = createWindow(null, TYPE_BASE_APPLICATION, dc, "app"); - dc.mInputMethodInputTarget = app; + dc.setImeInputTarget(app); assertEquals(app, dc.computeImeControlTarget()); app.removeImmediately(); - assertNull(dc.mInputMethodInputTarget); + assertNull(dc.getImeTarget(IME_TARGET_INPUT)); assertNull(dc.computeImeControlTarget()); } @@ -989,20 +993,21 @@ public class DisplayContentTests extends WindowTestsBase { public void testComputeImeControlTarget() throws Exception { final DisplayContent dc = createNewDisplay(); dc.setRemoteInsetsController(createDisplayWindowInsetsController()); - dc.mInputMethodInputTarget = createWindow(null, TYPE_BASE_APPLICATION, "app"); - dc.mInputMethodTarget = dc.mInputMethodInputTarget; - assertEquals(dc.mInputMethodInputTarget, dc.computeImeControlTarget()); + dc.setImeInputTarget(createWindow(null, TYPE_BASE_APPLICATION, "app")); + dc.setImeLayeringTarget(dc.getImeTarget(IME_TARGET_INPUT).getWindow()); + assertEquals(dc.getImeTarget(IME_TARGET_INPUT).getWindow(), dc.computeImeControlTarget()); } @Test public void testComputeImeControlTarget_splitscreen() throws Exception { final DisplayContent dc = createNewDisplay(); - dc.mInputMethodInputTarget = createWindow(null, TYPE_BASE_APPLICATION, "app"); - dc.mInputMethodInputTarget.setWindowingMode( + dc.setImeInputTarget(createWindow(null, TYPE_BASE_APPLICATION, "app")); + dc.getImeTarget(IME_TARGET_INPUT).getWindow().setWindowingMode( WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); - dc.mInputMethodTarget = dc.mInputMethodInputTarget; + dc.setImeLayeringTarget(dc.getImeTarget(IME_TARGET_INPUT).getWindow()); dc.setRemoteInsetsController(createDisplayWindowInsetsController()); - assertNotEquals(dc.mInputMethodInputTarget, dc.computeImeControlTarget()); + assertNotEquals(dc.getImeTarget(IME_TARGET_INPUT).getWindow(), + dc.computeImeControlTarget()); } @UseTestDisplay(addWindows = W_ACTIVITY) @@ -1010,8 +1015,9 @@ public class DisplayContentTests extends WindowTestsBase { public void testComputeImeControlTarget_notMatchParentBounds() throws Exception { spyOn(mAppWindow.mActivityRecord); doReturn(false).when(mAppWindow.mActivityRecord).matchParentBounds(); - mDisplayContent.mInputMethodInputTarget = mAppWindow; - mDisplayContent.mInputMethodTarget = mDisplayContent.mInputMethodInputTarget; + mDisplayContent.setImeInputTarget(mAppWindow); + mDisplayContent.setImeLayeringTarget( + mDisplayContent.getImeTarget(IME_TARGET_INPUT).getWindow()); mDisplayContent.setRemoteInsetsController(createDisplayWindowInsetsController()); assertEquals(mAppWindow, mDisplayContent.computeImeControlTarget()); } @@ -1637,7 +1643,7 @@ public class DisplayContentTests extends WindowTestsBase { TYPE_BASE_APPLICATION, "nextImeTargetApp"); spyOn(child1); doReturn(true).when(child1).inSplitScreenWindowingMode(); - mDisplayContent.mInputMethodTarget = child1; + mDisplayContent.setImeLayeringTarget(child1); spyOn(nextImeTargetApp); spyOn(mAppWindow); @@ -1648,7 +1654,7 @@ public class DisplayContentTests extends WindowTestsBase { child1.removeImmediately(); verify(mDisplayContent).computeImeTarget(true); - assertNull(mDisplayContent.mInputMethodInputTarget); + assertNull(mDisplayContent.getImeTarget(IME_TARGET_INPUT)); verify(child1, never()).needsRelativeLayeringToIme(); } diff --git a/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java index 59d195b670a8..5f9626711896 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/ImeInsetsSourceProviderTest.java @@ -52,19 +52,19 @@ public class ImeInsetsSourceProviderTest extends WindowTestsBase { public void testTransparentControlTargetWindowCanShowIme() { final WindowState appWin = createWindow(null, TYPE_APPLICATION, "app"); final WindowState popup = createWindow(appWin, TYPE_APPLICATION, "popup"); - mDisplayContent.mInputMethodControlTarget = popup; - mDisplayContent.mInputMethodTarget = appWin; + mDisplayContent.setImeControlTarget(popup); + mDisplayContent.setImeLayeringTarget(appWin); popup.mAttrs.format = PixelFormat.TRANSPARENT; mImeProvider.scheduleShowImePostLayout(appWin); - assertTrue(mImeProvider.isImeTargetFromDisplayContentAndImeSame()); + assertTrue(mImeProvider.isReadyToShowIme()); } @Test public void testInputMethodInputTargetCanShowIme() { WindowState target = createWindow(null, TYPE_APPLICATION, "app"); - mDisplayContent.mInputMethodTarget = target; + mDisplayContent.setImeLayeringTarget(target); mImeProvider.scheduleShowImePostLayout(target); - assertTrue(mImeProvider.isImeTargetFromDisplayContentAndImeSame()); + assertTrue(mImeProvider.isReadyToShowIme()); } @Test @@ -74,8 +74,8 @@ public class ImeInsetsSourceProviderTest extends WindowTestsBase { mImeProvider.setWindow(ime, null, null); WindowState target = createWindow(null, TYPE_APPLICATION, "app"); - mDisplayContent.mInputMethodTarget = target; - mDisplayContent.mInputMethodControlTarget = target; + mDisplayContent.setImeLayeringTarget(target); + mDisplayContent.setImeControlTarget(target); mImeProvider.scheduleShowImePostLayout(target); assertFalse(mImeProvider.isImeShowing()); diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java index 90caf35e2936..276643847712 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java @@ -31,6 +31,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; 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.DisplayContent.IME_TARGET_INPUT; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -181,16 +182,18 @@ public class InsetsStateControllerTest extends WindowTestsBase { // This can be the IME z-order target while app cannot be the IME z-order target. // This is also the only IME control target in this test, so IME won't be invisible caused // by the control-target change. - mDisplayContent.mInputMethodInputTarget = createWindow(null, TYPE_APPLICATION, "base"); + mDisplayContent.updateImeInputAndControlTarget( + createWindow(null, TYPE_APPLICATION, "base")); // Make IME and stay visible during the test. mImeWindow.setHasSurface(true); getController().getSourceProvider(ITYPE_IME).setWindow(mImeWindow, null, null); - getController().onImeControlTargetChanged(mDisplayContent.mInputMethodInputTarget); + getController().onImeControlTargetChanged(mDisplayContent.getImeTarget(IME_TARGET_INPUT)); final InsetsState requestedState = new InsetsState(); requestedState.getSource(ITYPE_IME).setVisible(true); - mDisplayContent.mInputMethodInputTarget.updateRequestedVisibility(requestedState); - getController().onInsetsModified(mDisplayContent.mInputMethodInputTarget); + mDisplayContent.getImeTarget(IME_TARGET_INPUT).getWindow() + .updateRequestedVisibility(requestedState); + getController().onInsetsModified(mDisplayContent.getImeTarget(IME_TARGET_INPUT)); // Send our spy window (app) into the system so that we can detect the invocation. final WindowState win = createWindow(null, TYPE_APPLICATION, "app"); diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java index 9af2b96f3f78..171aa76032db 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java @@ -91,10 +91,9 @@ public class RootWindowContainerTests extends WindowTestsBase { @Test public void testAllPausedActivitiesComplete() { DisplayContent displayContent = mWm.mRoot.getDisplayContent(DEFAULT_DISPLAY); - TaskDisplayArea taskDisplayArea = displayContent.getDefaultTaskDisplayArea(); - Task stack = taskDisplayArea.getRootTaskAt(0); ActivityRecord activity = createActivityRecord(displayContent); - stack.mPausingActivity = activity; + Task task = activity.getTask(); + task.setPausingActivity(activity); activity.setState(PAUSING, "test PAUSING"); assertThat(mWm.mRoot.allPausedActivitiesComplete()).isFalse(); diff --git a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java index 6821d47d5b1a..e2be39b6eb15 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/RunningTasksTest.java @@ -34,6 +34,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import java.util.ArrayList; +import java.util.List; /** * Build/Install/Run: @@ -70,9 +71,12 @@ public class RunningTasksTest extends WindowTestsBase { final int numTasks = 10; int activeTime = 0; + final List<Task> rootTasks = new ArrayList<>(); + display.getDefaultTaskDisplayArea().forAllRootTasks(task -> { + rootTasks.add(task); + }, false /* traverseTopToBottom */); for (int i = 0; i < numTasks; i++) { - createTask(display.getDefaultTaskDisplayArea().getRootTaskAt(i % numStacks), - ".Task" + i, i, activeTime++, null); + createTask(rootTasks.get(i % numStacks), ".Task" + i, i, activeTime++, null); } // Ensure that the latest tasks were returned in order of decreasing last active time, diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java index dd6e490b8282..c7175a0c424d 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java @@ -30,6 +30,7 @@ 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.spyOn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; +import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING; import static com.android.server.wm.Task.ActivityState.STOPPED; import static org.junit.Assert.assertEquals; @@ -270,7 +271,7 @@ public class SizeCompatTests extends WindowTestsBase { // The position should be horizontal centered. assertEquals((displayWidth - bounds.width()) / 2, bounds.left); - mActivity.mDisplayContent.mInputMethodTarget = addWindowToActivity(mActivity); + mActivity.mDisplayContent.setImeLayeringTarget(addWindowToActivity(mActivity)); // Make sure IME cannot attach to the app, otherwise IME window will also be shifted. assertFalse(mActivity.mDisplayContent.isImeAttachedToApp()); @@ -290,9 +291,9 @@ public class SizeCompatTests extends WindowTestsBase { assertFitted(); rotateDisplay(mActivity.mDisplayContent, ROTATION_90); - mActivity.mDisplayContent.mInputMethodTarget = addWindowToActivity(mActivity); - mActivity.mDisplayContent.mInputMethodInputTarget = - mActivity.mDisplayContent.mInputMethodTarget; + mActivity.mDisplayContent.setImeLayeringTarget(addWindowToActivity(mActivity)); + mActivity.mDisplayContent.setImeInputTarget( + mActivity.mDisplayContent.getImeTarget(IME_TARGET_LAYERING).getWindow()); // Because the aspect ratio of display doesn't exceed the max aspect ratio of activity. // The activity should still fill its parent container and IME can attach to the activity. assertTrue(mActivity.matchParentBounds()); diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java index 788ef5ad2ec4..6046c9b2c2b1 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java @@ -20,20 +20,19 @@ import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; +import static com.android.server.wm.utils.CommonUtils.runWithShellPermissionIdentity; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import android.app.Activity; -import android.app.ActivityManager; import android.app.ActivityManager.TaskDescription; import android.app.ActivityOptions; import android.app.ActivityTaskManager; import android.app.ActivityView; -import android.app.IActivityManager; import android.app.ITaskStackListener; -import android.app.Instrumentation; import android.app.Instrumentation.ActivityMonitor; import android.app.TaskStackListener; import android.content.ComponentName; @@ -44,7 +43,6 @@ import android.os.Bundle; import android.os.RemoteException; import android.os.SystemClock; import android.platform.test.annotations.Presubmit; -import android.support.test.uiautomator.UiDevice; import android.text.TextUtils; import android.view.Display; import android.view.ViewGroup; @@ -52,10 +50,7 @@ import android.view.ViewGroup; import androidx.test.filters.FlakyTest; import androidx.test.filters.MediumTest; -import com.android.compatibility.common.util.SystemUtil; - import org.junit.After; -import org.junit.Before; import org.junit.Test; import java.util.concurrent.ArrayBlockingQueue; @@ -70,17 +65,11 @@ import java.util.function.Predicate; @MediumTest public class TaskStackChangedListenerTest { - private IActivityManager mService; private ITaskStackListener mTaskStackListener; private static final int WAIT_TIMEOUT_MS = 5000; private static final Object sLock = new Object(); - @Before - public void setUp() throws Exception { - mService = ActivityManager.getService(); - } - @After public void tearDown() throws Exception { ActivityTaskManager.getService().unregisterTaskStackListener(mTaskStackListener); @@ -374,7 +363,7 @@ public class TaskStackChangedListenerTest { final ActivityMonitor monitor = new ActivityMonitor(activityClass.getName(), null, false); getInstrumentation().addMonitor(monitor); final Context context = getInstrumentation().getContext(); - SystemUtil.runWithShellPermissionIdentity(() -> context.startActivity( + runWithShellPermissionIdentity(() -> context.startActivity( new Intent(context, activityClass).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), options.toBundle())); final TestActivity activity = diff --git a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java index eb5f1f9b9c5f..ccf2394e7f81 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java +++ b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java @@ -372,6 +372,11 @@ class TestWindowManagerPolicy implements WindowManagerPolicy { } @Override + public int applyKeyguardOcclusionChange() { + return 0; + } + + @Override public void setPipVisibilityLw(boolean visible) { } diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java index 4909b1d7629e..00c2aa5ebc63 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java @@ -20,8 +20,8 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN; -import static android.window.TransitionInfo.TRANSIT_HIDE; -import static android.window.TransitionInfo.TRANSIT_OPEN; +import static android.view.WindowManager.TRANSIT_OPEN; +import static android.view.WindowManager.TRANSIT_TO_BACK; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -74,21 +74,22 @@ public class TransitionTests extends WindowTestsBase { closing.mVisibleRequested = false; opening.mVisibleRequested = true; - int transitType = TRANSIT_OLD_TASK_OPEN; + int transit = TRANSIT_OLD_TASK_OPEN; + int flags = 0; // Check basic both tasks participating participants.add(oldTask); participants.add(newTask); ArraySet<WindowContainer> targets = Transition.calculateTargets(participants, changes); - TransitionInfo info = Transition.calculateTransitionInfo(transitType, targets, changes); + TransitionInfo info = Transition.calculateTransitionInfo(transit, flags, targets, changes); assertEquals(2, info.getChanges().size()); - assertEquals(transitType, info.getType()); + assertEquals(transit, info.getType()); // Check that children are pruned participants.add(opening); participants.add(closing); targets = Transition.calculateTargets(participants, changes); - info = Transition.calculateTransitionInfo(transitType, targets, changes); + info = Transition.calculateTransitionInfo(transit, flags, targets, changes); assertEquals(2, info.getChanges().size()); assertNotNull(info.getChange(newTask.mRemoteToken.toWindowContainerToken())); assertNotNull(info.getChange(oldTask.mRemoteToken.toWindowContainerToken())); @@ -96,7 +97,7 @@ public class TransitionTests extends WindowTestsBase { // Check combined prune and promote participants.remove(newTask); targets = Transition.calculateTargets(participants, changes); - info = Transition.calculateTransitionInfo(transitType, targets, changes); + info = Transition.calculateTransitionInfo(transit, flags, targets, changes); assertEquals(2, info.getChanges().size()); assertNotNull(info.getChange(newTask.mRemoteToken.toWindowContainerToken())); assertNotNull(info.getChange(oldTask.mRemoteToken.toWindowContainerToken())); @@ -104,7 +105,7 @@ public class TransitionTests extends WindowTestsBase { // Check multi promote participants.remove(oldTask); targets = Transition.calculateTargets(participants, changes); - info = Transition.calculateTransitionInfo(transitType, targets, changes); + info = Transition.calculateTransitionInfo(transit, flags, targets, changes); assertEquals(2, info.getChanges().size()); assertNotNull(info.getChange(newTask.mRemoteToken.toWindowContainerToken())); assertNotNull(info.getChange(oldTask.mRemoteToken.toWindowContainerToken())); @@ -138,23 +139,24 @@ public class TransitionTests extends WindowTestsBase { opening.mVisibleRequested = true; opening2.mVisibleRequested = true; - int transitType = TRANSIT_OLD_TASK_OPEN; + int transit = TRANSIT_OLD_TASK_OPEN; + int flags = 0; // Check full promotion from leaf participants.add(oldTask); participants.add(opening); participants.add(opening2); ArraySet<WindowContainer> targets = Transition.calculateTargets(participants, changes); - TransitionInfo info = Transition.calculateTransitionInfo(transitType, targets, changes); + TransitionInfo info = Transition.calculateTransitionInfo(transit, flags, targets, changes); assertEquals(2, info.getChanges().size()); - assertEquals(transitType, info.getType()); + assertEquals(transit, info.getType()); assertNotNull(info.getChange(newTask.mRemoteToken.toWindowContainerToken())); assertNotNull(info.getChange(oldTask.mRemoteToken.toWindowContainerToken())); // Check that unchanging but visible descendant of sibling prevents promotion participants.remove(opening2); targets = Transition.calculateTargets(participants, changes); - info = Transition.calculateTransitionInfo(transitType, targets, changes); + info = Transition.calculateTransitionInfo(transit, flags, targets, changes); assertEquals(2, info.getChanges().size()); assertNotNull(info.getChange(newNestedTask.mRemoteToken.toWindowContainerToken())); assertNotNull(info.getChange(oldTask.mRemoteToken.toWindowContainerToken())); @@ -184,29 +186,30 @@ public class TransitionTests extends WindowTestsBase { showing.mVisibleRequested = true; showing2.mVisibleRequested = true; - int transitType = TRANSIT_OLD_TASK_OPEN; + int transit = TRANSIT_OLD_TASK_OPEN; + int flags = 0; // Check promotion to DisplayArea participants.add(showing); participants.add(showing2); ArraySet<WindowContainer> targets = Transition.calculateTargets(participants, changes); - TransitionInfo info = Transition.calculateTransitionInfo(transitType, targets, changes); + TransitionInfo info = Transition.calculateTransitionInfo(transit, flags, targets, changes); assertEquals(1, info.getChanges().size()); - assertEquals(transitType, info.getType()); + assertEquals(transit, info.getType()); assertNotNull(info.getChange(tda.mRemoteToken.toWindowContainerToken())); ITaskOrganizer mockOrg = mock(ITaskOrganizer.class); // Check that organized tasks get reported even if not top showTask.mTaskOrganizer = mockOrg; targets = Transition.calculateTargets(participants, changes); - info = Transition.calculateTransitionInfo(transitType, targets, changes); + info = Transition.calculateTransitionInfo(transit, flags, targets, changes); assertEquals(2, info.getChanges().size()); assertNotNull(info.getChange(tda.mRemoteToken.toWindowContainerToken())); assertNotNull(info.getChange(showTask.mRemoteToken.toWindowContainerToken())); // Even if DisplayArea explicitly participating participants.add(tda); targets = Transition.calculateTargets(participants, changes); - info = Transition.calculateTransitionInfo(transitType, targets, changes); + info = Transition.calculateTransitionInfo(transit, flags, targets, changes); assertEquals(2, info.getChanges().size()); } @@ -231,13 +234,14 @@ public class TransitionTests extends WindowTestsBase { ArraySet<WindowContainer> targets = Transition.calculateTargets( transition.mParticipants, transition.mChanges); - TransitionInfo info = Transition.calculateTransitionInfo(0, targets, transition.mChanges); + TransitionInfo info = Transition.calculateTransitionInfo( + 0, 0, targets, transition.mChanges); assertEquals(2, info.getChanges().size()); // There was an existence change on open, so it should be OPEN rather than SHOW assertEquals(TRANSIT_OPEN, info.getChange(openTask.mRemoteToken.toWindowContainerToken()).getMode()); // No exestence change on closing, so HIDE rather than CLOSE - assertEquals(TRANSIT_HIDE, + assertEquals(TRANSIT_TO_BACK, info.getChange(closeTask.mRemoteToken.toWindowContainerToken()).getMode()); } @@ -267,7 +271,8 @@ public class TransitionTests extends WindowTestsBase { ArraySet<WindowContainer> targets = Transition.calculateTargets( transition.mParticipants, transition.mChanges); - TransitionInfo info = Transition.calculateTransitionInfo(0, targets, transition.mChanges); + TransitionInfo info = Transition.calculateTransitionInfo( + 0, 0, targets, transition.mChanges); assertEquals(taskCount, info.getChanges().size()); // verify order is top-to-bottem for (int i = 0; i < taskCount; ++i) { diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java index 78e873e2b0a3..f13847559aa0 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java @@ -56,7 +56,7 @@ public class WindowContainerTraversalTests extends WindowTestsBase { WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD, TYPE_BASE_APPLICATION, mDisplayContent, "splitScreenSecondaryWindow"); - mDisplayContent.mInputMethodTarget = splitScreenWindow; + mDisplayContent.setImeLayeringTarget(splitScreenWindow); Consumer<WindowState> c = mock(Consumer.class); mDisplayContent.forAllWindows(c, false); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java index d2be50d02ef3..4a6906b88710 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java @@ -292,7 +292,7 @@ public class WindowFrameTests extends WindowTestsBase { // Make IME attach to the window and can produce insets. final DisplayContent dc = mTestDisplayContent; - dc.mInputMethodTarget = w; + dc.setImeLayeringTarget(w); WindowState mockIme = mock(WindowState.class); Mockito.doReturn(true).when(mockIme).isVisibleNow(); dc.mInputMethodWindow = mockIme; 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 f123bc16e52c..3c8268533b6e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java @@ -741,11 +741,10 @@ public class WindowOrganizerTests extends WindowTestsBase { } private List<Task> getTasksCreatedByOrganizer(DisplayContent dc) { - ArrayList<Task> out = new ArrayList<>(); - dc.forAllTaskDisplayAreas(taskDisplayArea -> { - for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { - final Task t = taskDisplayArea.getRootTaskAt(sNdx); - if (t.mCreatedByOrganizer) out.add(t); + final ArrayList<Task> out = new ArrayList<>(); + dc.forAllRootTasks(task -> { + if (task.mCreatedByOrganizer) { + out.add(task); } }); return out; diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java index a57de094a210..76f8207b4ad8 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -789,7 +789,7 @@ public class WindowStateTests extends WindowTestsBase { public void testNeedsRelativeLayeringToIme_notAttached() { WindowState sameTokenWindow = createWindow(null, TYPE_BASE_APPLICATION, mAppWindow.mToken, "SameTokenWindow"); - mDisplayContent.mInputMethodTarget = mAppWindow; + mDisplayContent.setImeLayeringTarget(mAppWindow); sameTokenWindow.mActivityRecord.getStack().setWindowingMode( WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); assertTrue(sameTokenWindow.needsRelativeLayeringToIme()); @@ -802,7 +802,7 @@ public class WindowStateTests extends WindowTestsBase { public void testNeedsRelativeLayeringToIme_startingWindow() { WindowState sameTokenWindow = createWindow(null, TYPE_APPLICATION_STARTING, mAppWindow.mToken, "SameTokenWindow"); - mDisplayContent.mInputMethodTarget = mAppWindow; + mDisplayContent.setImeLayeringTarget(mAppWindow); sameTokenWindow.mActivityRecord.getStack().setWindowingMode( WINDOWING_MODE_SPLIT_SCREEN_PRIMARY); assertFalse(sameTokenWindow.needsRelativeLayeringToIme()); 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 d64b46d925ff..e13a5952ccac 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java @@ -1121,12 +1121,9 @@ class WindowTestsBase extends SystemServiceTestsBase { mService.mTaskOrganizerController.setLaunchRoot(mDisplayId, mSecondary.mRemoteToken.toWindowContainerToken()); DisplayContent dc = mService.mRootWindowContainer.getDisplayContent(mDisplayId); - dc.forAllTaskDisplayAreas(taskDisplayArea -> { - for (int sNdx = taskDisplayArea.getRootTaskCount() - 1; sNdx >= 0; --sNdx) { - final Task stack = taskDisplayArea.getRootTaskAt(sNdx); - if (!WindowConfiguration.isSplitScreenWindowingMode(stack.getWindowingMode())) { - stack.reparent(mSecondary, POSITION_BOTTOM); - } + dc.forAllRootTasks(stack -> { + if (!WindowConfiguration.isSplitScreenWindowingMode(stack.getWindowingMode())) { + stack.reparent(mSecondary, POSITION_BOTTOM); } }); } diff --git a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java index e44d47a59fe5..811a14666db9 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java @@ -218,7 +218,7 @@ public class ZOrderingTests extends WindowTestsBase { @Test public void testAssignWindowLayers_ForImeWithNoTarget() { - mDisplayContent.mInputMethodTarget = null; + mDisplayContent.setImeLayeringTarget(null); mDisplayContent.assignChildLayers(mTransaction); // The Ime has an higher base layer than app windows and lower base layer than system @@ -236,7 +236,7 @@ public class ZOrderingTests extends WindowTestsBase { @Test public void testAssignWindowLayers_ForImeWithAppTarget() { final WindowState imeAppTarget = createWindow("imeAppTarget"); - mDisplayContent.mInputMethodTarget = imeAppTarget; + mDisplayContent.setImeLayeringTarget(imeAppTarget); mDisplayContent.assignChildLayers(mTransaction); @@ -262,7 +262,7 @@ public class ZOrderingTests extends WindowTestsBase { TYPE_APPLICATION_MEDIA_OVERLAY, imeAppTarget.mToken, "imeAppTargetChildBelowWindow"); - mDisplayContent.mInputMethodTarget = imeAppTarget; + mDisplayContent.setImeLayeringTarget(imeAppTarget); mDisplayContent.assignChildLayers(mTransaction); // Ime should be above all app windows except for child windows that are z-ordered above it @@ -284,7 +284,7 @@ public class ZOrderingTests extends WindowTestsBase { final WindowState imeAppTarget = createWindow("imeAppTarget"); final WindowState appAboveImeTarget = createWindow("appAboveImeTarget"); - mDisplayContent.mInputMethodTarget = imeAppTarget; + mDisplayContent.setImeLayeringTarget(imeAppTarget); mDisplayContent.assignChildLayers(mTransaction); // Ime should be above all app windows except for non-fullscreen app window above it and @@ -307,7 +307,7 @@ public class ZOrderingTests extends WindowTestsBase { mDisplayContent, "imeSystemOverlayTarget", true /* ownerCanAddInternalSystemWindow */); - mDisplayContent.mInputMethodTarget = imeSystemOverlayTarget; + mDisplayContent.setImeLayeringTarget(imeSystemOverlayTarget); mDisplayContent.assignChildLayers(mTransaction); // The IME target base layer is higher than all window except for the nav bar window, so the @@ -330,7 +330,7 @@ public class ZOrderingTests extends WindowTestsBase { @Test public void testAssignWindowLayers_ForStatusBarImeTarget() { - mDisplayContent.mInputMethodTarget = mStatusBarWindow; + mDisplayContent.setImeLayeringTarget(mStatusBarWindow); mDisplayContent.assignChildLayers(mTransaction); assertWindowHigher(mImeWindow, mChildAppWindowAbove); diff --git a/services/tests/wmtests/src/com/android/server/wm/utils/CommonUtils.java b/services/tests/wmtests/src/com/android/server/wm/utils/CommonUtils.java new file mode 100644 index 000000000000..99d73cf5f7d3 --- /dev/null +++ b/services/tests/wmtests/src/com/android/server/wm/utils/CommonUtils.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wm.utils; + +import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; + +import android.app.UiAutomation; + +/** Provides common utility functions. */ +public class CommonUtils { + public static UiAutomation getUiAutomation() { + return getInstrumentation().getUiAutomation(); + } + + public static void runWithShellPermissionIdentity(Runnable runnable) { + getUiAutomation().adoptShellPermissionIdentity(); + try { + runnable.run(); + } finally { + getUiAutomation().dropShellPermissionIdentity(); + } + } +} diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index aa36e47a359b..3815326b6886 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -184,10 +184,12 @@ public class UsageStatsService extends SystemService implements private static class ActivityData { private final String mTaskRootPackage; private final String mTaskRootClass; + private final String mUsageSourcePackage; public int lastEvent = Event.NONE; - private ActivityData(String taskRootPackage, String taskRootClass) { + private ActivityData(String taskRootPackage, String taskRootClass, String sourcePackage) { mTaskRootPackage = taskRootPackage; mTaskRootClass = taskRootClass; + mUsageSourcePackage = sourcePackage; } } @@ -840,23 +842,25 @@ public class UsageStatsService extends SystemService implements .APP_USAGE_EVENT_OCCURRED__EVENT_TYPE__MOVE_TO_FOREGROUND); // check if this activity has already been resumed if (mVisibleActivities.get(event.mInstanceId) != null) break; - final ActivityData resumedData = new ActivityData(event.mTaskRootPackage, - event.mTaskRootClass); - resumedData.lastEvent = Event.ACTIVITY_RESUMED; - mVisibleActivities.put(event.mInstanceId, resumedData); + final String usageSourcePackage; + switch(mUsageSource) { + case USAGE_SOURCE_CURRENT_ACTIVITY: + usageSourcePackage = event.mPackage; + break; + case USAGE_SOURCE_TASK_ROOT_ACTIVITY: + default: + usageSourcePackage = event.mTaskRootPackage; + break; + } try { - switch(mUsageSource) { - case USAGE_SOURCE_CURRENT_ACTIVITY: - mAppTimeLimit.noteUsageStart(event.mPackage, userId); - break; - case USAGE_SOURCE_TASK_ROOT_ACTIVITY: - default: - mAppTimeLimit.noteUsageStart(event.mTaskRootPackage, userId); - break; - } + mAppTimeLimit.noteUsageStart(usageSourcePackage, userId); } catch (IllegalArgumentException iae) { Slog.e(TAG, "Failed to note usage start", iae); } + final ActivityData resumedData = new ActivityData(event.mTaskRootPackage, + event.mTaskRootClass, usageSourcePackage); + resumedData.lastEvent = Event.ACTIVITY_RESUMED; + mVisibleActivities.put(event.mInstanceId, resumedData); break; case Event.ACTIVITY_PAUSED: final ActivityData pausedData = mVisibleActivities.get(event.mInstanceId); @@ -928,15 +932,7 @@ public class UsageStatsService extends SystemService implements event.mTaskRootClass = prevData.mTaskRootClass; } try { - switch(mUsageSource) { - case USAGE_SOURCE_CURRENT_ACTIVITY: - mAppTimeLimit.noteUsageStop(event.mPackage, userId); - break; - case USAGE_SOURCE_TASK_ROOT_ACTIVITY: - default: - mAppTimeLimit.noteUsageStop(event.mTaskRootPackage, userId); - break; - } + mAppTimeLimit.noteUsageStop(prevData.mUsageSourcePackage, userId); } catch (IllegalArgumentException iae) { Slog.w(TAG, "Failed to note usage stop", iae); } diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/OWNERS b/services/voiceinteraction/java/com/android/server/soundtrigger/OWNERS new file mode 100644 index 000000000000..e5d037003ac4 --- /dev/null +++ b/services/voiceinteraction/java/com/android/server/soundtrigger/OWNERS @@ -0,0 +1,2 @@ +ytai@google.com +elaurent@google.com diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java index 4bf93a26ec03..283fae563ea3 100644 --- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java +++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java @@ -1038,6 +1038,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { if (mModule != null) { mModule.detach(); mModule = null; + mServiceDisabled = false; } } } diff --git a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java index 76291631b37d..8531b507a92f 100644 --- a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java +++ b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java @@ -26,7 +26,7 @@ import android.os.Build; import android.os.CarrierAssociatedAppEntry; import android.os.SystemConfigManager; import android.os.UserHandle; -import android.permission.PermissionManager; +import android.permission.LegacyPermissionManager; import android.provider.Settings; import android.telephony.TelephonyManager; import android.util.ArrayMap; @@ -141,8 +141,8 @@ public final class CarrierAppUtils { Map<String, List<CarrierAssociatedAppEntry>> systemCarrierAssociatedAppsDisabledUntilUsed, Context context) { PackageManager packageManager = context.getPackageManager(); - PermissionManager permissionManager = - (PermissionManager) context.getSystemService(Context.PERMISSION_SERVICE); + LegacyPermissionManager permissionManager = (LegacyPermissionManager) + context.getSystemService(Context.LEGACY_PERMISSION_SERVICE); List<ApplicationInfo> candidates = getDefaultCarrierAppCandidatesHelper( userId, systemCarrierAppsDisabledUntilUsed, context); if (candidates == null || candidates.isEmpty()) { diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java index 4bb7cc47d702..556df885dec3 100644 --- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java +++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java @@ -27,7 +27,7 @@ import android.os.Binder; import android.os.Build; import android.os.Process; import android.os.UserHandle; -import android.permission.PermissionManager; +import android.permission.LegacyPermissionManager; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.util.Log; @@ -327,8 +327,8 @@ public final class TelephonyPermissions { return true; } - PermissionManager permissionManager = (PermissionManager) context.getSystemService( - Context.PERMISSION_SERVICE); + LegacyPermissionManager permissionManager = (LegacyPermissionManager) + context.getSystemService(Context.LEGACY_PERMISSION_SERVICE); if (permissionManager.checkDeviceIdentifierAccess(callingPackage, message, callingFeatureId, pid, uid) == PackageManager.PERMISSION_GRANTED) { return true; diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java index 8b7a243c30e6..d502da9fb9ec 100644 --- a/telephony/java/android/telephony/DataFailCause.java +++ b/telephony/java/android/telephony/DataFailCause.java @@ -916,6 +916,84 @@ public final class DataFailCause { /** System preference change back to SRAT during handoff */ public static final int HANDOFF_PREFERENCE_CHANGED = 0x8CB; + //IKE error notifications message as specified in 3GPP TS 24.302 (Section 8.1.2.2). + + /** The PDN connection corresponding to the requested APN has been rejected. */ + public static final int IWLAN_PDN_CONNECTION_REJECTION = 0x2000; + /** + * The PDN connection has been rejected. No additional PDN connections can be established + * for the UE due to the network policies or capabilities. + */ + public static final int IWLAN_MAX_CONNECTION_REACHED = 0x2001; + /** + * The PDN connection has been rejected due to a semantic error in TFT operation. + */ + public static final int IWLAN_SEMANTIC_ERROR_IN_THE_TFT_OPERATION = 0x2031; + /** + * The PDN connection has been rejected due to a syntactic error in TFT operation. + */ + public static final int IWLAN_SYNTACTICAL_ERROR_IN_THE_TFT_OPERATION = 0x2032; + /** + * The PDN connection has been rejected due to sematic errors in the packet filter. + */ + public static final int IWLAN_SEMANTIC_ERRORS_IN_PACKET_FILTERS = 0x2034; + /** + * The PDN connection has been rejected due to syntactic errors in the packet filter. + */ + public static final int IWLAN_SYNTACTICAL_ERRORS_IN_PACKET_FILTERS = 0x2035; + /** + * No non-3GPP subscription is associated with the IMSI. + * The UE is not allowed to use non-3GPP access to EPC. + */ + public static final int IWLAN_NON_3GPP_ACCESS_TO_EPC_NOT_ALLOWED = 0x2328; + /** The user identified by the IMSI is unknown. */ + public static final int IWLAN_USER_UNKNOWN = 0x2329; + /** + * The requested APN is not included in the user's profile, + * and therefore is not authorized for that user. + */ + public static final int IWLAN_NO_APN_SUBSCRIPTION = 0x232A; + /** The user is barred from using the non-3GPP access or the subscribed APN. */ + public static final int IWLAN_AUTHORIZATION_REJECTED = 0x232B; + /** The Mobile Equipment used is not acceptable to the network */ + public static final int IWLAN_ILLEGAL_ME = 0x232E; + /** + * The network has determined that the requested procedure cannot be completed successfully + * due to network failure. + */ + public static final int IWLAN_NETWORK_FAILURE = 0x2904; + /** The access type is restricted to the user. */ + public static final int IWLAN_RAT_TYPE_NOT_ALLOWED = 0x2AF9; + /** The network does not accept emergency PDN bringup request using an IMEI */ + public static final int IWLAN_IMEI_NOT_ACCEPTED = 0x2AFD; + /** + * The ePDG performs PLMN filtering (based on roaming agreements) and rejects + * the request from the UE. + * The UE requests service in a PLMN where the UE is not allowed to operate. + */ + public static final int IWLAN_PLMN_NOT_ALLOWED = 0x2B03; + /** The ePDG does not support un-authenticated IMSI based emergency PDN bringup **/ + public static final int IWLAN_UNAUTHENTICATED_EMERGENCY_NOT_SUPPORTED = 0x2B2F; + + // Device is unable to establish an IPSec tunnel with the ePDG for any reason + // e.g authentication fail or certificate validation or DNS Resolution and timeout failure. + + /** IKE configuration error resulting in failure */ + public static final int IWLAN_IKEV2_CONFIG_FAILURE = 0x4000; + /** + * Sent in the response to an IKE_AUTH message when, for some reason, + * the authentication failed. + */ + public static final int IWLAN_IKEV2_AUTH_FAILURE = 0x4001; + /** 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; + /** Unable to resolve FQDN for the ePDG to an IP address */ + public static final int IWLAN_DNS_RESOLUTION_NAME_FAILURE = 0x4004; + /** No response received from the DNS Server due to a timeout*/ + public static final int IWLAN_DNS_RESOLUTION_TIMEOUT = 0x4005; + // OEM sepecific error codes. To be used by OEMs when they don't // want to reveal error code which would be replaced by ERROR_UNSPECIFIED public static final int OEM_DCFAILCAUSE_1 = 0x1001; @@ -1341,6 +1419,34 @@ public final class DataFailCause { 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(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, + "IWLAN_SEMANTIC_ERROR_IN_THE_TFT_OPERATION"); + sFailCauseMap.put(IWLAN_SYNTACTICAL_ERROR_IN_THE_TFT_OPERATION, + "IWLAN_SYNTACTICAL_ERROR_IN_THE_TFT_OPERATION"); + sFailCauseMap.put(IWLAN_SEMANTIC_ERRORS_IN_PACKET_FILTERS, + "IWLAN_SEMANTIC_ERRORS_IN_PACKET_FILTERS"); + sFailCauseMap.put(IWLAN_SYNTACTICAL_ERRORS_IN_PACKET_FILTERS, + "IWLAN_SYNTACTICAL_ERRORS_IN_PACKET_FILTERS"); + sFailCauseMap.put(IWLAN_NON_3GPP_ACCESS_TO_EPC_NOT_ALLOWED, + "IWLAN_NON_3GPP_ACCESS_TO_EPC_NOT_ALLOWED"); + sFailCauseMap.put(IWLAN_USER_UNKNOWN, "IWLAN_USER_UNKNOWN"); + sFailCauseMap.put(IWLAN_NO_APN_SUBSCRIPTION, "IWLAN_NO_APN_SUBSCRIPTION"); + sFailCauseMap.put(IWLAN_AUTHORIZATION_REJECTED, "IWLAN_AUTHORIZATION_REJECTED"); + sFailCauseMap.put(IWLAN_ILLEGAL_ME, "IWLAN_ILLEGAL_ME"); + sFailCauseMap.put(IWLAN_NETWORK_FAILURE, "IWLAN_NETWORK_FAILURE"); + sFailCauseMap.put(IWLAN_RAT_TYPE_NOT_ALLOWED, "IWLAN_RAT_TYPE_NOT_ALLOWED"); + sFailCauseMap.put(IWLAN_IMEI_NOT_ACCEPTED, "IWLAN_IMEI_NOT_ACCEPTED"); + sFailCauseMap.put(IWLAN_PLMN_NOT_ALLOWED, "IWLAN_PLMN_NOT_ALLOWED"); + sFailCauseMap.put(IWLAN_UNAUTHENTICATED_EMERGENCY_NOT_SUPPORTED, + "IWLAN_UNAUTHENTICATED_EMERGENCY_NOT_SUPPORTED"); + sFailCauseMap.put(IWLAN_IKEV2_CONFIG_FAILURE, "IWLAN_IKEV2_CONFIG_FAILURE"); + sFailCauseMap.put(IWLAN_IKEV2_AUTH_FAILURE, "IWLAN_IKEV2_AUTH_FAILURE"); + sFailCauseMap.put(IWLAN_IKEV2_MSG_TIMEOUT, "IWLAN_IKEV2_MSG_TIMEOUT"); + sFailCauseMap.put(IWLAN_IKEV2_CERT_INVALID, "IWLAN_IKEV2_CERT_INVALID"); + sFailCauseMap.put(IWLAN_DNS_RESOLUTION_NAME_FAILURE, "IWLAN_DNS_RESOLUTION_NAME_FAILURE"); + sFailCauseMap.put(IWLAN_DNS_RESOLUTION_TIMEOUT, "IWLAN_DNS_RESOLUTION_TIMEOUT"); sFailCauseMap.put(OEM_DCFAILCAUSE_1, "OEM_DCFAILCAUSE_1"); sFailCauseMap.put(OEM_DCFAILCAUSE_2, "OEM_DCFAILCAUSE_2"); sFailCauseMap.put(OEM_DCFAILCAUSE_3, "OEM_DCFAILCAUSE_3"); diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index b48df717e56c..31a12493b33c 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -23,6 +23,7 @@ import static android.provider.Telephony.Carriers.INVALID_APN_ID; import static com.android.internal.util.Preconditions.checkNotNull; import android.Manifest; +import android.annotation.BytesLong; import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.LongDef; @@ -126,7 +127,6 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Objects; -import java.util.Set; import java.util.UUID; import java.util.concurrent.Executor; import java.util.function.Consumer; @@ -551,6 +551,21 @@ public class TelephonyManager { return getPhoneCount() > 1; } + private static final int MAXIMUM_CALL_COMPOSER_PICTURE_SIZE = 80000; + + // TODO(hallliu): link to upload method in docs + /** + * Indicates the maximum size of the call composure picture. + * + * Pictures sent via uploadCallComposerPicture must not exceed this size, or an + * {@link IllegalArgumentException} will be thrown. + * + * @return Maximum file size in bytes. + */ + public static @BytesLong long getMaximumCallComposerPictureSize() { + return MAXIMUM_CALL_COMPOSER_PICTURE_SIZE; + } + // // Broadcast Intent actions // @@ -1501,6 +1516,16 @@ public class TelephonyManager { public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL = 4; /** + * Used as an int value for {@link #EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE} + * to indicate that default subscription for data/sms/voice is now determined, that + * it should dismiss any dialog or pop-ups that is asking user to select default sub. + * This is used when, for example, opportunistic subscription is configured. At that + * time the primary becomes default sub there's no need to ask user to select anymore. + * @hide + */ + public static final int EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DISMISS = 5; + + /** * Integer intent extra to be used with {@link #ACTION_PRIMARY_SUBSCRIPTION_LIST_CHANGED} * to indicate if the SIM combination in DSDS has limitation or compatible issue. * e.g. two CDMA SIMs may disrupt each other's voice call in certain scenarios. diff --git a/telephony/java/android/telephony/data/ApnThrottleStatus.java b/telephony/java/android/telephony/data/ApnThrottleStatus.java index 51461d17690a..eec140869466 100644 --- a/telephony/java/android/telephony/data/ApnThrottleStatus.java +++ b/telephony/java/android/telephony/data/ApnThrottleStatus.java @@ -261,6 +261,10 @@ public final class ApnThrottleStatus implements Parcelable { private long mThrottleExpiryTimeMillis; private @RetryType int mRetryType; private @ThrottleType int mThrottleType; + + /** + * @hide + */ public static final long NO_THROTTLE_EXPIRY_TIME = DataCallResponse.RETRY_DURATION_UNDEFINED; diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java index 090c970c2b53..556f2d5bdbef 100644 --- a/telephony/java/android/telephony/data/DataCallResponse.java +++ b/telephony/java/android/telephony/data/DataCallResponse.java @@ -253,7 +253,9 @@ public final class DataCallResponse implements Parcelable { public int getCause() { return mCause; } /** - * @return The suggested data retry time in milliseconds. + * @return The suggested data retry time in milliseconds. 0 when network does not + * suggest a retry time (Note this is different from the replacement + * {@link #getRetryDurationMillis()}). * * @deprecated Use {@link #getRetryDurationMillis()} instead. */ diff --git a/telephony/java/android/telephony/ims/DelegateRegistrationState.java b/telephony/java/android/telephony/ims/DelegateRegistrationState.java index 3558a9b79ce0..66281edc0de1 100644 --- a/telephony/java/android/telephony/ims/DelegateRegistrationState.java +++ b/telephony/java/android/telephony/ims/DelegateRegistrationState.java @@ -62,7 +62,8 @@ public final class DelegateRegistrationState implements Parcelable { /** * This feature tag is being deregistered because the PDN that the IMS registration is on is *changing. - * All open SIP dialogs need to be closed before the PDN change can proceed. + * All open SIP dialogs need to be closed before the PDN change can proceed using + * {@link SipDelegateConnection#closeDialog(String)}. */ public static final int DEREGISTERING_REASON_PDN_CHANGE = 3; @@ -73,7 +74,8 @@ public final class DelegateRegistrationState implements Parcelable { * a user triggered hange, such as data being enabled/disabled. * <p> * All open SIP dialogs associated with the new deprovisioned feature tag need to be closed - * before the IMS registration modification can proceed. + * using {@link SipDelegateConnection#closeDialog(String)} before the IMS registration + * modification can proceed. */ public static final int DEREGISTERING_REASON_PROVISIONING_CHANGE = 4; @@ -81,8 +83,8 @@ public final class DelegateRegistrationState implements Parcelable { * This feature tag is deregistering because the SipDelegate associated with this feature tag * needs to change its supported feature set. * <p> - * All open SIP Dialogs associated with this feature tag must be closed before this operation - * can proceed. + * All open SIP Dialogs associated with this feature tag must be closed + * using {@link SipDelegateConnection#closeDialog(String)} before this operation can proceed. */ public static final int DEREGISTERING_REASON_FEATURE_TAGS_CHANGING = 5; @@ -90,8 +92,8 @@ public final class DelegateRegistrationState implements Parcelable { * This feature tag is deregistering because the SipDelegate is in the process of being * destroyed. * <p> - * All open SIP Dialogs associated with this feature tag must be closed before this operation - * can proceed. + * All open SIP Dialogs associated with this feature tag must be closed + * using {@link SipDelegateConnection#closeDialog(String)} before this operation can proceed. */ public static final int DEREGISTERING_REASON_DESTROY_PENDING = 6; diff --git a/telephony/java/android/telephony/ims/SipDelegateConnection.java b/telephony/java/android/telephony/ims/SipDelegateConnection.java index c3cc1edf590b..04a772cd873d 100644 --- a/telephony/java/android/telephony/ims/SipDelegateConnection.java +++ b/telephony/java/android/telephony/ims/SipDelegateConnection.java @@ -62,6 +62,22 @@ public interface SipDelegateConnection { void notifyMessageReceived(@NonNull String viaTransactionId); /** + * The SIP Dialog associated with the provided Call-ID is being closed and routing resources + * associated with the SIP dialog are free to be released. + * <p> + * Calling this method is also mandatory for situations where the framework IMS stack is waiting + * for pending SIP dialogs to be closed before it can perform a handover or apply a provisioning + * change. See {@link DelegateRegistrationState} for more information about + * the scenarios where this can occur. + * <p> + * This method will need to be called for each SIP dialog managed by this application when it is + * closed. + * @param callId The call-ID header value associated with the ongoing SIP Dialog that is + * closing. + */ + void closeDialog(@NonNull String callId); + + /** * Notify the SIP delegate that the SIP message has been received from * {@link DelegateMessageCallback#onMessageReceived(SipMessage)}, however there was an error * processing it. diff --git a/telephony/java/android/telephony/ims/aidl/ISipDelegate.aidl b/telephony/java/android/telephony/ims/aidl/ISipDelegate.aidl index 5d6766a65155..ad75be439da8 100644 --- a/telephony/java/android/telephony/ims/aidl/ISipDelegate.aidl +++ b/telephony/java/android/telephony/ims/aidl/ISipDelegate.aidl @@ -26,7 +26,5 @@ oneway interface ISipDelegate { void sendMessage(in SipMessage sipMessage, long configVersion); void notifyMessageReceived(in String viaTransactionId); void notifyMessageReceiveError(in String viaTransactionId, int reason); - - // only used by SipDelegate. void closeDialog(in String callId); } diff --git a/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java index 29ba8e2d50c4..a35039bd7668 100644 --- a/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java +++ b/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java @@ -199,6 +199,19 @@ public class SipDelegateConnectionAidlWrapper implements SipDelegateConnection, } } + @Override + public void closeDialog(String callId) { + try { + ISipDelegate conn = getSipDelegateBinder(); + if (conn == null) { + return; + } + conn.closeDialog(callId); + } catch (RemoteException e) { + // Nothing to do here, app will eventually get remote death callback. + } + } + // Also called upon IImsRcsController death (telephony process dies). @Override public void binderDied() { diff --git a/telephony/java/android/telephony/ims/stub/SipDelegate.java b/telephony/java/android/telephony/ims/stub/SipDelegate.java index d7e7b62dd550..b036b5e71125 100644 --- a/telephony/java/android/telephony/ims/stub/SipDelegate.java +++ b/telephony/java/android/telephony/ims/stub/SipDelegate.java @@ -19,7 +19,9 @@ package android.telephony.ims.stub; import android.annotation.NonNull; import android.annotation.SystemApi; import android.telephony.ims.DelegateMessageCallback; +import android.telephony.ims.DelegateRegistrationState; import android.telephony.ims.ImsService; +import android.telephony.ims.SipDelegateConnection; import android.telephony.ims.SipDelegateImsConfiguration; import android.telephony.ims.SipDelegateManager; import android.telephony.ims.SipMessage; @@ -65,10 +67,13 @@ public interface SipDelegate { * The framework is requesting that routing resources associated with the SIP dialog using the * provided Call-ID to be cleaned up. * <p> - * Typically a SIP Dialog close event will be signalled by that dialog receiving a BYE or 200 OK - * message, however, in some cases, the framework will request that the ImsService close the + * Typically, a SIP Dialog close event will be signalled by that dialog receiving a BYE or + * 200 OK message, however, the IMS application will still call + * {@link SipDelegateConnection#closeDialog(String)} to signal to the framework that resources + * can be released. In some cases, the framework will request that the ImsService close the * dialog due to the open dialog holding up an event such as applying a provisioning change or - * handing over to another transport type. + * handing over to another transport type. See {@link DelegateRegistrationState}. + * * @param callId The call-ID header value associated with the ongoing SIP Dialog that the * framework is requesting be closed. */ diff --git a/test-mock/src/android/test/mock/OWNERS b/test-mock/src/android/test/mock/OWNERS new file mode 100644 index 000000000000..36d9cb2654bb --- /dev/null +++ b/test-mock/src/android/test/mock/OWNERS @@ -0,0 +1 @@ +set noparent diff --git a/tests/Compatibility/Android.bp b/tests/Compatibility/Android.bp index 7dc44fa4a260..c14e705b09ab 100644 --- a/tests/Compatibility/Android.bp +++ b/tests/Compatibility/Android.bp @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -android_test { +android_test_helper_app { name: "AppCompatibilityTest", static_libs: ["androidx.test.rules"], // Include all test java files. diff --git a/tests/FlickerTests/OWNERS b/tests/FlickerTests/OWNERS index 0862c05e0ee4..f35a318acbf7 100644 --- a/tests/FlickerTests/OWNERS +++ b/tests/FlickerTests/OWNERS @@ -1 +1,2 @@ include /services/core/java/com/android/server/wm/OWNERS +natanieljr@google.com
\ No newline at end of file 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 bb03237ca4c6..bd7e8d7683d1 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt @@ -48,11 +48,12 @@ fun WmAssertion.navBarWindowIsAlwaysVisible( } fun WmAssertion.visibleWindowsShownMoreThanOneConsecutiveEntry( + ignoreWindows: List<String> = emptyList(), bugId: Int = 0, enabled: Boolean = bugId == 0 ) { - all("visibleWindowShownMoreThanOneConsecutiveEntry", bugId, enabled) { - this.visibleWindowsShownMoreThanOneConsecutiveEntry() + all("visibleWindowsShownMoreThanOneConsecutiveEntry", bugId, enabled) { + this.visibleWindowsShownMoreThanOneConsecutiveEntry(ignoreWindows) } } @@ -204,11 +205,12 @@ fun LayersAssertion.statusBarLayerRotatesScales( } fun LayersAssertion.visibleLayersShownMoreThanOneConsecutiveEntry( + ignoreLayers: List<String> = emptyList(), bugId: Int = 0, enabled: Boolean = bugId == 0 ) { all("visibleLayersShownMoreThanOneConsecutiveEntry", bugId, enabled) { - this.visibleLayersShownMoreThanOneConsecutiveEntry() + this.visibleLayersShownMoreThanOneConsecutiveEntry(ignoreLayers) } } diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt index f4de36e99952..3565ca40474e 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt @@ -22,6 +22,7 @@ import android.support.test.launcherhelper.LauncherStrategyFactory import androidx.test.uiautomator.By import androidx.test.uiautomator.UiDevice import androidx.test.uiautomator.Until +import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper import org.junit.Assert open class ImeAppHelper( @@ -38,7 +39,7 @@ open class ImeAppHelper( 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 (!device.waitForIME()) { + if (!WindowManagerStateHelper().waitImeWindowShown()) { Assert.fail("IME did not appear") } } @@ -46,6 +47,8 @@ open class ImeAppHelper( open fun closeIME(device: UiDevice) { device.pressBack() // Using only the AccessibilityInfo it is not possible to identify if the IME is active - device.waitForIdle(1000) + if (!WindowManagerStateHelper().waitImeWindowGone()) { + Assert.fail("IME did not close") + } } }
\ No newline at end of file diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt index a73264d304f8..b341e621d9ed 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt @@ -27,6 +27,8 @@ import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper 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.visibleWindowsShownMoreThanOneConsecutiveEntry +import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible import com.android.server.wm.flicker.navBarLayerRotatesAndScales import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible @@ -66,8 +68,10 @@ class CloseImeAutoOpenWindowToAppTest( withTag { buildTestTag("imeToAppAutoOpen", testApp, configuration) } repeat { configuration.repetitions } setup { - eachRun { + test { device.wakeUpAndGoToHomeScreen() + } + eachRun { this.setRotation(configuration.startRotation) testApp.open() testApp.openIME(device) @@ -80,14 +84,15 @@ class CloseImeAutoOpenWindowToAppTest( } } transitions { - device.pressBack() - device.waitForIdle() + testApp.closeIME(device) } assertions { windowManagerTrace { navBarWindowIsAlwaysVisible() statusBarWindowIsAlwaysVisible() - imeAppWindowIsAlwaysVisible(testApp, bugId = 141458352) + visibleWindowsShownMoreThanOneConsecutiveEntry(listOf("InputMethod")) + + imeAppWindowIsAlwaysVisible(testApp) } layersTrace { @@ -96,8 +101,10 @@ class CloseImeAutoOpenWindowToAppTest( noUncoveredRegions(configuration.startRotation) navBarLayerRotatesAndScales(configuration.startRotation) statusBarLayerRotatesScales(configuration.startRotation) + visibleLayersShownMoreThanOneConsecutiveEntry() + imeLayerBecomesInvisible(bugId = 141458352) - imeAppLayerIsAlwaysVisible(testApp, bugId = 141458352) + imeAppLayerIsAlwaysVisible(testApp) } } } diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt index 6cc2e2236127..51a4ca86681b 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt @@ -27,6 +27,8 @@ import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper 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.visibleWindowsShownMoreThanOneConsecutiveEntry +import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible import com.android.server.wm.flicker.navBarLayerRotatesAndScales import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible @@ -68,8 +70,10 @@ class CloseImeAutoOpenWindowToHomeTest( } repeat { configuration.repetitions } setup { - eachRun { + test { device.wakeUpAndGoToHomeScreen() + } + eachRun { this.setRotation(configuration.startRotation) testApp.open() testApp.openIME(device) @@ -89,6 +93,8 @@ class CloseImeAutoOpenWindowToHomeTest( windowManagerTrace { navBarWindowIsAlwaysVisible() statusBarWindowIsAlwaysVisible() + visibleWindowsShownMoreThanOneConsecutiveEntry(listOf(IME_WINDOW_TITLE)) + imeWindowBecomesInvisible(bugId = 141458352) imeAppWindowBecomesInvisible(testApp, bugId = 157449248) } @@ -100,10 +106,14 @@ class CloseImeAutoOpenWindowToHomeTest( Surface.ROTATION_0, bugId = 140855415) statusBarLayerRotatesScales(configuration.startRotation, Surface.ROTATION_0) - navBarLayerIsAlwaysVisible(enabled = false) - statusBarLayerIsAlwaysVisible(enabled = false) + navBarLayerIsAlwaysVisible( + enabled = Surface.ROTATION_0 == configuration.startRotation) + statusBarLayerIsAlwaysVisible( + enabled = Surface.ROTATION_0 == configuration.startRotation) + visibleLayersShownMoreThanOneConsecutiveEntry(listOf(IME_WINDOW_TITLE)) + imeLayerBecomesInvisible(bugId = 141458352) - imeAppLayerBecomesInvisible(testApp, bugId = 153739621) + imeAppLayerBecomesInvisible(testApp) } } } diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt index 136cf86037a1..663d45607f93 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt @@ -31,6 +31,8 @@ import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible import com.android.server.wm.flicker.navBarLayerRotatesAndScales import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible import com.android.server.wm.flicker.noUncoveredRegions +import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry +import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry import com.android.server.wm.flicker.repetitions import com.android.server.wm.flicker.startRotation import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible @@ -65,8 +67,10 @@ class CloseImeWindowToAppTest( withTestName { buildTestTag("imeToApp", testApp, configuration) } repeat { configuration.repetitions } setup { - eachRun { + test { device.wakeUpAndGoToHomeScreen() + } + eachRun { this.setRotation(configuration.startRotation) testApp.open() testApp.openIME(device) @@ -79,13 +83,14 @@ class CloseImeWindowToAppTest( } } transitions { - device.pressBack() - device.waitForIdle() + testApp.closeIME(device) } assertions { windowManagerTrace { navBarWindowIsAlwaysVisible() statusBarWindowIsAlwaysVisible() + visibleWindowsShownMoreThanOneConsecutiveEntry(listOf("InputMethod")) + imeAppWindowIsAlwaysVisible(testApp) } @@ -95,6 +100,8 @@ class CloseImeWindowToAppTest( noUncoveredRegions(configuration.startRotation) navBarLayerRotatesAndScales(configuration.startRotation) statusBarLayerRotatesScales(configuration.startRotation) + visibleLayersShownMoreThanOneConsecutiveEntry() + imeLayerBecomesInvisible(enabled = false) imeAppLayerIsAlwaysVisible(testApp) } diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt index 8d9881ec2063..bfe5264ed358 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt @@ -33,6 +33,8 @@ import com.android.server.wm.flicker.navBarLayerIsAlwaysVisible import com.android.server.wm.flicker.navBarLayerRotatesAndScales import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible import com.android.server.wm.flicker.noUncoveredRegions +import com.android.server.wm.flicker.visibleWindowsShownMoreThanOneConsecutiveEntry +import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry import com.android.server.wm.flicker.repetitions import com.android.server.wm.flicker.startRotation import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible @@ -95,6 +97,8 @@ class CloseImeWindowToHomeTest( windowManagerTrace { navBarWindowIsAlwaysVisible() statusBarWindowIsAlwaysVisible() + visibleWindowsShownMoreThanOneConsecutiveEntry(listOf(IME_WINDOW_TITLE)) + imeWindowBecomesInvisible() imeAppWindowBecomesInvisible(testApp) } @@ -106,10 +110,14 @@ class CloseImeWindowToHomeTest( Surface.ROTATION_0, bugId = 140855415) statusBarLayerRotatesScales(configuration.startRotation, Surface.ROTATION_0) - navBarLayerIsAlwaysVisible(enabled = false) - statusBarLayerIsAlwaysVisible(enabled = false) + navBarLayerIsAlwaysVisible( + enabled = Surface.ROTATION_0 == configuration.startRotation) + statusBarLayerIsAlwaysVisible( + enabled = Surface.ROTATION_0 == configuration.startRotation) + visibleLayersShownMoreThanOneConsecutiveEntry(listOf(IME_WINDOW_TITLE)) + imeLayerBecomesInvisible(bugId = 153739621) - imeAppLayerBecomesInvisible(testApp, bugId = 153739621) + imeAppLayerBecomesInvisible(testApp) } } } 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 5767a94025e9..64a8f304298b 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 @@ -30,6 +30,8 @@ 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.visibleWindowsShownMoreThanOneConsecutiveEntry +import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry import com.android.server.wm.flicker.noUncoveredRegions import com.android.server.wm.flicker.repetitions import com.android.server.wm.flicker.startRotation @@ -89,6 +91,7 @@ class OpenImeWindowTest( windowManagerTrace { navBarWindowIsAlwaysVisible() statusBarWindowIsAlwaysVisible() + visibleWindowsShownMoreThanOneConsecutiveEntry() all("imeWindowBecomesVisible") { this.skipUntilFirstAssertion() @@ -104,6 +107,7 @@ class OpenImeWindowTest( noUncoveredRegions(configuration.startRotation) navBarLayerRotatesAndScales(configuration.startRotation) statusBarLayerRotatesScales(configuration.startRotation) + visibleLayersShownMoreThanOneConsecutiveEntry() imeLayerBecomesVisible() } diff --git a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java index 2a24d1ac22d2..3d4dc4d67dcc 100644 --- a/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java +++ b/tests/net/integration/util/com/android/server/NetworkAgentWrapper.java @@ -29,7 +29,7 @@ import static com.android.server.ConnectivityServiceTestUtils.transportToLegacyT import static junit.framework.Assert.assertTrue; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.fail; import android.content.Context; import android.net.ConnectivityManager; @@ -38,7 +38,6 @@ import android.net.Network; import android.net.NetworkAgent; import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; -import android.net.NetworkInfo; import android.net.NetworkProvider; import android.net.NetworkSpecifier; import android.net.SocketKeepalive; @@ -53,9 +52,9 @@ import com.android.testutils.HandlerUtils; import com.android.testutils.TestableNetworkCallback; import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork { - private final NetworkInfo mNetworkInfo; private final NetworkCapabilities mNetworkCapabilities; private final HandlerThread mHandlerThread; private final Context mContext; @@ -63,6 +62,7 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork { private final ConditionVariable mDisconnected = new ConditionVariable(); private final ConditionVariable mPreventReconnectReceived = new ConditionVariable(); + private final AtomicBoolean mConnected = new AtomicBoolean(false); private int mScore; private NetworkAgent mNetworkAgent; private int mStartKeepaliveError = SocketKeepalive.ERROR_UNSUPPORTED; @@ -76,7 +76,6 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork { NetworkCapabilities ncTemplate, Context context) throws Exception { final int type = transportToLegacyType(transport); final String typeName = ConnectivityManager.getNetworkTypeName(type); - mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock"); mNetworkCapabilities = (ncTemplate != null) ? ncTemplate : new NetworkCapabilities(); mNetworkCapabilities.addCapability(NET_CAPABILITY_NOT_SUSPENDED); mNetworkCapabilities.addTransportType(transport); @@ -108,22 +107,29 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork { mHandlerThread = new HandlerThread(mLogTag); mHandlerThread.start(); - mNetworkAgent = makeNetworkAgent(linkProperties); + mNetworkAgent = makeNetworkAgent(linkProperties, type, typeName); } - protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties) + protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties, + final int type, final String typeName) throws Exception { - return new InstrumentedNetworkAgent(this, linkProperties); + return new InstrumentedNetworkAgent(this, linkProperties, type, typeName); } public static class InstrumentedNetworkAgent extends NetworkAgent { private final NetworkAgentWrapper mWrapper; - - public InstrumentedNetworkAgent(NetworkAgentWrapper wrapper, LinkProperties lp) { - super(wrapper.mHandlerThread.getLooper(), wrapper.mContext, wrapper.mLogTag, - wrapper.mNetworkInfo, wrapper.mNetworkCapabilities, lp, wrapper.mScore, - new NetworkAgentConfig(), NetworkProvider.ID_NONE); + private static final String PROVIDER_NAME = "InstrumentedNetworkAgentProvider"; + + public InstrumentedNetworkAgent(NetworkAgentWrapper wrapper, LinkProperties lp, + final int type, final String typeName) { + super(wrapper.mContext, wrapper.mHandlerThread.getLooper(), wrapper.mLogTag, + wrapper.mNetworkCapabilities, lp, wrapper.mScore, + new NetworkAgentConfig.Builder() + .setLegacyType(type).setLegacyTypeName(typeName).build(), + new NetworkProvider(wrapper.mContext, wrapper.mHandlerThread.getLooper(), + PROVIDER_NAME)); mWrapper = wrapper; + register(); } @Override @@ -212,10 +218,12 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork { } public void connect() { - assertNotEquals("MockNetworkAgents can only be connected once", - mNetworkInfo.getDetailedState(), NetworkInfo.DetailedState.CONNECTED); - mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, null); - mNetworkAgent.sendNetworkInfo(mNetworkInfo); + if (!mConnected.compareAndSet(false /* expect */, true /* update */)) { + // compareAndSet returns false when the value couldn't be updated because it did not + // match the expected value. + fail("Test NetworkAgents can only be connected once"); + } + mNetworkAgent.markConnected(); } public void suspend() { @@ -227,8 +235,7 @@ public class NetworkAgentWrapper implements TestableNetworkCallback.HasNetwork { } public void disconnect() { - mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null, null); - mNetworkAgent.sendNetworkInfo(mNetworkInfo); + mNetworkAgent.unregister(); } @Override diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java index aec2f48cccea..b3bdd6055c62 100644 --- a/tests/net/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java @@ -18,6 +18,7 @@ package com.android.server; import static android.Manifest.permission.CHANGE_NETWORK_STATE; import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS; +import static android.app.PendingIntent.FLAG_IMMUTABLE; import static android.content.Intent.ACTION_USER_ADDED; import static android.content.Intent.ACTION_USER_REMOVED; import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED; @@ -187,6 +188,7 @@ import android.net.RouteInfo; import android.net.RouteInfoParcel; import android.net.SocketKeepalive; import android.net.UidRange; +import android.net.UidRangeParcel; import android.net.Uri; import android.net.VpnManager; import android.net.metrics.IpConnectivityLog; @@ -645,8 +647,8 @@ public class ConnectivityServiceTest { } @Override - protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties) - throws Exception { + protected InstrumentedNetworkAgent makeNetworkAgent(LinkProperties linkProperties, + final int type, final String typeName) throws Exception { mNetworkMonitor = mock(INetworkMonitor.class); final Answer validateAnswer = inv -> { @@ -665,7 +667,8 @@ public class ConnectivityServiceTest { any() /* name */, nmCbCaptor.capture()); - final InstrumentedNetworkAgent na = new InstrumentedNetworkAgent(this, linkProperties) { + final InstrumentedNetworkAgent na = new InstrumentedNetworkAgent(this, linkProperties, + type, typeName) { @Override public void networkStatus(int status, String redirectUrl) { mRedirectUrl = redirectUrl; @@ -1053,7 +1056,7 @@ public class ConnectivityServiceTest { public MockVpn(int userId) { super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService, - userId, mock(KeyStore.class)); + mMockNetd, userId, mock(KeyStore.class)); mConfig = new VpnConfig(); } @@ -1092,10 +1095,11 @@ public class ConnectivityServiceTest { mMockNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp, mNetworkCapabilities); mMockNetworkAgent.waitForIdle(TIMEOUT_MS); - verify(mNetworkManagementService, times(1)) - .addVpnUidRanges(eq(mMockVpn.getNetId()), eq(uids.toArray(new UidRange[0]))); - verify(mNetworkManagementService, never()) - .removeVpnUidRanges(eq(mMockVpn.getNetId()), any()); + + verify(mMockNetd, times(1)).networkAddUidRanges(eq(mMockVpn.getNetId()), + eq(toUidRangeStableParcels(uids))); + verify(mMockNetd, never()) + .networkRemoveUidRanges(eq(mMockVpn.getNetId()), any()); mAgentRegistered = true; mNetworkCapabilities.set(mMockNetworkAgent.getNetworkCapabilities()); mNetworkAgent = mMockNetworkAgent.getNetworkAgent(); @@ -1167,6 +1171,11 @@ public class ConnectivityServiceTest { } } + private UidRangeParcel[] toUidRangeStableParcels(final @NonNull Set<UidRange> ranges) { + return ranges.stream().map( + r -> new UidRangeParcel(r.start, r.stop)).toArray(UidRangeParcel[]::new); + } + private void mockVpn(int uid) { synchronized (mService.mVpns) { int userId = UserHandle.getUserId(uid); @@ -2547,10 +2556,8 @@ public class ConnectivityServiceTest { @Test public void testNoMutableNetworkRequests() throws Exception { - // TODO(b/173157160) Please replace FLAG_MUTABLE_UNAUDITED below - // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. - PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent("a"), - PendingIntent.FLAG_MUTABLE_UNAUDITED); + final PendingIntent pendingIntent = PendingIntent.getBroadcast( + mContext, 0 /* requestCode */, new Intent("a"), FLAG_IMMUTABLE); NetworkRequest request1 = new NetworkRequest.Builder() .addCapability(NET_CAPABILITY_VALIDATED) .build(); @@ -3210,21 +3217,17 @@ public class ConnectivityServiceTest { assertThrows(SecurityException.class, () -> mCm.registerNetworkCallback(r, new NetworkCallback())); - // TODO(b/173157160) Please replace FLAG_MUTABLE_UNAUDITED below - // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. assertThrows(SecurityException.class, () -> mCm.registerNetworkCallback(r, PendingIntent.getService( - mServiceContext, 0, new Intent(), PendingIntent.FLAG_MUTABLE_UNAUDITED))); + mServiceContext, 0 /* requestCode */, new Intent(), FLAG_IMMUTABLE))); // Requesting a Network with signal strength should get IllegalArgumentException. assertThrows(IllegalArgumentException.class, () -> mCm.requestNetwork(r, new NetworkCallback())); - // TODO(b/173157160) Please replace FLAG_MUTABLE_UNAUDITED below - // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. assertThrows(IllegalArgumentException.class, () -> mCm.requestNetwork(r, PendingIntent.getService( - mServiceContext, 0, new Intent(), PendingIntent.FLAG_MUTABLE_UNAUDITED))); + mServiceContext, 0 /* requestCode */, new Intent(), FLAG_IMMUTABLE))); } @Test @@ -4688,16 +4691,14 @@ public class ConnectivityServiceTest { } j = 0; while (j++ < INTENTS / 2) { - // TODO(b/173157160) Please replace FLAG_MUTABLE_UNAUDITED below - // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. - PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("a" + j), PendingIntent.FLAG_MUTABLE_UNAUDITED); + final PendingIntent pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */, + new Intent("a" + j), FLAG_IMMUTABLE); mCm.requestNetwork(networkRequest, pi); registered.add(pi); } while (j++ < INTENTS) { - // TODO(b/173157160) Please replace FLAG_MUTABLE_UNAUDITED below - // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. - PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, new Intent("b" + j), PendingIntent.FLAG_MUTABLE_UNAUDITED); + final PendingIntent pi = PendingIntent.getBroadcast(mContext, 0 /* requestCode */, + new Intent("b" + j), FLAG_IMMUTABLE); mCm.registerNetworkCallback(networkRequest, pi); registered.add(pi); } @@ -4711,15 +4712,13 @@ public class ConnectivityServiceTest { ); assertThrows(TooManyRequestsException.class, () -> mCm.requestNetwork(networkRequest, - // TODO(b/173157160) Please replace FLAG_MUTABLE_UNAUDITED below - // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. - PendingIntent.getBroadcast(mContext, 0, new Intent("c"), PendingIntent.FLAG_MUTABLE_UNAUDITED)) + PendingIntent.getBroadcast(mContext, 0 /* requestCode */, + new Intent("c"), FLAG_IMMUTABLE)) ); assertThrows(TooManyRequestsException.class, () -> mCm.registerNetworkCallback(networkRequest, - // TODO(b/173157160) Please replace FLAG_MUTABLE_UNAUDITED below - // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. - PendingIntent.getBroadcast(mContext, 0, new Intent("d"), PendingIntent.FLAG_MUTABLE_UNAUDITED)) + PendingIntent.getBroadcast(mContext, 0 /* requestCode */, + new Intent("d"), FLAG_IMMUTABLE)) ); for (Object o : registered) { @@ -4748,20 +4747,16 @@ public class ConnectivityServiceTest { waitForIdle(); for (int i = 0; i < MAX_REQUESTS; i++) { - // TODO(b/173157160) Please replace FLAG_MUTABLE_UNAUDITED below - // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. - PendingIntent pendingIntent = - PendingIntent.getBroadcast(mContext, 0, new Intent("e" + i), PendingIntent.FLAG_MUTABLE_UNAUDITED); + final PendingIntent pendingIntent = PendingIntent.getBroadcast( + mContext, 0 /* requestCode */, new Intent("e" + i), FLAG_IMMUTABLE); mCm.requestNetwork(networkRequest, pendingIntent); mCm.unregisterNetworkCallback(pendingIntent); } waitForIdle(); for (int i = 0; i < MAX_REQUESTS; i++) { - // TODO(b/173157160) Please replace FLAG_MUTABLE_UNAUDITED below - // with either FLAG_IMMUTABLE (recommended) or FLAG_MUTABLE. - PendingIntent pendingIntent = - PendingIntent.getBroadcast(mContext, 0, new Intent("f" + i), PendingIntent.FLAG_MUTABLE_UNAUDITED); + final PendingIntent pendingIntent = PendingIntent.getBroadcast( + mContext, 0 /* requestCode */, new Intent("f" + i), FLAG_IMMUTABLE); mCm.registerNetworkCallback(networkRequest, pendingIntent); mCm.unregisterNetworkCallback(pendingIntent); } @@ -4959,8 +4954,8 @@ public class ConnectivityServiceTest { expectForceUpdateIfaces(onlyCell, MOBILE_IFNAME); reset(mStatsService); - // Captive portal change shouldn't update ifaces - mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL); + // Temp metered change shouldn't update ifaces + mCellNetworkAgent.addCapability(NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED); waitForIdle(); verify(mStatsService, never()) .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME), @@ -5476,6 +5471,7 @@ public class ConnectivityServiceTest { final Network wifi = mWiFiNetworkAgent.getNetwork(); final NetworkCapabilities initialCaps = new NetworkCapabilities(); + initialCaps.addTransportType(TRANSPORT_VPN); initialCaps.addCapability(NET_CAPABILITY_INTERNET); initialCaps.removeCapability(NET_CAPABILITY_NOT_VPN); @@ -5507,44 +5503,45 @@ public class ConnectivityServiceTest { withWifiAndMobileUnderlying.setLinkDownstreamBandwidthKbps(10); withWifiAndMobileUnderlying.setLinkUpstreamBandwidthKbps(20); + final NetworkCapabilities initialCapsNotMetered = new NetworkCapabilities(initialCaps); + initialCapsNotMetered.addCapability(NET_CAPABILITY_NOT_METERED); + NetworkCapabilities caps = new NetworkCapabilities(initialCaps); - final boolean notDeclaredMetered = false; - mService.applyUnderlyingCapabilities(new Network[]{}, caps, notDeclaredMetered); + mService.applyUnderlyingCapabilities(new Network[]{}, initialCapsNotMetered, caps); assertEquals(withNoUnderlying, caps); caps = new NetworkCapabilities(initialCaps); - mService.applyUnderlyingCapabilities(new Network[]{null}, caps, notDeclaredMetered); + mService.applyUnderlyingCapabilities(new Network[]{null}, initialCapsNotMetered, caps); assertEquals(withNoUnderlying, caps); caps = new NetworkCapabilities(initialCaps); - mService.applyUnderlyingCapabilities(new Network[]{mobile}, caps, notDeclaredMetered); + mService.applyUnderlyingCapabilities(new Network[]{mobile}, initialCapsNotMetered, caps); assertEquals(withMobileUnderlying, caps); - mService.applyUnderlyingCapabilities(new Network[]{wifi}, caps, notDeclaredMetered); + mService.applyUnderlyingCapabilities(new Network[]{wifi}, initialCapsNotMetered, caps); assertEquals(withWifiUnderlying, caps); - final boolean isDeclaredMetered = true; withWifiUnderlying.removeCapability(NET_CAPABILITY_NOT_METERED); caps = new NetworkCapabilities(initialCaps); - mService.applyUnderlyingCapabilities(new Network[]{wifi}, caps, isDeclaredMetered); + mService.applyUnderlyingCapabilities(new Network[]{wifi}, initialCaps, caps); assertEquals(withWifiUnderlying, caps); caps = new NetworkCapabilities(initialCaps); - mService.applyUnderlyingCapabilities(new Network[]{mobile, wifi}, caps, isDeclaredMetered); + mService.applyUnderlyingCapabilities(new Network[]{mobile, wifi}, initialCaps, caps); assertEquals(withWifiAndMobileUnderlying, caps); withWifiUnderlying.addCapability(NET_CAPABILITY_NOT_METERED); caps = new NetworkCapabilities(initialCaps); mService.applyUnderlyingCapabilities(new Network[]{null, mobile, null, wifi}, - caps, notDeclaredMetered); + initialCapsNotMetered, caps); assertEquals(withWifiAndMobileUnderlying, caps); caps = new NetworkCapabilities(initialCaps); mService.applyUnderlyingCapabilities(new Network[]{null, mobile, null, wifi}, - caps, notDeclaredMetered); + initialCapsNotMetered, caps); assertEquals(withWifiAndMobileUnderlying, caps); - mService.applyUnderlyingCapabilities(null, caps, notDeclaredMetered); + mService.applyUnderlyingCapabilities(null, initialCapsNotMetered, caps); assertEquals(withWifiUnderlying, caps); } diff --git a/tests/net/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java b/tests/net/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java index c53462cfb0b2..950d7163c78a 100644 --- a/tests/net/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java +++ b/tests/net/java/com/android/server/connectivity/MultipathPolicyTrackerTest.java @@ -130,6 +130,7 @@ public class MultipathPolicyTrackerTest { when(mContext.getResources()).thenReturn(mResources); when(mContext.getApplicationInfo()).thenReturn(new ApplicationInfo()); + // Mock user id to all users that Context#registerReceiver will register with all users too. doReturn(UserHandle.ALL.getIdentifier()).when(mUserAllContext).getUserId(); when(mContext.createContextAsUser(eq(UserHandle.ALL), anyInt())) .thenReturn(mUserAllContext); diff --git a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java index de35f910d53a..3556c72776dc 100644 --- a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java +++ b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java @@ -58,7 +58,6 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; -import android.content.pm.UserInfo; import android.net.INetd; import android.net.UidRange; import android.os.Build; @@ -123,10 +122,10 @@ public class PermissionMonitorTest { MockitoAnnotations.initMocks(this); when(mContext.getPackageManager()).thenReturn(mPackageManager); when(mContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mUserManager); - when(mUserManager.getAliveUsers()).thenReturn( - Arrays.asList(new UserInfo[] { - new UserInfo(MOCK_USER1, "", 0), - new UserInfo(MOCK_USER2, "", 0), + when(mUserManager.getUserHandles(eq(true))).thenReturn( + Arrays.asList(new UserHandle[] { + new UserHandle(MOCK_USER1), + new UserHandle(MOCK_USER2), })); mPermissionMonitor = spy(new PermissionMonitor(mContext, mNetdService, mDeps)); diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java index 337507ac1d46..6e380be6c583 100644 --- a/tests/net/java/com/android/server/connectivity/VpnTest.java +++ b/tests/net/java/com/android/server/connectivity/VpnTest.java @@ -58,6 +58,7 @@ import android.content.pm.ServiceInfo; import android.content.pm.UserInfo; import android.content.res.Resources; import android.net.ConnectivityManager; +import android.net.INetd; import android.net.Ikev2VpnProfile; import android.net.InetAddresses; import android.net.IpPrefix; @@ -70,6 +71,7 @@ import android.net.NetworkCapabilities; import android.net.NetworkInfo.DetailedState; import android.net.RouteInfo; import android.net.UidRange; +import android.net.UidRangeParcel; import android.net.VpnManager; import android.net.VpnService; import android.net.ipsec.ike.IkeSessionCallback; @@ -172,11 +174,13 @@ public class VpnTest { mPackages.put(PKGS[i], PKG_UIDS[i]); } } + private static final UidRange PRI_USER_RANGE = UidRange.createForUser(primaryUser.id); @Mock(answer = Answers.RETURNS_DEEP_STUBS) private Context mContext; @Mock private UserManager mUserManager; @Mock private PackageManager mPackageManager; @Mock private INetworkManagementService mNetService; + @Mock private INetd mNetd; @Mock private AppOpsManager mAppOps; @Mock private NotificationManager mNotificationManager; @Mock private Vpn.SystemServices mSystemServices; @@ -256,8 +260,7 @@ public class VpnTest { null, null); assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { - UidRange.createForUser(primaryUser.id), - UidRange.createForUser(restrictedProfileA.id) + PRI_USER_RANGE, UidRange.createForUser(restrictedProfileA.id) })), ranges); } @@ -269,9 +272,7 @@ public class VpnTest { final Set<UidRange> ranges = vpn.createUserAndRestrictedProfilesRanges(primaryUser.id, null, null); - assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { - UidRange.createForUser(primaryUser.id) - })), ranges); + assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { PRI_USER_RANGE })), ranges); } @Test @@ -282,15 +283,13 @@ public class VpnTest { final Set<UidRange> ranges = new ArraySet<>(); vpn.addUserToRanges(ranges, primaryUser.id, null, null); - assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { - UidRange.createForUser(primaryUser.id) - })), ranges); + assertEquals(new ArraySet<>(Arrays.asList(new UidRange[] { PRI_USER_RANGE })), ranges); } @Test public void testUidAllowAndDenylist() throws Exception { final Vpn vpn = createVpn(primaryUser.id); - final UidRange user = UidRange.createForUser(primaryUser.id); + final UidRange user = PRI_USER_RANGE; final String[] packages = {PKGS[0], PKGS[1], PKGS[2]}; // Allowed list @@ -339,62 +338,67 @@ public class VpnTest { @Test public void testLockdownChangingPackage() throws Exception { final Vpn vpn = createVpn(primaryUser.id); - final UidRange user = UidRange.createForUser(primaryUser.id); + final UidRange user = PRI_USER_RANGE; // Default state. - assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); + assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], + user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); // Set always-on without lockdown. assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, null, mKeyStore)); - assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); + assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], + user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); // Set always-on with lockdown. assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, null, mKeyStore)); - verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] { - new UidRange(user.start, user.start + PKG_UIDS[1] - 1), - new UidRange(user.start + PKG_UIDS[1] + 1, user.stop) + verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] { + new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1), + new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop) })); - assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); + + assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[2], + user.start + PKG_UIDS[3]); assertUnblocked(vpn, user.start + PKG_UIDS[1]); // Switch to another app. assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null, mKeyStore)); - verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] { - new UidRange(user.start, user.start + PKG_UIDS[1] - 1), - new UidRange(user.start + PKG_UIDS[1] + 1, user.stop) + verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[] { + new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1), + new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop) })); - verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] { - new UidRange(user.start, user.start + PKG_UIDS[3] - 1), - new UidRange(user.start + PKG_UIDS[3] + 1, user.stop) + + verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] { + new UidRangeParcel(user.start, user.start + PKG_UIDS[3] - 1), + new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop) })); - assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]); + assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], + user.start + PKG_UIDS[2]); assertUnblocked(vpn, user.start + PKG_UIDS[3]); } @Test public void testLockdownAllowlist() throws Exception { final Vpn vpn = createVpn(primaryUser.id); - final UidRange user = UidRange.createForUser(primaryUser.id); + final UidRange user = PRI_USER_RANGE; // Set always-on with lockdown and allow app PKGS[2] from lockdown. assertTrue(vpn.setAlwaysOnPackage( PKGS[1], true, Collections.singletonList(PKGS[2]), mKeyStore)); - verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] { - new UidRange(user.start, user.start + PKG_UIDS[1] - 1), - new UidRange(user.start + PKG_UIDS[2] + 1, user.stop) + verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] { + new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1), + new UidRangeParcel(user.start + PKG_UIDS[2] + 1, user.stop) })); assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[3]); assertUnblocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]); - // Change allowed app list to PKGS[3]. assertTrue(vpn.setAlwaysOnPackage( PKGS[1], true, Collections.singletonList(PKGS[3]), mKeyStore)); - verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] { - new UidRange(user.start + PKG_UIDS[2] + 1, user.stop) + verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[] { + new UidRangeParcel(user.start + PKG_UIDS[2] + 1, user.stop) })); - verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] { - new UidRange(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1), - new UidRange(user.start + PKG_UIDS[3] + 1, user.stop) + verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] { + new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1), + new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop) })); assertBlocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[2]); assertUnblocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[3]); @@ -402,25 +406,25 @@ public class VpnTest { // Change the VPN app. assertTrue(vpn.setAlwaysOnPackage( PKGS[0], true, Collections.singletonList(PKGS[3]), mKeyStore)); - verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] { - new UidRange(user.start, user.start + PKG_UIDS[1] - 1), - new UidRange(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1) + verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[] { + new UidRangeParcel(user.start, user.start + PKG_UIDS[1] - 1), + new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1) })); - verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] { - new UidRange(user.start, user.start + PKG_UIDS[0] - 1), - new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1) + verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] { + new UidRangeParcel(user.start, user.start + PKG_UIDS[0] - 1), + new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1) })); assertBlocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]); assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[3]); // Remove the list of allowed packages. assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, null, mKeyStore)); - verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] { - new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1), - new UidRange(user.start + PKG_UIDS[3] + 1, user.stop) + verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[] { + new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1), + new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop) })); - verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] { - new UidRange(user.start + PKG_UIDS[0] + 1, user.stop), + verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] { + new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.stop), })); assertBlocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); @@ -429,12 +433,12 @@ public class VpnTest { // Add the list of allowed packages. assertTrue(vpn.setAlwaysOnPackage( PKGS[0], true, Collections.singletonList(PKGS[1]), mKeyStore)); - verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] { - new UidRange(user.start + PKG_UIDS[0] + 1, user.stop) + verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[] { + new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.stop) })); - verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] { - new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1), - new UidRange(user.start + PKG_UIDS[1] + 1, user.stop) + verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] { + new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1), + new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop) })); assertBlocked(vpn, user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]); assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1]); @@ -447,13 +451,13 @@ public class VpnTest { // allowed package should change from PGKS[1] to PKGS[2]. assertTrue(vpn.setAlwaysOnPackage( PKGS[0], true, Arrays.asList("com.foo.app", PKGS[2], "com.bar.app"), mKeyStore)); - verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[]{ - new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1), - new UidRange(user.start + PKG_UIDS[1] + 1, user.stop) + verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[]{ + new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1), + new UidRangeParcel(user.start + PKG_UIDS[1] + 1, user.stop) })); - verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[]{ - new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[2] - 1), - new UidRange(user.start + PKG_UIDS[2] + 1, user.stop) + verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[]{ + new UidRangeParcel(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[2] - 1), + new UidRangeParcel(user.start + PKG_UIDS[2] + 1, user.stop) })); } @@ -467,86 +471,86 @@ public class VpnTest { restrictedProfileA.flags); tempProfile.restrictedProfileParentId = primaryUser.id; - final UidRange user = UidRange.createForUser(primaryUser.id); + final UidRange user = PRI_USER_RANGE; final UidRange profile = UidRange.createForUser(tempProfile.id); // Set lockdown. assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null, mKeyStore)); - verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] { - new UidRange(user.start, user.start + PKG_UIDS[3] - 1), - new UidRange(user.start + PKG_UIDS[3] + 1, user.stop) + verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] { + new UidRangeParcel(user.start, user.start + PKG_UIDS[3] - 1), + new UidRangeParcel(user.start + PKG_UIDS[3] + 1, user.stop) })); - // Verify restricted user isn't affected at first. assertUnblocked(vpn, profile.start + PKG_UIDS[0]); // Add the restricted user. setMockedUsers(primaryUser, tempProfile); vpn.onUserAdded(tempProfile.id); - verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] { - new UidRange(profile.start, profile.start + PKG_UIDS[3] - 1), - new UidRange(profile.start + PKG_UIDS[3] + 1, profile.stop) + verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(new UidRangeParcel[] { + new UidRangeParcel(profile.start, profile.start + PKG_UIDS[3] - 1), + new UidRangeParcel(profile.start + PKG_UIDS[3] + 1, profile.stop) })); // Remove the restricted user. tempProfile.partial = true; vpn.onUserRemoved(tempProfile.id); - verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] { - new UidRange(profile.start, profile.start + PKG_UIDS[3] - 1), - new UidRange(profile.start + PKG_UIDS[3] + 1, profile.stop) + verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(new UidRangeParcel[] { + new UidRangeParcel(profile.start, profile.start + PKG_UIDS[3] - 1), + new UidRangeParcel(profile.start + PKG_UIDS[3] + 1, profile.stop) })); } @Test public void testLockdownRuleRepeatability() throws Exception { final Vpn vpn = createVpn(primaryUser.id); - + final UidRangeParcel[] primaryUserRangeParcel = new UidRangeParcel[] { + new UidRangeParcel(PRI_USER_RANGE.start, PRI_USER_RANGE.stop)}; // Given legacy lockdown is already enabled, vpn.setLockdown(true); - verify(mNetService, times(1)).setAllowOnlyVpnForUids( - eq(true), aryEq(new UidRange[] {UidRange.createForUser(primaryUser.id)})); + + verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(primaryUserRangeParcel)); // Enabling legacy lockdown twice should do nothing. vpn.setLockdown(true); - verify(mNetService, times(1)).setAllowOnlyVpnForUids(anyBoolean(), any(UidRange[].class)); + verify(mNetd, times(1)) + .networkRejectNonSecureVpn(anyBoolean(), any(UidRangeParcel[].class)); // And disabling should remove the rules exactly once. vpn.setLockdown(false); - verify(mNetService, times(1)).setAllowOnlyVpnForUids( - eq(false), aryEq(new UidRange[] {UidRange.createForUser(primaryUser.id)})); + verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(primaryUserRangeParcel)); // Removing the lockdown again should have no effect. vpn.setLockdown(false); - verify(mNetService, times(2)).setAllowOnlyVpnForUids(anyBoolean(), any(UidRange[].class)); + verify(mNetd, times(2)).networkRejectNonSecureVpn( + anyBoolean(), any(UidRangeParcel[].class)); } @Test public void testLockdownRuleReversibility() throws Exception { final Vpn vpn = createVpn(primaryUser.id); - - final UidRange[] entireUser = { - UidRange.createForUser(primaryUser.id) + final UidRangeParcel[] entireUser = { + new UidRangeParcel(PRI_USER_RANGE.start, PRI_USER_RANGE.stop) }; - final UidRange[] exceptPkg0 = { - new UidRange(entireUser[0].start, entireUser[0].start + PKG_UIDS[0] - 1), - new UidRange(entireUser[0].start + PKG_UIDS[0] + 1, entireUser[0].stop) + final UidRangeParcel[] exceptPkg0 = { + new UidRangeParcel(entireUser[0].start, entireUser[0].start + PKG_UIDS[0] - 1), + new UidRangeParcel(entireUser[0].start + PKG_UIDS[0] + 1, entireUser[0].stop) }; - final InOrder order = inOrder(mNetService); + final InOrder order = inOrder(mNetd); // Given lockdown is enabled with no package (legacy VPN), vpn.setLockdown(true); - order.verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(entireUser)); + order.verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(entireUser)); // When a new VPN package is set the rules should change to cover that package. vpn.prepare(null, PKGS[0], VpnManager.TYPE_VPN_SERVICE); - order.verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(entireUser)); - order.verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(exceptPkg0)); + order.verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(entireUser)); + order.verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(exceptPkg0)); // When that VPN package is unset, everything should be undone again in reverse. vpn.prepare(null, VpnConfig.LEGACY_VPN, VpnManager.TYPE_VPN_SERVICE); - order.verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(exceptPkg0)); - order.verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(entireUser)); + order.verify(mNetd).networkRejectNonSecureVpn(eq(false), aryEq(exceptPkg0)); + order.verify(mNetd).networkRejectNonSecureVpn(eq(true), aryEq(entireUser)); } @Test @@ -1186,7 +1190,7 @@ public class VpnTest { .thenReturn(asUserContext); final TestLooper testLooper = new TestLooper(); final Vpn vpn = new Vpn(testLooper.getLooper(), mContext, new TestDeps(), mNetService, - userId, mKeyStore, mSystemServices, mIkev2SessionCreator); + mNetd, userId, mKeyStore, mSystemServices, mIkev2SessionCreator); verify(mConnectivityManager, times(1)).registerNetworkProvider(argThat( provider -> provider.getName().contains("VpnNetworkProvider") )); diff --git a/tools/split-select/OWNERS b/tools/split-select/OWNERS new file mode 100644 index 000000000000..6c50ede5bb8c --- /dev/null +++ b/tools/split-select/OWNERS @@ -0,0 +1 @@ +include /core/java/android/content/res/OWNERS
\ No newline at end of file diff --git a/tools/stats_log_api_gen/.clang-format b/tools/stats_log_api_gen/.clang-format deleted file mode 100644 index cead3a079435..000000000000 --- a/tools/stats_log_api_gen/.clang-format +++ /dev/null @@ -1,17 +0,0 @@ -BasedOnStyle: Google -AllowShortIfStatementsOnASingleLine: true -AllowShortFunctionsOnASingleLine: false -AllowShortLoopsOnASingleLine: true -BinPackArguments: true -BinPackParameters: true -ColumnLimit: 100 -CommentPragmas: NOLINT:.* -ContinuationIndentWidth: 8 -DerivePointerAlignment: false -IndentWidth: 4 -PointerAlignment: Left -TabWidth: 4 -AccessModifierOffset: -4 -IncludeCategories: - - Regex: '^"Log\.h"' - Priority: -1 diff --git a/tools/stats_log_api_gen/Android.bp b/tools/stats_log_api_gen/Android.bp deleted file mode 100644 index ab8702b79ab5..000000000000 --- a/tools/stats_log_api_gen/Android.bp +++ /dev/null @@ -1,150 +0,0 @@ -// -// Copyright (C) 2017 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -// ========================================================== -// Build the host executable: stats-log-api-gen -// ========================================================== -cc_binary_host { - name: "stats-log-api-gen", - srcs: [ - "Collation.cpp", - "java_writer.cpp", - "java_writer_q.cpp", - "main.cpp", - "native_writer.cpp", - "utils.cpp", - ], - cflags: [ - "-Wall", - "-Werror", - ], - - shared_libs: [ - "libstats_proto_host", - "libprotobuf-cpp-full", - "libbase", - ], - - proto: { - type: "full", - }, -} - -// ========================================================== -// Build the host test executable: stats-log-api-gen -// ========================================================== -cc_test_host { - name: "stats-log-api-gen-test", - cflags: [ - "-Wall", - "-Wextra", - "-Werror", - "-g", - "-DUNIT_TEST", - ], - srcs: [ - "Collation.cpp", - "test_collation.cpp", - "test.proto", - ], - - static_libs: [ - "libgmock_host", - ], - - shared_libs: [ - "libstats_proto_host", - "libprotobuf-cpp-full", - ], - - proto: { - type: "full", - include_dirs: [ - "external/protobuf/src", - ], - }, -} - -// ========================================================== -// Native library -// ========================================================== -genrule { - name: "statslog.h", - tools: ["stats-log-api-gen"], - cmd: "$(location stats-log-api-gen) --header $(genDir)/statslog.h", - out: [ - "statslog.h", - ], -} - -genrule { - name: "statslog.cpp", - tools: ["stats-log-api-gen"], - cmd: "$(location stats-log-api-gen) --cpp $(genDir)/statslog.cpp", - out: [ - "statslog.cpp", - ], -} - -cc_library { - name: "libstatslog", - host_supported: true, - generated_sources: [ - "statslog.cpp", - ], - generated_headers: [ - "statslog.h" - ], - cflags: [ - "-Wall", - "-Werror", - ], - export_generated_headers: [ - "statslog.h" - ], - shared_libs: [ - "liblog", - "libcutils", - ], - target: { - android: { - shared_libs: [ - "libstatssocket", - "libstatspull", - ], - export_shared_lib_headers: [ - "libstatssocket", - "libstatspull", - ], - }, - host: { - static_libs: [ - "libstatssocket", - "libstatspull", - "statsd-aidl-ndk_platform", - ], - shared_libs: ["libbinder_ndk"], - export_static_lib_headers: [ - "libstatssocket", - "libstatspull", - ], - }, - darwin: { - enabled: false, - }, - }, -} - diff --git a/tools/stats_log_api_gen/Collation.cpp b/tools/stats_log_api_gen/Collation.cpp deleted file mode 100644 index 56f4db0b2aed..000000000000 --- a/tools/stats_log_api_gen/Collation.cpp +++ /dev/null @@ -1,601 +0,0 @@ -/* - * Copyright (C) 2017, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "Collation.h" - -#include <stdio.h> - -#include <map> - -#include "frameworks/proto_logging/stats/atoms.pb.h" - -namespace android { -namespace stats_log_api_gen { - -using google::protobuf::OneofDescriptor; -using google::protobuf::EnumDescriptor; -using google::protobuf::FieldDescriptor; -using google::protobuf::FileDescriptor; -using google::protobuf::SourceLocation; -using std::make_shared; -using std::map; - -const bool dbg = false; - -// -// AtomDecl class -// - -AtomDecl::AtomDecl() : code(0), name() { -} - -AtomDecl::AtomDecl(const AtomDecl& that) - : code(that.code), - name(that.name), - message(that.message), - fields(that.fields), - fieldNumberToAnnotations(that.fieldNumberToAnnotations), - primaryFields(that.primaryFields), - exclusiveField(that.exclusiveField), - defaultState(that.defaultState), - triggerStateReset(that.triggerStateReset), - nested(that.nested), - uidField(that.uidField) { -} - -AtomDecl::AtomDecl(int c, const string& n, const string& m) : code(c), name(n), message(m) { -} - -AtomDecl::~AtomDecl() { -} - -/** - * Print an error message for a FieldDescriptor, including the file name and - * line number. - */ -static void print_error(const FieldDescriptor* field, const char* format, ...) { - const Descriptor* message = field->containing_type(); - const FileDescriptor* file = message->file(); - - SourceLocation loc; - if (field->GetSourceLocation(&loc)) { - // TODO(b/162454173): this will work if we can figure out how to pass - // --include_source_info to protoc - fprintf(stderr, "%s:%d: ", file->name().c_str(), loc.start_line); - } else { - fprintf(stderr, "%s: ", file->name().c_str()); - } - va_list args; - va_start(args, format); - vfprintf(stderr, format, args); - va_end(args); -} - -/** - * Convert a protobuf type into a java type. - */ -static java_type_t java_type(const FieldDescriptor* field) { - int protoType = field->type(); - switch (protoType) { - case FieldDescriptor::TYPE_DOUBLE: - return JAVA_TYPE_DOUBLE; - case FieldDescriptor::TYPE_FLOAT: - return JAVA_TYPE_FLOAT; - case FieldDescriptor::TYPE_INT64: - return JAVA_TYPE_LONG; - case FieldDescriptor::TYPE_UINT64: - return JAVA_TYPE_LONG; - case FieldDescriptor::TYPE_INT32: - return JAVA_TYPE_INT; - case FieldDescriptor::TYPE_FIXED64: - return JAVA_TYPE_LONG; - case FieldDescriptor::TYPE_FIXED32: - return JAVA_TYPE_INT; - case FieldDescriptor::TYPE_BOOL: - return JAVA_TYPE_BOOLEAN; - case FieldDescriptor::TYPE_STRING: - return JAVA_TYPE_STRING; - case FieldDescriptor::TYPE_GROUP: - return JAVA_TYPE_UNKNOWN; - case FieldDescriptor::TYPE_MESSAGE: - if (field->message_type()->full_name() == "android.os.statsd.AttributionNode") { - return JAVA_TYPE_ATTRIBUTION_CHAIN; - } else if (field->message_type()->full_name() == "android.os.statsd.KeyValuePair") { - return JAVA_TYPE_KEY_VALUE_PAIR; - } else if (field->options().GetExtension(os::statsd::log_mode) == - os::statsd::LogMode::MODE_BYTES) { - return JAVA_TYPE_BYTE_ARRAY; - } else { - return JAVA_TYPE_OBJECT; - } - case FieldDescriptor::TYPE_BYTES: - return JAVA_TYPE_BYTE_ARRAY; - case FieldDescriptor::TYPE_UINT32: - return JAVA_TYPE_INT; - case FieldDescriptor::TYPE_ENUM: - return JAVA_TYPE_ENUM; - case FieldDescriptor::TYPE_SFIXED32: - return JAVA_TYPE_INT; - case FieldDescriptor::TYPE_SFIXED64: - return JAVA_TYPE_LONG; - case FieldDescriptor::TYPE_SINT32: - return JAVA_TYPE_INT; - case FieldDescriptor::TYPE_SINT64: - return JAVA_TYPE_LONG; - default: - return JAVA_TYPE_UNKNOWN; - } -} - -/** - * Gather the enums info. - */ -void collate_enums(const EnumDescriptor& enumDescriptor, AtomField* atomField) { - for (int i = 0; i < enumDescriptor.value_count(); i++) { - atomField->enumValues[enumDescriptor.value(i)->number()] = - enumDescriptor.value(i)->name(); - } -} - -static void addAnnotationToAtomDecl(AtomDecl* atomDecl, const int fieldNumber, - const AnnotationId annotationId, - const AnnotationType annotationType, - const AnnotationValue annotationValue) { - if (dbg) { - printf(" Adding annotation to %s: [%d] = {id: %d, type: %d}\n", atomDecl->name.c_str(), - fieldNumber, annotationId, annotationType); - } - atomDecl->fieldNumberToAnnotations[fieldNumber].insert( - make_shared<Annotation>(annotationId, atomDecl->code, annotationType, annotationValue)); -} - -static int collate_field_annotations(AtomDecl* atomDecl, const FieldDescriptor* field, - const int fieldNumber, const java_type_t& javaType) { - int errorCount = 0; - - if (field->options().HasExtension(os::statsd::state_field_option)) { - const os::statsd::StateAtomFieldOption& stateFieldOption = - field->options().GetExtension(os::statsd::state_field_option); - const bool primaryField = stateFieldOption.primary_field(); - const bool exclusiveState = stateFieldOption.exclusive_state(); - const bool primaryFieldFirstUid = stateFieldOption.primary_field_first_uid(); - - // Check the field is only one of primaryField, exclusiveState, or primaryFieldFirstUid. - if (primaryField + primaryFieldFirstUid + exclusiveState > 1) { - print_error(field, - "Field can be max 1 of primary_field, exclusive_state, " - "or primary_field_first_uid: '%s'\n", - atomDecl->message.c_str()); - errorCount++; - } - - if (primaryField) { - if (javaType == JAVA_TYPE_UNKNOWN || javaType == JAVA_TYPE_ATTRIBUTION_CHAIN || - javaType == JAVA_TYPE_OBJECT || javaType == JAVA_TYPE_BYTE_ARRAY) { - print_error(field, "Invalid primary state field: '%s'\n", - atomDecl->message.c_str()); - errorCount++; - } else { - atomDecl->primaryFields.push_back(fieldNumber); - addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_PRIMARY_FIELD, - ANNOTATION_TYPE_BOOL, AnnotationValue(true)); - } - } - - if (primaryFieldFirstUid) { - if (javaType != JAVA_TYPE_ATTRIBUTION_CHAIN) { - print_error(field, - "PRIMARY_FIELD_FIRST_UID annotation is only for AttributionChains: " - "'%s'\n", - atomDecl->message.c_str()); - errorCount++; - } else { - atomDecl->primaryFields.push_back(FIRST_UID_IN_CHAIN_ID); - addAnnotationToAtomDecl(atomDecl, fieldNumber, - ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, ANNOTATION_TYPE_BOOL, - AnnotationValue(true)); - } - } - - if (exclusiveState) { - if (javaType == JAVA_TYPE_UNKNOWN || javaType == JAVA_TYPE_ATTRIBUTION_CHAIN || - javaType == JAVA_TYPE_OBJECT || javaType == JAVA_TYPE_BYTE_ARRAY) { - print_error(field, "Invalid exclusive state field: '%s'\n", - atomDecl->message.c_str()); - errorCount++; - } - - if (atomDecl->exclusiveField != 0) { - print_error(field, - "Cannot have more than one exclusive state field in an " - "atom: '%s'\n", - atomDecl->message.c_str()); - errorCount++; - } else { - atomDecl->exclusiveField = fieldNumber; - addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_EXCLUSIVE_STATE, - ANNOTATION_TYPE_BOOL, AnnotationValue(true)); - } - - if (stateFieldOption.has_default_state_value()) { - const int defaultState = stateFieldOption.default_state_value(); - atomDecl->defaultState = defaultState; - - addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_DEFAULT_STATE, - ANNOTATION_TYPE_INT, AnnotationValue(defaultState)); - } - - if (stateFieldOption.has_trigger_state_reset_value()) { - const int triggerStateReset = stateFieldOption.trigger_state_reset_value(); - - atomDecl->triggerStateReset = triggerStateReset; - addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_TRIGGER_STATE_RESET, - ANNOTATION_TYPE_INT, AnnotationValue(triggerStateReset)); - } - - if (stateFieldOption.has_nested()) { - const bool nested = stateFieldOption.nested(); - atomDecl->nested = nested; - - addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_STATE_NESTED, - ANNOTATION_TYPE_BOOL, AnnotationValue(nested)); - } - } - } - - if (field->options().GetExtension(os::statsd::is_uid) == true) { - if (javaType != JAVA_TYPE_INT) { - print_error(field, "is_uid annotation can only be applied to int32 fields: '%s'\n", - atomDecl->message.c_str()); - errorCount++; - } - - if (atomDecl->uidField == 0) { - atomDecl->uidField = fieldNumber; - - addAnnotationToAtomDecl(atomDecl, fieldNumber, ANNOTATION_ID_IS_UID, - ANNOTATION_TYPE_BOOL, AnnotationValue(true)); - } else { - print_error(field, - "Cannot have more than one field in an atom with is_uid " - "annotation: '%s'\n", - atomDecl->message.c_str()); - errorCount++; - } - } - - return errorCount; -} - -/** - * Gather the info about an atom proto. - */ -int collate_atom(const Descriptor* atom, AtomDecl* atomDecl, vector<java_type_t>* signature) { - int errorCount = 0; - - // Build a sorted list of the fields. Descriptor has them in source file - // order. - map<int, const FieldDescriptor*> fields; - for (int j = 0; j < atom->field_count(); j++) { - const FieldDescriptor* field = atom->field(j); - fields[field->number()] = field; - } - - // Check that the parameters start at 1 and go up sequentially. - int expectedNumber = 1; - for (map<int, const FieldDescriptor*>::const_iterator it = fields.begin(); it != fields.end(); - it++) { - const int number = it->first; - const FieldDescriptor* field = it->second; - if (number != expectedNumber) { - print_error(field, - "Fields must be numbered consecutively starting at 1:" - " '%s' is %d but should be %d\n", - field->name().c_str(), number, expectedNumber); - errorCount++; - expectedNumber = number; - continue; - } - expectedNumber++; - } - - // Check that only allowed types are present. Remove any invalid ones. - for (map<int, const FieldDescriptor*>::const_iterator it = fields.begin(); it != fields.end(); - it++) { - const FieldDescriptor* field = it->second; - bool isBinaryField = field->options().GetExtension(os::statsd::log_mode) == - os::statsd::LogMode::MODE_BYTES; - - java_type_t javaType = java_type(field); - - if (javaType == JAVA_TYPE_UNKNOWN) { - print_error(field, "Unknown type for field: %s\n", field->name().c_str()); - errorCount++; - continue; - } else if (javaType == JAVA_TYPE_OBJECT && atomDecl->code < PULL_ATOM_START_ID) { - // Allow attribution chain, but only at position 1. - print_error(field, "Message type not allowed for field in pushed atoms: %s\n", - field->name().c_str()); - errorCount++; - continue; - } else if (javaType == JAVA_TYPE_BYTE_ARRAY && !isBinaryField) { - print_error(field, "Raw bytes type not allowed for field: %s\n", field->name().c_str()); - errorCount++; - continue; - } - - if (isBinaryField && javaType != JAVA_TYPE_BYTE_ARRAY) { - print_error(field, "Cannot mark field %s as bytes.\n", field->name().c_str()); - errorCount++; - continue; - } - - // Doubles are not supported yet. - if (javaType == JAVA_TYPE_DOUBLE) { - print_error(field, - "Doubles are not supported in atoms. Please change field %s " - "to float\n", - field->name().c_str()); - errorCount++; - continue; - } - - if (field->is_repeated() && - !(javaType == JAVA_TYPE_ATTRIBUTION_CHAIN || javaType == JAVA_TYPE_KEY_VALUE_PAIR)) { - print_error(field, - "Repeated fields are not supported in atoms. Please make " - "field %s not " - "repeated.\n", - field->name().c_str()); - errorCount++; - continue; - } - } - - // Check that if there's an attribution chain, it's at position 1. - for (map<int, const FieldDescriptor*>::const_iterator it = fields.begin(); it != fields.end(); - it++) { - int number = it->first; - if (number != 1) { - const FieldDescriptor* field = it->second; - java_type_t javaType = java_type(field); - if (javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) { - print_error(field, - "AttributionChain fields must have field id 1, in message: '%s'\n", - atom->name().c_str()); - errorCount++; - } - } - } - - // Build the type signature and the atom data. - for (map<int, const FieldDescriptor*>::const_iterator it = fields.begin(); it != fields.end(); - it++) { - const FieldDescriptor* field = it->second; - java_type_t javaType = java_type(field); - bool isBinaryField = field->options().GetExtension(os::statsd::log_mode) == - os::statsd::LogMode::MODE_BYTES; - - AtomField atField(field->name(), javaType); - - if (javaType == JAVA_TYPE_ENUM) { - // All enums are treated as ints when it comes to function signatures. - collate_enums(*field->enum_type(), &atField); - } - - // Generate signature for atom. - if (javaType == JAVA_TYPE_ENUM) { - // All enums are treated as ints when it comes to function signatures. - signature->push_back(JAVA_TYPE_INT); - } else if (javaType == JAVA_TYPE_OBJECT && isBinaryField) { - signature->push_back(JAVA_TYPE_BYTE_ARRAY); - } else { - signature->push_back(javaType); - } - - atomDecl->fields.push_back(atField); - - errorCount += collate_field_annotations(atomDecl, field, it->first, javaType); - } - - return errorCount; -} - -// This function flattens the fields of the AttributionNode proto in an Atom -// proto and generates the corresponding atom decl and signature. -bool get_non_chained_node(const Descriptor* atom, AtomDecl* atomDecl, - vector<java_type_t>* signature) { - // Build a sorted list of the fields. Descriptor has them in source file - // order. - map<int, const FieldDescriptor*> fields; - for (int j = 0; j < atom->field_count(); j++) { - const FieldDescriptor* field = atom->field(j); - fields[field->number()] = field; - } - - AtomDecl attributionDecl; - vector<java_type_t> attributionSignature; - collate_atom(android::os::statsd::AttributionNode::descriptor(), &attributionDecl, - &attributionSignature); - - // Build the type signature and the atom data. - bool has_attribution_node = false; - for (map<int, const FieldDescriptor*>::const_iterator it = fields.begin(); it != fields.end(); - it++) { - const FieldDescriptor* field = it->second; - java_type_t javaType = java_type(field); - if (javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) { - atomDecl->fields.insert(atomDecl->fields.end(), attributionDecl.fields.begin(), - attributionDecl.fields.end()); - signature->insert(signature->end(), attributionSignature.begin(), - attributionSignature.end()); - has_attribution_node = true; - - } else { - AtomField atField(field->name(), javaType); - if (javaType == JAVA_TYPE_ENUM) { - // All enums are treated as ints when it comes to function signatures. - signature->push_back(JAVA_TYPE_INT); - collate_enums(*field->enum_type(), &atField); - } else { - signature->push_back(javaType); - } - atomDecl->fields.push_back(atField); - } - } - return has_attribution_node; -} - -static void populateFieldNumberToAtomDeclSet(const shared_ptr<AtomDecl>& atomDecl, - FieldNumberToAtomDeclSet* fieldNumberToAtomDeclSet) { - for (FieldNumberToAnnotations::const_iterator it = atomDecl->fieldNumberToAnnotations.begin(); - it != atomDecl->fieldNumberToAnnotations.end(); it++) { - const int fieldNumber = it->first; - (*fieldNumberToAtomDeclSet)[fieldNumber].insert(atomDecl); - } -} - -/** - * Gather the info about the atoms. - */ -int collate_atoms(const Descriptor* descriptor, const string& moduleName, Atoms* atoms) { - int errorCount = 0; - - for (int i = 0; i < descriptor->field_count(); i++) { - const FieldDescriptor* atomField = descriptor->field(i); - - if (moduleName != DEFAULT_MODULE_NAME) { - const int moduleCount = atomField->options().ExtensionSize(os::statsd::module); - int j; - for (j = 0; j < moduleCount; ++j) { - const string atomModuleName = - atomField->options().GetExtension(os::statsd::module, j); - if (atomModuleName == moduleName) { - break; - } - } - - // This atom is not in the module we're interested in; skip it. - if (moduleCount == j) { - if (dbg) { - printf(" Skipping %s (%d)\n", atomField->name().c_str(), atomField->number()); - } - continue; - } - } - - if (dbg) { - printf(" %s (%d)\n", atomField->name().c_str(), atomField->number()); - } - - // StatsEvent only has one oneof, which contains only messages. Don't allow - // other types. - if (atomField->type() != FieldDescriptor::TYPE_MESSAGE) { - print_error(atomField, - "Bad type for atom. StatsEvent can only have message type " - "fields: %s\n", - atomField->name().c_str()); - errorCount++; - continue; - } - - const Descriptor* atom = atomField->message_type(); - shared_ptr<AtomDecl> atomDecl = - make_shared<AtomDecl>(atomField->number(), atomField->name(), atom->name()); - - if (atomField->options().GetExtension(os::statsd::truncate_timestamp)) { - addAnnotationToAtomDecl(atomDecl.get(), ATOM_ID_FIELD_NUMBER, - ANNOTATION_ID_TRUNCATE_TIMESTAMP, ANNOTATION_TYPE_BOOL, - AnnotationValue(true)); - if (dbg) { - printf("%s can have timestamp truncated\n", atomField->name().c_str()); - } - } - - vector<java_type_t> signature; - errorCount += collate_atom(atom, atomDecl.get(), &signature); - if (!atomDecl->primaryFields.empty() && atomDecl->exclusiveField == 0) { - print_error(atomField, "Cannot have a primary field without an exclusive field: %s\n", - atomField->name().c_str()); - errorCount++; - continue; - } - - const OneofDescriptor* oneofAtom = atomField->containing_oneof(); - if (oneofAtom == nullptr) { - print_error(atomField, "Atom is not declared in a `oneof` field: %s\n", - atomField->name().c_str()); - errorCount++; - continue; - } else if ((oneofAtom->name() != ONEOF_PUSHED_ATOM_NAME) && - (oneofAtom->name() != ONEOF_PULLED_ATOM_NAME)) { - print_error(atomField, "Atom is neither a pushed nor pulled atom: %s\n", - atomField->name().c_str()); - errorCount++; - continue; - } - - FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet = oneofAtom->name() == - ONEOF_PUSHED_ATOM_NAME ? atoms->signatureInfoMap[signature] : - atoms->pulledAtomsSignatureInfoMap[signature]; - populateFieldNumberToAtomDeclSet(atomDecl, &fieldNumberToAtomDeclSet); - - atoms->decls.insert(atomDecl); - - shared_ptr<AtomDecl> nonChainedAtomDecl = - make_shared<AtomDecl>(atomField->number(), atomField->name(), atom->name()); - vector<java_type_t> nonChainedSignature; - if (get_non_chained_node(atom, nonChainedAtomDecl.get(), &nonChainedSignature)) { - FieldNumberToAtomDeclSet& nonChainedFieldNumberToAtomDeclSet = - atoms->nonChainedSignatureInfoMap[nonChainedSignature]; - populateFieldNumberToAtomDeclSet(nonChainedAtomDecl, - &nonChainedFieldNumberToAtomDeclSet); - - atoms->non_chained_decls.insert(nonChainedAtomDecl); - } - } - - if (dbg) { - // Signatures for pushed atoms. - printf("signatures = [\n"); - for (SignatureInfoMap::const_iterator it = atoms->signatureInfoMap.begin(); - it != atoms->signatureInfoMap.end(); it++) { - printf(" "); - for (vector<java_type_t>::const_iterator jt = it->first.begin(); jt != it->first.end(); - jt++) { - printf(" %d", static_cast<int>(*jt)); - } - printf("\n"); - } - - // Signatures for pull atoms. - for (SignatureInfoMap::const_iterator it = atoms->pulledAtomsSignatureInfoMap.begin(); - it != atoms->pulledAtomsSignatureInfoMap.end(); it++) { - printf(" "); - for (vector<java_type_t>::const_iterator jt = it->first.begin(); jt != it->first.end(); - jt++) { - printf(" %d", static_cast<int>(*jt)); - } - printf("\n"); - } - printf("]\n"); - } - - return errorCount; -} - -} // namespace stats_log_api_gen -} // namespace android diff --git a/tools/stats_log_api_gen/Collation.h b/tools/stats_log_api_gen/Collation.h deleted file mode 100644 index b13851c07d04..000000000000 --- a/tools/stats_log_api_gen/Collation.h +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (C) 2017, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_STATS_LOG_API_GEN_COLLATION_H -#define ANDROID_STATS_LOG_API_GEN_COLLATION_H - -#include <google/protobuf/descriptor.h> -#include <stdint.h> - -#include <map> -#include <set> -#include <vector> - -#include "frameworks/proto_logging/stats/atom_field_options.pb.h" - -namespace android { -namespace stats_log_api_gen { - -using google::protobuf::OneofDescriptor; -using google::protobuf::Descriptor; -using google::protobuf::FieldDescriptor; -using std::map; -using std::set; -using std::shared_ptr; -using std::string; -using std::vector; - -const int PULL_ATOM_START_ID = 10000; - -const int FIRST_UID_IN_CHAIN_ID = 0; - -/** - * The types of oneof atoms. - * - * `OneofDescriptor::name()` returns the name of the oneof. - */ -const char ONEOF_PUSHED_ATOM_NAME[] = "pushed"; -const char ONEOF_PULLED_ATOM_NAME[] = "pulled"; - -enum AnnotationId : uint8_t { - ANNOTATION_ID_IS_UID = 1, - ANNOTATION_ID_TRUNCATE_TIMESTAMP = 2, - ANNOTATION_ID_PRIMARY_FIELD = 3, - ANNOTATION_ID_EXCLUSIVE_STATE = 4, - ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID = 5, - ANNOTATION_ID_DEFAULT_STATE = 6, - ANNOTATION_ID_TRIGGER_STATE_RESET = 7, - ANNOTATION_ID_STATE_NESTED = 8, -}; - -const int ATOM_ID_FIELD_NUMBER = -1; - -const char DEFAULT_MODULE_NAME[] = "DEFAULT"; - -/** - * The types for atom parameters. - */ -typedef enum { - JAVA_TYPE_UNKNOWN = 0, - - JAVA_TYPE_ATTRIBUTION_CHAIN = 1, - JAVA_TYPE_BOOLEAN = 2, - JAVA_TYPE_INT = 3, - JAVA_TYPE_LONG = 4, - JAVA_TYPE_FLOAT = 5, - JAVA_TYPE_DOUBLE = 6, - JAVA_TYPE_STRING = 7, - JAVA_TYPE_ENUM = 8, - JAVA_TYPE_KEY_VALUE_PAIR = 9, - - JAVA_TYPE_OBJECT = -1, - JAVA_TYPE_BYTE_ARRAY = -2, -} java_type_t; - -enum AnnotationType { - ANNOTATION_TYPE_UNKNOWN = 0, - ANNOTATION_TYPE_INT = 1, - ANNOTATION_TYPE_BOOL = 2, -}; - -union AnnotationValue { - int intValue; - bool boolValue; - - explicit AnnotationValue(const int value) : intValue(value) { - } - explicit AnnotationValue(const bool value) : boolValue(value) { - } -}; - -struct Annotation { - const AnnotationId annotationId; - const int atomId; - AnnotationType type; - AnnotationValue value; - - inline Annotation(AnnotationId annotationId, int atomId, AnnotationType type, - AnnotationValue value) - : annotationId(annotationId), atomId(atomId), type(type), value(value) { - } - inline ~Annotation() { - } - - inline bool operator<(const Annotation& that) const { - return atomId == that.atomId ? annotationId < that.annotationId : atomId < that.atomId; - } -}; - -struct SharedComparator { - template <typename T> - inline bool operator()(const shared_ptr<T>& lhs, const shared_ptr<T>& rhs) const { - return (*lhs) < (*rhs); - } -}; - -using AnnotationSet = set<shared_ptr<Annotation>, SharedComparator>; - -using FieldNumberToAnnotations = map<int, AnnotationSet>; - -/** - * The name and type for an atom field. - */ -struct AtomField { - string name; - java_type_t javaType; - - // If the field is of type enum, the following map contains the list of enum - // values. - map<int /* numeric value */, string /* value name */> enumValues; - - inline AtomField() : name(), javaType(JAVA_TYPE_UNKNOWN) { - } - inline AtomField(const AtomField& that) - : name(that.name), javaType(that.javaType), enumValues(that.enumValues) { - } - - inline AtomField(string n, java_type_t jt) : name(n), javaType(jt) { - } - inline ~AtomField() { - } -}; - -/** - * The name and code for an atom. - */ -struct AtomDecl { - int code; - string name; - - string message; - vector<AtomField> fields; - - FieldNumberToAnnotations fieldNumberToAnnotations; - - vector<int> primaryFields; - int exclusiveField = 0; - int defaultState = INT_MAX; - int triggerStateReset = INT_MAX; - bool nested = true; - - int uidField = 0; - - AtomDecl(); - AtomDecl(const AtomDecl& that); - AtomDecl(int code, const string& name, const string& message); - ~AtomDecl(); - - inline bool operator<(const AtomDecl& that) const { - return (code == that.code) ? (name < that.name) : (code < that.code); - } -}; - -using AtomDeclSet = set<shared_ptr<AtomDecl>, SharedComparator>; - -// Maps a field number to a set of atoms that have annotation(s) for their field with that field -// number. -using FieldNumberToAtomDeclSet = map<int, AtomDeclSet>; - -using SignatureInfoMap = map<vector<java_type_t>, FieldNumberToAtomDeclSet>; - -struct Atoms { - SignatureInfoMap signatureInfoMap; - SignatureInfoMap pulledAtomsSignatureInfoMap; - AtomDeclSet decls; - AtomDeclSet non_chained_decls; - SignatureInfoMap nonChainedSignatureInfoMap; -}; - -/** - * Gather the information about the atoms. Returns the number of errors. - */ -int collate_atoms(const Descriptor* descriptor, const string& moduleName, Atoms* atoms); -int collate_atom(const Descriptor* atom, AtomDecl* atomDecl, vector<java_type_t>* signature); - -} // namespace stats_log_api_gen -} // namespace android - -#endif // ANDROID_STATS_LOG_API_GEN_COLLATION_H diff --git a/tools/stats_log_api_gen/OWNERS b/tools/stats_log_api_gen/OWNERS deleted file mode 100644 index 41a0c95f13c9..000000000000 --- a/tools/stats_log_api_gen/OWNERS +++ /dev/null @@ -1 +0,0 @@ -yro@google.com diff --git a/tools/stats_log_api_gen/java_writer.cpp b/tools/stats_log_api_gen/java_writer.cpp deleted file mode 100644 index 6fcf267cf39c..000000000000 --- a/tools/stats_log_api_gen/java_writer.cpp +++ /dev/null @@ -1,384 +0,0 @@ -/* - * Copyright (C) 2019, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "java_writer.h" - -#include "java_writer_q.h" -#include "utils.h" - -namespace android { -namespace stats_log_api_gen { - -static int write_java_q_logger_class(FILE* out, const SignatureInfoMap& signatureInfoMap, - const AtomDecl& attributionDecl) { - fprintf(out, "\n"); - fprintf(out, " // Write logging helper methods for statsd in Q and earlier.\n"); - fprintf(out, " private static class QLogger {\n"); - - write_java_q_logging_constants(out, " "); - - // Print Q write methods. - fprintf(out, "\n"); - fprintf(out, " // Write methods.\n"); - write_java_methods_q_schema(out, signatureInfoMap, attributionDecl, " "); - - fprintf(out, " }\n"); - return 0; -} - -static void write_java_annotation_constants(FILE* out) { - fprintf(out, " // Annotation constants.\n"); - - const map<AnnotationId, string>& ANNOTATION_ID_CONSTANTS = get_annotation_id_constants(); - for (const auto& [id, name] : ANNOTATION_ID_CONSTANTS) { - fprintf(out, " public static final byte %s = %hhu;\n", name.c_str(), id); - } - fprintf(out, "\n"); -} - -static void write_annotations(FILE* out, int argIndex, - const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet) { - FieldNumberToAtomDeclSet::const_iterator fieldNumberToAtomDeclSetIt = - fieldNumberToAtomDeclSet.find(argIndex); - if (fieldNumberToAtomDeclSet.end() == fieldNumberToAtomDeclSetIt) { - return; - } - const AtomDeclSet& atomDeclSet = fieldNumberToAtomDeclSetIt->second; - const map<AnnotationId, string>& ANNOTATION_ID_CONSTANTS = get_annotation_id_constants(); - for (const shared_ptr<AtomDecl>& atomDecl : atomDeclSet) { - const string atomConstant = make_constant_name(atomDecl->name); - fprintf(out, " if (%s == code) {\n", atomConstant.c_str()); - const AnnotationSet& annotations = atomDecl->fieldNumberToAnnotations.at(argIndex); - int resetState = -1; - int defaultState = -1; - for (const shared_ptr<Annotation>& annotation : annotations) { - const string& annotationConstant = ANNOTATION_ID_CONSTANTS.at(annotation->annotationId); - switch (annotation->type) { - case ANNOTATION_TYPE_INT: - if (ANNOTATION_ID_TRIGGER_STATE_RESET == annotation->annotationId) { - resetState = annotation->value.intValue; - } else if (ANNOTATION_ID_DEFAULT_STATE == annotation->annotationId) { - defaultState = annotation->value.intValue; - } else { - fprintf(out, " builder.addIntAnnotation(%s, %d);\n", - annotationConstant.c_str(), annotation->value.intValue); - } - break; - case ANNOTATION_TYPE_BOOL: - fprintf(out, " builder.addBooleanAnnotation(%s, %s);\n", - annotationConstant.c_str(), - annotation->value.boolValue ? "true" : "false"); - break; - default: - break; - } - } - if (defaultState != -1 && resetState != -1) { - const string& annotationConstant = - ANNOTATION_ID_CONSTANTS.at(ANNOTATION_ID_TRIGGER_STATE_RESET); - fprintf(out, " if (arg%d == %d) {\n", argIndex, resetState); - fprintf(out, " builder.addIntAnnotation(%s, %d);\n", - annotationConstant.c_str(), defaultState); - fprintf(out, " }\n"); - } - fprintf(out, " }\n"); - } -} - -static void write_method_signature(FILE* out, const vector<java_type_t>& signature, - const AtomDecl& attributionDecl) { - int argIndex = 1; - for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end(); - arg++) { - if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) { - for (const auto& chainField : attributionDecl.fields) { - fprintf(out, ", %s[] %s", java_type_name(chainField.javaType), - chainField.name.c_str()); - } - } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) { - fprintf(out, ", android.util.SparseArray<Object> valueMap"); - } else { - fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex); - } - argIndex++; - } -} - -static int write_method_body(FILE* out, const vector<java_type_t>& signature, - const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet, - const AtomDecl& attributionDecl, const string& indent) { - // Start StatsEvent.Builder. - fprintf(out, - "%s final StatsEvent.Builder builder = " - "StatsEvent.newBuilder();\n", - indent.c_str()); - - // Write atom code. - fprintf(out, "%s builder.setAtomId(code);\n", indent.c_str()); - write_annotations(out, ATOM_ID_FIELD_NUMBER, fieldNumberToAtomDeclSet); - - // Write the args. - int argIndex = 1; - for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end(); - arg++) { - switch (*arg) { - case JAVA_TYPE_BOOLEAN: - fprintf(out, "%s builder.writeBoolean(arg%d);\n", indent.c_str(), - argIndex); - break; - case JAVA_TYPE_INT: - case JAVA_TYPE_ENUM: - fprintf(out, "%s builder.writeInt(arg%d);\n", indent.c_str(), argIndex); - break; - case JAVA_TYPE_FLOAT: - fprintf(out, "%s builder.writeFloat(arg%d);\n", indent.c_str(), - argIndex); - break; - case JAVA_TYPE_LONG: - fprintf(out, "%s builder.writeLong(arg%d);\n", indent.c_str(), argIndex); - break; - case JAVA_TYPE_STRING: - fprintf(out, "%s builder.writeString(arg%d);\n", indent.c_str(), - argIndex); - break; - case JAVA_TYPE_BYTE_ARRAY: - fprintf(out, - "%s builder.writeByteArray(null == arg%d ? new byte[0] : " - "arg%d);\n", - indent.c_str(), argIndex, argIndex); - break; - case JAVA_TYPE_ATTRIBUTION_CHAIN: { - const char* uidName = attributionDecl.fields.front().name.c_str(); - const char* tagName = attributionDecl.fields.back().name.c_str(); - - fprintf(out, "%s builder.writeAttributionChain(\n", indent.c_str()); - fprintf(out, "%s null == %s ? new int[0] : %s,\n", - indent.c_str(), uidName, uidName); - fprintf(out, "%s null == %s ? new String[0] : %s);\n", - indent.c_str(), tagName, tagName); - break; - } - case JAVA_TYPE_KEY_VALUE_PAIR: - fprintf(out, "\n"); - fprintf(out, "%s // Write KeyValuePairs.\n", indent.c_str()); - fprintf(out, "%s final int count = valueMap.size();\n", indent.c_str()); - fprintf(out, "%s android.util.SparseIntArray intMap = null;\n", - indent.c_str()); - fprintf(out, "%s android.util.SparseLongArray longMap = null;\n", - indent.c_str()); - fprintf(out, "%s android.util.SparseArray<String> stringMap = null;\n", - indent.c_str()); - fprintf(out, "%s android.util.SparseArray<Float> floatMap = null;\n", - indent.c_str()); - fprintf(out, "%s for (int i = 0; i < count; i++) {\n", indent.c_str()); - fprintf(out, "%s final int key = valueMap.keyAt(i);\n", - indent.c_str()); - fprintf(out, "%s final Object value = valueMap.valueAt(i);\n", - indent.c_str()); - fprintf(out, "%s if (value instanceof Integer) {\n", indent.c_str()); - fprintf(out, "%s if (null == intMap) {\n", indent.c_str()); - fprintf(out, - "%s intMap = new " - "android.util.SparseIntArray();\n", - indent.c_str()); - fprintf(out, "%s }\n", indent.c_str()); - fprintf(out, "%s intMap.put(key, (Integer) value);\n", - indent.c_str()); - fprintf(out, "%s } else if (value instanceof Long) {\n", - indent.c_str()); - fprintf(out, "%s if (null == longMap) {\n", indent.c_str()); - fprintf(out, - "%s longMap = new " - "android.util.SparseLongArray();\n", - indent.c_str()); - fprintf(out, "%s }\n", indent.c_str()); - fprintf(out, "%s longMap.put(key, (Long) value);\n", - indent.c_str()); - fprintf(out, "%s } else if (value instanceof String) {\n", - indent.c_str()); - fprintf(out, "%s if (null == stringMap) {\n", indent.c_str()); - fprintf(out, - "%s stringMap = new " - "android.util.SparseArray<>();\n", - indent.c_str()); - fprintf(out, "%s }\n", indent.c_str()); - fprintf(out, "%s stringMap.put(key, (String) value);\n", - indent.c_str()); - fprintf(out, "%s } else if (value instanceof Float) {\n", - indent.c_str()); - fprintf(out, "%s if (null == floatMap) {\n", indent.c_str()); - fprintf(out, - "%s floatMap = new " - "android.util.SparseArray<>();\n", - indent.c_str()); - fprintf(out, "%s }\n", indent.c_str()); - fprintf(out, "%s floatMap.put(key, (Float) value);\n", - indent.c_str()); - fprintf(out, "%s }\n", indent.c_str()); - fprintf(out, "%s }\n", indent.c_str()); - fprintf(out, - "%s builder.writeKeyValuePairs(" - "intMap, longMap, stringMap, floatMap);\n", - indent.c_str()); - break; - default: - // Unsupported types: OBJECT, DOUBLE. - fprintf(stderr, "Encountered unsupported type."); - return 1; - } - write_annotations(out, argIndex, fieldNumberToAtomDeclSet); - argIndex++; - } - return 0; -} - -static int write_java_pushed_methods(FILE* out, const SignatureInfoMap& signatureInfoMap, - const AtomDecl& attributionDecl, const bool supportQ) { - for (auto signatureInfoMapIt = signatureInfoMap.begin(); - signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) { - // Print method signature. - fprintf(out, " public static void write(int code"); - const vector<java_type_t>& signature = signatureInfoMapIt->first; - const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet = signatureInfoMapIt->second; - write_method_signature(out, signature, attributionDecl); - fprintf(out, ") {\n"); - - // Print method body. - string indent(""); - if (supportQ) { - fprintf(out, " if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) {\n"); - indent = " "; - } - - int ret = write_method_body(out, signature, fieldNumberToAtomDeclSet, - attributionDecl, indent); - if (ret != 0) { - return ret; - } - fprintf(out, "\n"); - - fprintf(out, "%s builder.usePooledBuffer();\n", indent.c_str()); - fprintf(out, "%s StatsLog.write(builder.build());\n", indent.c_str()); - - // Add support for writing using Q schema if this is not the default module. - if (supportQ) { - fprintf(out, " } else {\n"); - fprintf(out, " QLogger.write(code"); - int argIndex = 1; - for (vector<java_type_t>::const_iterator arg = signature.begin(); - arg != signature.end(); arg++) { - if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) { - const char* uidName = attributionDecl.fields.front().name.c_str(); - const char* tagName = attributionDecl.fields.back().name.c_str(); - fprintf(out, ", %s, %s", uidName, tagName); - } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) { - // Module logging does not yet support key value pair. - fprintf(stderr, "Module logging does not yet support key value pair.\n"); - return 1; - } else { - fprintf(out, ", arg%d", argIndex); - } - argIndex++; - } - fprintf(out, ");\n"); - fprintf(out, " }\n"); // if - } - - fprintf(out, " }\n"); // method - fprintf(out, "\n"); - } - return 0; -} - -static int write_java_pulled_methods(FILE* out, const SignatureInfoMap& signatureInfoMap, - const AtomDecl& attributionDecl) { - for (auto signatureInfoMapIt = signatureInfoMap.begin(); - signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) { - // Print method signature. - fprintf(out, " public static StatsEvent buildStatsEvent(int code"); - const vector<java_type_t>& signature = signatureInfoMapIt->first; - const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet = signatureInfoMapIt->second; - write_method_signature(out, signature, attributionDecl); - fprintf(out, ") {\n"); - - // Print method body. - string indent(""); - int ret = write_method_body(out, signature, fieldNumberToAtomDeclSet, - attributionDecl, indent); - if (ret != 0) { - return ret; - } - fprintf(out, "\n"); - - fprintf(out, "%s return builder.build();\n", indent.c_str()); - - fprintf(out, " }\n"); // method - fprintf(out, "\n"); - } - return 0; -} - -int write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl, - const string& javaClass, const string& javaPackage, const bool supportQ, - const bool supportWorkSource) { - // Print prelude - fprintf(out, "// This file is autogenerated\n"); - fprintf(out, "\n"); - fprintf(out, "package %s;\n", javaPackage.c_str()); - fprintf(out, "\n"); - fprintf(out, "\n"); - if (supportQ) { - fprintf(out, "import android.os.Build;\n"); - fprintf(out, "import android.os.SystemClock;\n"); - } - - fprintf(out, "import android.util.StatsEvent;\n"); - fprintf(out, "import android.util.StatsLog;\n"); - - fprintf(out, "\n"); - fprintf(out, "\n"); - fprintf(out, "/**\n"); - fprintf(out, " * Utility class for logging statistics events.\n"); - fprintf(out, " */\n"); - fprintf(out, "public class %s {\n", javaClass.c_str()); - - write_java_atom_codes(out, atoms); - write_java_enum_values(out, atoms); - write_java_annotation_constants(out); - - int errors = 0; - - // Print write methods. - fprintf(out, " // Write methods\n"); - errors += write_java_pushed_methods(out, atoms.signatureInfoMap, attributionDecl, supportQ); - errors += write_java_non_chained_methods(out, atoms.nonChainedSignatureInfoMap); - errors += write_java_pulled_methods(out, atoms.pulledAtomsSignatureInfoMap, - attributionDecl); - if (supportWorkSource) { - errors += write_java_work_source_methods(out, atoms.signatureInfoMap); - } - - if (supportQ) { - errors += write_java_q_logger_class(out, atoms.signatureInfoMap, attributionDecl); - } - - fprintf(out, "}\n"); - - return errors; -} - -} // namespace stats_log_api_gen -} // namespace android diff --git a/tools/stats_log_api_gen/java_writer.h b/tools/stats_log_api_gen/java_writer.h deleted file mode 100644 index afd992be6c5e..000000000000 --- a/tools/stats_log_api_gen/java_writer.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2019, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_STATS_LOG_API_GEN_JAVA_WRITER_H -#define ANDROID_STATS_LOG_API_GEN_JAVA_WRITER_H - -#include <stdio.h> -#include <string.h> - -#include <map> -#include <set> -#include <vector> - -#include "Collation.h" - -namespace android { -namespace stats_log_api_gen { - -int write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl, - const string& javaClass, const string& javaPackage, const bool supportQ, - const bool supportWorkSource); - -} // namespace stats_log_api_gen -} // namespace android - -#endif // ANDROID_STATS_LOG_API_GEN_JAVA_WRITER_H diff --git a/tools/stats_log_api_gen/java_writer_q.cpp b/tools/stats_log_api_gen/java_writer_q.cpp deleted file mode 100644 index be7cb4aeb3f8..000000000000 --- a/tools/stats_log_api_gen/java_writer_q.cpp +++ /dev/null @@ -1,601 +0,0 @@ -/* - * Copyright (C) 2019, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "java_writer_q.h" - -#include "utils.h" - -namespace android { -namespace stats_log_api_gen { - -void write_java_q_logging_constants(FILE* out, const string& indent) { - fprintf(out, "%s// Payload limits.\n", indent.c_str()); - fprintf(out, "%sprivate static final int LOGGER_ENTRY_MAX_PAYLOAD = 4068;\n", indent.c_str()); - fprintf(out, - "%sprivate static final int MAX_EVENT_PAYLOAD = " - "LOGGER_ENTRY_MAX_PAYLOAD - 4;\n", - indent.c_str()); - - // Value types. Must match with EventLog.java and log.h. - fprintf(out, "\n"); - fprintf(out, "%s// Value types.\n", indent.c_str()); - fprintf(out, "%sprivate static final byte INT_TYPE = 0;\n", indent.c_str()); - fprintf(out, "%sprivate static final byte LONG_TYPE = 1;\n", indent.c_str()); - fprintf(out, "%sprivate static final byte STRING_TYPE = 2;\n", indent.c_str()); - fprintf(out, "%sprivate static final byte LIST_TYPE = 3;\n", indent.c_str()); - fprintf(out, "%sprivate static final byte FLOAT_TYPE = 4;\n", indent.c_str()); - - // Size of each value type. - // Booleans, ints, floats, and enums take 5 bytes, 1 for the type and 4 for - // the value. - fprintf(out, "\n"); - fprintf(out, "%s// Size of each value type.\n", indent.c_str()); - fprintf(out, "%sprivate static final int INT_TYPE_SIZE = 5;\n", indent.c_str()); - fprintf(out, "%sprivate static final int FLOAT_TYPE_SIZE = 5;\n", indent.c_str()); - // Longs take 9 bytes, 1 for the type and 8 for the value. - fprintf(out, "%sprivate static final int LONG_TYPE_SIZE = 9;\n", indent.c_str()); - // Strings take 5 metadata bytes: 1 byte is for the type, 4 are for the - // length. - fprintf(out, "%sprivate static final int STRING_TYPE_OVERHEAD = 5;\n", indent.c_str()); - fprintf(out, "%sprivate static final int LIST_TYPE_OVERHEAD = 2;\n", indent.c_str()); -} - -int write_java_methods_q_schema(FILE* out, const SignatureInfoMap& signatureInfoMap, - const AtomDecl& attributionDecl, const string& indent) { - int requiredHelpers = 0; - for (auto signatureInfoMapIt = signatureInfoMap.begin(); - signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) { - // Print method signature. - vector<java_type_t> signature = signatureInfoMapIt->first; - fprintf(out, "%spublic static void write(int code", indent.c_str()); - int argIndex = 1; - for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end(); - arg++) { - if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) { - for (const auto& chainField : attributionDecl.fields) { - fprintf(out, ", %s[] %s", java_type_name(chainField.javaType), - chainField.name.c_str()); - } - } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) { - fprintf(out, ", android.util.SparseArray<Object> valueMap"); - } else { - fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex); - } - argIndex++; - } - fprintf(out, ") {\n"); - - // Calculate the size of the buffer. - fprintf(out, "%s // Initial overhead of the list, timestamp, and atom tag.\n", - indent.c_str()); - fprintf(out, - "%s int needed = LIST_TYPE_OVERHEAD + LONG_TYPE_SIZE + " - "INT_TYPE_SIZE;\n", - indent.c_str()); - argIndex = 1; - for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end(); - arg++) { - switch (*arg) { - case JAVA_TYPE_BOOLEAN: - case JAVA_TYPE_INT: - case JAVA_TYPE_FLOAT: - case JAVA_TYPE_ENUM: - fprintf(out, "%s needed += INT_TYPE_SIZE;\n", indent.c_str()); - break; - case JAVA_TYPE_LONG: - // Longs take 9 bytes, 1 for the type and 8 for the value. - fprintf(out, "%s needed += LONG_TYPE_SIZE;\n", indent.c_str()); - break; - case JAVA_TYPE_STRING: - // Strings take 5 metadata bytes + length of byte encoded string. - fprintf(out, "%s if (arg%d == null) {\n", indent.c_str(), argIndex); - fprintf(out, "%s arg%d = \"\";\n", indent.c_str(), argIndex); - fprintf(out, "%s }\n", indent.c_str()); - fprintf(out, - "%s byte[] arg%dBytes = " - "arg%d.getBytes(java.nio.charset.StandardCharsets.UTF_8);\n", - indent.c_str(), argIndex, argIndex); - fprintf(out, "%s needed += STRING_TYPE_OVERHEAD + arg%dBytes.length;\n", - indent.c_str(), argIndex); - break; - case JAVA_TYPE_BYTE_ARRAY: - // Byte arrays take 5 metadata bytes + length of byte array. - fprintf(out, "%s if (arg%d == null) {\n", indent.c_str(), argIndex); - fprintf(out, "%s arg%d = new byte[0];\n", indent.c_str(), argIndex); - fprintf(out, "%s }\n", indent.c_str()); - fprintf(out, "%s needed += STRING_TYPE_OVERHEAD + arg%d.length;\n", - indent.c_str(), argIndex); - break; - case JAVA_TYPE_ATTRIBUTION_CHAIN: { - const char* uidName = attributionDecl.fields.front().name.c_str(); - const char* tagName = attributionDecl.fields.back().name.c_str(); - // Null checks on the params. - fprintf(out, "%s if (%s == null) {\n", indent.c_str(), uidName); - fprintf(out, "%s %s = new %s[0];\n", indent.c_str(), uidName, - java_type_name(attributionDecl.fields.front().javaType)); - fprintf(out, "%s }\n", indent.c_str()); - fprintf(out, "%s if (%s == null) {\n", indent.c_str(), tagName); - fprintf(out, "%s %s = new %s[0];\n", indent.c_str(), tagName, - java_type_name(attributionDecl.fields.back().javaType)); - fprintf(out, "%s }\n", indent.c_str()); - - // First check that the lengths of the uid and tag arrays are the - // same. - fprintf(out, "%s if (%s.length != %s.length) {\n", indent.c_str(), uidName, - tagName); - fprintf(out, "%s return;\n", indent.c_str()); - fprintf(out, "%s }\n", indent.c_str()); - fprintf(out, "%s int attrSize = LIST_TYPE_OVERHEAD;\n", indent.c_str()); - fprintf(out, "%s for (int i = 0; i < %s.length; i++) {\n", indent.c_str(), - tagName); - fprintf(out, "%s String str%d = (%s[i] == null) ? \"\" : %s[i];\n", - indent.c_str(), argIndex, tagName, tagName); - fprintf(out, - "%s int str%dlen = " - "str%d.getBytes(java.nio.charset.StandardCharsets.UTF_8)." - "length;\n", - indent.c_str(), argIndex, argIndex); - fprintf(out, - "%s attrSize += " - "LIST_TYPE_OVERHEAD + INT_TYPE_SIZE + STRING_TYPE_OVERHEAD + " - "str%dlen;\n", - indent.c_str(), argIndex); - fprintf(out, "%s }\n", indent.c_str()); - fprintf(out, "%s needed += attrSize;\n", indent.c_str()); - break; - } - case JAVA_TYPE_KEY_VALUE_PAIR: { - fprintf(out, "%s // Calculate bytes needed by Key Value Pairs.\n", - indent.c_str()); - fprintf(out, "%s final int count = valueMap.size();\n", indent.c_str()); - fprintf(out, "%s android.util.SparseIntArray intMap = null;\n", - indent.c_str()); - fprintf(out, "%s android.util.SparseLongArray longMap = null;\n", - indent.c_str()); - fprintf(out, "%s android.util.SparseArray<String> stringMap = null;\n", - indent.c_str()); - fprintf(out, "%s android.util.SparseArray<Float> floatMap = null;\n", - indent.c_str()); - fprintf(out, "%s int keyValuePairSize = LIST_TYPE_OVERHEAD;\n", - indent.c_str()); - fprintf(out, "%s for (int i = 0; i < count; i++) {\n", indent.c_str()); - fprintf(out, "%s final int key = valueMap.keyAt(i);\n", indent.c_str()); - fprintf(out, "%s final Object value = valueMap.valueAt(i);\n", - indent.c_str()); - fprintf(out, "%s if (value instanceof Integer) {\n", indent.c_str()); - fprintf(out, "%s keyValuePairSize += LIST_TYPE_OVERHEAD\n", - indent.c_str()); - fprintf(out, "%s + INT_TYPE_SIZE + INT_TYPE_SIZE;\n", - indent.c_str()); - fprintf(out, "%s if (null == intMap) {\n", indent.c_str()); - fprintf(out, "%s intMap = new android.util.SparseIntArray();\n", - indent.c_str()); - fprintf(out, "%s }\n", indent.c_str()); - fprintf(out, "%s intMap.put(key, (Integer) value);\n", - indent.c_str()); - fprintf(out, "%s } else if (value instanceof Long) {\n", indent.c_str()); - fprintf(out, "%s keyValuePairSize += LIST_TYPE_OVERHEAD\n", - indent.c_str()); - fprintf(out, "%s + INT_TYPE_SIZE + LONG_TYPE_SIZE;\n", - indent.c_str()); - fprintf(out, "%s if (null == longMap) {\n", indent.c_str()); - fprintf(out, - "%s longMap = new " - "android.util.SparseLongArray();\n", - indent.c_str()); - fprintf(out, "%s }\n", indent.c_str()); - fprintf(out, "%s longMap.put(key, (Long) value);\n", indent.c_str()); - fprintf(out, "%s } else if (value instanceof String) {\n", - indent.c_str()); - fprintf(out, - "%s final String str = (value == null) ? \"\" : " - "(String) value;\n", - indent.c_str()); - fprintf(out, - "%s final int len = " - "str.getBytes(java.nio.charset.StandardCharsets.UTF_8).length;\n", - indent.c_str()); - fprintf(out, - "%s keyValuePairSize += LIST_TYPE_OVERHEAD + " - "INT_TYPE_SIZE\n", - indent.c_str()); - fprintf(out, "%s + STRING_TYPE_OVERHEAD + len;\n", - indent.c_str()); - fprintf(out, "%s if (null == stringMap) {\n", indent.c_str()); - fprintf(out, - "%s stringMap = new " - "android.util.SparseArray<>();\n", - indent.c_str()); - fprintf(out, "%s }\n", indent.c_str()); - fprintf(out, "%s stringMap.put(key, str);\n", indent.c_str()); - fprintf(out, "%s } else if (value instanceof Float) {\n", - indent.c_str()); - fprintf(out, "%s keyValuePairSize += LIST_TYPE_OVERHEAD\n", - indent.c_str()); - fprintf(out, "%s + INT_TYPE_SIZE + FLOAT_TYPE_SIZE;\n", - indent.c_str()); - fprintf(out, "%s if (null == floatMap) {\n", indent.c_str()); - fprintf(out, - "%s floatMap = new " - "android.util.SparseArray<>();\n", - indent.c_str()); - fprintf(out, "%s }\n", indent.c_str()); - fprintf(out, "%s floatMap.put(key, (Float) value);\n", - indent.c_str()); - fprintf(out, "%s }\n", indent.c_str()); - fprintf(out, "%s }\n", indent.c_str()); - fprintf(out, "%s needed += keyValuePairSize;\n", indent.c_str()); - break; - } - default: - // Unsupported types: OBJECT, DOUBLE. - fprintf(stderr, "Module logging does not yet support Object and Double.\n"); - return 1; - } - argIndex++; - } - - // Now we have the size that is needed. Check for overflow and return if - // needed. - fprintf(out, "%s if (needed > MAX_EVENT_PAYLOAD) {\n", indent.c_str()); - fprintf(out, "%s return;\n", indent.c_str()); - fprintf(out, "%s }\n", indent.c_str()); - - // Create new buffer, and associated data types. - fprintf(out, "%s byte[] buff = new byte[needed];\n", indent.c_str()); - fprintf(out, "%s int pos = 0;\n", indent.c_str()); - - // Initialize the buffer with list data type. - fprintf(out, "%s buff[pos] = LIST_TYPE;\n", indent.c_str()); - fprintf(out, "%s buff[pos + 1] = %zu;\n", indent.c_str(), signature.size() + 2); - fprintf(out, "%s pos += LIST_TYPE_OVERHEAD;\n", indent.c_str()); - - // Write timestamp. - fprintf(out, "%s long elapsedRealtime = SystemClock.elapsedRealtimeNanos();\n", - indent.c_str()); - fprintf(out, "%s buff[pos] = LONG_TYPE;\n", indent.c_str()); - fprintf(out, "%s copyLong(buff, pos + 1, elapsedRealtime);\n", indent.c_str()); - fprintf(out, "%s pos += LONG_TYPE_SIZE;\n", indent.c_str()); - - // Write atom code. - fprintf(out, "%s buff[pos] = INT_TYPE;\n", indent.c_str()); - fprintf(out, "%s copyInt(buff, pos + 1, code);\n", indent.c_str()); - fprintf(out, "%s pos += INT_TYPE_SIZE;\n", indent.c_str()); - - // Write the args. - argIndex = 1; - for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end(); - arg++) { - switch (*arg) { - case JAVA_TYPE_BOOLEAN: - fprintf(out, "%s buff[pos] = INT_TYPE;\n", indent.c_str()); - fprintf(out, "%s copyInt(buff, pos + 1, arg%d? 1 : 0);\n", indent.c_str(), - argIndex); - fprintf(out, "%s pos += INT_TYPE_SIZE;\n", indent.c_str()); - break; - case JAVA_TYPE_INT: - case JAVA_TYPE_ENUM: - fprintf(out, "%s buff[pos] = INT_TYPE;\n", indent.c_str()); - fprintf(out, "%s copyInt(buff, pos + 1, arg%d);\n", indent.c_str(), - argIndex); - fprintf(out, "%s pos += INT_TYPE_SIZE;\n", indent.c_str()); - break; - case JAVA_TYPE_FLOAT: - requiredHelpers |= JAVA_MODULE_REQUIRES_FLOAT; - fprintf(out, "%s buff[pos] = FLOAT_TYPE;\n", indent.c_str()); - fprintf(out, "%s copyFloat(buff, pos + 1, arg%d);\n", indent.c_str(), - argIndex); - fprintf(out, "%s pos += FLOAT_TYPE_SIZE;\n", indent.c_str()); - break; - case JAVA_TYPE_LONG: - fprintf(out, "%s buff[pos] = LONG_TYPE;\n", indent.c_str()); - fprintf(out, "%s copyLong(buff, pos + 1, arg%d);\n", indent.c_str(), - argIndex); - fprintf(out, "%s pos += LONG_TYPE_SIZE;\n", indent.c_str()); - break; - case JAVA_TYPE_STRING: - fprintf(out, "%s buff[pos] = STRING_TYPE;\n", indent.c_str()); - fprintf(out, "%s copyInt(buff, pos + 1, arg%dBytes.length);\n", - indent.c_str(), argIndex); - fprintf(out, - "%s System.arraycopy(" - "arg%dBytes, 0, buff, pos + STRING_TYPE_OVERHEAD, " - "arg%dBytes.length);\n", - indent.c_str(), argIndex, argIndex); - fprintf(out, "%s pos += STRING_TYPE_OVERHEAD + arg%dBytes.length;\n", - indent.c_str(), argIndex); - break; - case JAVA_TYPE_BYTE_ARRAY: - fprintf(out, "%s buff[pos] = STRING_TYPE;\n", indent.c_str()); - fprintf(out, "%s copyInt(buff, pos + 1, arg%d.length);\n", indent.c_str(), - argIndex); - fprintf(out, - "%s System.arraycopy(" - "arg%d, 0, buff, pos + STRING_TYPE_OVERHEAD, arg%d.length);\n", - indent.c_str(), argIndex, argIndex); - fprintf(out, "%s pos += STRING_TYPE_OVERHEAD + arg%d.length;\n", - indent.c_str(), argIndex); - break; - case JAVA_TYPE_ATTRIBUTION_CHAIN: { - requiredHelpers |= JAVA_MODULE_REQUIRES_ATTRIBUTION; - const char* uidName = attributionDecl.fields.front().name.c_str(); - const char* tagName = attributionDecl.fields.back().name.c_str(); - - fprintf(out, "%s writeAttributionChain(buff, pos, %s, %s);\n", - indent.c_str(), uidName, tagName); - fprintf(out, "%s pos += attrSize;\n", indent.c_str()); - break; - } - case JAVA_TYPE_KEY_VALUE_PAIR: - requiredHelpers |= JAVA_MODULE_REQUIRES_FLOAT; - requiredHelpers |= JAVA_MODULE_REQUIRES_KEY_VALUE_PAIRS; - fprintf(out, - "%s writeKeyValuePairs(buff, pos, (byte) count, intMap, " - "longMap, " - "stringMap, floatMap);\n", - indent.c_str()); - fprintf(out, "%s pos += keyValuePairSize;\n", indent.c_str()); - break; - default: - // Unsupported types: OBJECT, DOUBLE. - fprintf(stderr, "Object and Double are not supported in module logging"); - return 1; - } - argIndex++; - } - - fprintf(out, "%s StatsLog.writeRaw(buff, pos);\n", indent.c_str()); - fprintf(out, "%s}\n", indent.c_str()); - fprintf(out, "\n"); - } - - write_java_helpers_for_q_schema_methods(out, attributionDecl, requiredHelpers, indent); - - return 0; -} - -void write_java_helpers_for_q_schema_methods(FILE* out, const AtomDecl& attributionDecl, - const int requiredHelpers, const string& indent) { - fprintf(out, "\n"); - fprintf(out, "%s// Helper methods for copying primitives\n", indent.c_str()); - fprintf(out, "%sprivate static void copyInt(byte[] buff, int pos, int val) {\n", - indent.c_str()); - fprintf(out, "%s buff[pos] = (byte) (val);\n", indent.c_str()); - fprintf(out, "%s buff[pos + 1] = (byte) (val >> 8);\n", indent.c_str()); - fprintf(out, "%s buff[pos + 2] = (byte) (val >> 16);\n", indent.c_str()); - fprintf(out, "%s buff[pos + 3] = (byte) (val >> 24);\n", indent.c_str()); - fprintf(out, "%s return;\n", indent.c_str()); - fprintf(out, "%s}\n", indent.c_str()); - fprintf(out, "\n"); - - fprintf(out, "%sprivate static void copyLong(byte[] buff, int pos, long val) {\n", - indent.c_str()); - fprintf(out, "%s buff[pos] = (byte) (val);\n", indent.c_str()); - fprintf(out, "%s buff[pos + 1] = (byte) (val >> 8);\n", indent.c_str()); - fprintf(out, "%s buff[pos + 2] = (byte) (val >> 16);\n", indent.c_str()); - fprintf(out, "%s buff[pos + 3] = (byte) (val >> 24);\n", indent.c_str()); - fprintf(out, "%s buff[pos + 4] = (byte) (val >> 32);\n", indent.c_str()); - fprintf(out, "%s buff[pos + 5] = (byte) (val >> 40);\n", indent.c_str()); - fprintf(out, "%s buff[pos + 6] = (byte) (val >> 48);\n", indent.c_str()); - fprintf(out, "%s buff[pos + 7] = (byte) (val >> 56);\n", indent.c_str()); - fprintf(out, "%s return;\n", indent.c_str()); - fprintf(out, "%s}\n", indent.c_str()); - fprintf(out, "\n"); - - if (requiredHelpers & JAVA_MODULE_REQUIRES_FLOAT) { - fprintf(out, "%sprivate static void copyFloat(byte[] buff, int pos, float val) {\n", - indent.c_str()); - fprintf(out, "%s copyInt(buff, pos, Float.floatToIntBits(val));\n", indent.c_str()); - fprintf(out, "%s return;\n", indent.c_str()); - fprintf(out, "%s}\n", indent.c_str()); - fprintf(out, "\n"); - } - - if (requiredHelpers & JAVA_MODULE_REQUIRES_ATTRIBUTION) { - fprintf(out, "%sprivate static void writeAttributionChain(byte[] buff, int pos", - indent.c_str()); - for (const auto& chainField : attributionDecl.fields) { - fprintf(out, ", %s[] %s", java_type_name(chainField.javaType), chainField.name.c_str()); - } - fprintf(out, ") {\n"); - - const char* uidName = attributionDecl.fields.front().name.c_str(); - const char* tagName = attributionDecl.fields.back().name.c_str(); - - // Write the first list begin. - fprintf(out, "%s buff[pos] = LIST_TYPE;\n", indent.c_str()); - fprintf(out, "%s buff[pos + 1] = (byte) (%s.length);\n", indent.c_str(), tagName); - fprintf(out, "%s pos += LIST_TYPE_OVERHEAD;\n", indent.c_str()); - - // Iterate through the attribution chain and write the nodes. - fprintf(out, "%s for (int i = 0; i < %s.length; i++) {\n", indent.c_str(), tagName); - // Write the list begin. - fprintf(out, "%s buff[pos] = LIST_TYPE;\n", indent.c_str()); - fprintf(out, "%s buff[pos + 1] = %lu;\n", indent.c_str(), - attributionDecl.fields.size()); - fprintf(out, "%s pos += LIST_TYPE_OVERHEAD;\n", indent.c_str()); - - // Write the uid. - fprintf(out, "%s buff[pos] = INT_TYPE;\n", indent.c_str()); - fprintf(out, "%s copyInt(buff, pos + 1, %s[i]);\n", indent.c_str(), uidName); - fprintf(out, "%s pos += INT_TYPE_SIZE;\n", indent.c_str()); - - // Write the tag. - fprintf(out, "%s String %sStr = (%s[i] == null) ? \"\" : %s[i];\n", indent.c_str(), - tagName, tagName, tagName); - fprintf(out, - "%s byte[] %sByte = " - "%sStr.getBytes(java.nio.charset.StandardCharsets.UTF_8);\n", - indent.c_str(), tagName, tagName); - fprintf(out, "%s buff[pos] = STRING_TYPE;\n", indent.c_str()); - fprintf(out, "%s copyInt(buff, pos + 1, %sByte.length);\n", indent.c_str(), tagName); - fprintf(out, - "%s System.arraycopy(" - "%sByte, 0, buff, pos + STRING_TYPE_OVERHEAD, %sByte.length);\n", - indent.c_str(), tagName, tagName); - fprintf(out, "%s pos += STRING_TYPE_OVERHEAD + %sByte.length;\n", indent.c_str(), - tagName); - fprintf(out, "%s }\n", indent.c_str()); - fprintf(out, "%s}\n", indent.c_str()); - fprintf(out, "\n"); - } - - if (requiredHelpers & JAVA_MODULE_REQUIRES_KEY_VALUE_PAIRS) { - fprintf(out, - "%sprivate static void writeKeyValuePairs(byte[] buff, int pos, " - "byte numPairs,\n", - indent.c_str()); - fprintf(out, "%s final android.util.SparseIntArray intMap,\n", indent.c_str()); - fprintf(out, "%s final android.util.SparseLongArray longMap,\n", indent.c_str()); - fprintf(out, "%s final android.util.SparseArray<String> stringMap,\n", - indent.c_str()); - fprintf(out, "%s final android.util.SparseArray<Float> floatMap) {\n", - indent.c_str()); - - // Start list of lists. - fprintf(out, "%s buff[pos] = LIST_TYPE;\n", indent.c_str()); - fprintf(out, "%s buff[pos + 1] = (byte) numPairs;\n", indent.c_str()); - fprintf(out, "%s pos += LIST_TYPE_OVERHEAD;\n", indent.c_str()); - - // Write integers. - fprintf(out, "%s final int intMapSize = null == intMap ? 0 : intMap.size();\n", - indent.c_str()); - fprintf(out, "%s for (int i = 0; i < intMapSize; i++) {\n", indent.c_str()); - fprintf(out, "%s buff[pos] = LIST_TYPE;\n", indent.c_str()); - fprintf(out, "%s buff[pos + 1] = (byte) 2;\n", indent.c_str()); - fprintf(out, "%s pos += LIST_TYPE_OVERHEAD;\n", indent.c_str()); - fprintf(out, "%s final int key = intMap.keyAt(i);\n", indent.c_str()); - fprintf(out, "%s final int value = intMap.valueAt(i);\n", indent.c_str()); - fprintf(out, "%s buff[pos] = INT_TYPE;\n", indent.c_str()); - fprintf(out, "%s copyInt(buff, pos + 1, key);\n", indent.c_str()); - fprintf(out, "%s pos += INT_TYPE_SIZE;\n", indent.c_str()); - fprintf(out, "%s buff[pos] = INT_TYPE;\n", indent.c_str()); - fprintf(out, "%s copyInt(buff, pos + 1, value);\n", indent.c_str()); - fprintf(out, "%s pos += INT_TYPE_SIZE;\n", indent.c_str()); - fprintf(out, "%s }\n", indent.c_str()); - - // Write longs. - fprintf(out, "%s final int longMapSize = null == longMap ? 0 : longMap.size();\n", - indent.c_str()); - fprintf(out, "%s for (int i = 0; i < longMapSize; i++) {\n", indent.c_str()); - fprintf(out, "%s buff[pos] = LIST_TYPE;\n", indent.c_str()); - fprintf(out, "%s buff[pos + 1] = (byte) 2;\n", indent.c_str()); - fprintf(out, "%s pos += LIST_TYPE_OVERHEAD;\n", indent.c_str()); - fprintf(out, "%s final int key = longMap.keyAt(i);\n", indent.c_str()); - fprintf(out, "%s final long value = longMap.valueAt(i);\n", indent.c_str()); - fprintf(out, "%s buff[pos] = INT_TYPE;\n", indent.c_str()); - fprintf(out, "%s copyInt(buff, pos + 1, key);\n", indent.c_str()); - fprintf(out, "%s pos += INT_TYPE_SIZE;\n", indent.c_str()); - fprintf(out, "%s buff[pos] = LONG_TYPE;\n", indent.c_str()); - fprintf(out, "%s copyLong(buff, pos + 1, value);\n", indent.c_str()); - fprintf(out, "%s pos += LONG_TYPE_SIZE;\n", indent.c_str()); - fprintf(out, "%s }\n", indent.c_str()); - - // Write Strings. - fprintf(out, - "%s final int stringMapSize = null == stringMap ? 0 : " - "stringMap.size();\n", - indent.c_str()); - fprintf(out, "%s for (int i = 0; i < stringMapSize; i++) {\n", indent.c_str()); - fprintf(out, "%s buff[pos] = LIST_TYPE;\n", indent.c_str()); - fprintf(out, "%s buff[pos + 1] = (byte) 2;\n", indent.c_str()); - fprintf(out, "%s pos += LIST_TYPE_OVERHEAD;\n", indent.c_str()); - fprintf(out, "%s final int key = stringMap.keyAt(i);\n", indent.c_str()); - fprintf(out, "%s final String value = stringMap.valueAt(i);\n", indent.c_str()); - fprintf(out, - "%s final byte[] valueBytes = " - "value.getBytes(java.nio.charset.StandardCharsets.UTF_8);\n", - indent.c_str()); - fprintf(out, "%s buff[pos] = INT_TYPE;\n", indent.c_str()); - fprintf(out, "%s copyInt(buff, pos + 1, key);\n", indent.c_str()); - fprintf(out, "%s pos += INT_TYPE_SIZE;\n", indent.c_str()); - fprintf(out, "%s buff[pos] = STRING_TYPE;\n", indent.c_str()); - fprintf(out, "%s copyInt(buff, pos + 1, valueBytes.length);\n", indent.c_str()); - fprintf(out, - "%s System.arraycopy(" - "valueBytes, 0, buff, pos + STRING_TYPE_OVERHEAD, " - "valueBytes.length);\n", - indent.c_str()); - fprintf(out, "%s pos += STRING_TYPE_OVERHEAD + valueBytes.length;\n", - indent.c_str()); - fprintf(out, "%s }\n", indent.c_str()); - - // Write floats. - fprintf(out, - "%s final int floatMapSize = null == floatMap ? 0 : " - "floatMap.size();\n", - indent.c_str()); - fprintf(out, "%s for (int i = 0; i < floatMapSize; i++) {\n", indent.c_str()); - fprintf(out, "%s buff[pos] = LIST_TYPE;\n", indent.c_str()); - fprintf(out, "%s buff[pos + 1] = (byte) 2;\n", indent.c_str()); - fprintf(out, "%s pos += LIST_TYPE_OVERHEAD;\n", indent.c_str()); - fprintf(out, "%s final int key = floatMap.keyAt(i);\n", indent.c_str()); - fprintf(out, "%s final float value = floatMap.valueAt(i);\n", indent.c_str()); - fprintf(out, "%s buff[pos] = INT_TYPE;\n", indent.c_str()); - fprintf(out, "%s copyInt(buff, pos + 1, key);\n", indent.c_str()); - fprintf(out, "%s pos += INT_TYPE_SIZE;\n", indent.c_str()); - fprintf(out, "%s buff[pos] = FLOAT_TYPE;\n", indent.c_str()); - fprintf(out, "%s copyFloat(buff, pos + 1, value);\n", indent.c_str()); - fprintf(out, "%s pos += FLOAT_TYPE_SIZE;\n", indent.c_str()); - fprintf(out, "%s }\n", indent.c_str()); - fprintf(out, "%s}\n", indent.c_str()); - fprintf(out, "\n"); - } -} - -// This method is called in main.cpp to generate StatsLog for modules that's -// compatible with Q at compile-time. -int write_stats_log_java_q_for_module(FILE* out, const Atoms& atoms, - const AtomDecl& attributionDecl, const string& javaClass, - const string& javaPackage, const bool supportWorkSource) { - // Print prelude - fprintf(out, "// This file is autogenerated\n"); - fprintf(out, "\n"); - fprintf(out, "package %s;\n", javaPackage.c_str()); - fprintf(out, "\n"); - fprintf(out, "import static java.nio.charset.StandardCharsets.UTF_8;\n"); - fprintf(out, "\n"); - fprintf(out, "import android.util.StatsLog;\n"); - fprintf(out, "import android.os.SystemClock;\n"); - fprintf(out, "\n"); - fprintf(out, "\n"); - fprintf(out, "/**\n"); - fprintf(out, " * Utility class for logging statistics events.\n"); - fprintf(out, " */\n"); - fprintf(out, "public class %s {\n", javaClass.c_str()); - - write_java_q_logging_constants(out, " "); - - write_java_atom_codes(out, atoms); - - write_java_enum_values(out, atoms); - - int errors = 0; - // Print write methods - fprintf(out, " // Write methods\n"); - errors += write_java_methods_q_schema(out, atoms.signatureInfoMap, attributionDecl, " "); - errors += write_java_non_chained_methods(out, atoms.nonChainedSignatureInfoMap); - if (supportWorkSource) { - errors += write_java_work_source_methods(out, atoms.signatureInfoMap); - } - - fprintf(out, "}\n"); - - return errors; -} - -} // namespace stats_log_api_gen -} // namespace android diff --git a/tools/stats_log_api_gen/java_writer_q.h b/tools/stats_log_api_gen/java_writer_q.h deleted file mode 100644 index 622ef3e37bad..000000000000 --- a/tools/stats_log_api_gen/java_writer_q.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2019, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_STATS_LOG_API_GEN_JAVA_WRITER_Q_H -#define ANDROID_STATS_LOG_API_GEN_JAVA_WRITER_Q_H - -#include <stdio.h> -#include <string.h> - -#include <map> -#include <set> -#include <vector> - -#include "Collation.h" - -namespace android { -namespace stats_log_api_gen { - -void write_java_q_logging_constants(FILE* out, const string& indent); - -int write_java_methods_q_schema(FILE* out, const SignatureInfoMap& signatureInfoMap, - const AtomDecl& attributionDecl, const string& indent); - -void write_java_helpers_for_q_schema_methods(FILE* out, const AtomDecl& attributionDecl, - const int requiredHelpers, const string& indent); - -int write_stats_log_java_q_for_module(FILE* out, const Atoms& atoms, - const AtomDecl& attributionDecl, const string& javaClass, - const string& javaPackage, const bool supportWorkSource); - -} // namespace stats_log_api_gen -} // namespace android - -#endif // ANDROID_STATS_LOG_API_GEN_JAVA_WRITER_Q_H diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp deleted file mode 100644 index 50f81760e8ef..000000000000 --- a/tools/stats_log_api_gen/main.cpp +++ /dev/null @@ -1,261 +0,0 @@ - -#include <getopt.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <map> -#include <set> -#include <vector> - -#include "Collation.h" -#include "frameworks/proto_logging/stats/atoms.pb.h" -#include "java_writer.h" -#include "java_writer_q.h" -#include "native_writer.h" -#include "utils.h" - -namespace android { -namespace stats_log_api_gen { - -using android::os::statsd::Atom; - -static void print_usage() { - fprintf(stderr, "usage: stats-log-api-gen OPTIONS\n"); - fprintf(stderr, "\n"); - fprintf(stderr, "OPTIONS\n"); - fprintf(stderr, " --cpp FILENAME the header file to output for write helpers\n"); - fprintf(stderr, " --header FILENAME the cpp file to output for write helpers\n"); - fprintf(stderr, " --help this message\n"); - fprintf(stderr, " --java FILENAME the java file to output\n"); - fprintf(stderr, " --module NAME optional, module name to generate outputs for\n"); - fprintf(stderr, - " --namespace COMMA,SEP,NAMESPACE required for cpp/header with " - "module\n"); - fprintf(stderr, - " comma separated namespace of " - "the files\n"); - fprintf(stderr, - " --importHeader NAME required for cpp/jni to say which header to " - "import " - "for write helpers\n"); - fprintf(stderr, " --javaPackage PACKAGE the package for the java file.\n"); - fprintf(stderr, " required for java with module\n"); - fprintf(stderr, " --javaClass CLASS the class name of the java class.\n"); - fprintf(stderr, " Optional for Java with module.\n"); - fprintf(stderr, " Default is \"StatsLogInternal\"\n"); - fprintf(stderr, " --supportQ Include runtime support for Android Q.\n"); - fprintf(stderr, - " --worksource Include support for logging WorkSource " - "objects.\n"); - fprintf(stderr, - " --compileQ Include compile-time support for Android Q " - "(Java only).\n"); -} - -/** - * Do the argument parsing and execute the tasks. - */ -static int run(int argc, char const* const* argv) { - string cppFilename; - string headerFilename; - string javaFilename; - string javaPackage; - string javaClass; - - string moduleName = DEFAULT_MODULE_NAME; - string cppNamespace = DEFAULT_CPP_NAMESPACE; - string cppHeaderImport = DEFAULT_CPP_HEADER_IMPORT; - bool supportQ = false; - bool supportWorkSource = false; - bool compileQ = false; - - int index = 1; - while (index < argc) { - if (0 == strcmp("--help", argv[index])) { - print_usage(); - return 0; - } else if (0 == strcmp("--cpp", argv[index])) { - index++; - if (index >= argc) { - print_usage(); - return 1; - } - cppFilename = argv[index]; - } else if (0 == strcmp("--header", argv[index])) { - index++; - if (index >= argc) { - print_usage(); - return 1; - } - headerFilename = argv[index]; - } else if (0 == strcmp("--java", argv[index])) { - index++; - if (index >= argc) { - print_usage(); - return 1; - } - javaFilename = argv[index]; - } else if (0 == strcmp("--module", argv[index])) { - index++; - if (index >= argc) { - print_usage(); - return 1; - } - moduleName = argv[index]; - } else if (0 == strcmp("--namespace", argv[index])) { - index++; - if (index >= argc) { - print_usage(); - return 1; - } - cppNamespace = argv[index]; - } else if (0 == strcmp("--importHeader", argv[index])) { - index++; - if (index >= argc) { - print_usage(); - return 1; - } - cppHeaderImport = argv[index]; - } else if (0 == strcmp("--javaPackage", argv[index])) { - index++; - if (index >= argc) { - print_usage(); - return 1; - } - javaPackage = argv[index]; - } else if (0 == strcmp("--javaClass", argv[index])) { - index++; - if (index >= argc) { - print_usage(); - return 1; - } - javaClass = argv[index]; - } else if (0 == strcmp("--supportQ", argv[index])) { - supportQ = true; - } else if (0 == strcmp("--worksource", argv[index])) { - supportWorkSource = true; - } else if (0 == strcmp("--compileQ", argv[index])) { - compileQ = true; - } - - index++; - } - - if (cppFilename.empty() && headerFilename.empty() && javaFilename.empty()) { - print_usage(); - return 1; - } - - if (DEFAULT_MODULE_NAME == moduleName && (supportQ || compileQ)) { - // Support for Q schema is not needed for default module. - fprintf(stderr, "%s cannot support Q schema\n", moduleName.c_str()); - return 1; - } - - if (supportQ && compileQ) { - // Runtime Q support is redundant if compile-time Q support is required. - fprintf(stderr, "Cannot specify compileQ and supportQ simultaneously.\n"); - return 1; - } - - // Collate the parameters - Atoms atoms; - int errorCount = collate_atoms(Atom::descriptor(), moduleName, &atoms); - if (errorCount != 0) { - return 1; - } - - AtomDecl attributionDecl; - vector<java_type_t> attributionSignature; - collate_atom(android::os::statsd::AttributionNode::descriptor(), &attributionDecl, - &attributionSignature); - - // Write the .cpp file - if (!cppFilename.empty()) { - FILE* out = fopen(cppFilename.c_str(), "w"); - if (out == nullptr) { - fprintf(stderr, "Unable to open file for write: %s\n", cppFilename.c_str()); - return 1; - } - // If this is for a specific module, the namespace must also be provided. - if (moduleName != DEFAULT_MODULE_NAME && cppNamespace == DEFAULT_CPP_NAMESPACE) { - fprintf(stderr, "Must supply --namespace if supplying a specific module\n"); - return 1; - } - // If this is for a specific module, the header file to import must also be - // provided. - if (moduleName != DEFAULT_MODULE_NAME && cppHeaderImport == DEFAULT_CPP_HEADER_IMPORT) { - fprintf(stderr, "Must supply --headerImport if supplying a specific module\n"); - return 1; - } - errorCount = android::stats_log_api_gen::write_stats_log_cpp( - out, atoms, attributionDecl, cppNamespace, cppHeaderImport, supportQ); - fclose(out); - } - - // Write the .h file - if (!headerFilename.empty()) { - FILE* out = fopen(headerFilename.c_str(), "w"); - if (out == nullptr) { - fprintf(stderr, "Unable to open file for write: %s\n", headerFilename.c_str()); - return 1; - } - // If this is for a specific module, the namespace must also be provided. - if (moduleName != DEFAULT_MODULE_NAME && cppNamespace == DEFAULT_CPP_NAMESPACE) { - fprintf(stderr, "Must supply --namespace if supplying a specific module\n"); - } - errorCount = android::stats_log_api_gen::write_stats_log_header(out, atoms, attributionDecl, - cppNamespace); - fclose(out); - } - - // Write the .java file - if (!javaFilename.empty()) { - if (javaClass.empty()) { - fprintf(stderr, "Must supply --javaClass if supplying a Java filename"); - return 1; - } - - if (javaPackage.empty()) { - fprintf(stderr, "Must supply --javaPackage if supplying a Java filename"); - return 1; - } - - if (moduleName.empty()) { - fprintf(stderr, "Must supply --module if supplying a Java filename"); - return 1; - } - - FILE* out = fopen(javaFilename.c_str(), "w"); - if (out == nullptr) { - fprintf(stderr, "Unable to open file for write: %s\n", javaFilename.c_str()); - return 1; - } - - if (compileQ) { - errorCount = android::stats_log_api_gen::write_stats_log_java_q_for_module( - out, atoms, attributionDecl, javaClass, javaPackage, supportWorkSource); - } else { - errorCount = android::stats_log_api_gen::write_stats_log_java( - out, atoms, attributionDecl, javaClass, javaPackage, supportQ, - supportWorkSource); - } - - fclose(out); - } - - return errorCount; -} - -} // namespace stats_log_api_gen -} // namespace android - -/** - * Main. - */ -int main(int argc, char const* const* argv) { - GOOGLE_PROTOBUF_VERIFY_VERSION; - - return android::stats_log_api_gen::run(argc, argv); -} diff --git a/tools/stats_log_api_gen/native_writer.cpp b/tools/stats_log_api_gen/native_writer.cpp deleted file mode 100644 index b4fb8dd8321b..000000000000 --- a/tools/stats_log_api_gen/native_writer.cpp +++ /dev/null @@ -1,423 +0,0 @@ -/* - * Copyright (C) 2019, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "native_writer.h" - -#include "utils.h" - -namespace android { -namespace stats_log_api_gen { - -static void write_native_annotation_constants(FILE* out) { - fprintf(out, "// Annotation constants.\n"); - - const map<AnnotationId, string>& ANNOTATION_ID_CONSTANTS = get_annotation_id_constants(); - for (const auto& [id, name] : ANNOTATION_ID_CONSTANTS) { - fprintf(out, "const uint8_t %s = %hhu;\n", name.c_str(), id); - } - fprintf(out, "\n"); -} - -static void write_annotations(FILE* out, int argIndex, - const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet, - const string& methodPrefix, const string& methodSuffix) { - FieldNumberToAtomDeclSet::const_iterator fieldNumberToAtomDeclSetIt = - fieldNumberToAtomDeclSet.find(argIndex); - if (fieldNumberToAtomDeclSet.end() == fieldNumberToAtomDeclSetIt) { - return; - } - const AtomDeclSet& atomDeclSet = fieldNumberToAtomDeclSetIt->second; - const map<AnnotationId, string>& ANNOTATION_ID_CONSTANTS = get_annotation_id_constants(); - for (const shared_ptr<AtomDecl>& atomDecl : atomDeclSet) { - const string atomConstant = make_constant_name(atomDecl->name); - fprintf(out, " if (%s == code) {\n", atomConstant.c_str()); - const AnnotationSet& annotations = atomDecl->fieldNumberToAnnotations.at(argIndex); - int resetState = -1; - int defaultState = -1; - for (const shared_ptr<Annotation>& annotation : annotations) { - const string& annotationConstant = ANNOTATION_ID_CONSTANTS.at(annotation->annotationId); - switch (annotation->type) { - case ANNOTATION_TYPE_INT: - if (ANNOTATION_ID_TRIGGER_STATE_RESET == annotation->annotationId) { - resetState = annotation->value.intValue; - } else if (ANNOTATION_ID_DEFAULT_STATE == annotation->annotationId) { - defaultState = annotation->value.intValue; - } else { - fprintf(out, " %saddInt32Annotation(%s%s, %d);\n", - methodPrefix.c_str(), methodSuffix.c_str(), - annotationConstant.c_str(), annotation->value.intValue); - } - break; - case ANNOTATION_TYPE_BOOL: - fprintf(out, " %saddBoolAnnotation(%s%s, %s);\n", methodPrefix.c_str(), - methodSuffix.c_str(), annotationConstant.c_str(), - annotation->value.boolValue ? "true" : "false"); - break; - default: - break; - } - } - if (defaultState != -1 && resetState != -1) { - const string& annotationConstant = - ANNOTATION_ID_CONSTANTS.at(ANNOTATION_ID_TRIGGER_STATE_RESET); - fprintf(out, " if (arg%d == %d) {\n", argIndex, resetState); - fprintf(out, " %saddInt32Annotation(%s%s, %d);\n", methodPrefix.c_str(), - methodSuffix.c_str(), annotationConstant.c_str(), defaultState); - fprintf(out, " }\n"); - } - fprintf(out, " }\n"); - } -} - -static int write_native_method_body(FILE* out, vector<java_type_t>& signature, - const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet, - const AtomDecl& attributionDecl) { - int argIndex = 1; - fprintf(out, " AStatsEvent_setAtomId(event, code);\n"); - write_annotations(out, ATOM_ID_FIELD_NUMBER, fieldNumberToAtomDeclSet, "AStatsEvent_", - "event, "); - for (vector<java_type_t>::const_iterator arg = signature.begin(); - arg != signature.end(); arg++) { - switch (*arg) { - case JAVA_TYPE_ATTRIBUTION_CHAIN: { - const char* uidName = attributionDecl.fields.front().name.c_str(); - const char* tagName = attributionDecl.fields.back().name.c_str(); - fprintf(out, - " AStatsEvent_writeAttributionChain(event, " - "reinterpret_cast<const uint32_t*>(%s), %s.data(), " - "static_cast<uint8_t>(%s_length));\n", - uidName, tagName, uidName); - break; - } - case JAVA_TYPE_BYTE_ARRAY: - fprintf(out, - " AStatsEvent_writeByteArray(event, " - "reinterpret_cast<const uint8_t*>(arg%d.arg), " - "arg%d.arg_length);\n", - argIndex, argIndex); - break; - case JAVA_TYPE_BOOLEAN: - fprintf(out, " AStatsEvent_writeBool(event, arg%d);\n", argIndex); - break; - case JAVA_TYPE_INT: // Fall through. - case JAVA_TYPE_ENUM: - fprintf(out, " AStatsEvent_writeInt32(event, arg%d);\n", argIndex); - break; - case JAVA_TYPE_FLOAT: - fprintf(out, " AStatsEvent_writeFloat(event, arg%d);\n", argIndex); - break; - case JAVA_TYPE_LONG: - fprintf(out, " AStatsEvent_writeInt64(event, arg%d);\n", argIndex); - break; - case JAVA_TYPE_STRING: - fprintf(out, " AStatsEvent_writeString(event, arg%d);\n", argIndex); - break; - default: - // Unsupported types: OBJECT, DOUBLE, KEY_VALUE_PAIRS - fprintf(stderr, "Encountered unsupported type."); - return 1; - } - write_annotations(out, argIndex, fieldNumberToAtomDeclSet, "AStatsEvent_", - "event, "); - argIndex++; - } - return 0; -} - -static int write_native_stats_write_methods(FILE* out, const SignatureInfoMap& signatureInfoMap, - const AtomDecl& attributionDecl, const bool supportQ) { - fprintf(out, "\n"); - for (auto signatureInfoMapIt = signatureInfoMap.begin(); - signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) { - vector<java_type_t> signature = signatureInfoMapIt->first; - const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet = signatureInfoMapIt->second; - // Key value pairs not supported in native. - if (std::find(signature.begin(), signature.end(), JAVA_TYPE_KEY_VALUE_PAIR) != - signature.end()) { - continue; - } - write_native_method_signature(out, "int stats_write(", signature, attributionDecl, " {"); - - // Write method body. - if (supportQ) { - int argIndex = 1; - fprintf(out, " StatsEventCompat event;\n"); - fprintf(out, " event.setAtomId(code);\n"); - write_annotations(out, ATOM_ID_FIELD_NUMBER, fieldNumberToAtomDeclSet, "event.", ""); - for (vector<java_type_t>::const_iterator arg = signature.begin(); - arg != signature.end(); arg++) { - switch (*arg) { - case JAVA_TYPE_ATTRIBUTION_CHAIN: { - const char* uidName = attributionDecl.fields.front().name.c_str(); - const char* tagName = attributionDecl.fields.back().name.c_str(); - fprintf(out, " event.writeAttributionChain(%s, %s_length, %s);\n", - uidName, uidName, tagName); - break; - } - case JAVA_TYPE_BYTE_ARRAY: - fprintf(out, " event.writeByteArray(arg%d.arg, arg%d.arg_length);\n", - argIndex, argIndex); - break; - case JAVA_TYPE_BOOLEAN: - fprintf(out, " event.writeBool(arg%d);\n", argIndex); - break; - case JAVA_TYPE_INT: // Fall through. - case JAVA_TYPE_ENUM: - fprintf(out, " event.writeInt32(arg%d);\n", argIndex); - break; - case JAVA_TYPE_FLOAT: - fprintf(out, " event.writeFloat(arg%d);\n", argIndex); - break; - case JAVA_TYPE_LONG: - fprintf(out, " event.writeInt64(arg%d);\n", argIndex); - break; - case JAVA_TYPE_STRING: - fprintf(out, " event.writeString(arg%d);\n", argIndex); - break; - default: - // Unsupported types: OBJECT, DOUBLE, KEY_VALUE_PAIRS. - fprintf(stderr, "Encountered unsupported type."); - return 1; - } - write_annotations(out, argIndex, fieldNumberToAtomDeclSet, "event.", ""); - argIndex++; - } - fprintf(out, " return event.writeToSocket();\n"); // end method body. - } else { - fprintf(out, " AStatsEvent* event = AStatsEvent_obtain();\n"); - int ret = write_native_method_body(out, signature, fieldNumberToAtomDeclSet, - attributionDecl); - if (ret != 0) { - return ret; - } - fprintf(out, " const int ret = AStatsEvent_write(event);\n"); - fprintf(out, " AStatsEvent_release(event);\n"); - fprintf(out, " return ret;\n"); // end method body. - } - fprintf(out, "}\n\n"); // end method. - } - return 0; -} - -static void write_native_stats_write_non_chained_methods(FILE* out, - const SignatureInfoMap& signatureInfoMap, - const AtomDecl& attributionDecl) { - fprintf(out, "\n"); - for (auto signature_it = signatureInfoMap.begin(); - signature_it != signatureInfoMap.end(); signature_it++) { - vector<java_type_t> signature = signature_it->first; - // Key value pairs not supported in native. - if (std::find(signature.begin(), signature.end(), JAVA_TYPE_KEY_VALUE_PAIR) != - signature.end()) { - continue; - } - - write_native_method_signature(out, "int stats_write_non_chained(", signature, - attributionDecl, " {"); - - vector<java_type_t> newSignature; - - // First two args form the attribution node so size goes down by 1. - newSignature.reserve(signature.size() - 1); - - // First arg is Attribution Chain. - newSignature.push_back(JAVA_TYPE_ATTRIBUTION_CHAIN); - - // Followed by the originial signature except the first 2 args. - newSignature.insert(newSignature.end(), signature.begin() + 2, signature.end()); - - const char* uidName = attributionDecl.fields.front().name.c_str(); - const char* tagName = attributionDecl.fields.back().name.c_str(); - fprintf(out, " const int32_t* %s = &arg1;\n", uidName); - fprintf(out, " const size_t %s_length = 1;\n", uidName); - fprintf(out, " const std::vector<char const*> %s(1, arg2);\n", tagName); - fprintf(out, " return "); - write_native_method_call(out, "stats_write", newSignature, attributionDecl, 2); - - fprintf(out, "}\n\n"); - } -} - -static int write_native_build_stats_event_methods(FILE* out, - const SignatureInfoMap& signatureInfoMap, - const AtomDecl& attributionDecl) { - fprintf(out, "\n"); - for (auto signatureInfoMapIt = signatureInfoMap.begin(); - signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) { - vector<java_type_t> signature = signatureInfoMapIt->first; - const FieldNumberToAtomDeclSet& fieldNumberToAtomDeclSet = signatureInfoMapIt->second; - // Key value pairs not supported in native. - if (std::find(signature.begin(), signature.end(), JAVA_TYPE_KEY_VALUE_PAIR) != - signature.end()) { - continue; - } - write_native_method_signature(out, "void addAStatsEvent(AStatsEventList* pulled_data, ", - signature, attributionDecl, " {"); - - fprintf(out, " AStatsEvent* event = AStatsEventList_addStatsEvent(pulled_data);\n"); - int ret = write_native_method_body(out, signature, fieldNumberToAtomDeclSet, - attributionDecl); - if (ret != 0) { - return ret; - } - fprintf(out, " AStatsEvent_build(event);\n"); // end method body. - - fprintf(out, "}\n\n"); // end method. - } - return 0; -} - -static void write_native_method_header(FILE* out, const string& methodName, - const SignatureInfoMap& signatureInfoMap, - const AtomDecl& attributionDecl) { - for (auto signatureInfoMapIt = signatureInfoMap.begin(); - signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) { - vector<java_type_t> signature = signatureInfoMapIt->first; - - // Key value pairs not supported in native. - if (std::find(signature.begin(), signature.end(), JAVA_TYPE_KEY_VALUE_PAIR) != - signature.end()) { - continue; - } - write_native_method_signature(out, methodName, signature, attributionDecl, ";"); - } -} - -int write_stats_log_cpp(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl, - const string& cppNamespace, const string& importHeader, - const bool supportQ) { - // Print prelude - fprintf(out, "// This file is autogenerated\n"); - fprintf(out, "\n"); - - fprintf(out, "#include <%s>\n", importHeader.c_str()); - if (supportQ) { - fprintf(out, "#include <StatsEventCompat.h>\n"); - } else { - fprintf(out, "#include <stats_event.h>\n"); - - if (!atoms.pulledAtomsSignatureInfoMap.empty()) { - fprintf(out, "#include <stats_pull_atom_callback.h>\n"); - } - } - - - - fprintf(out, "\n"); - write_namespace(out, cppNamespace); - - write_native_stats_write_methods(out, atoms.signatureInfoMap, attributionDecl, supportQ); - write_native_stats_write_non_chained_methods(out, atoms.nonChainedSignatureInfoMap, - attributionDecl); - write_native_build_stats_event_methods(out, atoms.pulledAtomsSignatureInfoMap, - attributionDecl); - - // Print footer - fprintf(out, "\n"); - write_closing_namespace(out, cppNamespace); - - return 0; -} - -int write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl, - const string& cppNamespace) { - // Print prelude - fprintf(out, "// This file is autogenerated\n"); - fprintf(out, "\n"); - fprintf(out, "#pragma once\n"); - fprintf(out, "\n"); - fprintf(out, "#include <stdint.h>\n"); - fprintf(out, "#include <vector>\n"); - fprintf(out, "#include <map>\n"); - fprintf(out, "#include <set>\n"); - if (!atoms.pulledAtomsSignatureInfoMap.empty()) { - fprintf(out, "#include <stats_pull_atom_callback.h>\n"); - } - fprintf(out, "\n"); - - write_namespace(out, cppNamespace); - fprintf(out, "\n"); - fprintf(out, "/*\n"); - fprintf(out, " * API For logging statistics events.\n"); - fprintf(out, " */\n"); - fprintf(out, "\n"); - - write_native_atom_constants(out, atoms, attributionDecl); - - // Print constants for the enum values. - fprintf(out, "//\n"); - fprintf(out, "// Constants for enum values\n"); - fprintf(out, "//\n\n"); - for (AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); atomIt != atoms.decls.end(); - atomIt++) { - for (vector<AtomField>::const_iterator field = (*atomIt)->fields.begin(); - field != (*atomIt)->fields.end(); field++) { - if (field->javaType == JAVA_TYPE_ENUM) { - fprintf(out, "// Values for %s.%s\n", (*atomIt)->message.c_str(), - field->name.c_str()); - for (map<int, string>::const_iterator value = field->enumValues.begin(); - value != field->enumValues.end(); value++) { - fprintf(out, "const int32_t %s__%s__%s = %d;\n", - make_constant_name((*atomIt)->message).c_str(), - make_constant_name(field->name).c_str(), - make_constant_name(value->second).c_str(), value->first); - } - fprintf(out, "\n"); - } - } - } - - write_native_annotation_constants(out); - - fprintf(out, "struct BytesField {\n"); - fprintf(out, - " BytesField(char const* array, size_t len) : arg(array), " - "arg_length(len) {}\n"); - fprintf(out, " char const* arg;\n"); - fprintf(out, " size_t arg_length;\n"); - fprintf(out, "};\n"); - fprintf(out, "\n"); - - // Print write methods - fprintf(out, "//\n"); - fprintf(out, "// Write methods\n"); - fprintf(out, "//\n"); - write_native_method_header(out, "int stats_write(", atoms.signatureInfoMap, attributionDecl); - fprintf(out, "\n"); - - fprintf(out, "//\n"); - fprintf(out, "// Write flattened methods\n"); - fprintf(out, "//\n"); - write_native_method_header(out, "int stats_write_non_chained(", atoms.nonChainedSignatureInfoMap, - attributionDecl); - fprintf(out, "\n"); - - // Print pulled atoms methods. - fprintf(out, "//\n"); - fprintf(out, "// Add AStatsEvent methods\n"); - fprintf(out, "//\n"); - write_native_method_header(out, "void addAStatsEvent(AStatsEventList* pulled_data, ", - atoms.pulledAtomsSignatureInfoMap, - attributionDecl); - - fprintf(out, "\n"); - write_closing_namespace(out, cppNamespace); - - return 0; -} - -} // namespace stats_log_api_gen -} // namespace android diff --git a/tools/stats_log_api_gen/native_writer.h b/tools/stats_log_api_gen/native_writer.h deleted file mode 100644 index 4e42d1fa2809..000000000000 --- a/tools/stats_log_api_gen/native_writer.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2019, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_STATS_LOG_API_GEN_NATIVE_WRITER_H -#define ANDROID_STATS_LOG_API_GEN_NATIVE_WRITER_H - -#include <stdio.h> -#include <string.h> - -#include "Collation.h" - -namespace android { -namespace stats_log_api_gen { - -int write_stats_log_cpp(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl, - const string& cppNamespace, const string& importHeader, - const bool supportQ); - -int write_stats_log_header(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl, - const string& cppNamespace); - -} // namespace stats_log_api_gen -} // namespace android - -#endif // ANDROID_STATS_LOG_API_GEN_NATIVE_WRITER_H diff --git a/tools/stats_log_api_gen/test.proto b/tools/stats_log_api_gen/test.proto deleted file mode 100644 index 18c52bfab2a4..000000000000 --- a/tools/stats_log_api_gen/test.proto +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -syntax = "proto2"; - -import "frameworks/proto_logging/stats/atoms.proto"; -import "frameworks/proto_logging/stats/atom_field_options.proto"; - -package android.stats_log_api_gen; - -message IntAtom { - optional int32 field1 = 1; -} - -message AnotherIntAtom { - optional int32 field1 = 1; -} - -message OutOfOrderAtom { - optional int32 field2 = 2; - optional int32 field1 = 1; -} - -enum AnEnum { - VALUE0 = 0; - VALUE1 = 1; -} - -message AllTypesAtom { - repeated android.os.statsd.AttributionNode attribution_chain = 1; - optional float float_field = 2; - optional int64 int64_field = 3; - optional uint64 uint64_field = 4; - optional int32 int32_field = 5; - optional fixed64 fixed64_field = 6; - optional fixed32 fixed32_field = 7; - optional bool bool_field = 8; - optional string string_field = 9; - optional uint32 uint32_field = 10; - optional AnEnum enum_field = 11; - optional sfixed32 sfixed32_field = 12; - optional sfixed64 sfixed64_field = 13; - optional sint32 sint32_field = 14; - optional sint64 sint64_field = 15; -} - -message Event { - oneof pushed { - OutOfOrderAtom out_of_order_atom = 2; - IntAtom int_atom = 1; - AnotherIntAtom another_int_atom = 3; - AllTypesAtom all_types_atom = 4; - } -} - -message BadTypesAtom { - optional IntAtom bad_int_atom = 1; - optional bytes bad_bytes = 2; - repeated int32 repeated_field = 3; - optional double double_field = 4; -} - -message BadTypesEvent { - oneof pushed { - BadTypesAtom bad_types_atom = 1; - } -} - -message BadSkippedFieldSingleAtom { - optional int32 field2 = 2; -} - -message BadSkippedFieldSingle { - oneof pushed { - BadSkippedFieldSingleAtom bad = 1; - } -} - -message BadSkippedFieldMultipleAtom { - optional int32 field1 = 1; - optional int32 field3 = 3; - optional int32 field5 = 5; -} - -message BadSkippedFieldMultiple { - oneof pushed { - BadSkippedFieldMultipleAtom bad = 1; - } -} - -message BadAttributionNodePositionAtom { - optional int32 field1 = 1; - repeated android.os.statsd.AttributionNode attribution = 2; -} - -message BadAttributionNodePosition { - oneof pushed { BadAttributionNodePositionAtom bad = 1; } -} - -message GoodEventWithBinaryFieldAtom { - oneof pushed { GoodBinaryFieldAtom field1 = 1; } -} - -message ComplexField { - optional string str = 1; -} - -message GoodBinaryFieldAtom { - optional int32 field1 = 1; - optional ComplexField bf = 2 [(android.os.statsd.log_mode) = MODE_BYTES]; -} - -message BadEventWithBinaryFieldAtom { - oneof pushed { BadBinaryFieldAtom field1 = 1; } -} - -message BadBinaryFieldAtom { - optional int32 field1 = 1; - optional ComplexField bf = 2; -} - -message BadStateAtoms { - oneof pushed { - BadStateAtom1 bad1 = 1; - BadStateAtom2 bad2 = 2; - BadStateAtom3 bad3 = 3; - } -} - -message GoodStateAtoms { - oneof pushed { - GoodStateAtom1 good1 = 1; - GoodStateAtom2 good2 = 2; - } -} - -// The atom has only primary field but no exclusive state field. -message BadStateAtom1 { - optional int32 uid = 1 [(android.os.statsd.state_field_option).primary_field = true]; -} - -// Only primative types can be annotated. -message BadStateAtom2 { - repeated android.os.statsd.AttributionNode attribution = 1 - [(android.os.statsd.state_field_option).primary_field = true]; - optional int32 state = 2 [(android.os.statsd.state_field_option).exclusive_state = true]; -} - -// Having 2 exclusive state field in the atom means the atom is badly designed. -// E.g., putting bluetooth state and wifi state in the same atom. -message BadStateAtom3 { - optional int32 uid = 1 [(android.os.statsd.state_field_option).primary_field = true]; - optional int32 state = 2 [(android.os.statsd.state_field_option).exclusive_state = true]; - optional int32 state2 = 3 [(android.os.statsd.state_field_option).exclusive_state = true]; -} - -message GoodStateAtom1 { - optional int32 uid = 1 [(android.os.statsd.state_field_option).primary_field = true]; - optional int32 state = 2 [(android.os.statsd.state_field_option).exclusive_state = true]; -} - -// Atoms can have exclusive state field, but no primary field. That means -// the state is globally exclusive (e.g., DisplayState). -message GoodStateAtom2 { - optional int32 uid = 1; - optional int32 state = 2 [(android.os.statsd.state_field_option).exclusive_state = true]; -} - -// We can have more than one primary fields. That means their combination is a -// primary key. -message GoodStateAtom3 { - optional int32 uid = 1 [(android.os.statsd.state_field_option).primary_field = true]; - optional int32 tid = 2 [(android.os.statsd.state_field_option).primary_field = true]; - optional int32 state = 3 [(android.os.statsd.state_field_option).exclusive_state = true]; -} - -message ModuleOneAtom { - optional int32 field = 1 [(android.os.statsd.is_uid) = true]; -} - -message ModuleTwoAtom { - optional int32 field = 1; -} - -message ModuleOneAndTwoAtom { - optional int32 field = 1 [(android.os.statsd.state_field_option).exclusive_state = true]; -} - -message NoModuleAtom { - optional string field = 1; -} - -message ModuleAtoms { - oneof pushed { - ModuleOneAtom module_one_atom = 1 [(android.os.statsd.module) = "module1"]; - ModuleTwoAtom module_two_atom = 2 [(android.os.statsd.module) = "module2"]; - ModuleOneAndTwoAtom module_one_and_two_atom = 3 [ - (android.os.statsd.module) = "module1", (android.os.statsd.module) = "module2" - ]; - NoModuleAtom no_module_atom = 4; - } -} - -message NotAPushNorPullAtom { - oneof event { - IntAtom int_atom = 1; - } -} - -message AtomNotInAOneof { - optional IntAtom int_atom = 1; -} - -message PushedAndPulledAtoms { - oneof pushed { - IntAtom int_atom_1 = 1; - } - - oneof pulled { - OutOfOrderAtom out_of_order_atom = 11; - AnotherIntAtom another_int_atom = 10; - } -} diff --git a/tools/stats_log_api_gen/test_collation.cpp b/tools/stats_log_api_gen/test_collation.cpp deleted file mode 100644 index 6f78921d8f1c..000000000000 --- a/tools/stats_log_api_gen/test_collation.cpp +++ /dev/null @@ -1,432 +0,0 @@ -/* - * Copyright (C) 2017, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <gtest/gtest.h> -#include <stdio.h> - -#include "Collation.h" -#include "frameworks/base/tools/stats_log_api_gen/test.pb.h" - -namespace android { -namespace stats_log_api_gen { - -using std::map; -using std::vector; - -/** - * Return whether the map contains a vector of the elements provided. - */ -static bool map_contains_vector(const SignatureInfoMap& s, int count, ...) { - va_list args; - vector<java_type_t> v(count); - - va_start(args, count); - for (int i = 0; i < count; i++) { - v[i] = static_cast<java_type_t>(va_arg(args, int)); - } - va_end(args); - - return s.find(v) != s.end(); -} - -/** - * Expect that the provided map contains the elements provided. - */ -#define EXPECT_MAP_CONTAINS_SIGNATURE(s, ...) \ - do { \ - int count = sizeof((int[]){__VA_ARGS__}) / sizeof(int); \ - EXPECT_TRUE(map_contains_vector(s, count, __VA_ARGS__)); \ - } while (0) - -/** Expects that the provided atom has no enum values for any field. */ -#define EXPECT_NO_ENUM_FIELD(atom) \ - do { \ - for (vector<AtomField>::const_iterator field = atom->fields.begin(); \ - field != atom->fields.end(); field++) { \ - EXPECT_TRUE(field->enumValues.empty()); \ - } \ - } while (0) - -/** Expects that exactly one specific field has expected enum values. */ -#define EXPECT_HAS_ENUM_FIELD(atom, field_name, values) \ - do { \ - for (vector<AtomField>::const_iterator field = atom->fields.begin(); \ - field != atom->fields.end(); field++) { \ - if (field->name == field_name) { \ - EXPECT_EQ(field->enumValues, values); \ - } else { \ - EXPECT_TRUE(field->enumValues.empty()); \ - } \ - } \ - } while (0) - -/** - * Test a correct collation, with all the types. - */ -TEST(CollationTest, CollateStats) { - Atoms atoms; - int errorCount = collate_atoms(Event::descriptor(), DEFAULT_MODULE_NAME, &atoms); - - EXPECT_EQ(0, errorCount); - EXPECT_EQ(3ul, atoms.signatureInfoMap.size()); - - // IntAtom, AnotherIntAtom - EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_INT); - - // OutOfOrderAtom - EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_INT, JAVA_TYPE_INT); - - // AllTypesAtom - EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, - JAVA_TYPE_ATTRIBUTION_CHAIN, // AttributionChain - JAVA_TYPE_FLOAT, // float - JAVA_TYPE_LONG, // int64 - JAVA_TYPE_LONG, // uint64 - JAVA_TYPE_INT, // int32 - JAVA_TYPE_LONG, // fixed64 - JAVA_TYPE_INT, // fixed32 - JAVA_TYPE_BOOLEAN, // bool - JAVA_TYPE_STRING, // string - JAVA_TYPE_INT, // uint32 - JAVA_TYPE_INT, // AnEnum - JAVA_TYPE_INT, // sfixed32 - JAVA_TYPE_LONG, // sfixed64 - JAVA_TYPE_INT, // sint32 - JAVA_TYPE_LONG // sint64 - ); - - EXPECT_EQ(4ul, atoms.decls.size()); - - AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); - EXPECT_EQ(1, (*atomIt)->code); - EXPECT_EQ("int_atom", (*atomIt)->name); - EXPECT_EQ("IntAtom", (*atomIt)->message); - EXPECT_NO_ENUM_FIELD((*atomIt)); - atomIt++; - - EXPECT_EQ(2, (*atomIt)->code); - EXPECT_EQ("out_of_order_atom", (*atomIt)->name); - EXPECT_EQ("OutOfOrderAtom", (*atomIt)->message); - EXPECT_NO_ENUM_FIELD((*atomIt)); - atomIt++; - - EXPECT_EQ(3, (*atomIt)->code); - EXPECT_EQ("another_int_atom", (*atomIt)->name); - EXPECT_EQ("AnotherIntAtom", (*atomIt)->message); - EXPECT_NO_ENUM_FIELD((*atomIt)); - atomIt++; - - EXPECT_EQ(4, (*atomIt)->code); - EXPECT_EQ("all_types_atom", (*atomIt)->name); - EXPECT_EQ("AllTypesAtom", (*atomIt)->message); - map<int, string> enumValues; - enumValues[0] = "VALUE0"; - enumValues[1] = "VALUE1"; - EXPECT_HAS_ENUM_FIELD((*atomIt), "enum_field", enumValues); - atomIt++; - - EXPECT_EQ(atoms.decls.end(), atomIt); -} - -/** - * Test that event class that contains stuff other than the atoms is rejected. - */ -TEST(CollationTest, NonMessageTypeFails) { - Atoms atoms; - int errorCount = collate_atoms(IntAtom::descriptor(), DEFAULT_MODULE_NAME, &atoms); - - EXPECT_EQ(1, errorCount); -} - -/** - * Test that atoms that have non-primitive types or repeated fields are - * rejected. - */ -TEST(CollationTest, FailOnBadTypes) { - Atoms atoms; - int errorCount = collate_atoms(BadTypesEvent::descriptor(), DEFAULT_MODULE_NAME, &atoms); - - EXPECT_EQ(4, errorCount); -} - -/** - * Test that atoms that skip field numbers (in the first position) are rejected. - */ -TEST(CollationTest, FailOnSkippedFieldsSingle) { - Atoms atoms; - int errorCount = - collate_atoms(BadSkippedFieldSingle::descriptor(), DEFAULT_MODULE_NAME, &atoms); - - EXPECT_EQ(1, errorCount); -} - -/** - * Test that atoms that skip field numbers (not in the first position, and - * multiple times) are rejected. - */ -TEST(CollationTest, FailOnSkippedFieldsMultiple) { - Atoms atoms; - int errorCount = - collate_atoms(BadSkippedFieldMultiple::descriptor(), DEFAULT_MODULE_NAME, &atoms); - - EXPECT_EQ(2, errorCount); -} - -/** - * Test that atoms that have an attribution chain not in the first position are - * rejected. - */ -TEST(CollationTest, FailBadAttributionNodePosition) { - Atoms atoms; - int errorCount = - collate_atoms(BadAttributionNodePosition::descriptor(), DEFAULT_MODULE_NAME, &atoms); - - EXPECT_EQ(1, errorCount); -} - -TEST(CollationTest, FailOnBadStateAtomOptions) { - Atoms atoms; - int errorCount = collate_atoms(BadStateAtoms::descriptor(), DEFAULT_MODULE_NAME, &atoms); - - EXPECT_EQ(3, errorCount); -} - -TEST(CollationTest, PassOnGoodStateAtomOptions) { - Atoms atoms; - int errorCount = collate_atoms(GoodStateAtoms::descriptor(), DEFAULT_MODULE_NAME, &atoms); - EXPECT_EQ(0, errorCount); -} - -TEST(CollationTest, PassOnGoodBinaryFieldAtom) { - Atoms atoms; - int errorCount = - collate_atoms(GoodEventWithBinaryFieldAtom::descriptor(), DEFAULT_MODULE_NAME, &atoms); - EXPECT_EQ(0, errorCount); -} - -TEST(CollationTest, FailOnBadBinaryFieldAtom) { - Atoms atoms; - int errorCount = - collate_atoms(BadEventWithBinaryFieldAtom::descriptor(), DEFAULT_MODULE_NAME, &atoms); - EXPECT_GT(errorCount, 0); -} - -TEST(CollationTest, PassOnLogFromModuleAtom) { - Atoms atoms; - int errorCount = collate_atoms(ModuleAtoms::descriptor(), DEFAULT_MODULE_NAME, &atoms); - EXPECT_EQ(errorCount, 0); - EXPECT_EQ(atoms.decls.size(), 4ul); -} - -TEST(CollationTest, RecognizeModuleAtom) { - Atoms atoms; - int errorCount = collate_atoms(ModuleAtoms::descriptor(), DEFAULT_MODULE_NAME, &atoms); - EXPECT_EQ(errorCount, 0); - EXPECT_EQ(atoms.decls.size(), 4ul); - EXPECT_EQ(atoms.signatureInfoMap.size(), 2u); - EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_INT); - EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_STRING); - - SignatureInfoMap::const_iterator signatureInfoMapIt; - const vector<java_type_t>* signature; - const FieldNumberToAtomDeclSet* fieldNumberToAtomDeclSet; - FieldNumberToAtomDeclSet::const_iterator fieldNumberToAtomDeclSetIt; - const AtomDeclSet* atomDeclSet; - AtomDeclSet::const_iterator atomDeclSetIt; - AtomDecl* atomDecl; - FieldNumberToAnnotations* fieldNumberToAnnotations; - FieldNumberToAnnotations::const_iterator fieldNumberToAnnotationsIt; - const AnnotationSet* annotationSet; - AnnotationSet::const_iterator annotationSetIt; - Annotation* annotation; - - signatureInfoMapIt = atoms.signatureInfoMap.begin(); - signature = &(signatureInfoMapIt->first); - fieldNumberToAtomDeclSet = &signatureInfoMapIt->second; - EXPECT_EQ(1ul, signature->size()); - EXPECT_EQ(JAVA_TYPE_INT, signature->at(0)); - EXPECT_EQ(1ul, fieldNumberToAtomDeclSet->size()); - fieldNumberToAtomDeclSetIt = fieldNumberToAtomDeclSet->begin(); - EXPECT_EQ(1, fieldNumberToAtomDeclSetIt->first); - atomDeclSet = &fieldNumberToAtomDeclSetIt->second; - EXPECT_EQ(2ul, atomDeclSet->size()); - atomDeclSetIt = atomDeclSet->begin(); - atomDecl = atomDeclSetIt->get(); - EXPECT_EQ(1, atomDecl->code); - fieldNumberToAnnotations = &atomDecl->fieldNumberToAnnotations; - fieldNumberToAnnotationsIt = fieldNumberToAnnotations->find(1); - EXPECT_NE(fieldNumberToAnnotations->end(), fieldNumberToAnnotationsIt); - annotationSet = &fieldNumberToAnnotationsIt->second; - EXPECT_EQ(1ul, annotationSet->size()); - annotationSetIt = annotationSet->begin(); - annotation = annotationSetIt->get(); - EXPECT_EQ(ANNOTATION_ID_IS_UID, annotation->annotationId); - EXPECT_EQ(1, annotation->atomId); - EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type); - EXPECT_TRUE(annotation->value.boolValue); - - atomDeclSetIt++; - atomDecl = atomDeclSetIt->get(); - EXPECT_EQ(3, atomDecl->code); - fieldNumberToAnnotations = &atomDecl->fieldNumberToAnnotations; - fieldNumberToAnnotationsIt = fieldNumberToAnnotations->find(1); - EXPECT_NE(fieldNumberToAnnotations->end(), fieldNumberToAnnotationsIt); - annotationSet = &fieldNumberToAnnotationsIt->second; - EXPECT_EQ(1ul, annotationSet->size()); - annotationSetIt = annotationSet->begin(); - annotation = annotationSetIt->get(); - EXPECT_EQ(ANNOTATION_ID_EXCLUSIVE_STATE, annotation->annotationId); - EXPECT_EQ(3, annotation->atomId); - EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type); - EXPECT_TRUE(annotation->value.boolValue); - - signatureInfoMapIt++; - signature = &signatureInfoMapIt->first; - fieldNumberToAtomDeclSet = &signatureInfoMapIt->second; - EXPECT_EQ(1ul, signature->size()); - EXPECT_EQ(JAVA_TYPE_STRING, signature->at(0)); - EXPECT_EQ(0ul, fieldNumberToAtomDeclSet->size()); -} - -TEST(CollationTest, RecognizeModule1Atom) { - Atoms atoms; - const string moduleName = "module1"; - int errorCount = collate_atoms(ModuleAtoms::descriptor(), moduleName, &atoms); - EXPECT_EQ(errorCount, 0); - EXPECT_EQ(atoms.decls.size(), 2ul); - EXPECT_EQ(atoms.signatureInfoMap.size(), 1u); - EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_INT); - - SignatureInfoMap::const_iterator signatureInfoMapIt; - const vector<java_type_t>* signature; - const FieldNumberToAtomDeclSet* fieldNumberToAtomDeclSet; - FieldNumberToAtomDeclSet::const_iterator fieldNumberToAtomDeclSetIt; - const AtomDeclSet* atomDeclSet; - AtomDeclSet::const_iterator atomDeclSetIt; - AtomDecl* atomDecl; - FieldNumberToAnnotations* fieldNumberToAnnotations; - FieldNumberToAnnotations::const_iterator fieldNumberToAnnotationsIt; - const AnnotationSet* annotationSet; - AnnotationSet::const_iterator annotationSetIt; - Annotation* annotation; - - signatureInfoMapIt = atoms.signatureInfoMap.begin(); - signature = &(signatureInfoMapIt->first); - fieldNumberToAtomDeclSet = &signatureInfoMapIt->second; - EXPECT_EQ(1ul, signature->size()); - EXPECT_EQ(JAVA_TYPE_INT, signature->at(0)); - EXPECT_EQ(1ul, fieldNumberToAtomDeclSet->size()); - fieldNumberToAtomDeclSetIt = fieldNumberToAtomDeclSet->begin(); - EXPECT_EQ(1, fieldNumberToAtomDeclSetIt->first); - atomDeclSet = &fieldNumberToAtomDeclSetIt->second; - EXPECT_EQ(2ul, atomDeclSet->size()); - atomDeclSetIt = atomDeclSet->begin(); - atomDecl = atomDeclSetIt->get(); - EXPECT_EQ(1, atomDecl->code); - fieldNumberToAnnotations = &atomDecl->fieldNumberToAnnotations; - fieldNumberToAnnotationsIt = fieldNumberToAnnotations->find(1); - EXPECT_NE(fieldNumberToAnnotations->end(), fieldNumberToAnnotationsIt); - annotationSet = &fieldNumberToAnnotationsIt->second; - EXPECT_EQ(1ul, annotationSet->size()); - annotationSetIt = annotationSet->begin(); - annotation = annotationSetIt->get(); - EXPECT_EQ(ANNOTATION_ID_IS_UID, annotation->annotationId); - EXPECT_EQ(1, annotation->atomId); - EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type); - EXPECT_TRUE(annotation->value.boolValue); - - atomDeclSetIt++; - atomDecl = atomDeclSetIt->get(); - EXPECT_EQ(3, atomDecl->code); - fieldNumberToAnnotations = &atomDecl->fieldNumberToAnnotations; - fieldNumberToAnnotationsIt = fieldNumberToAnnotations->find(1); - EXPECT_NE(fieldNumberToAnnotations->end(), fieldNumberToAnnotationsIt); - annotationSet = &fieldNumberToAnnotationsIt->second; - EXPECT_EQ(1ul, annotationSet->size()); - annotationSetIt = annotationSet->begin(); - annotation = annotationSetIt->get(); - EXPECT_EQ(ANNOTATION_ID_EXCLUSIVE_STATE, annotation->annotationId); - EXPECT_EQ(3, annotation->atomId); - EXPECT_EQ(ANNOTATION_TYPE_BOOL, annotation->type); - EXPECT_TRUE(annotation->value.boolValue); -} - -/** - * Test that an atom is not a pushed nor pulled atom. - */ -TEST(CollationTest, InvalidAtomType) { - Atoms atoms; - int errorCount = collate_atoms(NotAPushNorPullAtom::descriptor(), DEFAULT_MODULE_NAME, &atoms); - - EXPECT_EQ(1, errorCount); -} - -/** - * Test that an atom was not declared in a `oneof` field. - */ -TEST(CollationTest, AtomNotDeclaredInAOneof) { - Atoms atoms; - int errorCount = collate_atoms(AtomNotInAOneof::descriptor(), DEFAULT_MODULE_NAME, &atoms); - - EXPECT_EQ(1, errorCount); -} - -/** - * Test a correct collation with pushed and pulled atoms. - */ -TEST(CollationTest, CollatePushedAndPulledAtoms) { - Atoms atoms; - int errorCount = collate_atoms(PushedAndPulledAtoms::descriptor(), DEFAULT_MODULE_NAME, &atoms); - - EXPECT_EQ(0, errorCount); - EXPECT_EQ(1ul, atoms.signatureInfoMap.size()); - EXPECT_EQ(2ul, atoms.pulledAtomsSignatureInfoMap.size()); - - // IntAtom - EXPECT_MAP_CONTAINS_SIGNATURE(atoms.signatureInfoMap, JAVA_TYPE_INT); - - // AnotherIntAtom - EXPECT_MAP_CONTAINS_SIGNATURE(atoms.pulledAtomsSignatureInfoMap, JAVA_TYPE_INT); - - // OutOfOrderAtom - EXPECT_MAP_CONTAINS_SIGNATURE(atoms.pulledAtomsSignatureInfoMap, JAVA_TYPE_INT, JAVA_TYPE_INT); - - EXPECT_EQ(3ul, atoms.decls.size()); - - AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); - EXPECT_EQ(1, (*atomIt)->code); - EXPECT_EQ("int_atom_1", (*atomIt)->name); - EXPECT_EQ("IntAtom", (*atomIt)->message); - EXPECT_NO_ENUM_FIELD((*atomIt)); - atomIt++; - - EXPECT_EQ(10, (*atomIt)->code); - EXPECT_EQ("another_int_atom", (*atomIt)->name); - EXPECT_EQ("AnotherIntAtom", (*atomIt)->message); - EXPECT_NO_ENUM_FIELD((*atomIt)); - atomIt++; - - EXPECT_EQ(11, (*atomIt)->code); - EXPECT_EQ("out_of_order_atom", (*atomIt)->name); - EXPECT_EQ("OutOfOrderAtom", (*atomIt)->message); - EXPECT_NO_ENUM_FIELD((*atomIt)); - atomIt++; - - EXPECT_EQ(atoms.decls.end(), atomIt); -} - -} // namespace stats_log_api_gen -} // namespace android diff --git a/tools/stats_log_api_gen/utils.cpp b/tools/stats_log_api_gen/utils.cpp deleted file mode 100644 index 1eaf42acf153..000000000000 --- a/tools/stats_log_api_gen/utils.cpp +++ /dev/null @@ -1,467 +0,0 @@ -/* - * Copyright (C) 2019, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "utils.h" - -namespace android { -namespace stats_log_api_gen { - -/** - * Inlining this method because "android-base/strings.h" is not available on - * google3. - */ -static vector<string> Split(const string& s, const string& delimiters) { - GOOGLE_CHECK_NE(delimiters.size(), 0U); - - vector<string> result; - - size_t base = 0; - size_t found; - while (true) { - found = s.find_first_of(delimiters, base); - result.push_back(s.substr(base, found - base)); - if (found == s.npos) break; - base = found + 1; - } - - return result; -} - -static void build_non_chained_decl_map(const Atoms& atoms, - std::map<int, AtomDeclSet::const_iterator>* decl_map) { - for (AtomDeclSet::const_iterator atomIt = atoms.non_chained_decls.begin(); - atomIt != atoms.non_chained_decls.end(); atomIt++) { - decl_map->insert(std::make_pair((*atomIt)->code, atomIt)); - } -} - -const map<AnnotationId, string>& get_annotation_id_constants() { - static const map<AnnotationId, string>* ANNOTATION_ID_CONSTANTS = - new map<AnnotationId, string>{ - {ANNOTATION_ID_IS_UID, "ANNOTATION_ID_IS_UID"}, - {ANNOTATION_ID_TRUNCATE_TIMESTAMP, "ANNOTATION_ID_TRUNCATE_TIMESTAMP"}, - {ANNOTATION_ID_PRIMARY_FIELD, "ANNOTATION_ID_PRIMARY_FIELD"}, - {ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, "ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID"}, - {ANNOTATION_ID_EXCLUSIVE_STATE, "ANNOTATION_ID_EXCLUSIVE_STATE"}, - {ANNOTATION_ID_TRIGGER_STATE_RESET, "ANNOTATION_ID_TRIGGER_STATE_RESET"}, - {ANNOTATION_ID_STATE_NESTED, "ANNOTATION_ID_STATE_NESTED"}}; - - return *ANNOTATION_ID_CONSTANTS; -} - -/** - * Turn lower and camel case into upper case with underscores. - */ -string make_constant_name(const string& str) { - string result; - const int N = str.size(); - bool underscore_next = false; - for (int i = 0; i < N; i++) { - char c = str[i]; - if (c >= 'A' && c <= 'Z') { - if (underscore_next) { - result += '_'; - underscore_next = false; - } - } else if (c >= 'a' && c <= 'z') { - c = 'A' + c - 'a'; - underscore_next = true; - } else if (c == '_') { - underscore_next = false; - } - result += c; - } - return result; -} - -const char* cpp_type_name(java_type_t type) { - switch (type) { - case JAVA_TYPE_BOOLEAN: - return "bool"; - case JAVA_TYPE_INT: - case JAVA_TYPE_ENUM: - return "int32_t"; - case JAVA_TYPE_LONG: - return "int64_t"; - case JAVA_TYPE_FLOAT: - return "float"; - case JAVA_TYPE_DOUBLE: - return "double"; - case JAVA_TYPE_STRING: - return "char const*"; - case JAVA_TYPE_BYTE_ARRAY: - return "const BytesField&"; - default: - return "UNKNOWN"; - } -} - -const char* java_type_name(java_type_t type) { - switch (type) { - case JAVA_TYPE_BOOLEAN: - return "boolean"; - case JAVA_TYPE_INT: - case JAVA_TYPE_ENUM: - return "int"; - case JAVA_TYPE_LONG: - return "long"; - case JAVA_TYPE_FLOAT: - return "float"; - case JAVA_TYPE_DOUBLE: - return "double"; - case JAVA_TYPE_STRING: - return "java.lang.String"; - case JAVA_TYPE_BYTE_ARRAY: - return "byte[]"; - default: - return "UNKNOWN"; - } -} - -// Native -// Writes namespaces for the cpp and header files, returning the number of -// namespaces written. -void write_namespace(FILE* out, const string& cppNamespaces) { - vector<string> cppNamespaceVec = Split(cppNamespaces, ","); - for (const string& cppNamespace : cppNamespaceVec) { - fprintf(out, "namespace %s {\n", cppNamespace.c_str()); - } -} - -// Writes namespace closing brackets for cpp and header files. -void write_closing_namespace(FILE* out, const string& cppNamespaces) { - vector<string> cppNamespaceVec = Split(cppNamespaces, ","); - for (auto it = cppNamespaceVec.rbegin(); it != cppNamespaceVec.rend(); ++it) { - fprintf(out, "} // namespace %s\n", it->c_str()); - } -} - -static void write_cpp_usage(FILE* out, const string& method_name, const string& atom_code_name, - const shared_ptr<AtomDecl> atom, const AtomDecl& attributionDecl) { - fprintf(out, " * Usage: %s(StatsLog.%s", method_name.c_str(), atom_code_name.c_str()); - - for (vector<AtomField>::const_iterator field = atom->fields.begin(); - field != atom->fields.end(); field++) { - if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) { - for (const auto& chainField : attributionDecl.fields) { - if (chainField.javaType == JAVA_TYPE_STRING) { - fprintf(out, ", const std::vector<%s>& %s", cpp_type_name(chainField.javaType), - chainField.name.c_str()); - } else { - fprintf(out, ", const %s* %s, size_t %s_length", - cpp_type_name(chainField.javaType), chainField.name.c_str(), - chainField.name.c_str()); - } - } - } else if (field->javaType == JAVA_TYPE_KEY_VALUE_PAIR) { - fprintf(out, - ", const std::map<int, int32_t>& %s_int" - ", const std::map<int, int64_t>& %s_long" - ", const std::map<int, char const*>& %s_str" - ", const std::map<int, float>& %s_float", - field->name.c_str(), field->name.c_str(), field->name.c_str(), - field->name.c_str()); - } else { - fprintf(out, ", %s %s", cpp_type_name(field->javaType), field->name.c_str()); - } - } - fprintf(out, ");\n"); -} - -void write_native_atom_constants(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl) { - fprintf(out, "/**\n"); - fprintf(out, " * Constants for atom codes.\n"); - fprintf(out, " */\n"); - fprintf(out, "enum {\n"); - - std::map<int, AtomDeclSet::const_iterator> atom_code_to_non_chained_decl_map; - build_non_chained_decl_map(atoms, &atom_code_to_non_chained_decl_map); - - size_t i = 0; - // Print atom constants - for (AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); atomIt != atoms.decls.end(); - atomIt++) { - string constant = make_constant_name((*atomIt)->name); - fprintf(out, "\n"); - fprintf(out, " /**\n"); - fprintf(out, " * %s %s\n", (*atomIt)->message.c_str(), (*atomIt)->name.c_str()); - write_cpp_usage(out, "stats_write", constant, *atomIt, attributionDecl); - - auto non_chained_decl = atom_code_to_non_chained_decl_map.find((*atomIt)->code); - if (non_chained_decl != atom_code_to_non_chained_decl_map.end()) { - write_cpp_usage(out, "stats_write_non_chained", constant, *non_chained_decl->second, - attributionDecl); - } - fprintf(out, " */\n"); - char const* const comma = (i == atoms.decls.size() - 1) ? "" : ","; - fprintf(out, " %s = %d%s\n", constant.c_str(), (*atomIt)->code, comma); - i++; - } - fprintf(out, "\n"); - fprintf(out, "};\n"); - fprintf(out, "\n"); -} - -void write_native_method_signature(FILE* out, const string& signaturePrefix, - const vector<java_type_t>& signature, - const AtomDecl& attributionDecl, const string& closer) { - fprintf(out, "%sint32_t code", signaturePrefix.c_str()); - int argIndex = 1; - for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end(); - arg++) { - if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) { - for (const auto& chainField : attributionDecl.fields) { - if (chainField.javaType == JAVA_TYPE_STRING) { - fprintf(out, ", const std::vector<%s>& %s", cpp_type_name(chainField.javaType), - chainField.name.c_str()); - } else { - fprintf(out, ", const %s* %s, size_t %s_length", - cpp_type_name(chainField.javaType), chainField.name.c_str(), - chainField.name.c_str()); - } - } - } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) { - fprintf(out, - ", const std::map<int, int32_t>& arg%d_1, " - "const std::map<int, int64_t>& arg%d_2, " - "const std::map<int, char const*>& arg%d_3, " - "const std::map<int, float>& arg%d_4", - argIndex, argIndex, argIndex, argIndex); - } else { - fprintf(out, ", %s arg%d", cpp_type_name(*arg), argIndex); - } - argIndex++; - } - fprintf(out, ")%s\n", closer.c_str()); -} - -void write_native_method_call(FILE* out, const string& methodName, - const vector<java_type_t>& signature, const AtomDecl& attributionDecl, - int argIndex) { - fprintf(out, "%s(code", methodName.c_str()); - for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end(); - arg++) { - if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) { - for (const auto& chainField : attributionDecl.fields) { - if (chainField.javaType == JAVA_TYPE_STRING) { - fprintf(out, ", %s", chainField.name.c_str()); - } else { - fprintf(out, ", %s, %s_length", chainField.name.c_str(), - chainField.name.c_str()); - } - } - } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) { - fprintf(out, ", arg%d_1, arg%d_2, arg%d_3, arg%d_4", argIndex, argIndex, argIndex, - argIndex); - } else { - fprintf(out, ", arg%d", argIndex); - } - argIndex++; - } - fprintf(out, ");\n"); -} - -// Java -void write_java_atom_codes(FILE* out, const Atoms& atoms) { - fprintf(out, " // Constants for atom codes.\n"); - - std::map<int, AtomDeclSet::const_iterator> atom_code_to_non_chained_decl_map; - build_non_chained_decl_map(atoms, &atom_code_to_non_chained_decl_map); - - // Print constants for the atom codes. - for (AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); atomIt != atoms.decls.end(); - atomIt++) { - string constant = make_constant_name((*atomIt)->name); - fprintf(out, "\n"); - fprintf(out, " /**\n"); - fprintf(out, " * %s %s<br>\n", (*atomIt)->message.c_str(), (*atomIt)->name.c_str()); - write_java_usage(out, "write", constant, **atomIt); - auto non_chained_decl = atom_code_to_non_chained_decl_map.find((*atomIt)->code); - if (non_chained_decl != atom_code_to_non_chained_decl_map.end()) { - write_java_usage(out, "write_non_chained", constant, **(non_chained_decl->second)); - } - fprintf(out, " */\n"); - fprintf(out, " public static final int %s = %d;\n", constant.c_str(), (*atomIt)->code); - } - fprintf(out, "\n"); -} - -void write_java_enum_values(FILE* out, const Atoms& atoms) { - fprintf(out, " // Constants for enum values.\n\n"); - for (AtomDeclSet::const_iterator atomIt = atoms.decls.begin(); atomIt != atoms.decls.end(); - atomIt++) { - for (vector<AtomField>::const_iterator field = (*atomIt)->fields.begin(); - field != (*atomIt)->fields.end(); field++) { - if (field->javaType == JAVA_TYPE_ENUM) { - fprintf(out, " // Values for %s.%s\n", (*atomIt)->message.c_str(), - field->name.c_str()); - for (map<int, string>::const_iterator value = field->enumValues.begin(); - value != field->enumValues.end(); value++) { - fprintf(out, " public static final int %s__%s__%s = %d;\n", - make_constant_name((*atomIt)->message).c_str(), - make_constant_name(field->name).c_str(), - make_constant_name(value->second).c_str(), value->first); - } - fprintf(out, "\n"); - } - } - } -} - -void write_java_usage(FILE* out, const string& method_name, const string& atom_code_name, - const AtomDecl& atom) { - fprintf(out, " * Usage: StatsLog.%s(StatsLog.%s", method_name.c_str(), - atom_code_name.c_str()); - for (vector<AtomField>::const_iterator field = atom.fields.begin(); field != atom.fields.end(); - field++) { - if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) { - fprintf(out, ", android.os.WorkSource workSource"); - } else if (field->javaType == JAVA_TYPE_KEY_VALUE_PAIR) { - fprintf(out, ", android.util.SparseArray<Object> value_map"); - } else if (field->javaType == JAVA_TYPE_BYTE_ARRAY) { - fprintf(out, ", byte[] %s", field->name.c_str()); - } else { - fprintf(out, ", %s %s", java_type_name(field->javaType), field->name.c_str()); - } - } - fprintf(out, ");<br>\n"); -} - -int write_java_non_chained_methods(FILE* out, const SignatureInfoMap& signatureInfoMap) { - for (auto signatureInfoMapIt = signatureInfoMap.begin(); - signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) { - // Print method signature. - fprintf(out, " public static void write_non_chained(int code"); - vector<java_type_t> signature = signatureInfoMapIt->first; - int argIndex = 1; - for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end(); - arg++) { - if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) { - fprintf(stderr, "Non chained signatures should not have attribution chains.\n"); - return 1; - } else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) { - fprintf(stderr, "Module logging does not yet support key value pair.\n"); - return 1; - } else { - fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex); - } - argIndex++; - } - fprintf(out, ") {\n"); - - fprintf(out, " write(code"); - argIndex = 1; - for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end(); - arg++) { - // First two args are uid and tag of attribution chain. - if (argIndex == 1) { - fprintf(out, ", new int[] {arg%d}", argIndex); - } else if (argIndex == 2) { - fprintf(out, ", new java.lang.String[] {arg%d}", argIndex); - } else { - fprintf(out, ", arg%d", argIndex); - } - argIndex++; - } - fprintf(out, ");\n"); - fprintf(out, " }\n"); - fprintf(out, "\n"); - } - return 0; -} - -int write_java_work_source_methods(FILE* out, const SignatureInfoMap& signatureInfoMap) { - fprintf(out, " // WorkSource methods.\n"); - for (auto signatureInfoMapIt = signatureInfoMap.begin(); - signatureInfoMapIt != signatureInfoMap.end(); signatureInfoMapIt++) { - vector<java_type_t> signature = signatureInfoMapIt->first; - // Determine if there is Attribution in this signature. - int attributionArg = -1; - int argIndexMax = 0; - for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end(); - arg++) { - argIndexMax++; - if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) { - if (attributionArg > -1) { - fprintf(stderr, "An atom contains multiple AttributionNode fields.\n"); - fprintf(stderr, "This is not supported. Aborting WorkSource method writing.\n"); - fprintf(out, - "\n// Invalid for WorkSource: more than one attribution " - "chain.\n"); - return 1; - } - attributionArg = argIndexMax; - } - } - if (attributionArg < 0) { - continue; - } - - fprintf(out, "\n"); - // Method header (signature) - fprintf(out, " public static void write(int code"); - int argIndex = 1; - for (vector<java_type_t>::const_iterator arg = signature.begin(); arg != signature.end(); - arg++) { - if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) { - fprintf(out, ", android.os.WorkSource ws"); - } else { - fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex); - } - argIndex++; - } - fprintf(out, ") {\n"); - - // write_non_chained() component. TODO: Remove when flat uids are no longer - // needed. - fprintf(out, " for (int i = 0; i < ws.size(); ++i) {\n"); - fprintf(out, " write_non_chained(code"); - for (int argIndex = 1; argIndex <= argIndexMax; argIndex++) { - if (argIndex == attributionArg) { - fprintf(out, ", ws.getUid(i), ws.getPackageName(i)"); - } else { - fprintf(out, ", arg%d", argIndex); - } - } - fprintf(out, ");\n"); - fprintf(out, " }\n"); // close for-loop - - // write() component. - fprintf(out, - " java.util.List<android.os.WorkSource.WorkChain> workChains = " - "ws.getWorkChains();\n"); - fprintf(out, " if (workChains != null) {\n"); - fprintf(out, - " for (android.os.WorkSource.WorkChain wc : workChains) " - "{\n"); - fprintf(out, " write(code"); - for (int argIndex = 1; argIndex <= argIndexMax; argIndex++) { - if (argIndex == attributionArg) { - fprintf(out, ", wc.getUids(), wc.getTags()"); - } else { - fprintf(out, ", arg%d", argIndex); - } - } - fprintf(out, ");\n"); - fprintf(out, " }\n"); // close for-loop - fprintf(out, " }\n"); // close if - fprintf(out, " }\n"); // close method - } - return 0; -} - -} // namespace stats_log_api_gen -} // namespace android diff --git a/tools/stats_log_api_gen/utils.h b/tools/stats_log_api_gen/utils.h deleted file mode 100644 index 13a7e2d8a54e..000000000000 --- a/tools/stats_log_api_gen/utils.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2019, The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_STATS_LOG_API_GEN_UTILS_H -#define ANDROID_STATS_LOG_API_GEN_UTILS_H - -#include <stdio.h> -#include <string.h> - -#include <map> -#include <set> -#include <vector> - -#include "Collation.h" - -namespace android { -namespace stats_log_api_gen { - -const char DEFAULT_CPP_NAMESPACE[] = "android,util"; -const char DEFAULT_CPP_HEADER_IMPORT[] = "statslog.h"; - -const int JAVA_MODULE_REQUIRES_FLOAT = 0x01; -const int JAVA_MODULE_REQUIRES_ATTRIBUTION = 0x02; -const int JAVA_MODULE_REQUIRES_KEY_VALUE_PAIRS = 0x04; - -const map<AnnotationId, string>& get_annotation_id_constants(); - -string make_constant_name(const string& str); - -const char* cpp_type_name(java_type_t type); - -const char* java_type_name(java_type_t type); - -// Common Native helpers -void write_namespace(FILE* out, const string& cppNamespaces); - -void write_closing_namespace(FILE* out, const string& cppNamespaces); - -void write_native_atom_constants(FILE* out, const Atoms& atoms, const AtomDecl& attributionDecl); - -void write_native_method_signature(FILE* out, const string& signaturePrefix, - const vector<java_type_t>& signature, - const AtomDecl& attributionDecl, const string& closer); - -void write_native_method_call(FILE* out, const string& methodName, - const vector<java_type_t>& signature, const AtomDecl& attributionDecl, - int argIndex = 1); - -// Common Java helpers. -void write_java_atom_codes(FILE* out, const Atoms& atoms); - -void write_java_enum_values(FILE* out, const Atoms& atoms); - -void write_java_usage(FILE* out, const string& method_name, const string& atom_code_name, - const AtomDecl& atom); - -int write_java_non_chained_methods(FILE* out, const SignatureInfoMap& signatureInfoMap); - -int write_java_work_source_methods(FILE* out, const SignatureInfoMap& signatureInfoMap); - -} // namespace stats_log_api_gen -} // namespace android - -#endif // ANDROID_STATS_LOG_API_GEN_UTILS_H diff --git a/wifi/Android.bp b/wifi/Android.bp index 7a9ca6012be5..c05f52c7bef5 100644 --- a/wifi/Android.bp +++ b/wifi/Android.bp @@ -43,6 +43,7 @@ filegroup { srcs: [ ":framework-wifi-updatable-java-sources", ":framework-wifi-updatable-exported-aidl-sources", + ":module-utils-os-aidls", ], } @@ -85,13 +86,14 @@ java_defaults { "framework-wifi-util-lib", "android.hardware.wifi-V1.0-java-constants", "modules-utils-build", + "modules-utils-os", ], libs: [ "unsupportedappusage", // for android.compat.annotation.UnsupportedAppUsage ], srcs: [ ":framework-wifi-updatable-sources", - ":framework-wifi-util-lib-aidls", + ":module-utils-os-aidls", ], } diff --git a/wifi/api/current.txt b/wifi/api/current.txt index e11b33efcc33..4b0d38df0260 100644 --- a/wifi/api/current.txt +++ b/wifi/api/current.txt @@ -35,6 +35,7 @@ package android.net.wifi { field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.ScanResult> CREATOR; field public String SSID; field public static final int WIFI_STANDARD_11AC = 5; // 0x5 + field public static final int WIFI_STANDARD_11AD = 7; // 0x7 field public static final int WIFI_STANDARD_11AX = 6; // 0x6 field public static final int WIFI_STANDARD_11N = 4; // 0x4 field public static final int WIFI_STANDARD_LEGACY = 1; // 0x1 @@ -1156,7 +1157,11 @@ package android.net.wifi.rtt { public final class RangingRequest implements android.os.Parcelable { method public int describeContents(); + method public static int getDefaultRttBurstSize(); method public static int getMaxPeers(); + method public static int getMaxRttBurstSize(); + method public static int getMinRttBurstSize(); + method public int getRttBurstSize(); method public void writeToParcel(android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.rtt.RangingRequest> CREATOR; } @@ -1168,6 +1173,7 @@ package android.net.wifi.rtt { method public android.net.wifi.rtt.RangingRequest.Builder addWifiAwarePeer(@NonNull android.net.MacAddress); method public android.net.wifi.rtt.RangingRequest.Builder addWifiAwarePeer(@NonNull android.net.wifi.aware.PeerHandle); method public android.net.wifi.rtt.RangingRequest build(); + method @NonNull public android.net.wifi.rtt.RangingRequest.Builder setRttBurstSize(int); } public final class RangingResult implements android.os.Parcelable { diff --git a/wifi/api/system-current.txt b/wifi/api/system-current.txt index 5a4a88645f01..257f9d53e59f 100644 --- a/wifi/api/system-current.txt +++ b/wifi/api/system-current.txt @@ -277,6 +277,7 @@ package android.net.wifi { method @Nullable public android.net.wifi.WifiConfiguration toWifiConfiguration(); field public static final int BAND_2GHZ = 1; // 0x1 field public static final int BAND_5GHZ = 2; // 0x2 + field public static final int BAND_60GHZ = 8; // 0x8 field public static final int BAND_6GHZ = 4; // 0x4 field @Deprecated public static final int BAND_ANY = 7; // 0x7 field public static final int RANDOMIZATION_NONE = 0; // 0x0 @@ -314,9 +315,13 @@ package android.net.wifi { field public static final int CHANNEL_WIDTH_160MHZ = 6; // 0x6 field public static final int CHANNEL_WIDTH_20MHZ = 2; // 0x2 field public static final int CHANNEL_WIDTH_20MHZ_NOHT = 1; // 0x1 + field public static final int CHANNEL_WIDTH_2160MHZ = 7; // 0x7 field public static final int CHANNEL_WIDTH_40MHZ = 3; // 0x3 + field public static final int CHANNEL_WIDTH_4320MHZ = 8; // 0x8 + field public static final int CHANNEL_WIDTH_6480MHZ = 9; // 0x9 field public static final int CHANNEL_WIDTH_80MHZ = 4; // 0x4 field public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 5; // 0x5 + field public static final int CHANNEL_WIDTH_8640MHZ = 10; // 0xa field public static final int CHANNEL_WIDTH_INVALID = 0; // 0x0 field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.SoftApInfo> CREATOR; } @@ -497,6 +502,7 @@ package android.net.wifi { method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void registerSoftApCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.SoftApCallback); method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void registerTrafficStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.WifiManager.TrafficStateCallback); method @RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE) public void removeOnWifiUsabilityStatsListener(@NonNull android.net.wifi.WifiManager.OnWifiUsabilityStatsListener); + method @RequiresPermission(android.Manifest.permission.NETWORK_AIRPLANE_MODE) public void restartWifiSubsystem(@Nullable String); method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void restoreBackupData(@NonNull byte[]); method @Nullable @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public android.net.wifi.SoftApConfiguration restoreSoftApBackupData(@NonNull byte[]); method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void restoreSupplicantBackupData(@NonNull byte[], @NonNull byte[]); @@ -521,11 +527,11 @@ package android.net.wifi { method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startLocalOnlyHotspot(@NonNull android.net.wifi.SoftApConfiguration, @Nullable java.util.concurrent.Executor, @Nullable android.net.wifi.WifiManager.LocalOnlyHotspotCallback); method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public boolean startScan(android.os.WorkSource); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startSubscriptionProvisioning(@NonNull android.net.wifi.hotspot2.OsuProvider, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.hotspot2.ProvisioningCallback); - method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void startTemporarilyDisablingAllNonCarrierMergedWifi(int); + method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startTemporarilyDisablingAllNonCarrierMergedWifi(int); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public boolean startTetheredHotspot(@Nullable android.net.wifi.SoftApConfiguration); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void stopEasyConnectSession(); method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public boolean stopSoftAp(); - method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void stopTemporarilyDisablingAllNonCarrierMergedWifi(); + method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void stopTemporarilyDisablingAllNonCarrierMergedWifi(); method @RequiresPermission(android.Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS) public void unregisterCoexCallback(@NonNull android.net.wifi.WifiManager.CoexCallback); method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void unregisterNetworkRequestMatchCallback(@NonNull android.net.wifi.WifiManager.NetworkRequestMatchCallback); method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void unregisterSoftApCallback(@NonNull android.net.wifi.WifiManager.SoftApCallback); @@ -634,6 +640,7 @@ package android.net.wifi { method public default void onCapabilityChanged(@NonNull android.net.wifi.SoftApCapability); method public default void onConnectedClientsChanged(@NonNull java.util.List<android.net.wifi.WifiClient>); method public default void onInfoChanged(@NonNull android.net.wifi.SoftApInfo); + method public default void onInfoListChanged(@NonNull java.util.List<android.net.wifi.SoftApInfo>); method public default void onStateChanged(int, int); } @@ -959,6 +966,10 @@ package android.net.wifi.p2p { package android.net.wifi.rtt { + public final class RangingRequest implements android.os.Parcelable { + method @NonNull public java.util.List<android.net.wifi.rtt.ResponderConfig> getRttPeers(); + } + public static final class RangingRequest.Builder { method public android.net.wifi.rtt.RangingRequest.Builder addResponder(@NonNull android.net.wifi.rtt.ResponderConfig); } diff --git a/wifi/jarjar-rules.txt b/wifi/jarjar-rules.txt index dc96df67e866..b15a8d75fabe 100644 --- a/wifi/jarjar-rules.txt +++ b/wifi/jarjar-rules.txt @@ -110,8 +110,6 @@ rule org.ksoap2.** com.android.wifi.x.@0 rule fi.iki.elonen.** com.android.wifi.x.@0 ## used by both framework-wifi and service-wifi ## -rule android.content.pm.BaseParceledListSlice* com.android.wifi.x.@0 -rule android.content.pm.ParceledListSlice* com.android.wifi.x.@0 rule android.os.HandlerExecutor* com.android.wifi.x.@0 rule android.telephony.Annotation* com.android.wifi.x.@0 rule com.android.internal.util.AsyncChannel* com.android.wifi.x.@0 diff --git a/wifi/java/android/net/wifi/ISoftApCallback.aidl b/wifi/java/android/net/wifi/ISoftApCallback.aidl index f81bcb9e06d7..a28a8fb626b1 100644 --- a/wifi/java/android/net/wifi/ISoftApCallback.aidl +++ b/wifi/java/android/net/wifi/ISoftApCallback.aidl @@ -53,6 +53,12 @@ oneway interface ISoftApCallback */ void onInfoChanged(in SoftApInfo softApInfo); + /** + * Service to manager callback providing informations of softap. + * + * @param softApInfoList is the list of the softap informations. {@link SoftApInfo} + */ + void onInfoListChanged(in List<SoftApInfo> softApInfoList); /** * Service to manager callback providing capability of softap. diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl index 866e913800fd..0d4e9c3a513d 100644 --- a/wifi/java/android/net/wifi/IWifiManager.aidl +++ b/wifi/java/android/net/wifi/IWifiManager.aidl @@ -16,8 +16,6 @@ package android.net.wifi; -import android.content.pm.ParceledListSlice; - import android.net.wifi.hotspot2.OsuProvider; import android.net.wifi.hotspot2.PasspointConfiguration; import android.net.wifi.hotspot2.IProvisioningCallback; @@ -47,6 +45,8 @@ import android.os.Messenger; import android.os.ResultReceiver; import android.os.WorkSource; +import com.android.modules.utils.ParceledListSlice; + /** * Interface that allows controlling and querying Wi-Fi connectivity. * @@ -300,4 +300,6 @@ interface IWifiManager void setCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged, boolean enabled); boolean isCarrierNetworkOffloadEnabled(int subscriptionId, boolean merged); + + void restartWifiSubsystem(String reason); } diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java index 4c23286258d8..9f8ecf14175d 100644 --- a/wifi/java/android/net/wifi/ScanResult.java +++ b/wifi/java/android/net/wifi/ScanResult.java @@ -320,6 +320,11 @@ public final class ScanResult implements Parcelable { public static final int WIFI_STANDARD_11AX = 6; /** + * Wi-Fi 802.11ad/ay + */ + public static final int WIFI_STANDARD_11AD = 7; + + /** * AP wifi standard. */ private @WifiStandard int mWifiStandard; @@ -352,6 +357,8 @@ public final class ScanResult implements Parcelable { return "11ac"; case WIFI_STANDARD_11AX: return "11ax"; + case WIFI_STANDARD_11AD: + return "11ad"; case WIFI_STANDARD_UNKNOWN: return "unknown"; } @@ -705,6 +712,13 @@ public final class ScanResult implements Parcelable { return UNSPECIFIED; } } + if (band == WifiScanner.WIFI_BAND_60_GHZ) { + if (channel >= BAND_60_GHZ_FIRST_CH_NUM && channel <= BAND_60_GHZ_LAST_CH_NUM) { + return ((channel - BAND_60_GHZ_FIRST_CH_NUM) * 2160) + BAND_60_GHZ_START_FREQ_MHZ; + } else { + return UNSPECIFIED; + } + } return UNSPECIFIED; } diff --git a/wifi/java/android/net/wifi/SecurityParams.java b/wifi/java/android/net/wifi/SecurityParams.java new file mode 100644 index 000000000000..0ab6f572fba3 --- /dev/null +++ b/wifi/java/android/net/wifi/SecurityParams.java @@ -0,0 +1,824 @@ +/* + * 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.wifi; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.net.wifi.WifiConfiguration.AuthAlgorithm; +import android.net.wifi.WifiConfiguration.GroupCipher; +import android.net.wifi.WifiConfiguration.GroupMgmtCipher; +import android.net.wifi.WifiConfiguration.KeyMgmt; +import android.net.wifi.WifiConfiguration.PairwiseCipher; +import android.net.wifi.WifiConfiguration.Protocol; +import android.net.wifi.WifiConfiguration.SecurityType; +import android.net.wifi.WifiConfiguration.SuiteBCipher; +import android.os.Parcel; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.BitSet; +import java.util.Objects; + +/** + * A class representing a security configuration. + * @hide + */ +public class SecurityParams { + private static final String TAG = "SecurityParams"; + + /** Passpoint Release 1 */ + public static final int PASSPOINT_R1 = 1; + + /** Passpoint Release 2 */ + public static final int PASSPOINT_R2 = 2; + + /** Passpoint Release 3 */ + public static final int PASSPOINT_R3 = 3; + + @IntDef(prefix = { "PASSPOINT_" }, value = { + PASSPOINT_R1, + PASSPOINT_R2, + PASSPOINT_R3, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface PasspointRelease {} + + private @SecurityType int mSecurityType = WifiConfiguration.SECURITY_TYPE_PSK; + + /** + * This indicates that this security type is enabled or disabled. + * Ex. While receiving Transition Disable Indication, older + * security should be disabled. + */ + private boolean mEnabled = true; + + /** + * The set of key management protocols supported by this configuration. + * See {@link KeyMgmt} for descriptions of the values. + * This is set automatically based on the security type. + */ + private BitSet mAllowedKeyManagement = new BitSet(); + + /** + * The set of security protocols supported by this configuration. + * See {@link Protocol} for descriptions of the values. + * This is set automatically based on the security type. + */ + private BitSet mAllowedProtocols = new BitSet(); + + /** + * The set of authentication protocols supported by this configuration. + * See {@link AuthAlgorithm} for descriptions of the values. + * This is set automatically based on the security type. + */ + private BitSet mAllowedAuthAlgorithms = new BitSet(); + + /** + * The set of pairwise ciphers for WPA supported by this configuration. + * See {@link PairwiseCipher} for descriptions of the values. + * This is set automatically based on the security type. + */ + private BitSet mAllowedPairwiseCiphers = new BitSet(); + + /** + * The set of group ciphers supported by this configuration. + * See {@link GroupCipher} for descriptions of the values. + * This is set automatically based on the security type. + */ + private BitSet mAllowedGroupCiphers = new BitSet(); + + /** + * The set of group management ciphers supported by this configuration. + * See {@link GroupMgmtCipher} for descriptions of the values. + */ + private BitSet mAllowedGroupManagementCiphers = new BitSet(); + + /** + * The set of SuiteB ciphers supported by this configuration. + * To be used for WPA3-Enterprise mode. Set automatically by the framework based on the + * certificate type that is used in this configuration. + */ + private BitSet mAllowedSuiteBCiphers = new BitSet(); + + /** + * True if the network requires Protected Management Frames (PMF), false otherwise. + */ + private boolean mRequirePmf = false; + + private @PasspointRelease int mPasspointRelease = PASSPOINT_R2; + + /** Indicate that this SAE security type only accepts H2E (Hash-to-Element) mode. */ + private boolean mIsSaeH2eOnlyMode = false; + + /** Indicate that this SAE security type only accepts PK (Public Key) mode. */ + private boolean mIsSaePkOnlyMode = false; + + /** Indicate whether this is added by auto-upgrade or not. */ + private boolean mIsAddedByAutoUpgrade = false; + + /** Constructor */ + private SecurityParams() { + } + + /** Copy constructor */ + public SecurityParams(@NonNull SecurityParams source) { + this.mSecurityType = source.mSecurityType; + this.mEnabled = source.mEnabled; + this.mAllowedKeyManagement = (BitSet) source.mAllowedKeyManagement.clone(); + this.mAllowedProtocols = (BitSet) source.mAllowedProtocols.clone(); + this.mAllowedAuthAlgorithms = (BitSet) source.mAllowedAuthAlgorithms.clone(); + this.mAllowedPairwiseCiphers = (BitSet) source.mAllowedPairwiseCiphers.clone(); + this.mAllowedGroupCiphers = (BitSet) source.mAllowedGroupCiphers.clone(); + this.mAllowedGroupManagementCiphers = + (BitSet) source.mAllowedGroupManagementCiphers.clone(); + this.mAllowedSuiteBCiphers = + (BitSet) source.mAllowedSuiteBCiphers.clone(); + this.mRequirePmf = source.mRequirePmf; + this.mIsSaeH2eOnlyMode = source.mIsSaeH2eOnlyMode; + this.mIsSaePkOnlyMode = source.mIsSaePkOnlyMode; + this.mIsAddedByAutoUpgrade = source.mIsAddedByAutoUpgrade; + } + + @Override + public boolean equals(Object thatObject) { + if (this == thatObject) { + return true; + } + if (!(thatObject instanceof SecurityParams)) { + return false; + } + SecurityParams that = (SecurityParams) thatObject; + + if (this.mSecurityType != that.mSecurityType) return false; + if (this.mEnabled != that.mEnabled) return false; + if (!this.mAllowedKeyManagement.equals(that.mAllowedKeyManagement)) return false; + if (!this.mAllowedProtocols.equals(that.mAllowedProtocols)) return false; + if (!this.mAllowedAuthAlgorithms.equals(that.mAllowedAuthAlgorithms)) return false; + if (!this.mAllowedPairwiseCiphers.equals(that.mAllowedPairwiseCiphers)) return false; + if (!this.mAllowedGroupCiphers.equals(that.mAllowedGroupCiphers)) return false; + if (!this.mAllowedGroupManagementCiphers.equals(that.mAllowedGroupManagementCiphers)) { + return false; + } + if (!this.mAllowedSuiteBCiphers.equals(that.mAllowedSuiteBCiphers)) return false; + if (this.mRequirePmf != that.mRequirePmf) return false; + if (this.mIsSaeH2eOnlyMode != that.mIsSaeH2eOnlyMode) return false; + if (this.mIsSaePkOnlyMode != that.mIsSaePkOnlyMode) return false; + if (this.mIsAddedByAutoUpgrade != that.mIsAddedByAutoUpgrade) return false; + + return true; + } + + @Override + public int hashCode() { + return Objects.hash(mSecurityType, mEnabled, + mAllowedKeyManagement, mAllowedProtocols, mAllowedAuthAlgorithms, + mAllowedPairwiseCiphers, mAllowedGroupCiphers, mAllowedGroupManagementCiphers, + mAllowedSuiteBCiphers, mRequirePmf, + mIsSaeH2eOnlyMode, mIsSaePkOnlyMode, mIsAddedByAutoUpgrade); + } + + /** + * Check the security type of this params. + * + * @param type the testing security type. + * @return true if this is for the corresponiding type. + */ + public boolean isSecurityType(@SecurityType int type) { + return type == mSecurityType; + } + + /** + * Check whether the security of given params is the same as this one. + * + * @param params the testing security params. + * @return true if their security types are the same. + */ + public boolean isSameSecurityType(SecurityParams params) { + return params.mSecurityType == mSecurityType; + } + + /** + * Update security params to legacy WifiConfiguration object. + * + * @param config the target configuration. + */ + public void updateLegacyWifiConfiguration(WifiConfiguration config) { + config.allowedKeyManagement = (BitSet) mAllowedKeyManagement.clone(); + config.allowedProtocols = (BitSet) mAllowedProtocols.clone(); + config.allowedAuthAlgorithms = (BitSet) mAllowedAuthAlgorithms.clone(); + config.allowedPairwiseCiphers = (BitSet) mAllowedPairwiseCiphers.clone(); + config.allowedGroupCiphers = (BitSet) mAllowedGroupCiphers.clone(); + config.allowedGroupManagementCiphers = (BitSet) mAllowedGroupManagementCiphers.clone(); + config.allowedSuiteBCiphers = (BitSet) mAllowedSuiteBCiphers.clone(); + config.requirePmf = mRequirePmf; + } + + /** + * Set this params enabled. + * + * @param enable enable a specific security type. + */ + public void setEnabled(boolean enable) { + mEnabled = enable; + } + + /** + * Indicate this params is enabled or not. + */ + public boolean isEnabled() { + return mEnabled; + } + + /** + * Set the supporting Fast Initial Link Set-up (FILS) key management. + * + * FILS can be applied to all security types. + * @param enableFilsSha256 Enable FILS SHA256. + * @param enableFilsSha384 Enable FILS SHA256. + */ + public void enableFils(boolean enableFilsSha256, boolean enableFilsSha384) { + if (enableFilsSha256) { + mAllowedKeyManagement.set(KeyMgmt.FILS_SHA256); + } + + if (enableFilsSha384) { + mAllowedKeyManagement.set(KeyMgmt.FILS_SHA384); + } + } + + /** + * Get the copy of allowed key management. + */ + public BitSet getAllowedKeyManagement() { + return (BitSet) mAllowedKeyManagement.clone(); + } + + /** + * Get the copy of allowed protocols. + */ + public BitSet getAllowedProtocols() { + return (BitSet) mAllowedProtocols.clone(); + } + + /** + * Get the copy of allowed auth algorithms. + */ + public BitSet getAllowedAuthAlgorithms() { + return (BitSet) mAllowedAuthAlgorithms.clone(); + } + + /** + * Get the copy of allowed pairwise ciphers. + */ + public BitSet getAllowedPairwiseCiphers() { + return (BitSet) mAllowedPairwiseCiphers.clone(); + } + + /** + * Get the copy of allowed group ciphers. + */ + public BitSet getAllowedGroupCiphers() { + return (BitSet) mAllowedGroupCiphers.clone(); + } + + /** + * Get the copy of allowed group management ciphers. + */ + public BitSet getAllowedGroupManagementCiphers() { + return (BitSet) mAllowedGroupManagementCiphers.clone(); + } + + /** + * Enable Suite-B ciphers. + * + * @param enableEcdheEcdsa enable Diffie-Hellman with Elliptic Curve ECDSA cipher support. + * @param enableEcdheRsa enable Diffie-Hellman with RSA cipher support. + */ + public void enableSuiteBCiphers(boolean enableEcdheEcdsa, boolean enableEcdheRsa) { + if (enableEcdheEcdsa) { + mAllowedSuiteBCiphers.set(SuiteBCipher.ECDHE_ECDSA); + } else { + mAllowedSuiteBCiphers.clear(SuiteBCipher.ECDHE_ECDSA); + } + + if (enableEcdheRsa) { + mAllowedSuiteBCiphers.set(SuiteBCipher.ECDHE_RSA); + } else { + mAllowedSuiteBCiphers.clear(SuiteBCipher.ECDHE_RSA); + } + } + + /** + * Get the copy of allowed suite-b ciphers. + */ + public BitSet getAllowedSuiteBCiphers() { + return (BitSet) mAllowedSuiteBCiphers.clone(); + } + + /** + * Indicate PMF is required or not. + */ + public boolean isRequirePmf() { + return mRequirePmf; + } + + /** + * Indicate that this is open security type. + */ + public boolean isOpenSecurityType() { + return isSecurityType(WifiConfiguration.SECURITY_TYPE_OPEN) + || isSecurityType(WifiConfiguration.SECURITY_TYPE_OWE); + } + + /** + * Indicate that this is enterprise security type. + */ + public boolean isEnterpriseSecurityType() { + return mAllowedKeyManagement.get(KeyMgmt.WPA_EAP) + || mAllowedKeyManagement.get(KeyMgmt.IEEE8021X) + || mAllowedKeyManagement.get(KeyMgmt.SUITE_B_192) + || mAllowedKeyManagement.get(KeyMgmt.WAPI_CERT); + } + + /** + * Enable Hash-to-Element only mode. + * + * @param enable set H2E only mode enabled or not. + */ + public void enableSaeH2eOnlyMode(boolean enable) { + mIsSaeH2eOnlyMode = enable; + } + + /** + * Indicate whether this params is H2E only mode. + * + * @return true if this is H2E only mode params. + */ + public boolean isSaeH2eOnlyMode() { + return mIsSaeH2eOnlyMode; + } + /** + * Enable Pubilc-Key only mode. + * + * @param enable set PK only mode enabled or not. + */ + public void enableSaePkOnlyMode(boolean enable) { + mIsSaePkOnlyMode = enable; + } + + /** + * Indicate whether this params is PK only mode. + * + * @return true if this is PK only mode params. + */ + public boolean isSaePkOnlyMode() { + return mIsSaePkOnlyMode; + } + + /** + * Set whether this is added by auto-upgrade. + * + * @param addedByAutoUpgrade true if added by auto-upgrade. + */ + public void setIsAddedByAutoUpgrade(boolean addedByAutoUpgrade) { + mIsAddedByAutoUpgrade = addedByAutoUpgrade; + } + + /** + * Indicate whether this is added by auto-upgrade or not. + * + * @return true if added by auto-upgrade; otherwise, false. + */ + public boolean isAddedByAutoUpgrade() { + return mIsAddedByAutoUpgrade; + } + + @Override + public String toString() { + StringBuilder sbuf = new StringBuilder(); + sbuf.append("Security Parameters:\n"); + sbuf.append(" Type: ").append(mSecurityType).append("\n"); + sbuf.append(" Enabled: ").append(mEnabled).append("\n"); + sbuf.append(" KeyMgmt:"); + for (int k = 0; k < mAllowedKeyManagement.size(); k++) { + if (mAllowedKeyManagement.get(k)) { + sbuf.append(" "); + if (k < KeyMgmt.strings.length) { + sbuf.append(KeyMgmt.strings[k]); + } else { + sbuf.append("??"); + } + } + } + sbuf.append('\n'); + sbuf.append(" Protocols:"); + for (int p = 0; p < mAllowedProtocols.size(); p++) { + if (mAllowedProtocols.get(p)) { + sbuf.append(" "); + if (p < Protocol.strings.length) { + sbuf.append(Protocol.strings[p]); + } else { + sbuf.append("??"); + } + } + } + sbuf.append('\n'); + sbuf.append(" AuthAlgorithms:"); + for (int a = 0; a < mAllowedAuthAlgorithms.size(); a++) { + if (mAllowedAuthAlgorithms.get(a)) { + sbuf.append(" "); + if (a < AuthAlgorithm.strings.length) { + sbuf.append(AuthAlgorithm.strings[a]); + } else { + sbuf.append("??"); + } + } + } + sbuf.append('\n'); + sbuf.append(" PairwiseCiphers:"); + for (int pc = 0; pc < mAllowedPairwiseCiphers.size(); pc++) { + if (mAllowedPairwiseCiphers.get(pc)) { + sbuf.append(" "); + if (pc < PairwiseCipher.strings.length) { + sbuf.append(PairwiseCipher.strings[pc]); + } else { + sbuf.append("??"); + } + } + } + sbuf.append('\n'); + sbuf.append(" GroupCiphers:"); + for (int gc = 0; gc < mAllowedGroupCiphers.size(); gc++) { + if (mAllowedGroupCiphers.get(gc)) { + sbuf.append(" "); + if (gc < GroupCipher.strings.length) { + sbuf.append(GroupCipher.strings[gc]); + } else { + sbuf.append("??"); + } + } + } + sbuf.append('\n'); + sbuf.append(" GroupMgmtCiphers:"); + for (int gmc = 0; gmc < mAllowedGroupManagementCiphers.size(); gmc++) { + if (mAllowedGroupManagementCiphers.get(gmc)) { + sbuf.append(" "); + if (gmc < GroupMgmtCipher.strings.length) { + sbuf.append(GroupMgmtCipher.strings[gmc]); + } else { + sbuf.append("??"); + } + } + } + sbuf.append('\n'); + sbuf.append(" SuiteBCiphers:"); + for (int sbc = 0; sbc < mAllowedSuiteBCiphers.size(); sbc++) { + if (mAllowedSuiteBCiphers.get(sbc)) { + sbuf.append(" "); + if (sbc < SuiteBCipher.strings.length) { + sbuf.append(SuiteBCipher.strings[sbc]); + } else { + sbuf.append("??"); + } + } + } + sbuf.append('\n'); + sbuf.append(" RequirePmf: ").append(mRequirePmf).append('\n'); + sbuf.append(" IsAddedByAutoUpgrade: ").append(mIsAddedByAutoUpgrade).append("\n"); + sbuf.append(" IsSaeH2eOnlyMode: ").append(mIsSaeH2eOnlyMode).append("\n"); + sbuf.append(" IsSaePkOnlyMode: ").append(mIsSaePkOnlyMode).append("\n"); + return sbuf.toString(); + } + + private static BitSet readBitSet(Parcel src) { + int cardinality = src.readInt(); + + BitSet set = new BitSet(); + for (int i = 0; i < cardinality; i++) { + set.set(src.readInt()); + } + + return set; + } + + private static void writeBitSet(Parcel dest, BitSet set) { + int nextSetBit = -1; + + dest.writeInt(set.cardinality()); + + while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1) { + dest.writeInt(nextSetBit); + } + } + + /** Write this object to the parcel. */ + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mSecurityType); + dest.writeBoolean(mEnabled); + writeBitSet(dest, mAllowedKeyManagement); + writeBitSet(dest, mAllowedProtocols); + writeBitSet(dest, mAllowedAuthAlgorithms); + writeBitSet(dest, mAllowedPairwiseCiphers); + writeBitSet(dest, mAllowedGroupCiphers); + writeBitSet(dest, mAllowedGroupManagementCiphers); + writeBitSet(dest, mAllowedSuiteBCiphers); + dest.writeBoolean(mRequirePmf); + dest.writeBoolean(mIsAddedByAutoUpgrade); + dest.writeBoolean(mIsSaeH2eOnlyMode); + dest.writeBoolean(mIsSaePkOnlyMode); + + } + + /** Create a SecurityParams object from the parcel. */ + public static final @NonNull SecurityParams createFromParcel(Parcel in) { + SecurityParams params = new SecurityParams(); + params.mSecurityType = in.readInt(); + params.mEnabled = in.readBoolean(); + params.mAllowedKeyManagement = readBitSet(in); + params.mAllowedProtocols = readBitSet(in); + params.mAllowedAuthAlgorithms = readBitSet(in); + params.mAllowedPairwiseCiphers = readBitSet(in); + params.mAllowedGroupCiphers = readBitSet(in); + params.mAllowedGroupManagementCiphers = readBitSet(in); + params.mAllowedSuiteBCiphers = readBitSet(in); + params.mRequirePmf = in.readBoolean(); + params.mIsAddedByAutoUpgrade = in.readBoolean(); + params.mIsSaeH2eOnlyMode = in.readBoolean(); + params.mIsSaePkOnlyMode = in.readBoolean(); + return params; + } + + /** + * Create EAP security params. + */ + public static @NonNull SecurityParams createWpaWpa2EnterpriseParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_EAP; + + params.mAllowedKeyManagement.set(KeyMgmt.WPA_EAP); + params.mAllowedKeyManagement.set(KeyMgmt.IEEE8021X); + + params.mAllowedProtocols.set(Protocol.RSN); + params.mAllowedProtocols.set(Protocol.WPA); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP); + params.mAllowedPairwiseCiphers.set(PairwiseCipher.TKIP); + + params.mAllowedGroupCiphers.set(GroupCipher.CCMP); + params.mAllowedGroupCiphers.set(GroupCipher.TKIP); + return params; + } + + /** + * Create Passpoint security params. + */ + public static @NonNull SecurityParams createPasspointParams(@PasspointRelease int release) { + SecurityParams params = new SecurityParams(); + switch (release) { + case PASSPOINT_R1: + case PASSPOINT_R2: + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_PASSPOINT_R1_R2; + break; + case PASSPOINT_R3: + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_PASSPOINT_R3; + params.mRequirePmf = true; + break; + default: + throw new IllegalArgumentException("invalid passpoint release " + release); + } + + params.mAllowedKeyManagement.set(KeyMgmt.WPA_EAP); + params.mAllowedKeyManagement.set(KeyMgmt.IEEE8021X); + + params.mAllowedProtocols.set(Protocol.RSN); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP); + + params.mAllowedGroupCiphers.set(GroupCipher.CCMP); + + return params; + } + + /** + * Create Enhanced Open params. + */ + public static @NonNull SecurityParams createEnhancedOpenParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_OWE; + + params.mAllowedKeyManagement.set(KeyMgmt.OWE); + + params.mAllowedProtocols.set(Protocol.RSN); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP); + params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_128); + params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_256); + + params.mAllowedGroupCiphers.set(GroupCipher.CCMP); + params.mAllowedGroupCiphers.set(GroupCipher.GCMP_128); + params.mAllowedGroupCiphers.set(GroupCipher.GCMP_256); + + params.mRequirePmf = true; + return params; + } + + /** + * Create Open params. + */ + public static @NonNull SecurityParams createOpenParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_OPEN; + + params.mAllowedKeyManagement.set(KeyMgmt.NONE); + + params.mAllowedProtocols.set(Protocol.RSN); + params.mAllowedProtocols.set(Protocol.WPA); + return params; + } + + /** + * Create OSEN params. + */ + public static @NonNull SecurityParams createOsenParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_OSEN; + + params.mAllowedKeyManagement.set(KeyMgmt.OSEN); + + params.mAllowedProtocols.set(Protocol.OSEN); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP); + params.mAllowedPairwiseCiphers.set(PairwiseCipher.TKIP); + + params.mAllowedGroupCiphers.set(GroupCipher.CCMP); + params.mAllowedGroupCiphers.set(GroupCipher.TKIP); + return params; + } + + /** + * Create WAPI-CERT params. + */ + public static @NonNull SecurityParams createWapiCertParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_WAPI_CERT; + + params.mAllowedKeyManagement.set(KeyMgmt.WAPI_CERT); + + params.mAllowedProtocols.set(Protocol.WAPI); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.SMS4); + + params.mAllowedGroupCiphers.set(GroupCipher.SMS4); + return params; + } + + /** + * Create WAPI-PSK params. + */ + public static @NonNull SecurityParams createWapiPskParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_WAPI_PSK; + + params.mAllowedKeyManagement.set(KeyMgmt.WAPI_PSK); + + params.mAllowedProtocols.set(Protocol.WAPI); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.SMS4); + + params.mAllowedGroupCiphers.set(GroupCipher.SMS4); + return params; + } + + /** + * Create WEP params. + */ + public static @NonNull SecurityParams createWepParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_WEP; + + params.mAllowedKeyManagement.set(KeyMgmt.NONE); + + params.mAllowedProtocols.set(Protocol.RSN); + + params.mAllowedAuthAlgorithms.set(AuthAlgorithm.OPEN); + params.mAllowedAuthAlgorithms.set(AuthAlgorithm.SHARED); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP); + params.mAllowedPairwiseCiphers.set(PairwiseCipher.TKIP); + + params.mAllowedGroupCiphers.set(GroupCipher.CCMP); + params.mAllowedGroupCiphers.set(GroupCipher.TKIP); + params.mAllowedGroupCiphers.set(GroupCipher.WEP40); + params.mAllowedGroupCiphers.set(GroupCipher.WEP104); + return params; + } + + /** + * Create WPA3 Enterprise 192-bit params. + */ + public static @NonNull SecurityParams createWpa3Enterprise192BitParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT; + + params.mAllowedKeyManagement.set(KeyMgmt.WPA_EAP); + params.mAllowedKeyManagement.set(KeyMgmt.IEEE8021X); + params.mAllowedKeyManagement.set(KeyMgmt.SUITE_B_192); + + params.mAllowedProtocols.set(Protocol.RSN); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_128); + params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_256); + + params.mAllowedGroupCiphers.set(GroupCipher.GCMP_128); + params.mAllowedGroupCiphers.set(GroupCipher.GCMP_256); + + params.mAllowedGroupManagementCiphers.set(GroupMgmtCipher.BIP_GMAC_256); + + // Note: allowedSuiteBCiphers bitset will be set by the service once the + // certificates are attached to this profile + + params.mRequirePmf = true; + return params; + } + + /** + * Create WPA3 Enterprise params. + */ + public static @NonNull SecurityParams createWpa3EnterpriseParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE; + + params.mAllowedKeyManagement.set(KeyMgmt.WPA_EAP); + params.mAllowedKeyManagement.set(KeyMgmt.IEEE8021X); + + params.mAllowedProtocols.set(Protocol.RSN); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP); + params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_256); + + params.mAllowedGroupCiphers.set(GroupCipher.CCMP); + params.mAllowedGroupCiphers.set(GroupCipher.GCMP_256); + + params.mRequirePmf = true; + return params; + } + + /** + * Create WPA3 Personal params. + */ + public static @NonNull SecurityParams createWpa3PersonalParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_SAE; + + params.mAllowedKeyManagement.set(KeyMgmt.SAE); + + params.mAllowedProtocols.set(Protocol.RSN); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP); + params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_128); + params.mAllowedPairwiseCiphers.set(PairwiseCipher.GCMP_256); + + params.mAllowedGroupCiphers.set(GroupCipher.CCMP); + params.mAllowedGroupCiphers.set(GroupCipher.GCMP_128); + params.mAllowedGroupCiphers.set(GroupCipher.GCMP_256); + + params.mRequirePmf = true; + return params; + } + + /** + * Create WPA/WPA2 Personal params. + */ + public static @NonNull SecurityParams createWpaWpa2PersonalParams() { + SecurityParams params = new SecurityParams(); + params.mSecurityType = WifiConfiguration.SECURITY_TYPE_PSK; + + params.mAllowedKeyManagement.set(KeyMgmt.WPA_PSK); + + params.mAllowedProtocols.set(Protocol.RSN); + params.mAllowedProtocols.set(Protocol.WPA); + + params.mAllowedPairwiseCiphers.set(PairwiseCipher.CCMP); + params.mAllowedPairwiseCiphers.set(PairwiseCipher.TKIP); + + params.mAllowedGroupCiphers.set(GroupCipher.CCMP); + params.mAllowedGroupCiphers.set(GroupCipher.TKIP); + params.mAllowedGroupCiphers.set(GroupCipher.WEP40); + params.mAllowedGroupCiphers.set(GroupCipher.WEP104); + return params; + } +} diff --git a/wifi/java/android/net/wifi/SoftApCapability.java b/wifi/java/android/net/wifi/SoftApCapability.java index d570b7e8afa9..6f72f0b58b4b 100644 --- a/wifi/java/android/net/wifi/SoftApCapability.java +++ b/wifi/java/android/net/wifi/SoftApCapability.java @@ -116,6 +116,11 @@ public final class SoftApCapability implements Parcelable { private int[] mSupportedChannelListIn6g = EMPTY_INT_ARRAY; /** + * A list storing supported 60G channels. + */ + private int[] mSupportedChannelListIn60g = EMPTY_INT_ARRAY; + + /** * Get the maximum supported client numbers which AP resides on. */ public int getMaxSupportedClients() { @@ -147,8 +152,8 @@ public final class SoftApCapability implements Parcelable { * Set supported channel list in target band type. * * @param band One of the following band types: - * {@link SoftApConfiguation#BAND_2GHZ}, {@link SoftApConfiguation#BAND_5GHZ} or - * {@link SoftApConfiguation#BAND_6GHZ}. + * {@link SoftApConfiguation#BAND_2GHZ}, {@link SoftApConfiguation#BAND_5GHZ}, + * {@link SoftApConfiguation#BAND_6GHZ}, or {@link SoftApConfiguation#BAND_60GHZ}. * @param supportedChannelList supported channel list in target band * @return true if band and supportedChannelList are valid, otherwise false. * @@ -168,6 +173,9 @@ public final class SoftApCapability implements Parcelable { case SoftApConfiguration.BAND_6GHZ: mSupportedChannelListIn6g = supportedChannelList; break; + case SoftApConfiguration.BAND_60GHZ: + mSupportedChannelListIn60g = supportedChannelList; + break; default: throw new IllegalArgumentException("Invalid band: " + band); } @@ -181,8 +189,8 @@ public final class SoftApCapability implements Parcelable { * {@link SoftapConfiguration.Builder#setChannel(int, int)} API. * * @param band One of the following band types: - * {@link SoftApConfiguation#BAND_2GHZ}, {@link SoftApConfiguation#BAND_5GHZ} or - * {@link SoftApConfiguation#BAND_6GHZ}. + * {@link SoftApConfiguation#BAND_2GHZ}, {@link SoftApConfiguation#BAND_5GHZ}, + * {@link SoftApConfiguation#BAND_6GHZ}, {@link SoftApConfiguation#BAND_60GHZ}. * @return List of supported channels for the band. * * @throws IllegalArgumentException when band type is invalid. @@ -199,6 +207,8 @@ public final class SoftApCapability implements Parcelable { return mSupportedChannelListIn5g; case SoftApConfiguration.BAND_6GHZ: return mSupportedChannelListIn6g; + case SoftApConfiguration.BAND_60GHZ: + return mSupportedChannelListIn60g; default: throw new IllegalArgumentException("Invalid band: " + band); } @@ -214,6 +224,7 @@ public final class SoftApCapability implements Parcelable { mSupportedChannelListIn24g = source.mSupportedChannelListIn24g; mSupportedChannelListIn5g = source.mSupportedChannelListIn5g; mSupportedChannelListIn6g = source.mSupportedChannelListIn6g; + mSupportedChannelListIn60g = source.mSupportedChannelListIn60g; } } @@ -244,6 +255,7 @@ public final class SoftApCapability implements Parcelable { dest.writeIntArray(mSupportedChannelListIn24g); dest.writeIntArray(mSupportedChannelListIn5g); dest.writeIntArray(mSupportedChannelListIn6g); + dest.writeIntArray(mSupportedChannelListIn60g); } @NonNull @@ -255,6 +267,7 @@ public final class SoftApCapability implements Parcelable { capability.setSupportedChannelList(SoftApConfiguration.BAND_2GHZ, in.createIntArray()); capability.setSupportedChannelList(SoftApConfiguration.BAND_5GHZ, in.createIntArray()); capability.setSupportedChannelList(SoftApConfiguration.BAND_6GHZ, in.createIntArray()); + capability.setSupportedChannelList(SoftApConfiguration.BAND_60GHZ, in.createIntArray()); return capability; } @@ -273,6 +286,8 @@ public final class SoftApCapability implements Parcelable { .append(Arrays.toString(mSupportedChannelListIn24g)); sbuf.append("SupportedChannelListIn5g").append(Arrays.toString(mSupportedChannelListIn5g)); sbuf.append("SupportedChannelListIn6g").append(Arrays.toString(mSupportedChannelListIn6g)); + sbuf.append("SupportedChannelListIn60g") + .append(Arrays.toString(mSupportedChannelListIn60g)); return sbuf.toString(); } @@ -285,7 +300,8 @@ public final class SoftApCapability implements Parcelable { && mMaximumSupportedClientNumber == capability.mMaximumSupportedClientNumber && Arrays.equals(mSupportedChannelListIn24g, capability.mSupportedChannelListIn24g) && Arrays.equals(mSupportedChannelListIn5g, capability.mSupportedChannelListIn5g) - && Arrays.equals(mSupportedChannelListIn6g, capability.mSupportedChannelListIn6g); + && Arrays.equals(mSupportedChannelListIn6g, capability.mSupportedChannelListIn6g) + && Arrays.equals(mSupportedChannelListIn60g, capability.mSupportedChannelListIn60g); } @Override @@ -293,6 +309,7 @@ public final class SoftApCapability implements Parcelable { return Objects.hash(mSupportedFeatures, mMaximumSupportedClientNumber, Arrays.hashCode(mSupportedChannelListIn24g), Arrays.hashCode(mSupportedChannelListIn5g), - Arrays.hashCode(mSupportedChannelListIn6g)); + Arrays.hashCode(mSupportedChannelListIn6g), + Arrays.hashCode(mSupportedChannelListIn60g)); } } diff --git a/wifi/java/android/net/wifi/SoftApConfiguration.java b/wifi/java/android/net/wifi/SoftApConfiguration.java index 1bb9ebccb01a..d36acb72ff8a 100644 --- a/wifi/java/android/net/wifi/SoftApConfiguration.java +++ b/wifi/java/android/net/wifi/SoftApConfiguration.java @@ -88,6 +88,13 @@ public final class SoftApConfiguration implements Parcelable { public static final int BAND_6GHZ = 1 << 2; /** + * 60GHz band. + * @hide + */ + @SystemApi + public static final int BAND_60GHZ = 1 << 3; + + /** * Device is allowed to choose the optimal band (2Ghz, 5Ghz, 6Ghz) based on device capability, * operating country code and current radio conditions. * @hide @@ -104,11 +111,13 @@ public final class SoftApConfiguration implements Parcelable { BAND_2GHZ, BAND_5GHZ, BAND_6GHZ, + BAND_60GHZ, }) public @interface BandType {} private static boolean isBandValid(@BandType int band) { - return ((band != 0) && ((band & ~BAND_ANY) == 0)); + int bandAny = BAND_2GHZ | BAND_5GHZ | BAND_6GHZ | BAND_60GHZ; + return ((band != 0) && ((band & ~bandAny) == 0)); } private static final int MIN_CH_2G_BAND = 1; @@ -117,6 +126,8 @@ public final class SoftApConfiguration implements Parcelable { private static final int MAX_CH_5G_BAND = 196; private static final int MIN_CH_6G_BAND = 1; private static final int MAX_CH_6G_BAND = 253; + private static final int MIN_CH_60G_BAND = 1; + private static final int MAX_CH_60G_BAND = 6; @@ -139,6 +150,13 @@ public final class SoftApConfiguration implements Parcelable { return false; } break; + + case BAND_60GHZ: + if (channel < MIN_CH_60G_BAND || channel > MAX_CH_60G_BAND) { + return false; + } + break; + default: return false; } diff --git a/wifi/java/android/net/wifi/SoftApInfo.java b/wifi/java/android/net/wifi/SoftApInfo.java index 9a16facfec26..e42e7868e944 100644 --- a/wifi/java/android/net/wifi/SoftApInfo.java +++ b/wifi/java/android/net/wifi/SoftApInfo.java @@ -86,6 +86,34 @@ public final class SoftApInfo implements Parcelable { */ public static final int CHANNEL_WIDTH_160MHZ = 6; + /** + * AP Channel bandwidth is 2160 MHZ. + * + * @see #getBandwidth() + */ + public static final int CHANNEL_WIDTH_2160MHZ = 7; + + /** + * AP Channel bandwidth is 4320 MHZ. + * + * @see #getBandwidth() + */ + public static final int CHANNEL_WIDTH_4320MHZ = 8; + + /** + * AP Channel bandwidth is 6480 MHZ. + * + * @see #getBandwidth() + */ + public static final int CHANNEL_WIDTH_6480MHZ = 9; + + /** + * AP Channel bandwidth is 8640 MHZ. + * + * @see #getBandwidth() + */ + public static final int CHANNEL_WIDTH_8640MHZ = 10; + /** The frequency which AP resides on. */ private int mFrequency = 0; @@ -96,6 +124,10 @@ public final class SoftApInfo implements Parcelable { @Nullable private MacAddress mBssid; + /** The identifier of the AP instance which AP resides on with current info. */ + @Nullable + private String mApInstanceIdentifier; + /** * The operational mode of the AP. */ @@ -121,7 +153,9 @@ public final class SoftApInfo implements Parcelable { * * @return One of {@link #CHANNEL_WIDTH_20MHZ}, {@link #CHANNEL_WIDTH_40MHZ}, * {@link #CHANNEL_WIDTH_80MHZ}, {@link #CHANNEL_WIDTH_160MHZ}, - * {@link #CHANNEL_WIDTH_80MHZ_PLUS_MHZ} or {@link #CHANNEL_WIDTH_INVALID}. + * {@link #CHANNEL_WIDTH_80MHZ_PLUS_MHZ}, {@link #CHANNEL_WIDTH_2160MHZ}, + * {@link #CHANNEL_WIDTH_4320MHZ}, {@link #CHANNEL_WIDTH_6480MHZ}, + * {@link #CHANNEL_WIDTH_8640MHZ}, or {@link #CHANNEL_WIDTH_INVALID}. */ @WifiAnnotations.Bandwidth public int getBandwidth() { @@ -187,6 +221,28 @@ public final class SoftApInfo implements Parcelable { } /** + * Set the AP instance identifier. + * @hide + */ + public void setApInstanceIdentifier(@NonNull String apInstanceIdentifier) { + mApInstanceIdentifier = apInstanceIdentifier; + } + + /** + * Get the AP instance identifier. + * + * The AP instance identifier is a unique identity which can be used to + * associate the {@link SoftApInfo} to a specific {@link WifiClient} + * - see {@link WifiClient#getApInstanceIdentifier()} + * + * @hide + */ + @Nullable + public String getApInstanceIdentifier() { + return mApInstanceIdentifier; + } + + /** * @hide */ public SoftApInfo(@Nullable SoftApInfo source) { @@ -195,6 +251,7 @@ public final class SoftApInfo implements Parcelable { mBandwidth = source.mBandwidth; mBssid = source.mBssid; mWifiStandard = source.mWifiStandard; + mApInstanceIdentifier = source.mApInstanceIdentifier; } } @@ -217,6 +274,7 @@ public final class SoftApInfo implements Parcelable { dest.writeInt(mBandwidth); dest.writeParcelable(mBssid, flags); dest.writeInt(mWifiStandard); + dest.writeString(mApInstanceIdentifier); } @NonNull @@ -228,6 +286,7 @@ public final class SoftApInfo implements Parcelable { info.mBandwidth = in.readInt(); info.mBssid = in.readParcelable(MacAddress.class.getClassLoader()); info.mWifiStandard = in.readInt(); + info.mApInstanceIdentifier = in.readString(); return info; } @@ -245,6 +304,7 @@ public final class SoftApInfo implements Parcelable { sbuf.append(", frequency= ").append(mFrequency); if (mBssid != null) sbuf.append(",bssid=").append(mBssid.toString()); sbuf.append(", wifiStandard= ").append(mWifiStandard); + sbuf.append(", mApInstanceIdentifier= ").append(mApInstanceIdentifier); sbuf.append("}"); return sbuf.toString(); } @@ -257,11 +317,12 @@ public final class SoftApInfo implements Parcelable { return mFrequency == softApInfo.mFrequency && mBandwidth == softApInfo.mBandwidth && Objects.equals(mBssid, softApInfo.mBssid) - && mWifiStandard == softApInfo.mWifiStandard; + && mWifiStandard == softApInfo.mWifiStandard + && Objects.equals(mApInstanceIdentifier, softApInfo.mApInstanceIdentifier); } @Override public int hashCode() { - return Objects.hash(mFrequency, mBandwidth, mBssid, mWifiStandard); + return Objects.hash(mFrequency, mBandwidth, mBssid, mWifiStandard, mApInstanceIdentifier); } } diff --git a/wifi/java/android/net/wifi/WifiAnnotations.java b/wifi/java/android/net/wifi/WifiAnnotations.java index acda7e06c95d..807b40b5722c 100644 --- a/wifi/java/android/net/wifi/WifiAnnotations.java +++ b/wifi/java/android/net/wifi/WifiAnnotations.java @@ -57,6 +57,10 @@ public final class WifiAnnotations { SoftApInfo.CHANNEL_WIDTH_80MHZ, SoftApInfo.CHANNEL_WIDTH_80MHZ_PLUS_MHZ, SoftApInfo.CHANNEL_WIDTH_160MHZ, + SoftApInfo.CHANNEL_WIDTH_2160MHZ, + SoftApInfo.CHANNEL_WIDTH_4320MHZ, + SoftApInfo.CHANNEL_WIDTH_6480MHZ, + SoftApInfo.CHANNEL_WIDTH_8640MHZ, }) @Retention(RetentionPolicy.SOURCE) public @interface Bandwidth {} @@ -77,6 +81,7 @@ public final class WifiAnnotations { ScanResult.WIFI_STANDARD_11N, ScanResult.WIFI_STANDARD_11AC, ScanResult.WIFI_STANDARD_11AX, + ScanResult.WIFI_STANDARD_11AD, }) @Retention(RetentionPolicy.SOURCE) public @interface WifiStandard{} diff --git a/wifi/java/android/net/wifi/WifiClient.java b/wifi/java/android/net/wifi/WifiClient.java index 3794566f3d8f..85e2b3312b29 100644 --- a/wifi/java/android/net/wifi/WifiClient.java +++ b/wifi/java/android/net/wifi/WifiClient.java @@ -30,6 +30,9 @@ public final class WifiClient implements Parcelable { private final MacAddress mMacAddress; + /** The identifier of the AP instance which the client connected. */ + private final String mApInstanceIdentifier; + /** * The mac address of this client. */ @@ -38,15 +41,30 @@ public final class WifiClient implements Parcelable { return mMacAddress; } + /** + * Get AP instance identifier. + * + * The AP instance identifier is a unique identity which can be used to + * associate the {@link SoftApInfo} to a specific {@link WifiClient} + * - see {@link SoftApInfo#getApInstanceIdentifier()} + * @hide + */ + @NonNull + public String getApInstanceIdentifier() { + return mApInstanceIdentifier; + } + private WifiClient(Parcel in) { mMacAddress = in.readParcelable(null); + mApInstanceIdentifier = in.readString(); } /** @hide */ - public WifiClient(@NonNull MacAddress macAddress) { + public WifiClient(@NonNull MacAddress macAddress, @NonNull String apInstanceIdentifier) { Objects.requireNonNull(macAddress, "mMacAddress must not be null."); this.mMacAddress = macAddress; + this.mApInstanceIdentifier = apInstanceIdentifier; } @Override @@ -57,6 +75,7 @@ public final class WifiClient implements Parcelable { @Override public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeParcelable(mMacAddress, flags); + dest.writeString(mApInstanceIdentifier); } @NonNull @@ -75,6 +94,7 @@ public final class WifiClient implements Parcelable { public String toString() { return "WifiClient{" + "mMacAddress=" + mMacAddress + + "mApInstanceIdentifier=" + mApInstanceIdentifier + '}'; } @@ -83,13 +103,12 @@ public final class WifiClient implements Parcelable { if (this == o) return true; if (!(o instanceof WifiClient)) return false; WifiClient client = (WifiClient) o; - return mMacAddress.equals(client.mMacAddress); + return Objects.equals(mMacAddress, client.mMacAddress) + && mApInstanceIdentifier.equals(client.mApInstanceIdentifier); } @Override public int hashCode() { - return Objects.hash(mMacAddress); + return Objects.hash(mMacAddress, mApInstanceIdentifier); } } - - diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index 0009eced1295..ba4a54f9a489 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -19,6 +19,7 @@ package android.net.wifi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.compat.annotation.UnsupportedAppUsage; import android.content.pm.PackageManager; @@ -46,10 +47,13 @@ import com.android.net.module.util.MacAddressUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; import java.util.Arrays; import java.util.BitSet; import java.util.Calendar; +import java.util.Collections; import java.util.HashMap; +import java.util.List; /** * A class representing a configured Wi-Fi network, including the @@ -250,6 +254,11 @@ public class WifiConfiguration implements Parcelable { */ public static final int WAPI = 3; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = {WPA, RSN, OSEN, WAPI}) + public @interface ProtocolScheme {}; + public static final String varName = "proto"; public static final String[] strings = { "WPA", "RSN", "OSEN", "WAPI" }; @@ -274,6 +283,11 @@ public class WifiConfiguration implements Parcelable { /** SAE (Used only for WPA3-Personal) */ public static final int SAE = 3; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = {OPEN, SHARED, LEAP, SAE}) + public @interface AuthAlgorithmScheme {}; + public static final String varName = "auth_alg"; public static final String[] strings = { "OPEN", "SHARED", "LEAP", "SAE" }; @@ -308,6 +322,10 @@ public class WifiConfiguration implements Parcelable { */ public static final int GCMP_128 = 5; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = {NONE, TKIP, CCMP, GCMP_256, SMS4, GCMP_128}) + public @interface PairwiseCipherScheme {}; public static final String varName = "pairwise"; @@ -359,6 +377,11 @@ public class WifiConfiguration implements Parcelable { */ public static final int GCMP_128 = 7; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = {WEP40, WEP104, TKIP, CCMP, GTK_NOT_USED, GCMP_256, SMS4, GCMP_128}) + public @interface GroupCipherScheme {}; + public static final String varName = "group"; public static final String[] strings = @@ -387,9 +410,16 @@ public class WifiConfiguration implements Parcelable { /** GMAC-256 = Galois Message Authentication Code */ public static final int BIP_GMAC_256 = 2; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = {BIP_CMAC_256, BIP_GMAC_128, BIP_GMAC_256}) + public @interface GroupMgmtCipherScheme {}; + private static final String varName = "groupMgmt"; - private static final String[] strings = { "BIP_CMAC_256", + /** @hide */ + @SuppressLint("AllUpper") + public static final @NonNull String[] strings = { "BIP_CMAC_256", "BIP_GMAC_128", "BIP_GMAC_256"}; } @@ -410,9 +440,16 @@ public class WifiConfiguration implements Parcelable { /** Diffie-Hellman with_RSA signature */ public static final int ECDHE_RSA = 1; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = {ECDHE_ECDSA, ECDHE_RSA}) + public @interface SuiteBCipherScheme {}; + private static final String varName = "SuiteB"; - private static final String[] strings = { "ECDHE_ECDSA", "ECDHE_RSA" }; + /** @hide */ + @SuppressLint("AllUpper") + public static final String[] strings = { "ECDHE_ECDSA", "ECDHE_RSA" }; } /** Possible status of a network configuration. */ @@ -460,6 +497,25 @@ public class WifiConfiguration implements Parcelable { public static final int SECURITY_TYPE_WAPI_CERT = 8; /** Security type for a WPA3-Enterprise network. */ public static final int SECURITY_TYPE_EAP_WPA3_ENTERPRISE = 9; + /** + * Security type for an OSEN network. + * @hide + */ + public static final int SECURITY_TYPE_OSEN = 10; + /** + * Security type for a Passpoint R1/R2 network. + * Passpoint R1/R2 uses Enterprise security, where TKIP and WEP are not allowed. + * @hide + */ + public static final int SECURITY_TYPE_PASSPOINT_R1_R2 = 11; + + /** + * Security type for a Passpoint R3 network. + * Passpoint R3 uses Enterprise security, where TKIP and WEP are not allowed, + * and PMF must be set to Required. + * @hide + */ + public static final int SECURITY_TYPE_PASSPOINT_R3 = 12; /** * Security types we support. @@ -478,12 +534,23 @@ public class WifiConfiguration implements Parcelable { SECURITY_TYPE_WAPI_CERT, SECURITY_TYPE_EAP_WPA3_ENTERPRISE, SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT, + SECURITY_TYPE_PASSPOINT_R1_R2, + SECURITY_TYPE_PASSPOINT_R3, }) public @interface SecurityType {} + private List<SecurityParams> mSecurityParamsList = new ArrayList<>(); + + private void updateLegacySecurityParams() { + if (mSecurityParamsList.isEmpty()) return; + mSecurityParamsList.get(0).updateLegacyWifiConfiguration(this); + } + /** * Set the various security params to correspond to the provided security type. * This is accomplished by setting the various BitSets exposed in WifiConfiguration. + * <br> + * This API would clear existing security types and add a default one. * * @param securityType One of the following security types: * {@link #SECURITY_TYPE_OPEN}, @@ -491,103 +558,358 @@ public class WifiConfiguration implements Parcelable { * {@link #SECURITY_TYPE_PSK}, * {@link #SECURITY_TYPE_EAP}, * {@link #SECURITY_TYPE_SAE}, - * {@link #SECURITY_TYPE_EAP_SUITE_B}, * {@link #SECURITY_TYPE_OWE}, * {@link #SECURITY_TYPE_WAPI_PSK}, * {@link #SECURITY_TYPE_WAPI_CERT}, * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE}, - * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT} + * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT}, */ public void setSecurityParams(@SecurityType int securityType) { - // Clear all the bitsets. - allowedKeyManagement.clear(); - allowedProtocols.clear(); - allowedAuthAlgorithms.clear(); - allowedPairwiseCiphers.clear(); - allowedGroupCiphers.clear(); - allowedGroupManagementCiphers.clear(); - allowedSuiteBCiphers.clear(); + // Clear existing data. + mSecurityParamsList = new ArrayList<>(); + addSecurityParams(securityType); + } + /** + * Add the various security params. + * <br> + * This API would clear existing security types and add a default one. + * @hide + */ + public void setSecurityParams(SecurityParams params) { + // Clear existing data. + mSecurityParamsList = new ArrayList<>(); + addSecurityParams(params); + } + + /** + * Add the various security params to correspond to the provided security type. + * This is accomplished by setting the various BitSets exposed in WifiConfiguration. + * + * @param securityType One of the following security types: + * {@link #SECURITY_TYPE_OPEN}, + * {@link #SECURITY_TYPE_WEP}, + * {@link #SECURITY_TYPE_PSK}, + * {@link #SECURITY_TYPE_EAP}, + * {@link #SECURITY_TYPE_SAE}, + * {@link #SECURITY_TYPE_OWE}, + * {@link #SECURITY_TYPE_WAPI_PSK}, + * {@link #SECURITY_TYPE_WAPI_CERT}, + * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE}, + * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT}, + * + * @hide + */ + public void addSecurityParams(@SecurityType int securityType) { + // This ensures that there won't be duplicate security types. + if (mSecurityParamsList.stream().anyMatch(params -> params.isSecurityType(securityType))) { + throw new IllegalArgumentException("duplicate security type " + securityType); + } + SecurityParams params = null; switch (securityType) { case SECURITY_TYPE_OPEN: - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); + params = SecurityParams.createOpenParams(); break; case SECURITY_TYPE_WEP: - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); - allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN); - allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED); + params = SecurityParams.createWepParams(); break; case SECURITY_TYPE_PSK: - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); + params = SecurityParams.createWpaWpa2PersonalParams(); break; case SECURITY_TYPE_EAP: - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X); + params = SecurityParams.createWpaWpa2EnterpriseParams(); break; case SECURITY_TYPE_SAE: - allowedProtocols.set(WifiConfiguration.Protocol.RSN); - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SAE); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_128); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_128); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256); - requirePmf = true; + params = SecurityParams.createWpa3PersonalParams(); break; // The value of {@link SECURITY_TYPE_EAP_SUITE_B} is the same as - // {@link SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT}, remove it to avoid + // {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT}, remove it to avoid // duplicate case label errors. case SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT: - allowedProtocols.set(WifiConfiguration.Protocol.RSN); - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X); - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SUITE_B_192); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_128); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_128); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256); - allowedGroupManagementCiphers.set(WifiConfiguration.GroupMgmtCipher.BIP_GMAC_256); - // Note: allowedSuiteBCiphers bitset will be set by the service once the - // certificates are attached to this profile - requirePmf = true; + params = SecurityParams.createWpa3Enterprise192BitParams(); break; case SECURITY_TYPE_OWE: - allowedProtocols.set(WifiConfiguration.Protocol.RSN); - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.OWE); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_128); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_128); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256); - requirePmf = true; + params = SecurityParams.createEnhancedOpenParams(); break; case SECURITY_TYPE_WAPI_PSK: - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WAPI_PSK); - allowedProtocols.set(WifiConfiguration.Protocol.WAPI); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.SMS4); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.SMS4); + params = SecurityParams.createWapiPskParams(); break; case SECURITY_TYPE_WAPI_CERT: - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WAPI_CERT); - allowedProtocols.set(WifiConfiguration.Protocol.WAPI); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.SMS4); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.SMS4); + params = SecurityParams.createWapiCertParams(); break; case SECURITY_TYPE_EAP_WPA3_ENTERPRISE: - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); - allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X); - allowedProtocols.set(WifiConfiguration.Protocol.RSN); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); - allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.GCMP_256); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); - allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256); - requirePmf = true; + params = SecurityParams.createWpa3EnterpriseParams(); + break; + case SECURITY_TYPE_OSEN: + params = SecurityParams.createOsenParams(); + break; + case SECURITY_TYPE_PASSPOINT_R1_R2: + params = SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R2); + break; + case SECURITY_TYPE_PASSPOINT_R3: + params = SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R3); break; default: throw new IllegalArgumentException("unknown security type " + securityType); } + + addSecurityParams(params); + } + + /** @hide */ + public void addSecurityParams(@NonNull SecurityParams newParams) { + if (mSecurityParamsList.stream().anyMatch(params -> params.isSameSecurityType(newParams))) { + throw new IllegalArgumentException("duplicate security params " + newParams); + } + if (!mSecurityParamsList.isEmpty()) { + if (newParams.isEnterpriseSecurityType() && !isEnterprise()) { + throw new IllegalArgumentException( + "An enterprise security type cannot be added to a personal configuation."); + } + if (!newParams.isEnterpriseSecurityType() && isEnterprise()) { + throw new IllegalArgumentException( + "A personal security type cannot be added to an enterprise configuation."); + } + if (newParams.isOpenSecurityType() && !isOpenNetwork()) { + throw new IllegalArgumentException( + "An open security type cannot be added to a non-open configuation."); + } + if (!newParams.isOpenSecurityType() && isOpenNetwork()) { + throw new IllegalArgumentException( + "A non-open security type cannot be added to an open configuation."); + } + if (newParams.isSecurityType(SECURITY_TYPE_OSEN)) { + throw new IllegalArgumentException( + "An OSEN security type must be the only one type."); + } + } + mSecurityParamsList.add(new SecurityParams(newParams)); + updateLegacySecurityParams(); + } + + /** + * If there is no security params, generate one according to legacy fields. + * @hide + */ + public void convertLegacyFieldsToSecurityParamsIfNeeded() { + if (!mSecurityParamsList.isEmpty()) return; + + if (allowedKeyManagement.get(KeyMgmt.WAPI_CERT)) { + setSecurityParams(SECURITY_TYPE_WAPI_CERT); + } else if (allowedKeyManagement.get(KeyMgmt.WAPI_PSK)) { + setSecurityParams(SECURITY_TYPE_WAPI_PSK); + } else if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) { + setSecurityParams(SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT); + } else if (allowedKeyManagement.get(KeyMgmt.OWE)) { + setSecurityParams(SECURITY_TYPE_OWE); + } else if (allowedKeyManagement.get(KeyMgmt.SAE)) { + setSecurityParams(SECURITY_TYPE_SAE); + } else if (allowedKeyManagement.get(KeyMgmt.OSEN)) { + setSecurityParams(SECURITY_TYPE_OSEN); + } else if (allowedKeyManagement.get(KeyMgmt.WPA2_PSK)) { + setSecurityParams(SECURITY_TYPE_PSK); + } else if (allowedKeyManagement.get(KeyMgmt.WPA_EAP)) { + if (requirePmf) { + setSecurityParams(SECURITY_TYPE_EAP_WPA3_ENTERPRISE); + } else { + setSecurityParams(SECURITY_TYPE_EAP); + } + } else if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) { + setSecurityParams(SECURITY_TYPE_PSK); + } else if (allowedKeyManagement.get(KeyMgmt.NONE)) { + if (hasWepKeys()) { + setSecurityParams(SECURITY_TYPE_WEP); + } else { + setSecurityParams(SECURITY_TYPE_OPEN); + } + } else { + setSecurityParams(SECURITY_TYPE_OPEN); + } + } + + /** + * Disable the various security params to correspond to the provided security type. + * This is accomplished by setting the various BitSets exposed in WifiConfiguration. + * + * @param securityType One of the following security types: + * {@link #SECURITY_TYPE_OPEN}, + * {@link #SECURITY_TYPE_WEP}, + * {@link #SECURITY_TYPE_PSK}, + * {@link #SECURITY_TYPE_EAP}, + * {@link #SECURITY_TYPE_SAE}, + * {@link #SECURITY_TYPE_OWE}, + * {@link #SECURITY_TYPE_WAPI_PSK}, + * {@link #SECURITY_TYPE_WAPI_CERT}, + * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE}, + * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT}, + * + * @hide + */ + public void setSecurityParamsEnabled(@SecurityType int securityType, boolean enable) { + mSecurityParamsList.stream() + .filter(params -> params.isSecurityType(securityType)) + .findAny() + .ifPresent(params -> params.setEnabled(enable)); + } + + /** + * Get the specific security param. + * + * @param securityType One of the following security types: + * {@link #SECURITY_TYPE_OPEN}, + * {@link #SECURITY_TYPE_WEP}, + * {@link #SECURITY_TYPE_PSK}, + * {@link #SECURITY_TYPE_EAP}, + * {@link #SECURITY_TYPE_SAE}, + * {@link #SECURITY_TYPE_OWE}, + * {@link #SECURITY_TYPE_WAPI_PSK}, + * {@link #SECURITY_TYPE_WAPI_CERT}, + * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE}, + * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT}, + * + * @return the copy of specific security params if found; otherwise null. + * @hide + */ + public @Nullable SecurityParams getSecurityParams(@SecurityType int securityType) { + SecurityParams p = mSecurityParamsList.stream() + .filter(params -> params.isSecurityType(securityType)) + .findAny() + .orElse(null); + return (p != null) ? new SecurityParams(p) : null; + } + + /** + * Indicate whether this configuration is the specific security type. + * + * @param securityType One of the following security types: + * {@link #SECURITY_TYPE_OPEN}, + * {@link #SECURITY_TYPE_WEP}, + * {@link #SECURITY_TYPE_PSK}, + * {@link #SECURITY_TYPE_EAP}, + * {@link #SECURITY_TYPE_SAE}, + * {@link #SECURITY_TYPE_OWE}, + * {@link #SECURITY_TYPE_WAPI_PSK}, + * {@link #SECURITY_TYPE_WAPI_CERT}, + * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE}, + * {@link #SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT}, + * + * @return true if there is a security params matches the type. + * @hide + */ + public boolean isSecurityType(@SecurityType int securityType) { + return mSecurityParamsList.stream() + .anyMatch(params -> params.isSecurityType(securityType)); + } + + /** + * Get the security params list of this configuration. + * + * The returning list is a priority list, the first is the lowest priority and default one. + * + * @return this list of security params. + * @hide + */ + public List<SecurityParams> getSecurityParamsList() { + return Collections.unmodifiableList(mSecurityParamsList); + } + + /** + * Enable the support of Fast Initial Link Set-up (FILS). + * + * FILS can be applied to all security types. + * @param enableFilsSha256 Enable FILS SHA256. + * @param enableFilsSha384 Enable FILS SHA256. + * @hide + */ + public void enableFils(boolean enableFilsSha256, boolean enableFilsSha384) { + mSecurityParamsList.stream() + .forEach(params -> params.enableFils(enableFilsSha256, enableFilsSha384)); + updateLegacySecurityParams(); + } + + /** + * Indicate FILS SHA256 is enabled. + * + * @return true if FILS SHA256 is enabled. + * @hide + */ + public boolean isFilsSha256Enabled() { + return mSecurityParamsList.stream() + .anyMatch(params -> params.getAllowedKeyManagement().get(KeyMgmt.FILS_SHA256)); + } + + /** + * Indicate FILS SHA384 is enabled. + * + * @return true if FILS SHA384 is enabled. + * @hide + */ + public boolean isFilsSha384Enabled() { + return mSecurityParamsList.stream() + .anyMatch(params -> params.getAllowedKeyManagement().get(KeyMgmt.FILS_SHA384)); + } + + /** + * Enable Suite-B ciphers. + * + * @param enableEcdheEcdsa enable Diffie-Hellman with Elliptic Curve ECDSA cipher support. + * @param enableEcdheRsa enable Diffie-Hellman with RSA cipher support. + * @hide + */ + public void enableSuiteBCiphers(boolean enableEcdheEcdsa, boolean enableEcdheRsa) { + mSecurityParamsList.stream() + .filter(params -> params.isSecurityType(SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT)) + .findAny() + .ifPresent(params -> params.enableSuiteBCiphers(enableEcdheEcdsa, enableEcdheRsa)); + updateLegacySecurityParams(); + } + + /** + * Indicate ECDHE_ECDSA is enabled. + * + * @return true if enabled. + * @hide + */ + public boolean isSuiteBCipherEcdheEcdsaEnabled() { + return mSecurityParamsList.stream() + .anyMatch(params -> params.getAllowedSuiteBCiphers().get(SuiteBCipher.ECDHE_ECDSA)); + } + + /** + * Indicate ECDHE_RSA is enabled. + * + * @return true if enabled. + * @hide + */ + public boolean isSuiteBCipherEcdheRsaEnabled() { + return mSecurityParamsList.stream() + .anyMatch(params -> params.getAllowedSuiteBCiphers().get(SuiteBCipher.ECDHE_RSA)); + } + + /** + * Set SAE Hash-toElement only mode enabled. + * + * @param enable true if enabled; false otherwise. + * @hide + */ + public void enableSaeH2eOnlyMode(boolean enable) { + mSecurityParamsList.stream() + .filter(params -> params.isSecurityType(SECURITY_TYPE_SAE)) + .findAny() + .ifPresent(params -> params.enableSaeH2eOnlyMode(enable)); + } + + /** + * Set SAE Public-Key only mode enabled. + * + * @param enable true if enabled; false otherwise. + * @hide + */ + public void enableSaePkOnlyMode(boolean enable) { + mSecurityParamsList.stream() + .filter(params -> params.isSecurityType(SECURITY_TYPE_SAE)) + .findAny() + .ifPresent(params -> params.enableSaePkOnlyMode(enable)); } /** @hide */ @@ -1161,27 +1483,25 @@ public class WifiConfiguration implements Parcelable { return metered; } + /** Check whether wep keys exist. */ + private boolean hasWepKeys() { + if (wepKeys == null) return false; + for (int i = 0; i < wepKeys.length; i++) { + if (wepKeys[i] != null) { + return true; + } + } + return false; + } + /** * @hide - * Returns true if this WiFi config is for an open network. + * Returns true if this WiFi config is for an Open or Enhanced Open network. */ public boolean isOpenNetwork() { - final int cardinality = allowedKeyManagement.cardinality(); - final boolean hasNoKeyMgmt = cardinality == 0 - || (cardinality == 1 && (allowedKeyManagement.get(KeyMgmt.NONE) - || allowedKeyManagement.get(KeyMgmt.OWE))); - - boolean hasNoWepKeys = true; - if (wepKeys != null) { - for (int i = 0; i < wepKeys.length; i++) { - if (wepKeys[i] != null) { - hasNoWepKeys = false; - break; - } - } - } - - return hasNoKeyMgmt && hasNoWepKeys; + boolean hasNonOpenSecurityType = mSecurityParamsList.stream() + .anyMatch(params -> !params.isOpenSecurityType()); + return !hasNonOpenSecurityType && !hasWepKeys(); } /** @@ -2389,12 +2709,11 @@ public class WifiConfiguration implements Parcelable { */ @UnsupportedAppUsage public boolean isEnterprise() { - return (allowedKeyManagement.get(KeyMgmt.WPA_EAP) - || allowedKeyManagement.get(KeyMgmt.IEEE8021X) - || allowedKeyManagement.get(KeyMgmt.SUITE_B_192) - || allowedKeyManagement.get(KeyMgmt.WAPI_CERT)) + boolean hasEnterpriseSecurityType = mSecurityParamsList.stream() + .anyMatch(params -> params.isEnterpriseSecurityType()); + return (hasEnterpriseSecurityType && enterpriseConfig != null - && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE; + && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE); } private static String logTimeOfDay(long millis) { @@ -2576,6 +2895,10 @@ public class WifiConfiguration implements Parcelable { sbuf.append('*'); } + sbuf.append("\nSecurityParams List:\n"); + mSecurityParamsList.stream() + .forEach(params -> sbuf.append(params.toString())); + sbuf.append("\nEnterprise config:\n"); sbuf.append(enterpriseConfig); @@ -3024,6 +3347,7 @@ public class WifiConfiguration implements Parcelable { allowedGroupCiphers = (BitSet) source.allowedGroupCiphers.clone(); allowedGroupManagementCiphers = (BitSet) source.allowedGroupManagementCiphers.clone(); allowedSuiteBCiphers = (BitSet) source.allowedSuiteBCiphers.clone(); + mSecurityParamsList = new ArrayList(source.mSecurityParamsList); enterpriseConfig = new WifiEnterpriseConfig(source.enterpriseConfig); defaultGwMacAddress = source.defaultGwMacAddress; @@ -3114,6 +3438,10 @@ public class WifiConfiguration implements Parcelable { writeBitSet(dest, allowedGroupManagementCiphers); writeBitSet(dest, allowedSuiteBCiphers); + dest.writeInt(mSecurityParamsList.size()); + mSecurityParamsList.stream() + .forEach(params -> params.writeToParcel(dest, flags)); + dest.writeParcelable(enterpriseConfig, flags); dest.writeParcelable(mIpConfiguration, flags); @@ -3195,6 +3523,11 @@ public class WifiConfiguration implements Parcelable { config.allowedGroupManagementCiphers = readBitSet(in); config.allowedSuiteBCiphers = readBitSet(in); + int numSecurityParams = in.readInt(); + for (int i = 0; i < numSecurityParams; i++) { + config.mSecurityParamsList.add(SecurityParams.createFromParcel(in)); + } + config.enterpriseConfig = in.readParcelable(null); config.setIpConfiguration(in.readParcelable(null)); config.dhcpServer = in.readString(); @@ -3277,9 +3610,10 @@ public class WifiConfiguration implements Parcelable { * @hide */ public boolean needsPreSharedKey() { - return allowedKeyManagement.get(KeyMgmt.WPA_PSK) - || allowedKeyManagement.get(KeyMgmt.SAE) - || allowedKeyManagement.get(KeyMgmt.WAPI_PSK); + return mSecurityParamsList.stream() + .anyMatch(params -> params.isSecurityType(SECURITY_TYPE_PSK) + || params.isSecurityType(SECURITY_TYPE_SAE) + || params.isSecurityType(SECURITY_TYPE_WAPI_PSK)); } /** diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 2b931a380f43..bccb2410ae09 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -34,7 +34,6 @@ import android.annotation.SystemService; import android.app.ActivityManager; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; -import android.content.pm.ParceledListSlice; import android.net.ConnectivityManager; import android.net.DhcpInfo; import android.net.MacAddress; @@ -63,6 +62,7 @@ import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.android.modules.utils.ParceledListSlice; import com.android.modules.utils.build.SdkLevel; import java.lang.annotation.Retention; @@ -3041,6 +3041,37 @@ public class WifiManager { } /** + * Restart the Wi-Fi subsystem. + * + * Restarts the Wi-Fi subsystem - effectively disabling it and re-enabling it. All existing + * Access Point (AP) associations are torn down, all Soft APs are disabled, Wi-Fi Direct and + * Wi-Fi Aware are disabled. + * + * The state of the system after restart is not guaranteed to match its state before the API is + * called - for instance the device may associate to a different Access Point (AP), and tethered + * hotspots may or may not be restored. + * + * @param reason If non-null, requests a bug report and attaches the reason string to it. A bug + * report may still not be generated based on framework criteria - for instance, + * build type or throttling. The WiFi subsystem is restarted whether or not a bug + * report is requested or generated. + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.NETWORK_AIRPLANE_MODE) + public void restartWifiSubsystem(@Nullable String reason) { + if (!SdkLevel.isAtLeastS()) { + throw new UnsupportedOperationException(); + } + try { + mService.restartWifiSubsystem(reason); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Gets the Wi-Fi enabled state. * @return One of {@link #WIFI_STATE_DISABLED}, * {@link #WIFI_STATE_DISABLING}, {@link #WIFI_STATE_ENABLED}, @@ -3985,6 +4016,11 @@ public class WifiManager { /** * Called when information of softap changes. * + * Note: this API is only valid when the Soft AP is configured as a single AP + * - not as a bridged AP (2 Soft APs). When the Soft AP is configured as bridged AP + * this callback will not be triggered - use the + * {@link #onInfoListChanged(List<SoftApInfo>)} callback in bridged AP mode. + * * @param softApInfo is the softap information. {@link SoftApInfo} */ default void onInfoChanged(@NonNull SoftApInfo softApInfo) { @@ -3992,6 +4028,24 @@ public class WifiManager { } /** + * Called when information of softap changes. + * + * The number of the information elements in the list depends on Soft AP configuration + * and state. + * For instance, an empty list will be returned when the Soft AP is disabled. + * One information element will be returned in the list when the Soft AP is configured + * as a single AP, and two information elements will be returned in the list + * when the Soft AP is configured in bridged mode. + * + * See {@link #isBridgedApConcurrencySupported()} for the detail of the bridged AP. + * + * @param softApInfoList is the list of the softap information elements. {@link SoftApInfo} + */ + default void onInfoListChanged(@NonNull List<SoftApInfo> softApInfoList) { + // Do nothing: can be updated to add SoftApInfo details (e.g. channel) to the UI. + } + + /** * Called when capability of softap changes. * * @param softApCapability is the softap capability. {@link SoftApCapability} @@ -4071,6 +4125,19 @@ public class WifiManager { } @Override + public void onInfoListChanged(List<SoftApInfo> softApInfoList) { + if (mVerboseLoggingEnabled) { + Log.v(TAG, "SoftApCallbackProxy: onInfoListChange: softApInfoList=" + + softApInfoList); + } + + Binder.clearCallingIdentity(); + mExecutor.execute(() -> { + mCallback.onInfoListChanged(softApInfoList); + }); + } + + @Override public void onCapabilityChanged(SoftApCapability capability) { if (mVerboseLoggingEnabled) { Log.v(TAG, "SoftApCallbackProxy: onCapabilityChanged: SoftApCapability=" @@ -4580,7 +4647,9 @@ public class WifiManager { * @hide */ @SystemApi - @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_SETTINGS, + android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startTemporarilyDisablingAllNonCarrierMergedWifi(int subscriptionId) { try { mService.startTemporarilyDisablingAllNonCarrierMergedWifi(subscriptionId); @@ -4595,7 +4664,9 @@ public class WifiManager { * @hide */ @SystemApi - @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) + @RequiresPermission(anyOf = { + android.Manifest.permission.NETWORK_SETTINGS, + android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void stopTemporarilyDisablingAllNonCarrierMergedWifi() { try { mService.stopTemporarilyDisablingAllNonCarrierMergedWifi(); diff --git a/wifi/java/android/net/wifi/rtt/RangingRequest.java b/wifi/java/android/net/wifi/rtt/RangingRequest.java index 318efa61a110..04dfcf2f9cad 100644 --- a/wifi/java/android/net/wifi/rtt/RangingRequest.java +++ b/wifi/java/android/net/wifi/rtt/RangingRequest.java @@ -30,8 +30,11 @@ import android.os.Handler; import android.os.Parcel; import android.os.Parcelable; +import com.android.modules.utils.build.SdkLevel; + import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.StringJoiner; /** @@ -46,6 +49,9 @@ import java.util.StringJoiner; */ public final class RangingRequest implements Parcelable { private static final int MAX_PEERS = 10; + private static final int DEFAULT_RTT_BURST_SIZE = 8; + private static final int MIN_RTT_BURST_SIZE = 2; + private static final int MAX_RTT_BURST_SIZE = 17; /** * Returns the maximum number of peers to range which can be specified in a single {@code @@ -59,12 +65,80 @@ public final class RangingRequest implements Parcelable { return MAX_PEERS; } + /** + * Returns the default RTT burst size used to determine the average range. + * + * @return the RTT burst size used by default + */ + public static int getDefaultRttBurstSize() { + if (!SdkLevel.isAtLeastS()) { + throw new UnsupportedOperationException(); + } + return DEFAULT_RTT_BURST_SIZE; + } + + /** + * Returns the minimum RTT burst size that can be used to determine a average range. + * + * @return the minimum RTT burst size that can be used + */ + public static int getMinRttBurstSize() { + if (!SdkLevel.isAtLeastS()) { + throw new UnsupportedOperationException(); + } + return MIN_RTT_BURST_SIZE; + } + + /** + * Returns the minimum RTT burst size that can be used to determine a average range. + * + * @return the maximum RTT burst size that can be used + */ + public static int getMaxRttBurstSize() { + if (!SdkLevel.isAtLeastS()) { + throw new UnsupportedOperationException(); + } + return MAX_RTT_BURST_SIZE; + } + /** @hide */ public final List<ResponderConfig> mRttPeers; /** @hide */ - private RangingRequest(List<ResponderConfig> rttPeers) { + public final int mRttBurstSize; + + /** @hide */ + private RangingRequest(List<ResponderConfig> rttPeers, int rttBurstSize) { mRttPeers = rttPeers; + mRttBurstSize = rttBurstSize; + } + + /** + * Returns the list of RTT capable peers. + * + * @return the list of RTT capable peers in a common system representation + * + * @hide + */ + @SystemApi + @NonNull + public List<ResponderConfig> getRttPeers() { + if (!SdkLevel.isAtLeastS()) { + throw new UnsupportedOperationException(); + } + return mRttPeers; + } + + /** + * Returns the RTT burst size used to determine the average range. + * + * @return the RTT burst size used + */ + public int getRttBurstSize() { + if (!SdkLevel.isAtLeastS()) { + throw new UnsupportedOperationException(); + } + return mRttBurstSize; } @Override @@ -75,6 +149,7 @@ public final class RangingRequest implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { dest.writeList(mRttPeers); + dest.writeInt(mRttBurstSize); } public static final @android.annotation.NonNull Creator<RangingRequest> CREATOR = new Creator<RangingRequest>() { @@ -85,7 +160,7 @@ public final class RangingRequest implements Parcelable { @Override public RangingRequest createFromParcel(Parcel in) { - return new RangingRequest(in.readArrayList(null)); + return new RangingRequest(in.readArrayList(null), in.readInt()); } }; @@ -105,12 +180,20 @@ public final class RangingRequest implements Parcelable { throw new IllegalArgumentException( "Ranging to too many peers requested. Use getMaxPeers() API to get limit."); } - for (ResponderConfig peer: mRttPeers) { if (!peer.isValid(awareSupported)) { throw new IllegalArgumentException("Invalid Responder specification"); } } + if (SdkLevel.isAtLeastS()) { + if (mRttBurstSize < getMinRttBurstSize() || mRttBurstSize > getMaxRttBurstSize()) { + throw new IllegalArgumentException("RTT burst size is out of range"); + } + } else { + if (mRttBurstSize != DEFAULT_RTT_BURST_SIZE) { + throw new IllegalArgumentException("RTT burst size is not the default value"); + } + } } /** @@ -118,6 +201,32 @@ public final class RangingRequest implements Parcelable { */ public static final class Builder { private List<ResponderConfig> mRttPeers = new ArrayList<>(); + private int mRttBurstSize = DEFAULT_RTT_BURST_SIZE; + + /** + * Set the RTT Burst size for the ranging request. + * <p> + * If not set, the default RTT burst size given by + * {@link #getDefaultRttBurstSize()} is used to determine the default value. + * If set, the value must be in the range {@link #getMinRttBurstSize()} and + * {@link #getMaxRttBurstSize()} inclusively, or a + * {@link java.lang.IllegalArgumentException} will be thrown. + * + * @param rttBurstSize The number of FTM packets used to estimate a range. + * @return The builder to facilitate chaining + * {@code builder.setXXX(..).setXXX(..)}. + */ + @NonNull + public Builder setRttBurstSize(int rttBurstSize) { + if (!SdkLevel.isAtLeastS()) { + throw new UnsupportedOperationException(); + } + if (rttBurstSize < MIN_RTT_BURST_SIZE || rttBurstSize > MAX_RTT_BURST_SIZE) { + throw new IllegalArgumentException("RTT burst size out of range."); + } + mRttBurstSize = rttBurstSize; + return this; + } /** * Add the device specified by the {@link ScanResult} to the list of devices with @@ -241,7 +350,7 @@ public final class RangingRequest implements Parcelable { * builder. */ public RangingRequest build() { - return new RangingRequest(mRttPeers); + return new RangingRequest(mRttPeers, mRttBurstSize); } } @@ -257,11 +366,13 @@ public final class RangingRequest implements Parcelable { RangingRequest lhs = (RangingRequest) o; - return mRttPeers.size() == lhs.mRttPeers.size() && mRttPeers.containsAll(lhs.mRttPeers); + return mRttPeers.size() == lhs.mRttPeers.size() + && mRttPeers.containsAll(lhs.mRttPeers) + && mRttBurstSize == lhs.mRttBurstSize; } @Override public int hashCode() { - return mRttPeers.hashCode(); + return Objects.hash(mRttPeers, mRttBurstSize); } } diff --git a/wifi/tests/src/android/net/wifi/SecurityParamsTest.java b/wifi/tests/src/android/net/wifi/SecurityParamsTest.java new file mode 100644 index 000000000000..2f6b7245795f --- /dev/null +++ b/wifi/tests/src/android/net/wifi/SecurityParamsTest.java @@ -0,0 +1,502 @@ +/* + * 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.wifi; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +import android.net.wifi.WifiConfiguration.AuthAlgorithm; +import android.net.wifi.WifiConfiguration.GroupCipher; +import android.net.wifi.WifiConfiguration.GroupMgmtCipher; +import android.net.wifi.WifiConfiguration.KeyMgmt; +import android.net.wifi.WifiConfiguration.PairwiseCipher; +import android.net.wifi.WifiConfiguration.Protocol; +import android.os.Parcel; + +import androidx.test.filters.SmallTest; + +import org.junit.Test; + +import java.util.BitSet; + +/** + * Unit tests for {@link android.net.wifi.WifiInfo}. + */ +@SmallTest +public class SecurityParamsTest { + + private void verifySecurityParams(SecurityParams params, + int expectedSecurityType, + int[] expectedAllowedKeyManagement, + int[] expectedAllowedProtocols, + int[] expectedAllowedAuthAlgorithms, + int[] expectedAllowedPairwiseCiphers, + int[] expectedAllowedGroupCiphers, + boolean expectedRequirePmf) { + assertTrue(params.isSecurityType(expectedSecurityType)); + for (int b: expectedAllowedKeyManagement) { + assertTrue(params.getAllowedKeyManagement().get(b)); + } + for (int b: expectedAllowedProtocols) { + assertTrue(params.getAllowedProtocols().get(b)); + } + for (int b: expectedAllowedAuthAlgorithms) { + assertTrue(params.getAllowedAuthAlgorithms().get(b)); + } + for (int b: expectedAllowedPairwiseCiphers) { + assertTrue(params.getAllowedPairwiseCiphers().get(b)); + } + for (int b: expectedAllowedGroupCiphers) { + assertTrue(params.getAllowedGroupCiphers().get(b)); + } + assertEquals(expectedRequirePmf, params.isRequirePmf()); + } + + /** Verify EAP params creator. */ + @Test + public void testEapCreator() throws Exception { + SecurityParams p = SecurityParams.createWpaWpa2EnterpriseParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_EAP; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WPA_EAP, KeyMgmt.IEEE8021X}; + int[] expectedAllowedProtocols = new int[] {}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] {}; + int[] expectedAllowedGroupCiphers = new int[] {}; + boolean expectedRequirePmf = false; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify Passpoint R1 params creator. */ + @Test + public void testEapPasspointR1Creator() throws Exception { + SecurityParams p = SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R1); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_PASSPOINT_R1_R2; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WPA_EAP, KeyMgmt.IEEE8021X}; + int[] expectedAllowedProtocols = new int[] {}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] {}; + int[] expectedAllowedGroupCiphers = new int[] {}; + boolean expectedRequirePmf = false; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify Passpoint R2 params creator. */ + @Test + public void testEapPasspointR2Creator() throws Exception { + SecurityParams p = SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R2); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_PASSPOINT_R1_R2; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WPA_EAP, KeyMgmt.IEEE8021X}; + int[] expectedAllowedProtocols = new int[] {}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] {}; + int[] expectedAllowedGroupCiphers = new int[] {}; + boolean expectedRequirePmf = false; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify Passpoint R3 params creator. */ + @Test + public void testEapPasspointR3Creator() throws Exception { + SecurityParams p = SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R3); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_PASSPOINT_R3; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WPA_EAP, KeyMgmt.IEEE8021X}; + int[] expectedAllowedProtocols = new int[] {}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] {}; + int[] expectedAllowedGroupCiphers = new int[] {}; + boolean expectedRequirePmf = true; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify Enhanced Open params creator. */ + @Test + public void testEnhancedOpenCreator() throws Exception { + SecurityParams p = SecurityParams.createEnhancedOpenParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_OWE; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.OWE}; + int[] expectedAllowedProtocols = new int[] {Protocol.RSN}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] { + PairwiseCipher.CCMP, PairwiseCipher.GCMP_128, PairwiseCipher.GCMP_256}; + int[] expectedAllowedGroupCiphers = new int[] { + GroupCipher.CCMP, GroupCipher.GCMP_128, GroupCipher.GCMP_256}; + boolean expectedRequirePmf = true; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify Open params creator. */ + @Test + public void testOpenCreator() throws Exception { + SecurityParams p = SecurityParams.createOpenParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_OPEN; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.NONE}; + int[] expectedAllowedProtocols = new int[] {}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] {}; + int[] expectedAllowedGroupCiphers = new int[] {}; + boolean expectedRequirePmf = false; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify OSEN params creator. */ + @Test + public void testOsenCreator() throws Exception { + SecurityParams p = SecurityParams.createOsenParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_OSEN; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.OSEN}; + int[] expectedAllowedProtocols = new int[] {Protocol.OSEN}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] {}; + int[] expectedAllowedGroupCiphers = new int[] {}; + boolean expectedRequirePmf = false; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify WAPI CERT params creator. */ + @Test + public void testWapiCertCreator() throws Exception { + SecurityParams p = SecurityParams.createWapiCertParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_WAPI_CERT; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WAPI_CERT}; + int[] expectedAllowedProtocols = new int[] {Protocol.WAPI}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] {PairwiseCipher.SMS4}; + int[] expectedAllowedGroupCiphers = new int[] {GroupCipher.SMS4}; + boolean expectedRequirePmf = false; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify WAPI PSK params creator. */ + @Test + public void testWapiPskCreator() throws Exception { + SecurityParams p = SecurityParams.createWapiPskParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_WAPI_PSK; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WAPI_PSK}; + int[] expectedAllowedProtocols = new int[] {Protocol.WAPI}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] {PairwiseCipher.SMS4}; + int[] expectedAllowedGroupCiphers = new int[] {GroupCipher.SMS4}; + boolean expectedRequirePmf = false; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify WEP params creator. */ + @Test + public void testWepCreator() throws Exception { + SecurityParams p = SecurityParams.createWepParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_WEP; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.NONE}; + int[] expectedAllowedProtocols = new int[] {}; + int[] expectedAllowedAuthAlgorithms = new int[] {AuthAlgorithm.OPEN, AuthAlgorithm.SHARED}; + int[] expectedAllowedPairwiseCiphers = new int[] {}; + int[] expectedAllowedGroupCiphers = new int[] {}; + boolean expectedRequirePmf = false; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify WPA3 Enterprise 192-bit params creator. */ + @Test + public void testWpa3Enterprise192BitCreator() throws Exception { + SecurityParams p = SecurityParams.createWpa3Enterprise192BitParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT; + int[] expectedAllowedKeyManagement = new int[] { + KeyMgmt.WPA_EAP, KeyMgmt.IEEE8021X, KeyMgmt.SUITE_B_192}; + int[] expectedAllowedProtocols = new int[] {Protocol.RSN}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] { + PairwiseCipher.GCMP_128, PairwiseCipher.GCMP_256}; + int[] expectedAllowedGroupCiphers = new int[] {GroupCipher.GCMP_128, GroupCipher.GCMP_256}; + boolean expectedRequirePmf = true; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + + assertTrue(p.getAllowedGroupManagementCiphers().get(GroupMgmtCipher.BIP_GMAC_256)); + } + + /** Verify WPA3 Enterprise params creator. */ + @Test + public void testWpa3EnterpriseCreator() throws Exception { + SecurityParams p = SecurityParams.createWpa3EnterpriseParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WPA_EAP, KeyMgmt.IEEE8021X}; + int[] expectedAllowedProtocols = new int[] {Protocol.RSN}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] { + PairwiseCipher.CCMP, PairwiseCipher.GCMP_256}; + int[] expectedAllowedGroupCiphers = new int[] {GroupCipher.CCMP, GroupCipher.GCMP_256}; + boolean expectedRequirePmf = true; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify WPA3 Personal params creator. */ + @Test + public void testWpa3PersonalCreator() throws Exception { + SecurityParams p = SecurityParams.createWpa3PersonalParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_SAE; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.SAE}; + int[] expectedAllowedProtocols = new int[] {Protocol.RSN}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] { + PairwiseCipher.CCMP, PairwiseCipher.GCMP_128, PairwiseCipher.GCMP_256}; + int[] expectedAllowedGroupCiphers = new int[] { + GroupCipher.CCMP, GroupCipher.GCMP_128, GroupCipher.GCMP_256}; + boolean expectedRequirePmf = true; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify WPA2 Personal EAP params creator. */ + @Test + public void testWpaWpa2PersonalCreator() throws Exception { + SecurityParams p = SecurityParams.createWpaWpa2PersonalParams(); + int expectedSecurityType = WifiConfiguration.SECURITY_TYPE_PSK; + int[] expectedAllowedKeyManagement = new int[] {KeyMgmt.WPA_PSK}; + int[] expectedAllowedProtocols = new int[] {}; + int[] expectedAllowedAuthAlgorithms = new int[] {}; + int[] expectedAllowedPairwiseCiphers = new int[] {}; + int[] expectedAllowedGroupCiphers = new int[] {}; + boolean expectedRequirePmf = false; + verifySecurityParams(p, expectedSecurityType, + expectedAllowedKeyManagement, expectedAllowedProtocols, + expectedAllowedAuthAlgorithms, expectedAllowedPairwiseCiphers, + expectedAllowedGroupCiphers, expectedRequirePmf); + } + + /** Verify setter/getter methods */ + @Test + public void testCommonSetterGetter() throws Exception { + SecurityParams params = SecurityParams.createWpaWpa2PersonalParams(); + + // PSK setting + BitSet allowedKeyManagement = new BitSet(); + allowedKeyManagement.set(KeyMgmt.WPA_PSK); + + BitSet allowedProtocols = new BitSet(); + allowedProtocols.set(Protocol.RSN); + allowedProtocols.set(Protocol.WPA); + + BitSet allowedPairwiseCiphers = new BitSet(); + allowedPairwiseCiphers.set(PairwiseCipher.CCMP); + allowedPairwiseCiphers.set(PairwiseCipher.TKIP); + + BitSet allowedGroupCiphers = new BitSet(); + allowedGroupCiphers.set(GroupCipher.CCMP); + allowedGroupCiphers.set(GroupCipher.TKIP); + allowedGroupCiphers.set(GroupCipher.WEP40); + allowedGroupCiphers.set(GroupCipher.WEP104); + + assertEquals(allowedKeyManagement, params.getAllowedKeyManagement()); + assertTrue(params.getAllowedKeyManagement().get(KeyMgmt.WPA_PSK)); + + assertEquals(allowedProtocols, params.getAllowedProtocols()); + assertTrue(params.getAllowedProtocols().get(Protocol.RSN)); + assertTrue(params.getAllowedProtocols().get(Protocol.WPA)); + + assertEquals(allowedPairwiseCiphers, params.getAllowedPairwiseCiphers()); + assertTrue(params.getAllowedPairwiseCiphers().get(PairwiseCipher.CCMP)); + assertTrue(params.getAllowedPairwiseCiphers().get(PairwiseCipher.TKIP)); + + assertEquals(allowedGroupCiphers, params.getAllowedGroupCiphers()); + assertTrue(params.getAllowedGroupCiphers().get(GroupCipher.CCMP)); + assertTrue(params.getAllowedGroupCiphers().get(GroupCipher.TKIP)); + assertTrue(params.getAllowedGroupCiphers().get(GroupCipher.WEP40)); + assertTrue(params.getAllowedGroupCiphers().get(GroupCipher.WEP104)); + + params.setEnabled(false); + assertFalse(params.isEnabled()); + } + + /** Verify SAE-specific methods */ + @Test + public void testSaeMethods() throws Exception { + SecurityParams p = SecurityParams.createWpa3PersonalParams(); + + assertFalse(p.isAddedByAutoUpgrade()); + p.setIsAddedByAutoUpgrade(true); + assertTrue(p.isAddedByAutoUpgrade()); + + assertFalse(p.isSaeH2eOnlyMode()); + p.enableSaeH2eOnlyMode(true); + assertTrue(p.isSaeH2eOnlyMode()); + + assertFalse(p.isSaePkOnlyMode()); + p.enableSaePkOnlyMode(true); + assertTrue(p.isSaePkOnlyMode()); + } + + /** Verify copy constructor. */ + @Test + public void testCopyConstructor() throws Exception { + SecurityParams params = SecurityParams.createWpaWpa2PersonalParams(); + params.setEnabled(false); + params.setIsAddedByAutoUpgrade(true); + + SecurityParams copiedParams = new SecurityParams(params); + + assertTrue(params.isSameSecurityType(copiedParams)); + assertEquals(params.getAllowedKeyManagement(), copiedParams.getAllowedKeyManagement()); + assertEquals(params.getAllowedProtocols(), copiedParams.getAllowedProtocols()); + assertEquals(params.getAllowedAuthAlgorithms(), copiedParams.getAllowedAuthAlgorithms()); + assertEquals(params.getAllowedPairwiseCiphers(), copiedParams.getAllowedPairwiseCiphers()); + assertEquals(params.getAllowedGroupCiphers(), copiedParams.getAllowedGroupCiphers()); + assertEquals(params.getAllowedGroupManagementCiphers(), + copiedParams.getAllowedGroupManagementCiphers()); + assertEquals(params.getAllowedSuiteBCiphers(), copiedParams.getAllowedSuiteBCiphers()); + assertEquals(params.isRequirePmf(), copiedParams.isRequirePmf()); + assertEquals(params.isEnabled(), copiedParams.isEnabled()); + assertEquals(params.isSaeH2eOnlyMode(), copiedParams.isSaeH2eOnlyMode()); + assertEquals(params.isSaePkOnlyMode(), copiedParams.isSaePkOnlyMode()); + assertEquals(params.isAddedByAutoUpgrade(), copiedParams.isAddedByAutoUpgrade()); + } + + /** Check that two params are equal if and only if their types are the same. */ + @Test + public void testEquals() { + SecurityParams saeParams1 = SecurityParams.createWpa3PersonalParams(); + SecurityParams saeParams2 = SecurityParams.createWpa3PersonalParams(); + SecurityParams pskParams = SecurityParams.createWpaWpa2PersonalParams(); + assertEquals(saeParams1, saeParams2); + assertNotEquals(saeParams1, pskParams); + } + + /** Check that hash values are the same if and only if their types are the same. */ + @Test + public void testHashCode() { + SecurityParams saeParams1 = SecurityParams.createWpa3PersonalParams(); + SecurityParams saeParams2 = SecurityParams.createWpa3PersonalParams(); + SecurityParams pskParams = SecurityParams.createWpaWpa2PersonalParams(); + assertEquals(saeParams1.hashCode(), saeParams2.hashCode()); + assertNotEquals(saeParams1.hashCode(), pskParams.hashCode()); + } + + /** Verify open network check */ + @Test + public void testIsOpenNetwork() { + SecurityParams[] openSecurityParams = new SecurityParams[] { + SecurityParams.createEnhancedOpenParams(), + SecurityParams.createOpenParams(), + }; + for (SecurityParams p: openSecurityParams) { + assertTrue(p.isOpenSecurityType()); + } + + SecurityParams[] nonOpenSecurityParams = new SecurityParams[] { + SecurityParams.createWpaWpa2EnterpriseParams(), + SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R1), + SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R2), + SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R3), + SecurityParams.createOsenParams(), + SecurityParams.createWapiCertParams(), + SecurityParams.createWapiPskParams(), + SecurityParams.createWepParams(), + SecurityParams.createWpa3Enterprise192BitParams(), + SecurityParams.createWpa3EnterpriseParams(), + SecurityParams.createWpa3PersonalParams(), + SecurityParams.createWpaWpa2PersonalParams(), + }; + for (SecurityParams p: nonOpenSecurityParams) { + assertFalse(p.isOpenSecurityType()); + } + } + + /** Verify enterprise network check */ + @Test + public void testIsEnterpriseNetwork() { + SecurityParams[] enterpriseSecurityParams = new SecurityParams[] { + SecurityParams.createWpaWpa2EnterpriseParams(), + SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R1), + SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R2), + SecurityParams.createPasspointParams(SecurityParams.PASSPOINT_R3), + SecurityParams.createWapiCertParams(), + SecurityParams.createWpa3Enterprise192BitParams(), + SecurityParams.createWpa3EnterpriseParams(), + }; + for (SecurityParams p: enterpriseSecurityParams) { + assertTrue(p.isEnterpriseSecurityType()); + } + + SecurityParams[] nonEnterpriseSecurityParams = new SecurityParams[] { + SecurityParams.createEnhancedOpenParams(), + SecurityParams.createOpenParams(), + SecurityParams.createOsenParams(), + SecurityParams.createWapiPskParams(), + SecurityParams.createWepParams(), + SecurityParams.createWpa3PersonalParams(), + SecurityParams.createWpaWpa2PersonalParams(), + }; + for (SecurityParams p: nonEnterpriseSecurityParams) { + assertFalse(p.isEnterpriseSecurityType()); + } + } + + /** Check that parcel marshalling/unmarshalling works */ + @Test + public void testParcelMethods() { + SecurityParams params = SecurityParams.createWpa3PersonalParams(); + + Parcel parcelW = Parcel.obtain(); + params.writeToParcel(parcelW, 0); + byte[] bytes = parcelW.marshall(); + parcelW.recycle(); + + Parcel parcelR = Parcel.obtain(); + parcelR.unmarshall(bytes, 0, bytes.length); + parcelR.setDataPosition(0); + + SecurityParams reParams = SecurityParams.createFromParcel(parcelR); + assertEquals(params, reParams); + } +} diff --git a/wifi/tests/src/android/net/wifi/SoftApCapabilityTest.java b/wifi/tests/src/android/net/wifi/SoftApCapabilityTest.java index 702212b324f6..9e3b02266de1 100644 --- a/wifi/tests/src/android/net/wifi/SoftApCapabilityTest.java +++ b/wifi/tests/src/android/net/wifi/SoftApCapabilityTest.java @@ -42,10 +42,12 @@ public class SoftApCapabilityTest { | SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD; int[] testSupported2Glist = {1, 2, 3, 4}; int[] testSupported5Glist = {36, 149}; + int[] testSupported60Glist = {1, 2}; SoftApCapability capability = new SoftApCapability(testSoftApFeature); capability.setMaxSupportedClients(10); capability.setSupportedChannelList(SoftApConfiguration.BAND_2GHZ, testSupported2Glist); capability.setSupportedChannelList(SoftApConfiguration.BAND_5GHZ, testSupported5Glist); + capability.setSupportedChannelList(SoftApConfiguration.BAND_60GHZ, testSupported60Glist); SoftApCapability copiedCapability = new SoftApCapability(capability); @@ -64,9 +66,11 @@ public class SoftApCapabilityTest { capability.setMaxSupportedClients(10); int[] testSupported2Glist = {1, 2, 3, 4}; int[] testSupported5Glist = {36, 149}; + int[] testSupported60Glist = {1, 2}; capability.setSupportedChannelList(SoftApConfiguration.BAND_2GHZ, testSupported2Glist); capability.setSupportedChannelList(SoftApConfiguration.BAND_5GHZ, testSupported5Glist); + capability.setSupportedChannelList(SoftApConfiguration.BAND_60GHZ, testSupported60Glist); Parcel parcelW = Parcel.obtain(); capability.writeToParcel(parcelW, 0); diff --git a/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java b/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java index bcfdf7d80061..a609a120b61f 100644 --- a/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java +++ b/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java @@ -519,4 +519,14 @@ public class SoftApConfigurationTest { } assertTrue(isIllegalArgumentExceptionHappened); } + + @Test(expected = IllegalArgumentException.class) + public void testInvalidConfigWhenSet60GhzChannels() throws Exception { + SparseIntArray invalid_channels = new SparseIntArray(); + invalid_channels.put(SoftApConfiguration.BAND_60GHZ, 99); + SoftApConfiguration config = new SoftApConfiguration.Builder() + .setSsid("ssid") + .setChannels(invalid_channels) + .build(); + } } diff --git a/wifi/tests/src/android/net/wifi/SoftApInfoTest.java b/wifi/tests/src/android/net/wifi/SoftApInfoTest.java index 28758432119c..2121d10121b0 100644 --- a/wifi/tests/src/android/net/wifi/SoftApInfoTest.java +++ b/wifi/tests/src/android/net/wifi/SoftApInfoTest.java @@ -32,17 +32,22 @@ import org.junit.Test; */ @SmallTest public class SoftApInfoTest { - + private static final String TEST_AP_INSTANCE = "wlan1"; + private static final int TEST_FREQUENCY = 2412; + private static final int TEST_BANDWIDTH = SoftApInfo.CHANNEL_WIDTH_20MHZ; + private static final int TEST_WIFI_STANDARD = ScanResult.WIFI_STANDARD_LEGACY; + private static final MacAddress TEST_AP_MAC = MacAddress.fromString("aa:bb:cc:dd:ee:ff"); /** * Verifies copy constructor. */ @Test public void testCopyOperator() throws Exception { SoftApInfo info = new SoftApInfo(); - info.setFrequency(2412); - info.setBandwidth(SoftApInfo.CHANNEL_WIDTH_20MHZ); - info.setBssid(MacAddress.fromString("aa:bb:cc:dd:ee:ff")); - info.setWifiStandard(ScanResult.WIFI_STANDARD_LEGACY); + info.setFrequency(TEST_FREQUENCY); + info.setBandwidth(TEST_BANDWIDTH); + info.setBssid(TEST_AP_MAC); + info.setWifiStandard(TEST_WIFI_STANDARD); + info.setApInstanceIdentifier(TEST_AP_INSTANCE); SoftApInfo copiedInfo = new SoftApInfo(info); @@ -57,10 +62,11 @@ public class SoftApInfoTest { @Test public void testParcelOperation() throws Exception { SoftApInfo info = new SoftApInfo(); - info.setFrequency(2412); - info.setBandwidth(SoftApInfo.CHANNEL_WIDTH_20MHZ); - info.setBssid(MacAddress.fromString("aa:bb:cc:dd:ee:ff")); - info.setWifiStandard(ScanResult.WIFI_STANDARD_LEGACY); + info.setFrequency(TEST_FREQUENCY); + info.setBandwidth(TEST_BANDWIDTH); + info.setBssid(TEST_AP_MAC); + info.setWifiStandard(TEST_WIFI_STANDARD); + info.setApInstanceIdentifier(TEST_AP_INSTANCE); Parcel parcelW = Parcel.obtain(); info.writeToParcel(parcelW, 0); @@ -88,6 +94,27 @@ public class SoftApInfoTest { if (SdkLevel.isAtLeastS()) { assertEquals(info.getBssid(), null); assertEquals(info.getWifiStandard(), ScanResult.WIFI_STANDARD_UNKNOWN); + assertEquals(info.getApInstanceIdentifier(), null); + } + } + + /** + * Verifies the set/get method same as expected. + */ + @Test + public void testGetXXXAlignedWithSetXXX() throws Exception { + SoftApInfo info = new SoftApInfo(); + info.setFrequency(TEST_FREQUENCY); + info.setBandwidth(TEST_BANDWIDTH); + info.setBssid(TEST_AP_MAC); + info.setWifiStandard(TEST_WIFI_STANDARD); + info.setApInstanceIdentifier(TEST_AP_INSTANCE); + assertEquals(info.getFrequency(), TEST_FREQUENCY); + assertEquals(info.getBandwidth(), TEST_BANDWIDTH); + if (SdkLevel.isAtLeastS()) { + assertEquals(info.getBssid(), TEST_AP_MAC); + assertEquals(info.getWifiStandard(), TEST_WIFI_STANDARD); + assertEquals(info.getApInstanceIdentifier(), TEST_AP_INSTANCE); } } diff --git a/wifi/tests/src/android/net/wifi/WifiClientTest.java b/wifi/tests/src/android/net/wifi/WifiClientTest.java index 7a3baf9ebaf2..704656320a91 100644 --- a/wifi/tests/src/android/net/wifi/WifiClientTest.java +++ b/wifi/tests/src/android/net/wifi/WifiClientTest.java @@ -42,9 +42,9 @@ public class WifiClientTest { */ @Test public void testWifiClientParcelWriteRead() throws Exception { - WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS); + WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME); - assertParcelSane(writeWifiClient, 1); + assertParcelSane(writeWifiClient, 2); } /** @@ -52,12 +52,12 @@ public class WifiClientTest { */ @Test public void testWifiClientEquals() throws Exception { - WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS); - WifiClient writeWifiClientEquals = new WifiClient(MAC_ADDRESS); + WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME); + WifiClient writeWifiClientEquals = new WifiClient(MAC_ADDRESS, INTERFACE_NAME); assertEquals(writeWifiClient, writeWifiClientEquals); assertEquals(writeWifiClient.hashCode(), writeWifiClientEquals.hashCode()); - assertFieldCountEquals(1, WifiClient.class); + assertFieldCountEquals(2, WifiClient.class); } /** @@ -66,8 +66,8 @@ public class WifiClientTest { @Test public void testWifiClientNotEquals() throws Exception { final MacAddress macAddressNotEquals = MacAddress.fromString("00:00:00:00:00:00"); - WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS); - WifiClient writeWifiClientNotEquals = new WifiClient(macAddressNotEquals); + WifiClient writeWifiClient = new WifiClient(MAC_ADDRESS, INTERFACE_NAME); + WifiClient writeWifiClientNotEquals = new WifiClient(macAddressNotEquals, INTERFACE_NAME); assertNotEquals(writeWifiClient, writeWifiClientNotEquals); assertNotEquals(writeWifiClient.hashCode(), writeWifiClientNotEquals.hashCode()); diff --git a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java index c25374695463..f351e61b5eb8 100644 --- a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java +++ b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java @@ -20,11 +20,13 @@ import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_EAP; import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE; import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT; import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_OPEN; +import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_OSEN; import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_OWE; import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_PSK; import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_SAE; import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_WAPI_CERT; import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_WAPI_PSK; +import static android.net.wifi.WifiConfiguration.SECURITY_TYPE_WEP; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -34,9 +36,13 @@ import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertTrue; import android.net.MacAddress; +import android.net.wifi.WifiConfiguration.GroupCipher; import android.net.wifi.WifiConfiguration.KeyMgmt; import android.net.wifi.WifiConfiguration.NetworkSelectionStatus; +import android.net.wifi.WifiConfiguration.PairwiseCipher; +import android.net.wifi.WifiConfiguration.Protocol; import android.os.Parcel; +import android.util.Pair; import androidx.test.filters.SmallTest; @@ -45,6 +51,8 @@ import com.android.net.module.util.MacAddressUtils; import org.junit.Before; import org.junit.Test; +import java.util.List; + /** * Unit tests for {@link android.net.wifi.WifiConfiguration}. */ @@ -187,18 +195,24 @@ public class WifiConfigurationTest { @Test public void testIsOpenNetwork_NotOpen_HasAuthType() { - for (int keyMgmt = 0; keyMgmt < WifiConfiguration.KeyMgmt.strings.length; keyMgmt++) { - if (keyMgmt == WifiConfiguration.KeyMgmt.NONE - || keyMgmt == WifiConfiguration.KeyMgmt.OWE) { - continue; - } + int[] securityTypes = new int [] { + SECURITY_TYPE_WEP, + SECURITY_TYPE_PSK, + SECURITY_TYPE_EAP, + SECURITY_TYPE_SAE, + SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT, + SECURITY_TYPE_WAPI_PSK, + SECURITY_TYPE_WAPI_CERT, + SECURITY_TYPE_EAP_WPA3_ENTERPRISE, + SECURITY_TYPE_OSEN, + }; + for (int type: securityTypes) { WifiConfiguration config = new WifiConfiguration(); - config.allowedKeyManagement.clear(); - config.allowedKeyManagement.set(keyMgmt); + config.setSecurityParams(type); config.wepKeys = null; - assertFalse("Open network reported when key mgmt was set to " - + WifiConfiguration.KeyMgmt.strings[keyMgmt], config.isOpenNetwork()); + assertFalse("Open network reported when security type was set to " + + type, config.isOpenNetwork()); } } @@ -208,6 +222,7 @@ public class WifiConfigurationTest { config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); config.wepKeys = null; + config.convertLegacyFieldsToSecurityParamsIfNeeded(); assertFalse(config.isOpenNetwork()); } @@ -865,4 +880,243 @@ public class WifiConfigurationTest { } return sb.toString(); } + + private void verifyAllowedKeyManagement(WifiConfiguration config, int[] akms) { + for (int akm: akms) { + assertTrue(config.getSecurityParamsList().stream() + .anyMatch(params -> params.getAllowedKeyManagement().get(akm))); + } + } + + private void verifyAllowedProtocols(WifiConfiguration config, int[] aps) { + for (int ap: aps) { + assertTrue(config.getSecurityParamsList().stream() + .anyMatch(params -> params.getAllowedProtocols().get(ap))); + } + } + + private void verifyAllowedPairwiseCiphers(WifiConfiguration config, int[] apcs) { + for (int apc: apcs) { + assertTrue(config.getSecurityParamsList().stream() + .anyMatch(params -> params.getAllowedPairwiseCiphers().get(apc))); + } + } + + private void verifyAllowedGroupCiphers(WifiConfiguration config, int[] agcs) { + for (int agc: agcs) { + assertTrue(config.getSecurityParamsList().stream() + .anyMatch(params -> params.getAllowedGroupCiphers().get(agc))); + } + } + + /** Verify that adding security types works as expected. */ + @Test + public void testAddSecurityTypes() { + WifiConfiguration config = new WifiConfiguration(); + config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE); + config.addSecurityParams(SecurityParams.createWapiPskParams()); + List<SecurityParams> paramsList = config.getSecurityParamsList(); + assertEquals(3, paramsList.size()); + + verifyAllowedKeyManagement(config, new int[] { + KeyMgmt.WPA_PSK, KeyMgmt.SAE, KeyMgmt.WAPI_PSK}); + verifyAllowedProtocols(config, new int[] {Protocol.WPA, Protocol.RSN, Protocol.WAPI}); + verifyAllowedPairwiseCiphers(config, new int[] { + PairwiseCipher.CCMP, PairwiseCipher.TKIP, + PairwiseCipher.GCMP_128, PairwiseCipher.GCMP_256, + PairwiseCipher.SMS4}); + verifyAllowedGroupCiphers(config, new int[] { + GroupCipher.CCMP, GroupCipher.TKIP, + GroupCipher.GCMP_128, GroupCipher.GCMP_256, + GroupCipher.SMS4}); + } + + /** Check that a personal security type can be added to a personal configuration. */ + @Test + public void testAddPersonalTypeToPersonalConfiguration() { + WifiConfiguration config = new WifiConfiguration(); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE); + } + + /** Check that an enterprise security type can be added to an enterprise configuration. */ + @Test + public void testAddEnterpriseTypeToEnterpriseConfiguration() { + WifiConfiguration config = new WifiConfiguration(); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP); + config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM); + config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE); + } + + /** Verify that adding an enterprise type to a personal configuration. */ + @Test (expected = IllegalArgumentException.class) + public void testAddEnterpriseTypeToPersonalConfig() { + WifiConfiguration config = new WifiConfiguration(); + config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP); + } + + /** Verify that adding a personal type to an enterprise configuration. */ + @Test (expected = IllegalArgumentException.class) + public void testAddPersonalTypeToEnterpriseConfig() { + WifiConfiguration config = new WifiConfiguration(); + config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP); + config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM); + config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + } + + /** Check that an open security cannot be added to a non-open configuration. */ + @Test(expected = IllegalArgumentException.class) + public void testAddOpenTypeToNonOpenConfiguration() { + WifiConfiguration config = new WifiConfiguration(); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN); + } + + /** Check that a non-open security cannot be added to an open configuration. */ + @Test(expected = IllegalArgumentException.class) + public void testAddNonOpenTypeToOpenConfiguration() { + WifiConfiguration config = new WifiConfiguration(); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + } + + /** Check that a OSEN security cannot be added as additional type. */ + @Test(expected = IllegalArgumentException.class) + public void testAddOsenTypeToConfiguration() { + WifiConfiguration config = new WifiConfiguration(); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_OSEN); + } + + /** Verify that adding duplicate security types raises the exception. */ + @Test (expected = IllegalArgumentException.class) + public void testAddDuplicateSecurityTypes() { + WifiConfiguration config = new WifiConfiguration(); + config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + } + + /** Verify that adding duplicate security params raises the exception. */ + @Test (expected = IllegalArgumentException.class) + public void testAddDuplicateSecurityParams() { + WifiConfiguration config = new WifiConfiguration(); + config.addSecurityParams(SecurityParams.createWpaWpa2PersonalParams()); + config.addSecurityParams(SecurityParams.createWpaWpa2PersonalParams()); + } + + /** Verify that Suite-B type works as expected. */ + @Test + public void testAddSuiteBSecurityType() { + WifiConfiguration config = new WifiConfiguration(); + config.addSecurityParams(SecurityParams.createWpa3EnterpriseParams()); + config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.SIM); + config.enterpriseConfig.setPhase2Method(WifiEnterpriseConfig.Phase2.NONE); + config.addSecurityParams(SecurityParams.createWpa3Enterprise192BitParams()); + + assertFalse(config.isSuiteBCipherEcdheRsaEnabled()); + config.enableSuiteBCiphers(false, true); + assertTrue(config.isSuiteBCipherEcdheRsaEnabled()); + } + + /** Verify that FILS bit can be set correctly. */ + @Test + public void testFilsKeyMgmt() { + WifiConfiguration config = new WifiConfiguration(); + config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE); + + config.enableFils(false, true); + assertFalse(config.isFilsSha256Enabled()); + assertTrue(config.isFilsSha384Enabled()); + } + + /** Verify that SAE mode can be configured correctly. */ + @Test + public void testSaeTypeMethods() { + WifiConfiguration config = new WifiConfiguration(); + config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK); + config.addSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE); + + SecurityParams saeParams = config.getSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE); + assertNotNull(saeParams); + assertFalse(saeParams.isSaeH2eOnlyMode()); + assertFalse(saeParams.isSaePkOnlyMode()); + + config.enableSaeH2eOnlyMode(true); + config.enableSaePkOnlyMode(true); + + saeParams = config.getSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE); + assertNotNull(saeParams); + assertTrue(saeParams.isSaeH2eOnlyMode()); + assertTrue(saeParams.isSaePkOnlyMode()); + } + + /** Verify the legacy configuration conversion */ + @Test + public void testLegacyConfigurationConversion() { + Pair[] keyMgmtSecurityTypePairs = new Pair[] { + new Pair<>(KeyMgmt.WAPI_CERT, SECURITY_TYPE_WAPI_CERT), + new Pair<>(KeyMgmt.WAPI_PSK, SECURITY_TYPE_WAPI_PSK), + new Pair<>(KeyMgmt.SUITE_B_192, SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT), + new Pair<>(KeyMgmt.OWE, SECURITY_TYPE_OWE), + new Pair<>(KeyMgmt.SAE, SECURITY_TYPE_SAE), + new Pair<>(KeyMgmt.OSEN, SECURITY_TYPE_OSEN), + new Pair<>(KeyMgmt.WPA2_PSK, SECURITY_TYPE_PSK), + new Pair<>(KeyMgmt.WPA_EAP, SECURITY_TYPE_EAP), + new Pair<>(KeyMgmt.WPA_PSK, SECURITY_TYPE_PSK), + new Pair<>(KeyMgmt.NONE, SECURITY_TYPE_OPEN), + }; + + for (Pair pair: keyMgmtSecurityTypePairs) { + WifiConfiguration config = new WifiConfiguration(); + config.allowedKeyManagement.set((int) pair.first); + config.convertLegacyFieldsToSecurityParamsIfNeeded(); + assertNotNull(config.getSecurityParams((int) pair.second)); + } + + // If none of key management is set, it should be open. + WifiConfiguration emptyConfig = new WifiConfiguration(); + emptyConfig.convertLegacyFieldsToSecurityParamsIfNeeded(); + assertNotNull(emptyConfig.getSecurityParams(SECURITY_TYPE_OPEN)); + + // If EAP key management is set and requirePmf is true, it is WPA3 Enterprise. + WifiConfiguration wpa3EnterpriseConfig = new WifiConfiguration(); + wpa3EnterpriseConfig.allowedKeyManagement.set(KeyMgmt.WPA_EAP); + wpa3EnterpriseConfig.requirePmf = true; + wpa3EnterpriseConfig.convertLegacyFieldsToSecurityParamsIfNeeded(); + assertNotNull(wpa3EnterpriseConfig.getSecurityParams(SECURITY_TYPE_EAP_WPA3_ENTERPRISE)); + + // If key management is NONE and wep key is set, it is WEP type. + WifiConfiguration wepConfig = new WifiConfiguration(); + wepConfig.allowedKeyManagement.set(KeyMgmt.NONE); + wepConfig.wepKeys = new String[] {"\"abcdef\""}; + wepConfig.convertLegacyFieldsToSecurityParamsIfNeeded(); + assertNotNull(wepConfig.getSecurityParams(SECURITY_TYPE_WEP)); + } + + /** Verify the set security params by SecurityParams objects. */ + @Test + public void testSetBySecurityParamsObject() { + Pair[] securityParamsSecurityTypePairs = new Pair[] { + new Pair<>(SecurityParams.createWapiCertParams(), SECURITY_TYPE_WAPI_CERT), + new Pair<>(SecurityParams.createWapiPskParams(), SECURITY_TYPE_WAPI_PSK), + new Pair<>(SecurityParams.createWpa3Enterprise192BitParams(), + SECURITY_TYPE_EAP_WPA3_ENTERPRISE_192_BIT), + new Pair<>(SecurityParams.createEnhancedOpenParams(), SECURITY_TYPE_OWE), + new Pair<>(SecurityParams.createWpa3PersonalParams(), SECURITY_TYPE_SAE), + new Pair<>(SecurityParams.createOsenParams(), SECURITY_TYPE_OSEN), + new Pair<>(SecurityParams.createWpaWpa2EnterpriseParams(), SECURITY_TYPE_EAP), + new Pair<>(SecurityParams.createWpaWpa2PersonalParams(), SECURITY_TYPE_PSK), + new Pair<>(SecurityParams.createOpenParams(), SECURITY_TYPE_OPEN), + }; + for (Pair pair: securityParamsSecurityTypePairs) { + WifiConfiguration config = new WifiConfiguration(); + config.setSecurityParams((SecurityParams) pair.first); + assertNotNull(config.getSecurityParams((int) pair.second)); + } + } } diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java index 52e91394d8bf..bd56e5b49ee6 100644 --- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java +++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java @@ -137,6 +137,7 @@ public class WifiManagerTest { private static final int TEST_AP_FREQUENCY = 2412; private static final int TEST_AP_BANDWIDTH = SoftApInfo.CHANNEL_WIDTH_20MHZ; private static final int TEST_SUB_ID = 3; + private static final String TEST_AP_INSTANCE = "wlan1"; @Mock Context mContext; @Mock android.net.wifi.IWifiManager mWifiService; @@ -1111,6 +1112,27 @@ public class WifiManagerTest { verify(mSoftApCallback).onInfoChanged(testSoftApInfo); } + /* + * Verify client-provided callback is being called through callback proxy + */ + @Test + public void softApCallbackProxyCallsOnSoftApInfoListChanged() throws Exception { + SoftApInfo testSoftApInfo = new SoftApInfo(); + testSoftApInfo.setFrequency(TEST_AP_FREQUENCY); + testSoftApInfo.setBandwidth(TEST_AP_BANDWIDTH); + List<SoftApInfo> infoList = new ArrayList<>(); + infoList.add(testSoftApInfo); + ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor = + ArgumentCaptor.forClass(ISoftApCallback.Stub.class); + mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback); + verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(), + anyInt()); + + callbackCaptor.getValue().onInfoListChanged(infoList); + mLooper.dispatchAll(); + verify(mSoftApCallback).onInfoListChanged(infoList); + } + /* * Verify client-provided callback is being called through callback proxy @@ -1135,7 +1157,8 @@ public class WifiManagerTest { */ @Test public void softApCallbackProxyCallsOnBlockedClientConnecting() throws Exception { - WifiClient testWifiClient = new WifiClient(MacAddress.fromString("22:33:44:55:66:77")); + WifiClient testWifiClient = new WifiClient(MacAddress.fromString("22:33:44:55:66:77"), + TEST_AP_INSTANCE); ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor = ArgumentCaptor.forClass(ISoftApCallback.Stub.class); mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback); @@ -1157,6 +1180,8 @@ public class WifiManagerTest { SoftApInfo testSoftApInfo = new SoftApInfo(); testSoftApInfo.setFrequency(TEST_AP_FREQUENCY); testSoftApInfo.setBandwidth(TEST_AP_BANDWIDTH); + List<SoftApInfo> infoList = new ArrayList<>(); + infoList.add(testSoftApInfo); SoftApCapability testSoftApCapability = new SoftApCapability(0); testSoftApCapability.setMaxSupportedClients(10); ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor = @@ -1169,6 +1194,7 @@ public class WifiManagerTest { callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_ENABLING, 0); callbackCaptor.getValue().onConnectedClientsChanged(testClients); callbackCaptor.getValue().onInfoChanged(testSoftApInfo); + callbackCaptor.getValue().onInfoListChanged(infoList); callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL); callbackCaptor.getValue().onCapabilityChanged(testSoftApCapability); @@ -1177,6 +1203,7 @@ public class WifiManagerTest { verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_ENABLING, 0); verify(mSoftApCallback).onConnectedClientsChanged(testClients); verify(mSoftApCallback).onInfoChanged(testSoftApInfo); + verify(mSoftApCallback).onInfoListChanged(infoList); verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL); verify(mSoftApCallback).onCapabilityChanged(testSoftApCapability); } diff --git a/wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java b/wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java index e6eae416ba78..c8006fead55b 100644 --- a/wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java +++ b/wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java @@ -16,6 +16,8 @@ package android.net.wifi.rtt; +import static junit.framework.Assert.fail; + import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @@ -143,6 +145,7 @@ public class WifiRttManagerTest { PeerHandle peerHandle1 = new PeerHandle(12); RangingRequest.Builder builder = new RangingRequest.Builder(); + builder.setRttBurstSize(4); builder.addAccessPoint(scanResult1); builder.addAccessPoints(scanResults2and3); builder.addWifiAwarePeer(mac1); @@ -163,6 +166,60 @@ public class WifiRttManagerTest { } /** + * Validate the rtt burst size is set correctly when in range. + */ + @Test + public void testRangingRequestSetBurstSize() { + ScanResult scanResult = new ScanResult(); + scanResult.BSSID = "AA:BB:CC:DD:EE:FF"; + + // create request + RangingRequest.Builder builder = new RangingRequest.Builder(); + builder.setRttBurstSize(4); + builder.addAccessPoint(scanResult); + RangingRequest request = builder.build(); + + // confirm rtt burst size is set correctly to default value + assertEquals(request.getRttBurstSize(), 4); + } + + /** + * Validate the rtt burst size cannot be smaller than the minimum. + */ + @Test + public void testRangingRequestMinBurstSizeIsEnforced() { + ScanResult scanResult = new ScanResult(); + scanResult.BSSID = "AA:BB:CC:DD:EE:FF"; + + // create request + try { + RangingRequest.Builder builder = new RangingRequest.Builder(); + builder.setRttBurstSize(RangingRequest.getMinRttBurstSize() - 1); + fail("RTT burst size was smaller than min value."); + } catch (IllegalArgumentException e) { + // expected + } + } + + /** + * Validate the rtt burst size cannot exceed the maximum. + */ + @Test + public void testRangingRequestMaxBurstSizeIsEnforced() { + ScanResult scanResult = new ScanResult(); + scanResult.BSSID = "AA:BB:CC:DD:EE:FF"; + + // create request + try { + RangingRequest.Builder builder = new RangingRequest.Builder(); + builder.setRttBurstSize(RangingRequest.getMaxRttBurstSize() + 1); + fail("RTT Burst size exceeded max value."); + } catch (IllegalArgumentException e) { + // expected + } + } + + /** * Validate that can request as many range operation as the upper limit on number of requests. */ @Test @@ -175,7 +232,7 @@ public class WifiRttManagerTest { } MacAddress mac1 = MacAddress.fromString("00:01:02:03:04:05"); - // create request + // create request using max RTT Peers RangingRequest.Builder builder = new RangingRequest.Builder(); builder.addAccessPoint(scanResult); builder.addAccessPoints(scanResultList); @@ -185,6 +242,18 @@ public class WifiRttManagerTest { // verify request request.enforceValidity(true); + // confirm rtt burst size is set correctly to default value + assertEquals(request.getRttBurstSize(), RangingRequest.getDefaultRttBurstSize()); + // confirm the number of peers in the request is the max number of peers + List<ResponderConfig> rttPeers = request.getRttPeers(); + int numRttPeers = rttPeers.size(); + assertEquals(RangingRequest.getMaxPeers(), numRttPeers); + // confirm each peer has the correct mac address + for (int i = 0; i < numRttPeers - 1; ++i) { + assertEquals("AA:BB:CC:DD:EE:FF", rttPeers.get(i).macAddress.toString().toUpperCase()); + } + assertEquals("00:01:02:03:04:05", + rttPeers.get(numRttPeers - 1).macAddress.toString().toUpperCase()); } /** |